Exemple #1
0
void
vt100_resetParms()
{
	vt100_set_errorCode(0);                     // init to zero at run-time
	vt100_clear_errorText();
	
	//  set the "Reset/Power-Up Conditions" from the ATC 5.2b spec, page 7-4
	vt100_set_autoRepeat( 0 );
	vt100_set_autoWrap( 0 );
	vt100_set_autoScroll( 0 );
	vt100_set_currentAttribs( NO_ATTRIBUTES );  // clear Reverse Video, Character Blink and Underline Attribs, + Special Char
	
	vt100_set_cursorBlink( 1 );      // Turn on Cursor and its blinking state 
	vt100_set_cursorState( 1 ); 
	vt100_set_cursorPos( 1, 1);    // cursor at top left 
	
	vt100_clear_specialChars();    // clear all down to 0 bits which should be a blank char
	
	// set the initial tab stops at 9, 17, 25, 33 per ATC 5.2b spec, page 7-4 
	vt100_set_tabStop( (int16_t) ( 9 - 1) );      // our array starts with 0 
	vt100_set_tabStop( (int16_t) (17 - 1) ); 
	vt100_set_tabStop( (int16_t) (25 - 1) ); 
	vt100_set_tabStop( (int16_t) (33 - 1) ); 

	vt100_set_backLightTimeout( (int16_t) 6 );   // set timeout to 60 secs 
	vt100_set_backLight( (int16_t) 0);           // turn off the backlight 

	return;
	
}   // end - vt100_resetParms()
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