Source file: /~heha/messtech/matdde.zip/source/ddelib.cpp

#include <windows.h>
#include <ddeml.h>
#include <malloc.h>		//fuer _memmax()
#include <string.h>		//fuer memmove()
#include <stdlib.h>		//fuer atof()

#define DLLMEX
#include "header\mex.h"

#include "header\fastdde.h"
#include "header\testargs.h"	//fuer ErrorBeep()

#pragma hdrstop


/////////////////////////////////////////////////////////////////////////////////////////////////////
void GetMatrixSize( char huge* hDataString, DWORD* DataSize, int* rows, int* columns )
{
	DWORD i = 0;

	*rows = 0;		//Initialwerte
	*columns = 1;	//Initialwerte

	while ( hDataString[i++] && i < *DataSize )
	{
		if ( hDataString[i] == '\t' && *rows == 0 )		//Tabulatoren nur in der 1. Zeile der Matrix erfassen
			(*columns)++;								//und Anzahl der Spalten ermitteln
	    if ( hDataString[i] == '\r' )					//wenn Zeilenende, dann eine Zeile mehr
		    (*rows)++;
	}
	
	if (*rows == 0 && i > 1) (*rows)++;					//mindestens eine Zeile, sonst leere Matrix
	*DataSize = i;										//tatsaechliche Groesse bis zur abschliessenden Null
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Str2Double( double huge* dest, DWORD MatrixSize, char huge* hDataString, DWORD DataSize )
{
	DWORD i,k,m;
	i = k = m = 0;
	BOOL result = TRUE;
	char huge* pNextString = hDataString;
	char strBuffer[100];	//es werden bis zu 100 Stellen (max. Wert fuer atof) fuer eine Zahl kopiert
	
	while ( i < MatrixSize )
	{
		
		//Beginn der naechsten Zahl suchen 
		while ( m++ < DataSize )
		{
			if ( *pNextString == '\0' || *pNextString == '\t' ) 
			{
				pNextString++;
				break;		
			}
			if ( *pNextString == '\r' )
			{
				pNextString += 2;
				m++;
				break;
			}                 
			pNextString++;
		}                       
		
		if ( *hDataString == '\0' )	//wenn Daten fehlen
			return FALSE;
		
		if ( *hDataString == '\t' || *hDataString == '\r' ) 
		{            
			dest[i] = 0;
			result = FALSE;
		}
		else	
		{
			//lokale Kopie, wegen atof() -huge-Zeigerproblem
			hmemcpy( (char huge*) strBuffer, (char huge*) hDataString, min(sizeof(strBuffer), m - k) );	
			dest[i] = atof( strBuffer );  
		}
		
		k = m;
		hDataString = pNextString;
		i++;	
	}
	if (!result)
    	mexPrintf( "??? Possible empty element(s) of source matrix.\r\n" );	
    return TRUE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
void Transpose(	double huge* dest, double huge* src, UINT rows, UINT cols )
{                                                                 

	double huge* help;

//	*** Matrix transponieren                                            
	if (cols < rows) 
	{											//Spalten-Schleife aussen
		for ( UINT i = 0; i < cols; i++ )
		{
			help = src + (DWORD)i;
			for ( UINT k = 0; k < rows; k++ )
			{
				hmemcpy( dest, help, sizeof(double) );
				dest++; 
				help += (DWORD)cols;
			}
		}
    } else {									//Zeilen-Schleife aussen
    	for ( UINT k = 0; k < rows; k++ )
    	{
			help = dest + (DWORD)k;
    		for ( UINT i = 0; i < cols; i++ )
			{
				hmemcpy( help, src, sizeof(double) );
				src++; 
				help += (DWORD)rows;
			}
    	}
    }

}



/////////////////////////////////////////////////////////////////////////////////////////////////////
void HandleDdeError(UINT DdeError)
{
    static char szErr[31] = "??? DDEML: ";
    static char *DdeE[] = {
		"AdvAckTimeout"              ,
        "Busy"                       ,
        "DataAckTimeout"             ,
        "Dll_Not_Initialized"        ,
        "Dll_Usage"                  ,
        "ExecAckTimeout"             ,
        "InvalidParameter"           ,
        "Low Memory warning"         ,
        "Memory_Error"               ,
        "NotProcessed"               ,
        "No_Conv_Established"        ,
        "PokeAckTimeout"             ,
        "PostMsg_Failed"             ,
        "Reentrancy"                 ,
        "Server_Died"                ,
        "Sys_Error"                  ,
        "UnadvAckTimeout"            ,
        "Unfound_Queue_ID"           ,    
	};
    if (!DdeError) {   
        strcpy(&szErr[4], "0");
    } else if (DdeError > DMLERR_LAST || DdeError < DMLERR_FIRST) {
        strcpy(&szErr[4], "Unknown DDEML Error");
    } else {
        strcpy(&szErr[4], DdeE[DdeError - DMLERR_FIRST]);
    }
    strcat(szErr,".\r\n");
	mexPrintf(szErr);
	ErrorBeep();    
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CFTextStringReq( HDDEDATA hData, Matrix** DestMatrix )
{
	DWORD		DataSize, StringLen = 0;
    
	char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize );
    size_t LocalMax = _memmax();
	//Stringlaenge bestimmen
	char huge* hDataString_end = hDataString;
	while ( *(hDataString_end++) != '\0' && StringLen++ < DataSize);
	
	if (StringLen > LocalMax-1)		//besser: heapSize           malloc
	{
		mexPrintf( "??? Possible data lost. More then 64 KByte text.\r\n" );
		ErrorBeep();
		StringLen = LocalMax-1;
	}
	
	//Speicher reservieren, um String lokal umzukopieren
	//HLOCAL	hLocalString = LocalAlloc( LPTR, (UINT)((hDataString_end - hDataString) +1) );
	HLOCAL hLocalString = LocalAlloc( LPTR, (UINT)(StringLen+1) );
	if ( !hLocalString )
	{
		DdeUnaccessData( hData );
		
		mexPrintf( "??? Memory allocation error.\r\n" );
		ErrorBeep();
		return TRUE;
	}
    
	char* szString = (char*) LocalLock( hLocalString );
	//kopieren
	//hmemcpy( (char huge*) szString, (char huge*) hDataString, hDataString_end - hDataString );
	hmemcpy( (char huge*) szString, (char huge*) hDataString, StringLen+1 );
	
	*DestMatrix = mxCreateString( szString );	//arbeitet nicht mit huge-Speicher!
	//Speicher freigeben
	LocalUnlock( hLocalString );
	LocalFree( hLocalString );
    
    DdeUnaccessData( hData );
	    
	return FALSE;
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CFTextRequest( HDDEDATA hData, Matrix** DestMatrix )
{
	HGLOBAL		hGlobal;
	int rows, columns;  
	DWORD		DataSize;
	
	char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize);

	//GetMatrixSize( hDataString, &rows, &columns );
	GetMatrixSize( hDataString, &DataSize, &rows, &columns );
	DWORD matrixSize = (DWORD)rows * (DWORD)columns;

	//Speicher reservieren
	hGlobal = GlobalAlloc( GPTR, matrixSize * sizeof(double) );
	if ( !hGlobal )
	{
		DdeUnaccessData( hData );
		mexPrintf( "??? Memory allocation error.\r\n" );
		ErrorBeep();
		return TRUE;
	}
    
	double huge* dest = (double huge*) GlobalLock( hGlobal );	//Speicherbereich mit double-Werten
    
	if ( Str2Double( dest, matrixSize, hDataString, DataSize ) )	//Konvertierung string -> double	
	{

	//Matrix erzeugen
		if ((*DestMatrix = mxCreateFull( rows, columns, REAL )) )
		{

			double huge* src	= dest;		//die zu double konvertierten strings sind jetzt source
			dest				= (double huge*)mxGetPr( *DestMatrix ); 
	
	//Matrix transponieren                
			Transpose( dest, src, rows, columns );	//ddelib.c
		}
		else
		{
			mexPrintf( "??? Memory allocation error.\r\n" );
			ErrorBeep();
	    }
	}

	GlobalUnlock( hGlobal );
	GlobalFree( hGlobal );

	DdeUnaccessData( hData );

	return FALSE;
}



///////////////////////////////////////////////////////DDE-Excel Format
BOOL FastDDEReq( HDDEDATA hData, Matrix** DestMatrix )
{
	DWORD		DataSize;
	TableHeader	TabHeader;
	
	char huge* hDataBlock = (char huge*) DdeAccessData( hData, &DataSize );
	
//tdtTable-Header lesen
    hmemcpy( &TabHeader, hDataBlock, sizeof(TabHeader) );

//Matrix erzeugen
	if ( !(*DestMatrix = mxCreateFull( (int)TabHeader.rows, (int)TabHeader.columns, REAL )) )
	{
		DdeUnaccessData( hData );
		mexPrintf( "??? Memory allocation error.\r\n" );
		ErrorBeep();
    	return TRUE;
    }

    WORD i=0; WORD j, k=0;
	char huge* src		= hDataBlock + sizeof(TabHeader);
	char huge* dest		= (char huge*)mxGetPr( *DestMatrix ); 
	char huge* help		= dest;
	DWORD SourceBytes	= sizeof(TabHeader);
	DWORD BytesMoved	= 0;
	DWORD Size 			= (DWORD)TabHeader.rows * TabHeader.columns * sizeof(double);
	BOOL result			= TRUE;
	FloatHeader	FtHeader;

	while ( BytesMoved < Size )
    {
	    SourceBytes += sizeof(FtHeader);
	    if ( SourceBytes > DataSize )
		{
			result = FALSE;
			break;
		}
		//tdtFloat-Header kopieren
	    hmemcpy( (char*)&FtHeader, (char huge*)src, sizeof(FtHeader) );
        src += sizeof(FtHeader);
        SourceBytes += FtHeader.cbFloat;
        if ( FtHeader.Float != tdtFloat || SourceBytes > DataSize)
		{
			result = FALSE;
			break;
		}
	    //Double-Daten kopieren
		if (TabHeader.columns == 1 || TabHeader.rows == 1)		//Reihenfolge bleibt    
		{
        	hmemcpy( (char huge*)help, (char huge*)src, FtHeader.cbFloat);
        	src += FtHeader.cbFloat;
        	help += FtHeader.cbFloat;
        }
        else													//Transponieren
        {
			j = FtHeader.cbFloat;
		    while ( k < TabHeader.rows )
	    	{
	    		while ( i < TabHeader.columns )
				{
					if ( j < sizeof(double) )
						break;
					hmemcpy( help, src, sizeof(double) );
					j -= sizeof(double);
					src += sizeof(double); 
					help += TabHeader.rows * sizeof(double);
					i++;
				}
				if ( i < TabHeader.columns )
					break;
				i = 0;
				k++;
				help = dest + (DWORD)k * sizeof(double);		//huge-Adresse!
	    	}
        }
        BytesMoved += FtHeader.cbFloat;
    }
	
	DdeUnaccessData( hData );

	if (result)
		return FALSE;
	else
	{
		mexPrintf( "??? Error. Invalid binary data.\r\n" );
		ErrorBeep();
    	return TRUE;	
    }
}





void Go2Next( char huge*huge* );

/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL Old_Str2Double( double huge* dest, char huge* hDataString )
{
	DWORD i = 0;
	char strBuffer[60];		//es werden 60 Stellen (willkuerlicher Wert) fuer eine Zahl kopiert
							//das Feststellen der tatsaechlichen Laenge dauert zu lange
	
	while ( *hDataString != '\0' )
	{
		if ( *hDataString == '\t' || *hDataString == '\r' )
		{
			mexPrintf( "Matrix not actualized. Possible empty element of source matrix.\r\n" );
			return FALSE;
		}
		else	
		{
			hmemcpy( (char huge*) strBuffer, (char huge*) hDataString, sizeof(strBuffer) );	//lokale Kopie, wegen
			dest[i] = atof( strBuffer );                                                    //atof() -huge-Zeigerproblem
		}
		
		Go2Next( &hDataString );
		i++;	
	}

    return TRUE;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
_inline void Go2Next( char huge* huge* hDataString )
{
	do
	{
		switch ( **hDataString )
		{
			case '\t':	(*hDataString)++;
						return;
			case '\r':	(*hDataString) += 2;
						return;
		}
	}
	while ( (*hDataString)++ );
}



/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL RemoveHeader( TableHeader* TabHeader, BYTE huge* src )
{
//Groesse der Matrix in bytes
	DWORD		Size		= (DWORD)TabHeader->rows * (DWORD)TabHeader->columns * sizeof(double);
	DWORD		BytesMoved	= (DWORD)0;
	BOOL		result		= TRUE;
	BYTE huge*	dest		= src;

	FloatHeader	FtHeader;

	while ( BytesMoved < Size )
    {
	    hmemcpy( (char*)&FtHeader, (char huge*)src, sizeof(FtHeader) );
        src += sizeof(FtHeader);
		if ( FtHeader.Float != tdtFloat )
		{
			result = FALSE;
			break;
		}

		memmove( (char*)dest, (char*)src, FtHeader.cbFloat);

        src += FtHeader.cbFloat;
        dest += FtHeader.cbFloat;
        BytesMoved += FtHeader.cbFloat;
    }
    
    return result;
}
Detected encoding: ASCII (7 bit)2