/* *** lots of this is by Eric Auer 3/2001, but its inspired *** */ /* *** by LoadingATextFile.c from the eyetracker toolkit *** */ #define TRIALS_MAX 200 #define gDefKeyword TEXT("define") #define gInlineKeyword TEXT("inline") #define gGfxKeyword TEXT("image") // *** ^- this is new 11.6.2001 #define gDefKeywordLen 6 #define ScriptWidth 1024 #include #include #include "eyelink.h" #include "w32_exptsppt.h" #include "w32_demo.h" /* header file for this experiment */ #include #include // *** for isgraph #include // *** for strlen #include "AddUnicode.h" #include "reading_loadscript.h" // *** LPTCH glpScriptText = NULL; TRIALPARAMS TheTrials[TRIALS_MAX]; long glTrialCount; long glTrialLen; long CreateTrials(TCHAR* src, long len) { TCHAR pszBuffer[ScriptWidth+1]; TCHAR* src_end; TRIALPARAMS trialdefines[42]; // special use for pszTrialIdent! // but some values are unused (time, filename) long bComment; // *** ok, b implies bool, but I like int better long bDefine; // *** see above long lDefCount; // *** number of defines used up so far long lWord; // *** counting the words in the row long i,j,k; // *** used as define index and copying index and similar // *** long count = 0; glTrialCount = 0; lDefCount = 0; bComment = 0; lWord = 0; bDefine = 0; src_end = src + len; // *** hope this works while (src < src_end) // *** was count < len { sscanf(src, TEXT(" %1024s "), pszBuffer); // sscanf returns the no of % escapes that could be filled // *** whitespace in format string -> skip whitespace if ((pszBuffer[0] == ';') || (pszBuffer[0] == '#')) { // if bComment goes 0->1 we could do something bComment = 1; } if (bComment == 0) lWord++; // found non-comment word if (bComment == 0) { // this is the fun part! if (lWord == 1) { // if lWord is 1 - is the word "define" ? // then inc lDefCount, check for < 42, // set bDefine. ELSE look for the matching // define, inc glTrialCount, check for < 100 if (lstrcmp(pszBuffer,gDefKeyword) == 0) { bDefine = 1; // go to "define mode" if (lDefCount > 41) { MessageBox(full_screen_window, TEXT("42 or more defines in script: too many."), TEXT("Error"), MB_OK | MB_ICONERROR); return glTrialCount; // overflow!!! } } else { bDefine = 0; // go to "trial mode", init trial. if (glTrialCount > (TRIALS_MAX-1)) /* e.g. 99 */ { MessageBox(full_screen_window, TEXT("More than TRIALS_MAX trials in script."), TEXT("Error"), MB_OK | MB_ICONERROR); return TRIALS_MAX-1; // overflow!!! } TheTrials[glTrialCount].pszTrialIdent[0] = '\0'; TheTrials[glTrialCount].lTimeLimit = -1; TheTrials[glTrialCount].pszTextFilename[0] = '\0'; TheTrials[glTrialCount].lUsedButtons = -1; TheTrials[glTrialCount].pszText[0] = '\0'; // *** NEW May 21 2001 TheTrials[glTrialCount].bTextInline = 0; // *** inline text ... // *** the following members are new 11.6.2001 TheTrials[glTrialCount].bDriftCorrect = 0; TheTrials[glTrialCount].bHasImage = 0; TheTrials[glTrialCount].pszTplFilename[0] = '\0'; TheTrials[glTrialCount].hTplBmp = NULL; TheTrials[glTrialCount].bHasSound = 0; TheTrials[glTrialCount].pszWavFilename[0] = '\0'; for (i=0; i='0') && (pszBuffer[j]<='9'))) { if (pszBuffer[j]==' ') { /* ignore spaces */ } else { k = k * 10; // were we were gets more as we pass by k = k + (pszBuffer[j] - '0'); // hope TCHARS love this } j++; // dont forget this if you dont love endless loops } if (k < 100) { MessageBox(full_screen_window, TEXT("Timeout less than 100ms or parse error in script."), TEXT("Error"), MB_OK | MB_ICONERROR); return glTrialCount; // bail out! } TheTrials[glTrialCount].lTimeLimit = k; } else // if it is a define...: gaze activation // or Nogaze or DriftCorrect // that is, DC only if explicitly requested // and no gaze activation is used // *** this is new 11.6.2001 { if ((pszBuffer[0] == 'n') || (pszBuffer[0] == 'N')) { trialdefines[lDefCount].bGazeActivate = FALSE; trialdefines[lDefCount].bDriftCorrect = FALSE; } else { if ((pszBuffer[0] == 'd') || (pszBuffer[0] == 'D')) { trialdefines[lDefCount].bGazeActivate = FALSE; trialdefines[lDefCount].bDriftCorrect = TRUE; } else { trialdefines[lDefCount].bGazeActivate = TRUE; // gaze activation has no separate DC by definition... } } } } // EOF word 3 if (lWord == 4) { if (bDefine == 0) // if it is a trial...: filename *** or "inline" NEW May 21 2001 { if (strcmp(pszBuffer,gInlineKeyword)) // "inline" { // *** new 11.6.2001: image instead of text if (strcmp(pszBuffer,gGfxKeyword)) // "image" { strncpy(TheTrials[glTrialCount].pszTextFilename, pszBuffer,254); // better use sizeof! } else { // TextFilename now used for image file name, // if none given, directly used as template TheTrials[glTrialCount].bHasImage = TRUE; // do not store the word "image" :-) TheTrials[glTrialCount].pszTextFilename[0] = '\0'; TheTrials[glTrialCount].pszTplFilename[0] = '\0'; } } else { TheTrials[glTrialCount].bTextInline = 1; // true // do not store the word "inline" :-) TheTrials[glTrialCount].pszText[0] = '\0'; } } else // if it is a define...: stream { if ((pszBuffer[0] == 'n') || (pszBuffer[0] == 'N')) { trialdefines[lDefCount].bLogStream = FALSE; } else { trialdefines[lDefCount].bLogStream = TRUE; } trialdefines[lDefCount].lUsedButtons = 0; // init this! trialdefines[lDefCount].iButtonList[0] = '\0'; // int! } } // EOF word 4 // "define" class gaze stream (next: button(s)) // class ident timeout [filename|"inline"] (next: |) if ((lWord >= 5) && (bDefine == 0) && (TheTrials[glTrialCount].bTextInline != 0)) // inlined text { strncat(TheTrials[glTrialCount].pszText, pszBuffer, 1999 - strlen(TheTrials[glTrialCount].pszText)); // better use sizeof! if (strlen(TheTrials[glTrialCount].pszText)< 1998) strcat(TheTrials[glTrialCount].pszText," "); // else warn... buffer too full! } // EOF inlined text if ((lWord >= 5) && (bDefine == 0) && (TheTrials[glTrialCount].bTextInline == 0)) { // *** 11.6.2001: additional parameters, which are: // *** bHasImage is false: an optional sound file name // *** bHasImage is true: first, an optional template file name, // *** then, an optional sound file name! if (TheTrials[glTrialCount].bHasImage == 0) { // no image -> if it is word 5, it is the sound file name if (lWord == 5) { strncpy(TheTrials[glTrialCount].pszWavFilename, pszBuffer,254); // better use sizeof! TheTrials[glTrialCount].bHasSound = TRUE; } } // EOF text else { // image -> if it is word 5, it is the image file name // image -> if it is word 5, it is the template file name // image -> if it is word 6, it is the sound file name. if (lWord == 5) { strncpy(TheTrials[glTrialCount].pszTextFilename, pszBuffer,254); // better use sizeof! } if (lWord == 6) { strncpy(TheTrials[glTrialCount].pszTplFilename, pszBuffer,254); // better use sizeof! } if (lWord == 7) { strncpy(TheTrials[glTrialCount].pszWavFilename, pszBuffer,254); // better use sizeof! TheTrials[glTrialCount].bHasSound = TRUE; } } // EOF image } // EOF additional parameters if ((lWord >= 5) && (bDefine == 1)) // button list ignore rest of the line otherwise { // pszBuffer may be a char -> concat to list, count it // or a string -> expresses a special char -> as above // if unknown special char, return from func, maybe warn!!! i = 0; // our new button if (strlen(pszBuffer) > 1) // need to resolve? { // *** this could be done with much more style! // *** w32_exptsppt.h has 4 arrows, pgup/pgdn, esc, cr if (lstrcmp(pszBuffer,TEXT("left")) == 0) { i = CURS_LEFT; } if (lstrcmp(pszBuffer,TEXT("right")) == 0) { i = CURS_RIGHT; } if (lstrcmp(pszBuffer,TEXT("up")) == 0) { i = CURS_UP; } if (lstrcmp(pszBuffer,TEXT("down")) == 0) { i = CURS_DOWN; } if (lstrcmp(pszBuffer,TEXT("space")) == 0) { i = ' '; // char to int! (see toolkit->getkey) } } if ((strlen(pszBuffer) == 1) || (i != 0)) { if (strlen(pszBuffer) == 1) i = pszBuffer[0]; // char to int! if (trialdefines[lDefCount].lUsedButtons > 250) { MessageBox(full_screen_window, TEXT("Too many buttons defined in script."), TEXT("Error"), MB_OK | MB_ICONERROR); return glTrialCount; } trialdefines[lDefCount].iButtonList[ trialdefines[lDefCount].lUsedButtons] = i; trialdefines[lDefCount].lUsedButtons++; } else // buffer was empty or resolve failed { // ignore failure for now!!! } } // EOF button list } // end of fun part. while (!isgraph(*src)) { src++; } // skip leading whitespace // dont confuse isprint/isgraph src = src + strlen(pszBuffer); // trailing whitespace is no // problem here if ((*src == '\r') || (*src == '\n')) { if (lWord) // -> this line was useful { if (bDefine) { lDefCount++; } else { glTrialCount++; } } lWord=0; bComment=0; bDefine=0; while ((*src == '\r') || (*src == '\n')) { src++; } } // ???? } // end of "no comment" } // count from 1..n (so 0 means failure) glTrialCount++; return glTrialCount; } BOOL LoadScript(TCHAR* pszFilename, long* plTrials) { HANDLE hFile; BOOL bSucceeded; DWORD dwBytesRead; LPTCH lpTemp = NULL; UINT32 glScriptLen; // forgot that!? hFile = CreateFile(pszFilename, GENERIC_READ, (DWORD) 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) 0); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } // else glScriptLen = GetFileSize(hFile, NULL); lpTemp = (LPTCH) GlobalAlloc(0, glScriptLen+1); // *** 24.7.2001 see a few lines below !!! bSucceeded = ReadFile( hFile, // handle of file to read lpTemp, // pointer to buffer that receives data glScriptLen, // number of bytes to read &dwBytesRead, // pointer to number of bytes read NULL // pointer to structure for data ); lpTemp[glScriptLen] = 0; // *** 24.7.2001 forgot to close string, yuck !!! CloseHandle(hFile); if (!bSucceeded) { GlobalFree((HGLOBAL) lpTemp); return FALSE; } // else // *** glpScriptText = (LPTCH) GlobalAlloc(0, glScriptLen); plTrials[0] = CreateTrials(lpTemp, /* glpScriptText, */ glScriptLen); GlobalFree((HGLOBAL) lpTemp); return TRUE; } void ReleaseScript() { // *** GlobalFree((HGLOBAL) glpScriptText); } PTRIALPARAMS GetTrial(long trialno) { if ( (trialno <= glTrialCount) && (trialno > 0) ) { return &TheTrials[trialno-1]; } else { MessageBox(full_screen_window, TEXT("GetTrial was asked for non existant trial."), TEXT("Error"), MB_OK | MB_ICONERROR); return NULL; } }