#include <windows.h>
#include <ddeml.h>
#include <malloc.h> //fuer _memmax()
#include <string.h> //fuer str...()
#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, UINT* rows, UINT* 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;
BOOL result = TRUE;
char huge* pNextString = hDataString;
char strBuffer[100]; //es werden bis zu 100 Stellen (max. Wert fuer atof) fuer eine Zahl kopiert
i = k = m = 0;
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 )
{
UINT i, k;
double huge* help;
// *** Matrix transponieren
if (cols < rows) //weniger Spalten als Zeilen?
{ //Spalten-Schleife aussen
for ( i = 0; i < cols; i++ )
{
help = src + (DWORD)i;
for ( k = 0; k < rows; k++ )
{
hmemcpy( dest, help, sizeof(double) );
dest++;
help += (DWORD)cols;
}
}
} else { //Zeilen-Schleife aussen
for ( k = 0; k < rows; k++ )
{
help = dest + (DWORD)k;
for ( 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;
UINT MaxStringLen = 0x2000; //max. 8 K * 8 Byte = 64 KByte in String-Matrix
char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize );
//Stringlaenge bestimmen
char huge* hDataString_end = hDataString;
while ( *(hDataString_end++) != '\0' && StringLen < DataSize) StringLen++;
if (StringLen == DataSize) StringLen--;
if (StringLen > MaxStringLen) //abschneiden
{
mexPrintf( "??? Possible data lost. More then 8 KByte text.\r\n" );
ErrorBeep();
StringLen = MaxStringLen;
hmemcpy( &hDataString[StringLen], "\0", sizeof(char) ); //Null am Ende!
}
*DestMatrix = mxCreateString( hDataString ); //arbeitet nur mit Strings bis 8 KByte!
DdeUnaccessData( hData );
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CFTextReq( HDDEDATA hData, Matrix** DestMatrix )
{
HGLOBAL hGlobal;
UINT rows, columns;
DWORD DataSize, matrixSize;
double huge* src;
double huge* dest;
char huge* hDataString = (char huge*)DdeAccessData( hData, &DataSize);
GetMatrixSize( hDataString, &DataSize, &rows, &columns );
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 FALSE;
}
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 )) )
{
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 TRUE;
}
///////////////////////////////////////////////////////DDE-Excel Format
BOOL FastDDEReq( HDDEDATA hData, Matrix** DestMatrix )
{
WORD i=0; WORD j, k=0;
DWORD Size, DataSize, SourceBytes, BytesMoved = 0;
TableHeader TabHeader;
FloatHeader FtHeader;
BOOL result = TRUE;
char huge* src;
char huge* dest;
char huge* help;
char huge* hDataBlock = (char huge*) DdeAccessData( hData, &DataSize );
//tdtTable-Header lesen
hmemcpy( &TabHeader, hDataBlock, sizeof(TabHeader) );
Size= (DWORD)TabHeader.rows * TabHeader.columns * sizeof(double);
//Matrix erzeugen
if ( !(*DestMatrix = mxCreateFull( (int)TabHeader.rows, (int)TabHeader.columns, REAL )) ) //int?
{
DdeUnaccessData( hData );
mexPrintf( "??? Memory allocation error.\r\n" );
ErrorBeep();
return FALSE;
}
SourceBytes = sizeof(TabHeader);
src = hDataBlock + sizeof(TabHeader);
dest = (char huge*)mxGetPr( *DestMatrix );
help = dest;
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 TRUE;
else
{
mexPrintf( "??? Error. Invalid binary data.\r\n" );
ErrorBeep();
return FALSE;
}
}
Detected encoding: ASCII (7 bit) | 2
|