/** * \brief int16_t main() * * \param[in] pFileName - something like "dump_01.txt" * * \param[out] Description * * \return test framework main() routine * * */ int main (int argc, char *argv[]) { // arg0 is the actual command line that invoked this program! char *fileName = argv[1]; static char returnBuffer[BUFFER_LEN] = {'\0','\0','\0','\0','\0','\0','\0' }; int16_t result; int16_t fd = 0; int16_t autoIncrement = 0; // size of Front Panel Display - must be int variables for scanf() function int frontPanelRows = 0; int frontPanelCols = 0; // char *portName = "/dev/tty"; // use keyboard tty input for serial I/O char *portName = NULL; printf("\n\n Test Framework for vt100 emulator library "); printf("\n (command syntax: './vt filename')\n"); // get the working port name and fd fd = vt100_getPortFd(portName); // portName = "/dev/ttyS3"; // Initial setup of arrays in memory if( strcmp(fileName, "") == 0) fileName = "disp_dumpVD.txt"; printf("\n main: fileName is %s, portName is %s, port fd is %d \n", fileName, portName, fd); // Due to Dynamic Memory Allocation - can not call any routines until vt100_start() is called // result = vt100_dumpVD(fileName, 0, "Initial State"); // show original data array - with no number extenison // printf("\n\n Result of vt100_dumpVT = %d \n", result); // vt100_showVD(stdout, "Initial State"); // do compare on intial state // result = vt100_compareVD("display.8.40.start"); // printf("\n Default compareVD: display.8.40.start = %d \n", result); printf("\n\n Number of rows in the Front Panel Display: "); scanf("%d", &frontPanelRows ); printf("\n Number of columns in the Front Panel Display: "); scanf("%d", &frontPanelCols ); // vt100_start() printf("\n\n================= vt100_start() =============\n"); printf("\n - calling vt100_start() for port %s: with %d rows and %d columns\n", portName, frontPanelRows, frontPanelCols); // result = vt100_start(portName); // modify array result = vt100_start(NULL , frontPanelRows, frontPanelCols); // modify array if( result != 0 ) printf("\n ... returned error code = %d ", result); printf("\n Initial states of errorCode: %d and errorText %s ", vt100_get_errorCode(), vt100_get_errorText() ); vt100_dumpVD("dump.vt100_start", ++autoIncrement, "after vt100_start()"); vt100_showVD(stdout, "after vt100_start()"); vt100_clearVD(); // initialize or clear the display rows & columns from malloc garbage printf("\n\n========= vt100_clear - compare clear with display.clear =============\n"); vt100_dumpVD("dump.after_1st_clear", ++autoIncrement, "after 1st clear"); vt100_showVD(stdout, "after 1st vt100_clear(0 after the start()"); result = vt100_compareVD("display.clear"); printf("\n\n Result of vt100_compareVD = %d, for file: %s \n", result, "display.clear"); if( result != 0 ) printf("\n errorText = %s", vt100_get_errorText() ); printf("\n\n================= vt100_set_auxSwitch() ON ===========================\n"); result = vt100_set_auxSwitch( 1 ); vt100_dumpVD("auxSwitch.out", ++autoIncrement, "set_auxSwitch ON"); printf("\n\n Result vt100_set_auxSwitch = %d \n", result); vt100_showVD(stdout, "fileToVD"); sleep(1); printf("\n\n================= vt100_set_auxSwitch() OFF ==========================\n"); result = vt100_set_auxSwitch( 0 ); vt100_dumpVD("auxSwitch.out", ++autoIncrement, "set_auxSwitch OFF"); printf("\n\n Result vt100_set_auxSwitch = %d \n", result); vt100_showVD(stdout, "fileToVD"); sleep(1); printf("\n\n================= vt100_fileToVD - short file '1234.in' =============\n"); result = vt100_fileToVD("1234.in"); vt100_dumpVD("1234.out", ++autoIncrement, "fileToVD"); printf("\n\n Result vt100_fileToVD = %d \n", result); vt100_showVD(stdout, "fileToVD"); sleep(1); printf("\n ------------- return buffer: ------------"); vt100_vtInputBuffer(returnBuffer, sizeof (returnBuffer)); printf("\n returnBuffer starts on next line: \n%s\n-------------------\n", returnBuffer); sleep(2); printf("\n\n================= Command/Response sequences ========\n"); result = vt100_fileToVD("commands.in"); sleep(1); vt100_dumpVD("cmdResponses.out", ++autoIncrement, "CMD Responses"); printf("\n\n Result of cmdResponses using vt100_fileToVD = %d \n", result); vt100_showVD(stdout, "CMD_Repsonses "); sleep(1); printf("\n\n================= vt100_stringToVD # 1 - very short =============\n"); vt100_stringToVD("1234"); result = vt100_dumpVD("displayString.txt", ++autoIncrement, "short stringToVD"); printf("\n\n Result of vt100_dumpVD = %d \n", result); vt100_showVD(stdout, "short vt100_stringToVD"); printf("\n\n================= vt100_stringToVD # 2 - long multi-line ========\n"); vt100_stringToVD("This is a test \n#9999: of the emergency broadcasting system 0123456789ABC\n\n\n\tTAKE 2 \n\n\tThe END\t17abc\t25def\t33ghi\n\t\t\t7777"); result = vt100_dumpVD("displayString.txt", ++autoIncrement, "long stringToVD"); printf("\n\n Result of vt100_dumpVD = %d \n", result); vt100_showVD(stdout, "long vt100_stringToVD"); sleep(2); printf("\n\n============ Special Chars create (vt100_fileToVD) =============\n"); vt100_clearVD(); // initialize or clear the display rows & columns vt100_resetParms(); // restore all PARMs etc before doing Special Chars testing result = vt100_fileToVD("specialChars.in"); vt100_dumpVD("specialChars.out", ++autoIncrement, "Special Chars"); printf("\n\n Result of Special Chars vt100_fileToVD = %d \n", result); vt100_showVD(stdout, "Special Chars Compose "); sleep(1); printf("\n\n=========== Special Chars compare - display.special OK ============\n"); result = vt100_compareVD("display.special"); printf("\n\n Result of vt100_compareVD = %d, for file: %s \n", result, "display.special"); if( result != 0 ) printf("\n errorText = %s ", vt100_get_errorText() ); printf("\n\n======= Special Chars compare - display.special.bad - FAIL ========\n"); result = vt100_compareVD("display.special.bad"); printf("\n\n Result of vt100_compareVD = %d, for file: %s \n", result, "display.special.bad"); if( result != 0 ) printf("\n errorText = %s ", vt100_get_errorText() ); printf("\n\n============= vt100_fileToVD - junk screen =============\n"); result = vt100_fileToVD("testFileToVD.in"); vt100_dumpVD("testFileToVD.out", ++autoIncrement, "fileToVD"); printf("\n\n Result vt100_fileToVD = %d \n", result); vt100_showVD(stdout, "fileToVD"); printf("\n - compare the testFileToVD.in with the display.testIput "); result = vt100_compareVD("display.testInput"); printf("\n\n Result = %d, for file: %s \n", result, "display.testIput"); sleep(1); printf("\n ------------- return buffer: ------------"); vt100_vtInputBuffer(returnBuffer, sizeof (returnBuffer)); printf("\n returnBuffer starts on next line: \n%s\n-------------------\n", returnBuffer); sleep(1); printf("\n\n============= Command/Response sequences # 2 =======\n"); result = vt100_fileToVD("commands.in"); sleep(1); vt100_dumpVD("cmdResponses.out", ++autoIncrement, "CMD Responses"); printf("\n\n Result of cmdResponses using vt100_fileToVD = %d \n", result); vt100_showVD(stdout, "CMD_Repsonses "); sleep(1); printf("\n\n================= vt100_fromDumptoVD - display.fpm =============\n"); vt100_resetParms(); // restore to power up condition result = vt100_fromDumpToVD("display.fpm"); vt100_dumpVD("test_fromDumpToVD.out", ++autoIncrement, "fromDumpToVD"); printf("\n\n Result vt100_fromDumpToVD = %d \n", result); vt100_showVD(stdout, "fromDumpToVD"); printf("\n\n================= vt100_compareVD - display.fpm =============\n"); result = vt100_compareVD("display.fpm"); printf("\n\n Result of vt100_compareVD = %d, for file: %s \n", result, "display.fpm"); if( result != 0 ) printf("\n errorText = %s ", vt100_get_errorText() ); /************************* don't need to test this any more ..... printf("\n\n================= vt100_fromDumptoVD - bad file =======\n"); result = vt100_fromDumpToVD("display.fail"); vt100_dumpVD("test_fromDumpToVD.out", ++autoIncrement, "fromDumpToVD_FAIL"); printf("\n\n Result vt100_fromDumpToVD = %d \n", result); vt100_showVD(stdout, "fromDumpToVD_FAIL"); ****************************************************/ printf("\n\n================= vt100_fromDumptoVD - display.config =============\n"); // vt100_resetParms(); // restore to power up condition result = vt100_fromDumpToVD("display.config"); vt100_dumpVD("disp_dumpVD.tst", ++autoIncrement, "fromDumpToVD - config"); printf("\n\n Result vt100_fromDumpToVD = %d \n", result); // printf("\n errorCode: %d, errorText: %s ", vt100_get_errorCode(),vt100_get_errorText() ); vt100_showVD(stdout, "fromDumpToVD - config"); printf("\n\n================= vt100_compareVD - display.config =============\n"); result = vt100_compareVD("display.config"); printf("\n\n Result of vt100_compareVD = %d, for file: %s \n", result, "display.config"); if( result != 0 ) printf("\n errorText = %s ", vt100_get_errorText() ); printf("\n\n================= vt100_scrollVD - UP =======\n"); vt100_scrollVD(1); vt100_dumpVD("test_scrollVD_UP.out", ++autoIncrement, "scrollVD-UP!"); vt100_showVD(stdout, "scrollVD-UP!"); printf("\n\n================= vt100_scrollVD - DOWN =======\n"); vt100_scrollVD(-1); vt100_dumpVD("test_scrollVD_DOWN.out", ++autoIncrement, "scrollVD-DOWN!"); vt100_showVD(stdout, "scrollVD-DOWN!"); /* ****************** don't need this test anymore ************ printf("\n\n================= vt100_scrollVD - Bad arg =======\n"); vt100_scrollVD(5); vt100_dumpVD("test_scrollVD_badArg.out", ++autoIncrement, "scrollVD-badArg!"); vt100_showVD(stdout, "scrollVD-badArg!"); *********************************************/ /************************* usleep(3); // 300 msecs ? printf("\n\n\n\n SYSTEM CALL to show process ID:"); system( "ps -e | grep vt"); printf("\n--------------------------------\n\n"); ***********************************/ vt100_end(); sleep (1); // give time for last calls to output to screen? exit(0); } // end - main ()
int16_t // no return value - provided by vt100_getError() vt100_thread(THREAD_ARGS *args ) { // char nextChar; // input character from Serial port // int16_t fd = 0; // file descriptor for Serial Port open, read, write const char *portName; VIRTUAL_DISPLAY *pVDisplay; // pointer to virtual Display char *pTextBuffer = NULL; // malloc'd text area char *pAttribsBuffer = NULL; // malloc'd attribs area char **pTextPtrsBuffer = NULL; // malloc'd text pointers (rows) area char **pAttribsPtrsBuffer = NULL; // malloc'd attribs pointers (rows) area int16_t rows = 0; int16_t cols = 0; int16_t bumpUpCols = 0; int16_t numBytes = 0; int16_t numPtrBytes = 0; int16_t rowLength = 0; int16_t i = 0; // array loop variable // unpack the two most crucial parameters - rows & cols - from args rows = args[0].thr_DisplayRows; cols = args[0].thr_DisplayCols; // have to allocate space on even pointer boundaries for rows bumpUpCols = cols % sizeof( char *); // see if number of columns is on a pointer boundary if( bumpUpCols) cols += ( sizeof(char *) - bumpUpCols); // if not (non-zero remainder), force to next boundary numBytes = rows * cols; rowLength = cols * (sizeof(char)); #if DEBUG_ON printf("\n\nvt100_THREAD %d is STARTING", args[0].thr_threadId); printf("\n - on port %s with display rows %d and cols %d, pointer size is %d bytes", args[0].thr_portName, rows, cols, sizeof( char *) ); printf("\n malloc() %d bytes each for Virtual Display text & data arrays", numBytes ); #endif // // Concept - since screen size can vary in number of row or columns, // we have dynamic arrays for the text display and the attributes display // The Virtual Display for text is a list of pointers - 1 per line, and // a similar list of pointers for the attributes - 1 pointer per line // /* * First - malloc() all Virtual Display data area and set up pointer arrays * */ pTextBuffer = (char *) malloc(numBytes); pAttribsBuffer = (char *) malloc(numBytes); numPtrBytes = numRows * (sizeof (char *)); pTextPtrsBuffer = (char **) malloc(numPtrBytes ); pAttribsPtrsBuffer = (char **) malloc(numPtrBytes ); if( (pTextBuffer == NULL) || (pAttribsBuffer == NULL) || (pTextPtrsBuffer == NULL) || (pAttribsPtrsBuffer == NULL) ) { #if DEBUG_ON & DEBUG_MALLOC printf("\n\nvt100_thread: malloc probs: numBytes %d, numPtrBytes %d ", numBytes, numPtrBytes ); printf("\n Ptrs are: %0x, %0x, %0x, %0x", (unsigned int) pTextBuffer, (unsigned int) pAttribsBuffer, (unsigned int) pTextPtrsBuffer, (unsigned int) pAttribsPtrsBuffer ); #endif return( vt100_set_errorCode(ERR_09_MEM_ALLOC) ); } #if DEBUG_ON & DEBUG_THREAD printf("\n\nvt100_thread: malloc results: numBytes %d, numPtrBytes %d ", numBytes, numPtrBytes ); #endif // init the Virtual Display with the buffer addresses & row pointer arrays // buffer & array addresses used for later free() calls vDisplay.pText = pTextPtrsBuffer; vDisplay.pAttribs = pAttribsPtrsBuffer; vDisplay.pTextBuf = pTextBuffer; vDisplay.pAttribsBuf = pAttribsBuffer; vDisplay.ptrsBufSize = numPtrBytes; vDisplay.charsBufSize = numBytes; // set up the pointer arrays from malloc'd memory for( i = 0; i < rows ; i++ ) // distribute the memory into pointer arrays { pTextPtrsBuffer[i] = pTextBuffer; pTextBuffer += rowLength; pAttribsPtrsBuffer[i] = pAttribsBuffer; pAttribsBuffer += rowLength; #if DEBUG_ON & DEBUG_MALLOC printf("\n row %d: TextPtr: %0x, Attribs Ptr: %0x,", i+1, (unsigned int) pTextPtrsBuffer[i], (unsigned int) pAttribsPtrsBuffer[i] ); #endif } #if DEBUG_ON & DEBUG_MALLOC printf("\n vDisplay struct: TextPtrBuffer: %0x, AttribsPtrBuffer: %0x,", (unsigned int) pTextPtrsBuffer, (unsigned int) pAttribsPtrsBuffer ); printf("\n=========================================================="); for( i = 0; i < rows; i++ ) { printf("\n %d: text %0x, attrib %0x ", i, (unsigned int) vDisplay.pText[i], (unsigned int) vDisplay.pAttribs[i]); } #endif // check if fpui port is present and can be opened portName = args[0].thr_portName; pVDisplay = args[0].thr_DisplayPtr; if( portName == NULL ) // no fpui present - can't read any chars { while(!vt100_allDone) { #if DEBUG_ON & DEBUG_THREAD printf("T%d, ", ++counter); if( counter % 10) printf("\n"); #endif sleep(1); // wait 1secs - allow asynch call to process file input } } else { // we are given port to open like "/dev/fpi" // we will open the port and process characters received to the VT #if DEBUG_ON // clear the display and show the results // do compare on the display that was just cleared with the local dump file // this must be removed for delivery - should not be accessed from the library routines int16_t result = 0; vt100_clearVD(); // start clean & clear before text input result = vt100_compareVD("display.clear"); printf("\nvt100_thread: compareVD: display.clear = %d \n", result); vt100_showVD(stdout, "After call to vt100_clearVD"); #endif if( (fdSerialPort = openSerialPort(portName) ) <= 0 ){ // Error on open #if DEBUG_ON printf("\n ERR_05_PORT_OPEN; received %d trying to open %s \n", fdSerialPort, portName); #endif vt100_set_errorCode(ERR_05_PORT_OPEN); threadErrorCode = ERR_05_PORT_OPEN; vt100_allDone = TRUE; } #if DEBUG_ON printf("\nTHREAD %d ready to read input from %s ... ", args[0].thr_threadId, portName); printf("\n Please start entering input:\n (terminate with a 'z' on a new line}\n"); #endif while(!vt100_allDone ) { vt100_processInput( fdSerialPort, NULL, pVDisplay ); // read Serial Port and process forever - no line buffer here } // end forever while loop // all done - close the serial port and exit closeSerialPort(fdSerialPort); // vt100_dumpVD("dump.thread.after", "thread after key inputs"); } // end - good serial port #if DEBUG_ON printf("\n\n vt100 - exiting thread # %d", args[0].thr_threadId ); #endif sleep(1); // free the malloc'd memory in reverse order free( vDisplay.pAttribs ); free( vDisplay.pText ); free( vDisplay.pAttribsBuf ); free( vDisplay.pTextBuf ); pthread_exit(&threadErrorCode); // return error code to the original start function // return (errorCode); } // end vt100_thread()
void process_ESC_Seq(int16_t fd, VIRTUAL_DISPLAY *VD_ptr, char **pBuffPtr) { char ESC_sequence[MAX_ESC_SEQ_LEN]; // holds the <ESC> sequence chars char outputSeqBuffer[MAX_ESC_SEQ_LEN]; // output buffer to make string for serial port write int16_t outBufLen = 0; // length of the output string int16_t numBytesWritten = 0; // bytes written to the Serial Port char nextChar = 0; int tempIntValue = 0; int16_t seqCode = 0; int seqValue = 0; int16_t initCol = 0; // starting column (from cursorPos) in a line int16_t i=0, j=0; static int ESC_line = 0, ESC_col = 0; // for Py;Px conversions char *pESC = ESC_sequence; // ptr for parsing through ESC sequence char **pTextArray = VD_ptr->pText; // set up the malloc'd data area pointers char **pAttribsArray = VD_ptr->pAttribs; char *pRowText = NULL; char *pRowAttribs = NULL; //static int seq = 0; ESC_sequence[0] = ESC_CHAR; // init the start of the sequence ESC_sequence[1] = 0; ESC_sequence[2] = 0; ESC_sequence[3] = 0; pRowText = pTextArray[cursorPos.cp_row]; pRowAttribs = pAttribsArray[cursorPos.cp_row]; //read the ESC sequence nextChar = getNextChar(fd, pBuffPtr); switch (nextChar) { case 'D': // scroll window up one line vt100_scrollVD( 1 ); break; case 'E': // move to next line ? start of line or just next row below? // if ( (cursorPos.cp_row += 1) > numRows - 1 ) if( cursorPos.cp_row < (numRows - 1) ) cursorPos.cp_row++ ; // rows start with 0 // cursorPos.cp_col = 0; // comment out for now - just move down 1 row break; case 'H': // set tab at current column tabCol = cursorPos.cp_col; tabStops[tabCol] = 'T'; // show an ASCII 'T' instead of ' ' seqCode = 0; break; case 'M': // scroll window down one line vt100_scrollVD( -1 ); break; case 'P': // Compose Special Character // sequence is <ESC> P P1 [ Pn ; Pn ; Pn ; .... f ESC_sequence[1] = 'P'; seqCode = get_ESC_Seq(fd, ESC_sequence, pBuffPtr); if( seqCode == CURSOR_POSITION ) // should have found an 'f' terminator seqCode = COMPOSE_SPECIAL; // this should occur #if DEBUG_ON & DEBUG_SPECIAL else printf("\n process_ESC_seq(): Compose SPECIAL CHAR # %d: seqCode was %d, should be %d ", ESC_sequence[2], seqCode, CURSOR_POSITION ); #endif break; case '[': // <ESC> [ sequence // get rest of sequence and process ESC_sequence[1] = '['; seqCode = get_ESC_Seq(fd, ESC_sequence, pBuffPtr); //printf("get_ESC_Seq:ESC[0x%02x,0x%02x seqCode=%d\n", ESC_sequence[2], ESC_sequence[3], seqCode); break; case '6': // <ESC> 6 n sequence - CURSOR_POSITION request // this is an older VT-100 original query // CursorPos, Parameters/Attributes, auxSwitch status if( (nextChar = getNextChar(fd, pBuffPtr)) == 'n' ) { // dummy this in to be the same as the new STATUS QUERY COMMANDS for RESPONSES ESC_sequence[1] = '['; ESC_sequence[2] = '6'; ESC_sequence[3] = 'n'; seqCode = STATUS_QUERY; } else { ESC_sequence[1] = '6'; ESC_sequence[2] = nextChar; // don't know really what to do here - this is not defined // no further processing will happen without the 'seqCode' being set } break; case '7': // <ESC> 7 sequence - SAVE_CURSOR_POS ESC_sequence[1] = '7'; seqCode = SAVE_CURSOR_POS; break; case '8': // <ESC> 8 sequence - REST_CURSOR_POS ESC_sequence[1] = '8'; seqCode = REST_CURSOR_POS; break; case 'G': // <ESC> G sequence - Graphics Mode Commands ESC_sequence[1] = 'G'; nextChar = getNextChar(fd, pBuffPtr); ESC_sequence[2] = nextChar; switch (nextChar) { case 'U': nextChar = getNextChar(fd, pBuffPtr); if (nextChar == '0') graphicModeFlags &= ~(GRAPHIC_UNDERLAY_1 | GRAPHIC_UNDERLAY_2); else if (nextChar == '1') graphicModeFlags |= GRAPHIC_UNDERLAY_1; else if (nextChar == '2') graphicModeFlags |= GRAPHIC_UNDERLAY_2; ESC_sequence[3] = nextChar; break; case 'O': nextChar = getNextChar(fd, pBuffPtr); if (nextChar == '0') graphicModeFlags &= ~(GRAPHIC_OVERLAY_1 | GRAPHIC_OVERLAY_2); else if (nextChar == '1') graphicModeFlags |= GRAPHIC_OVERLAY_1; else if (nextChar == '2') graphicModeFlags |= GRAPHIC_OVERLAY_2; ESC_sequence[3] = nextChar; break; case 'C': nextChar = getNextChar(fd, pBuffPtr); if (nextChar == '0') graphicModeFlags &= ~(GRAPHIC_CURSOR_U | GRAPHIC_CURSOR_O); else if (nextChar == 'U') graphicModeFlags |= GRAPHIC_CURSOR_U; else if (nextChar == 'O') graphicModeFlags |= GRAPHIC_CURSOR_O; ESC_sequence[3] = nextChar; break; default: break; } break; default: // unknown or not-handled ESC sequence break; } if( seqCode > 0 ) // valid ESC Sequence that needs processing? { seqValue = 0; if( isdigit ( ESC_sequence[2])) { if( sscanf( &ESC_sequence[2], "%d", &seqValue) != 1 ) { printf("sscanf error for seqCode %d\n", seqCode); seqValue = 0; } } else if( isdigit ( ESC_sequence[3])) // is this <ESC>[?NN or something similar { if( sscanf( &ESC_sequence[3], "%d", &seqValue) != 1 ) { printf("sscanf error for seqCode %d\n", seqCode); seqValue = 0; } } // now have valid sequence code and numeric value if present #if DEBUG_ON & DEBUG_ESC_SEQ printf("process_ESC_sequence for <ESC> [ 0x%02x, seqCode=%d\n", seqValue, seqCode); #endif switch( seqCode) { case CURSOR_UP: if ( (cursorPos.cp_row -= seqValue) < 0 ) cursorPos.cp_row = 0; break; case CURSOR_DOWN: if ( (cursorPos.cp_row += seqValue) >= (numRows - 1) ) // cursorPos values start with 0 cursorPos.cp_row = numRows - 1; // rows start with 0 break; case CURSOR_RIGHT: if ( (cursorPos.cp_col += seqValue) >= (numCols - 1) ) // cursorPos values start with 0 cursorPos.cp_col = numCols - 1; // force to last position break; case CURSOR_LEFT: if ( (cursorPos.cp_col -= seqValue) < 0 ) cursorPos.cp_col = 0; // force to start of line position break; case HOME_CURSOR: cursorPos.cp_row = 0; cursorPos.cp_col = 0; break; case CURSOR_POSITION: cursorPos.cp_row = 0; cursorPos.cp_col = 0; // check for row;column position as opposed to top left if( isdigit( ESC_sequence[2]) ) // if no number - then home to top left { if( sscanf(&ESC_sequence[2], "%d;%d", &ESC_line, &ESC_col) >= 2 ) { // ESC sequence starts row and cols with a 1 to 8 row # and 1 to 40 col # // first - confirm within boundaries and set to boundaries if be if( ESC_line < 1 ) ESC_line = 1; if( ESC_col < 1 ) ESC_col = 1; if( ESC_line > numRows) ESC_line = numRows; if( ESC_col > numCols) ESC_col = numCols; // internally we use cols from 0 to numCols and // row numbers from 0 to numRows // so we will subtract 1 from ESC_line & ESC_col cursorPos.cp_row = ESC_line - 1; cursorPos.cp_col = ESC_col - 1; } } break; case SET_AUTO_MODES: //printf("\nprocess_ESC_Seq() - [?%d h - SET_AUTO_MODES\n", seqValue); switch (seqValue) { case 5: if( ESC_sequence[2] == '?') // set Reverse Video vt100_set_reverseVideo((int16_t) ON ); else if( ESC_sequence[2] == '<') vt100_set_backLight( (int16_t) ON ); else #if DEBUG_ON printf("\n process_ESC_Seq() - [ ??? 5 h - SET_AUTO_MODES "); #else ; // do nothing - maybe non-implemented <ESC> sequence #endif break; case 7: vt100_set_autoWrap((int16_t) TEXT_WRAP_NL); break; case 8: vt100_set_autoRepeat( (int16_t) ON ); break; case 24: // UNDERLINE MODE ON currentAttribs |= ATTRIB_UNDER; // bit flags "OR" break; case 25: // could be 25 or 025 in <ESC>[ sequence - 2 different actions if(ESC_sequence[2] == '0') vt100_set_cursorState(ON); else currentAttribs |= ATTRIB_BLINK; // bit flags "OR" break; case 27: // set Reverse Video vt100_set_reverseVideo((int16_t) ON ); currentAttribs |= ATTRIB_REVERSE; break; case 33: // Cursor Blink ON vt100_set_cursorBlink(ON); break; case 47: // AutoScroll ON vt100_set_autoScroll( (int16_t) ON ); break; default: break; } break; case CLEAR_AUTO_MODES: switch (seqValue) { case 5: if( ESC_sequence[2] == '?') // turn off Reverse Video vt100_set_reverseVideo((int16_t) OFF ); else if( ESC_sequence[2] == '<') vt100_set_backLight( (int16_t) OFF ); else #if DEBUG_ON printf("\n process_ESC_Seq() - [ ??? 5 l - CLEAR_AUTO_MODES "); #else ; // do nothing - maybe non-implemented <ESC> sequence #endif break; case 7: vt100_set_autoWrap((int16_t) TEXT_WRAP_OFF); break; case 8: vt100_set_autoRepeat( (int16_t) OFF ); break; case 24: // UNDERLINE MODE OFF currentAttribs &= ~ATTRIB_UNDER; break; case 25: // could be 25 or 025 in <ESC>[ sequence - 2 different actions if(ESC_sequence[2] == '0') vt100_set_cursorState(OFF); else currentAttribs &= ~ATTRIB_BLINK; // clear the Blink bit break; case 27: // Turn Off Reverse Video vt100_set_reverseVideo((int16_t) OFF ); currentAttribs &= ~ATTRIB_REVERSE; break; case 33: // Cursor Blink OFF vt100_set_cursorBlink(OFF); break; case 47: // AutoScroll OFF vt100_set_autoScroll( (int16_t) OFF ); break; default: break; } break; case CLEAR_DISPLAY: // have to do the rest of the codes - clear is only switch (seqValue) { case 0: // Clear screen from cursor down i = cursorPos.cp_row; initCol = cursorPos.cp_col; for(i = cursorPos.cp_row; i < numRows ; i++ ){ pRowText = pTextArray[i]; pRowAttribs = pAttribsArray[i]; for(j = initCol; j < numCols; j++ ) { *pRowText++ = ' '; // set to blanks for Text and *pRowAttribs++ = '0'; // ASCII Zeroes for the attributes // VD_ptr->text[i][j] = ' '; // blanks for cleared text // VD_ptr->attribs[i][j] = '0'; // zero for cleared attributes } initCol = 0; // clear all the rest of the rows going down } break; case 1: // Clear screen from cursor up i = cursorPos.cp_row; initCol = cursorPos.cp_col; for(i = cursorPos.cp_row; i >= 0 ; i-- ){ pRowText = pTextArray[i]; pRowAttribs = pAttribsArray[i]; for(j = initCol; j >= 0; j-- ) { *pRowText++ = ' '; // set to blanks for Text and *pRowAttribs++ = '0'; // ASCII Zeroes for the attributes // VD_ptr->text[i][j] = ' '; // blanks for cleared text // VD_ptr->attribs[i][j] = '0'; // zero for cleared attributes } initCol = numCols - 1; // clear rest of rows going up, starting from last column } break; case 2: // Clear entire screen vt100_clearVD(); break; default: break; } break; case CLEAR_LINE: // cursorPos has line number switch (seqValue) { case 0: // Clear from cursor to the right for(j = cursorPos.cp_col; j < numCols; j++ ) { pRowText[j] = ' '; // blanks for cleared text pRowAttribs[j] = '0'; // zero for cleared attributes } break; case 1: // Clear line from cursor to the left for(j = cursorPos.cp_col; j >= 0; j-- ) { pRowText[j] = ' '; // blanks for cleared text pRowAttribs[j] = '0'; // zero for cleared attributes } break; case 2: // Clear entire line for(j = 0; j < numCols; j++ ) { pRowText[j] = ' '; // blanks for cleared text pRowAttribs[j] = '0'; // zero for cleared attributes } break; default: break; } break; case CLEAR_TABS: switch (seqValue) { case 0: // Clear a tab at the current column tabStops[cursorPos.cp_col] = '0'; break; case 3: // Clear all tab stops for(j = 0; j < numCols; j++ ) { tabStops[j] = '0'; } break; default: // unknown tabstop seqValue break; } break; case CHAR_ATTRIBUTES: switch (seqValue) { case RESET_ATTRIBUTES: // clear all attributes // what about the bit 8 for the Special Character??? // it can't be kept in currentAttribs because it only applies to one character at a time currentAttribs = '0'; break; case BLINK_ON: currentAttribs |= ATTRIB_BLINK; // bit flags "OR" break; case REVERSE_ON: currentAttribs |= ATTRIB_REVERSE; // bit flags "OR" break; case UNDER_ON: currentAttribs |= ATTRIB_UNDER; // bit flags "OR" break; default: break; } break; case BACKLIGHT_TIMEOUT: vt100_set_backLightTimeout(seqValue); // sequence value sets timeout in seconds // NOTE: These routines currently have no implementation of // this timeout countdown between key strokes by user // at the Front Panel. break; case COMPOSE_SPECIAL: // Compose a Special bit-mapped character - seqValue has which one // sequence is <ESC> P P1 [ Pn ; Pn ; Pn ; .... f pESC = &ESC_sequence[4]; // should be the first 8-bit # seqValue = ESC_sequence[2] - '0'; if ((seqValue < 1) || (seqValue > 8)) { printf("\nvt100_processInput error: invalid special char %d", seqValue); break; } #if DEBUG_ON & DEBUG_SPECIAL printf("\n Composing SpecChar # %d [%c] : %s ", seqValue, ESC_sequence[2], &ESC_sequence[1] ); #endif for(i=0; i < BYTES_PER_SPEC_CHAR; i++) // up to 8 elements before the 'f' delimiter { sscanf(pESC, "%d", &tempIntValue); specialChars[seqValue-1][i] = (uint8_t) tempIntValue; while( isdigit( *pESC) ) // bypass the number just converted pESC++; if( *pESC == ';' ) { pESC++; // skip the ';' delimiter to get to the next bit-map byte } if( *pESC == 'f' ){ // this will allow a ";f" sequence even though it might be wrong i++; // account for this Pn Value before breaking the loop break; // special chars can be 5 - 8 columns long; Pn = P1 - P8 } } #if DEBUG_ON & DEBUG_SPECIAL if( *pESC != 'f' ) { printf("\n vt100_processInput error: loading Special Char # %d: terminator '%c' should be 'f'", seqValue, *pESC); // NOTE: This could be caused it there are more than 8 Pn values, which would make a very wide // Special Character, which would be invalid and cleared out } #endif if( (i >= MIN_SPEC_CHAR_COLS ) && (i <= MAX_SPEC_CHAR_COLS ) ) { specialCharColumns[seqValue-1] = i; // should be a number in range 5 - 8 } else { // should clear out this invalid attempt #if DEBUG_ON & DEBUG_SPECIAL printf("\n vt100_processInput: Invalid attempt to set up Special Character # %d - only %d columns", seqValue, i); #endif for(i=0; i < BYTES_PER_SPEC_CHAR; i++) // up to 8 elements before the 'f' delimiter { specialChars[seqValue-1][i] = 0; } } break; case SPECIAL_CHAR: // display one of 8 Special Characters as a ASCII Digit '1' thru '8' // and put the Atrribute Bit On for Speciall Char for that character only // The special character number is in the "seqValue" variable processInputChar((char) ((uint8_t) ( (0x30 + seqValue) | 0x80) ), pVD); // ASCII '0' + seq + bit 7 break; case STATUS_QUERY: // one of three possible queries - cursorPos, attribs/parameters, auxSwitch state // all need to have responses generated and written to the serial port fd if open // have to send (transmit) cursor pos message onto Serial Port (fd) // sequence is: <ESC>[<row>;<col>R or similar // clear and load an output buffer for response #if DEBUG_ON & DEBUG_SERIAL printf("\n vt100_process_ESC_Seq: STATUS QUERY # %c\n", ESC_sequence[2]); #endif for(i = 0; i < MAX_ESC_SEQ_LEN; i++ ){ outputSeqBuffer[i] = '\0'; } outputSeqBuffer[0] = ESC_CHAR; outputSeqBuffer[1] = '['; switch ( ESC_sequence[2] ) { case '6': // return Cursor Position sprintf(&outputSeqBuffer[2], "%d;%dR", cursorPos.cp_row + 1, cursorPos.cp_col + 1); break; case 'A': // return Auxillary Switch Status sprintf(&outputSeqBuffer[2], "%cR", vt100_get_auxSwitch()?'h':'l' ); break; case 'B': // return status of various attributes and parameters sprintf(&outputSeqBuffer[2], "%c;%c;%c;%c;%d;%cR", vt100_get_autoWrap()?'h':'l', vt100_get_autoScroll()?'h':'l', vt100_get_autoRepeat()?'h':'l', vt100_get_backLight()?'h':'l', vt100_get_backLightTimeout(), vt100_get_auxSwitch()?'h':'l'); break; default: break; } outBufLen = strlen(outputSeqBuffer); if( fdSerialPort > 0 ) { numBytesWritten = writeSerialPort(fdSerialPort, outputSeqBuffer, outBufLen ); if( numBytesWritten == outBufLen ) { ; // good command written out } else { ; // null statement - placeholder #if DEBUG_ON & DEBUG_SERIAL // ERR_07_PORT_WRITE if there was a return value printf("\n vt100_process_ESC_Seq: Only wrote %d of %d bytes to Serial port for CMD/RESP", numBytesWritten, outBufLen); #endif } } else { #if DEBUG_ON & DEBUG_SERIAL printf("\n vt100_process_ESC_Seq: write out to serial port %d chars:\n %s ", outBufLen, outputSeqBuffer); #endif } break; case SAVE_CURSOR_POS: vt100_save_cursorPos(); break; case REST_CURSOR_POS: vt100_rest_cursorPos(); break; default: break; } // end switch } // end if //printf("ESC%d|%d[%d;%d]", seqCode, seqValue, cursorPos.cp_row, cursorPos.cp_col); //vt100_dumpVD("process_ESC", seq++,"after ESC sequence"); } // end process_ESC_Seq