Add DECSTR and RIS
Implement soft and hard resets (handling intermediate bytes a little better in the process).
This commit is contained in:
		
							parent
							
								
									c28b3597dd
								
							
						
					
					
						commit
						a37657ac52
					
				
							
								
								
									
										197
									
								
								ANSI.c
									
									
									
									
									
								
							
							
						
						
									
										197
									
								
								ANSI.c
									
									
									
									
									
								
							| @ -176,7 +176,8 @@ | |||||||
|     added insert mode; |     added insert mode; | ||||||
|     BS/CUB/HPB after wrap will move back to the previous line(s); |     BS/CUB/HPB after wrap will move back to the previous line(s); | ||||||
|     added DECOM, DECSTBM, SD & SU; |     added DECOM, DECSTBM, SD & SU; | ||||||
|     only flush before accessing the console, adding a mode to flush immediately. |     only flush before accessing the console, adding a mode to flush immediately; | ||||||
|  |     added DECSTR & RIS. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include "ansicon.h" | #include "ansicon.h" | ||||||
| @ -213,10 +214,11 @@ struct Cache | |||||||
| 
 | 
 | ||||||
| #define MAX_ARG 16		// max number of args in an escape sequence
 | #define MAX_ARG 16		// max number of args in an escape sequence
 | ||||||
| int   state;			// automata state
 | int   state;			// automata state
 | ||||||
| TCHAR prefix;			// escape sequence prefix ( '[', ']' or '(' );
 | TCHAR prefix;			// escape sequence prefix ( '[' or ']' );
 | ||||||
| TCHAR prefix2;			// secondary prefix ( '?' or '>' );
 | TCHAR prefix2;			// secondary prefix ( one of '<=>?' );
 | ||||||
| TCHAR suffix;			// escape sequence suffix
 | TCHAR suffix;			// escape sequence final byte
 | ||||||
| TCHAR suffix2;			// escape sequence secondary suffix
 | TCHAR suffix2;			// escape sequence intermediate byte
 | ||||||
|  | int   ibytes;			// count of intermediate bytes
 | ||||||
| int   es_argc;			// escape sequence args count
 | int   es_argc;			// escape sequence args count
 | ||||||
| int   es_argv[MAX_ARG]; 	// escape sequence args
 | int   es_argv[MAX_ARG]; 	// escape sequence args
 | ||||||
| TCHAR Pt_arg[MAX_PATH*2];	// text parameter for Operating System Command
 | TCHAR Pt_arg[MAX_PATH*2];	// text parameter for Operating System Command
 | ||||||
| @ -945,6 +947,56 @@ void init_tabs( int size ) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | // ========== Reset
 | ||||||
|  | 
 | ||||||
|  | void InterpretEscSeq( void ); | ||||||
|  | 
 | ||||||
|  | void Reset( BOOL hard ) | ||||||
|  | { | ||||||
|  |   CONSOLE_CURSOR_INFO CursInfo; | ||||||
|  |   CONSOLE_SCREEN_BUFFER_INFOX csbix; | ||||||
|  | 
 | ||||||
|  |   GetConsoleCursorInfo( hConOut, &CursInfo ); | ||||||
|  |   CursInfo.bVisible = TRUE; | ||||||
|  |   SetConsoleCursorInfo( hConOut, &CursInfo ); | ||||||
|  |   im = | ||||||
|  |   om = | ||||||
|  |   tb_margins = | ||||||
|  |   pState->crm = FALSE; | ||||||
|  |   awm = TRUE; | ||||||
|  |   SetConsoleMode( hConOut, cache[0].mode | ENABLE_WRAP_AT_EOL_OUTPUT ); | ||||||
|  |   shifted = G0_special = SaveG0 = FALSE; | ||||||
|  |   pState->SavePos.X = pState->SavePos.Y = 0; | ||||||
|  |   pState->SaveAttr = 0; | ||||||
|  |   es_argv[0] = es_argc = 0; | ||||||
|  |   prefix = '['; | ||||||
|  |   prefix2 = suffix2 = 0; | ||||||
|  |   suffix = 'm'; | ||||||
|  |   InterpretEscSeq(); | ||||||
|  | 
 | ||||||
|  |   if (hard) | ||||||
|  |   { | ||||||
|  |     pState->tabs = | ||||||
|  |     pState->noclear = FALSE; | ||||||
|  |     prefix2 = '?'; | ||||||
|  |     es_argv[0] = 3; es_argc = 1; | ||||||
|  |     suffix2 = '+'; | ||||||
|  |     suffix = 'l'; | ||||||
|  |     InterpretEscSeq(); | ||||||
|  |     screen_top = -1; | ||||||
|  |     csbix.cbSize = sizeof(csbix); | ||||||
|  |     if (GetConsoleScreenBufferInfoX && | ||||||
|  | 	GetConsoleScreenBufferInfoX( hConOut, &csbix )) | ||||||
|  |     { | ||||||
|  |       memcpy( csbix.ColorTable, pState->palette, sizeof(csbix.ColorTable) ); | ||||||
|  |       ++csbix.srWindow.Right; | ||||||
|  |       ++csbix.srWindow.Bottom; | ||||||
|  |       SetConsoleScreenBufferInfoX( hConOut, &csbix ); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| // ========== Print functions
 | // ========== Print functions
 | ||||||
| 
 | 
 | ||||||
| //-----------------------------------------------------------------------------
 | //-----------------------------------------------------------------------------
 | ||||||
| @ -981,7 +1033,7 @@ void InterpretEscSeq( void ) | |||||||
| 
 | 
 | ||||||
|   if (prefix == '[') |   if (prefix == '[') | ||||||
|   { |   { | ||||||
|     if (prefix2 == '?') |     if (prefix2 == '?' && (suffix2 == 0 || suffix2 == '+')) | ||||||
|     { |     { | ||||||
|       if (suffix == 'h' || suffix == 'l') |       if (suffix == 'h' || suffix == 'l') | ||||||
|       { |       { | ||||||
| @ -1093,7 +1145,7 @@ void InterpretEscSeq( void ) | |||||||
|       top    = TOP; |       top    = TOP; | ||||||
|       bottom = BOTTOM; |       bottom = BOTTOM; | ||||||
|     } |     } | ||||||
|     switch (suffix) |     if (suffix2 == 0 || suffix2 == '+') switch (suffix) | ||||||
|     { |     { | ||||||
|       case 'm': // SGR
 |       case 'm': // SGR
 | ||||||
| 	if (es_argc == 0) es_argc++; // ESC[m == ESC[0m
 | 	if (es_argc == 0) es_argc++; // ESC[m == ESC[0m
 | ||||||
| @ -1580,82 +1632,78 @@ void InterpretEscSeq( void ) | |||||||
| 	} | 	} | ||||||
|       return; |       return; | ||||||
| 
 | 
 | ||||||
|       case 'h': // SM - ESC[#h Set Mode
 |       case 'h': // SM - ESC[#...h Set Mode
 | ||||||
|  |       case 'l': // RM - ESC[#...l Reset Mode
 | ||||||
|  |       { | ||||||
|  | 	BOOL state = (suffix == 'h'); | ||||||
| 	for (i = 0; i < es_argc; i++) | 	for (i = 0; i < es_argc; i++) | ||||||
| 	  if (suffix2 == '+') | 	  if (suffix2 == '+') switch (es_argv[i]) | ||||||
| 	  { | 	  { | ||||||
| 	    switch (es_argv[i]) | 	    case 1: // ACFM
 | ||||||
| 	    { | 	      pState->fm = state; | ||||||
| 	      case 1: // ACFM
 | 	    break; | ||||||
| 		pState->fm = TRUE; |  | ||||||
| 	      break; |  | ||||||
| 	    } |  | ||||||
| 	  } | 	  } | ||||||
| 	  else switch (es_argv[i]) | 	  else switch (es_argv[i]) | ||||||
| 	  { | 	  { | ||||||
| 	    case 3: // CRM
 | 	    case 3: // CRM
 | ||||||
| 	      pState->crm = TRUE; | 	      pState->crm = state; | ||||||
| 	    break; | 	    break; | ||||||
| 
 | 
 | ||||||
| 	    case 4: // IRM
 | 	    case 4: // IRM
 | ||||||
| 	      im = TRUE; | 	      im = state; | ||||||
| 	    break; | 	    break; | ||||||
| 	  } | 	  } | ||||||
|  | 	return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       default: | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (suffix2 == '!') switch (suffix) | ||||||
|  |     { | ||||||
|  |       case 'p': // DECSTR - ESC[!p Soft reset
 | ||||||
|  | 	if (es_argc != 0) return; | ||||||
|  | 	Reset( FALSE ); | ||||||
|       return; |       return; | ||||||
| 
 | 
 | ||||||
|       case 'l': // RM - ESC[#l Reset Mode
 |       default: | ||||||
| 	for (i = 0; i < es_argc; i++) |  | ||||||
| 	  if (suffix2 == '+') |  | ||||||
| 	  { |  | ||||||
| 	    switch (es_argv[i]) |  | ||||||
| 	    { |  | ||||||
| 	      case 1: // ACFM
 |  | ||||||
| 		pState->fm = FALSE; |  | ||||||
| 	      break; |  | ||||||
| 	    } |  | ||||||
| 	  } |  | ||||||
| 	  else switch (es_argv[i]) // CRM - ESC[3l is handled during parsing
 |  | ||||||
| 	  { |  | ||||||
| 	    case 4: // IRM
 |  | ||||||
| 	      im = FALSE; |  | ||||||
| 	    break; |  | ||||||
| 	  } |  | ||||||
|       return; |       return; | ||||||
| 
 |     } | ||||||
|       case '~': |     if (suffix2 == ',') switch (suffix) | ||||||
| 	if (suffix2 == ',') // DECPS - ESC[#;#;#...,~ Play Sound
 |     { | ||||||
| 	{ |       case '~': // DECPS - ESC[#;#;#...,~ Play Sound
 | ||||||
| 	  // Frequencies of notes obtained from:
 |       { | ||||||
| 	  //	https://pages.mtu.edu/~suits/notefreqs.html
 | 	// Frequencies of notes obtained from:
 | ||||||
| 	  //	http://www.liutaiomottola.com/formulae/freqtab.htm
 | 	//	https://pages.mtu.edu/~suits/notefreqs.html
 | ||||||
| 	  // This is different to what the VT520 manual has, but since that
 | 	//	http://www.liutaiomottola.com/formulae/freqtab.htm
 | ||||||
| 	  // only specifies four frequencies, so be it.  I've also rounded to
 | 	// This is different to what the VT520 manual has, but since that
 | ||||||
| 	  // even numbers, as the Beep function seems to stutter on odd.
 | 	// only specifies four frequencies, so be it. I've also rounded to
 | ||||||
| 	  static const DWORD snd_freq[] = { 0, | 	// even numbers, as the Beep function seems to stutter on odd.
 | ||||||
|  | 	static const DWORD snd_freq[] = { 0, | ||||||
| //	C    C#/Db  D	 D#/Eb	E     F    F#/Gb  G    G#/Ab  A    A#/Bb  B
 | //	C    C#/Db  D	 D#/Eb	E     F    F#/Gb  G    G#/Ab  A    A#/Bb  B
 | ||||||
| /* 5 */  524,  554,  588,  622,  660,  698,  740,  784,  830,  880,  932,  988, | /* 5 */  524,  554,  588,  622,  660,  698,  740,  784,  830,  880,  932,  988, | ||||||
| /* 6 */ 1046, 1108, 1174, 1244, 1318, 1396, 1480, 1568, 1662, 1760, 1864, 1976, | /* 6 */ 1046, 1108, 1174, 1244, 1318, 1396, 1480, 1568, 1662, 1760, 1864, 1976, | ||||||
| /* 7 */ 2094 | /* 7 */ 2094 | ||||||
| 	  }; | 	}; | ||||||
| 	  DWORD dur; | 	DWORD dur; | ||||||
| 	  if (es_argc < 2) return; | 	if (es_argc < 2) return; | ||||||
| 	  dur = es_argv[1]; | 	dur = es_argv[1]; | ||||||
| 	  if (dur <= 48)		// use 1/32 second
 | 	if (dur <= 48)	// use 1/32 second
 | ||||||
| 	    dur = 1000 * dur / 32; | 	  dur = 1000 * dur / 32; | ||||||
| 	  else if (dur > 8000)		// max out at 8 seconds
 | 	else if (dur > 8000)		// max out at 8 seconds
 | ||||||
| 	    dur = 8000; | 	  dur = 8000; | ||||||
| 	  if (es_argc == 2)		// no notes
 | 	if (es_argc == 2)		// no notes
 | ||||||
|  | 	  Sleep( dur ); | ||||||
|  | 	else for (i = 2; i < es_argc; ++i) | ||||||
|  | 	{ | ||||||
|  | 	  if (es_argv[0] == 0) // zero volume
 | ||||||
| 	    Sleep( dur ); | 	    Sleep( dur ); | ||||||
| 	  else for (i = 2; i < es_argc; ++i) | 	  else | ||||||
| 	  { | 	    Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]] | ||||||
| 	    if (es_argv[0] == 0)	// zero volume
 | 						 : es_argv[i], dur ); | ||||||
| 	      Sleep( dur ); |  | ||||||
| 	    else |  | ||||||
| 	      Beep( (es_argv[i] < lenof(snd_freq)) ? snd_freq[es_argv[i]] |  | ||||||
| 						   : es_argv[i], dur ); |  | ||||||
| 	  } |  | ||||||
| 	} | 	} | ||||||
|       return; | 	return; | ||||||
|  |       } | ||||||
| 
 | 
 | ||||||
|       default: |       default: | ||||||
|       return; |       return; | ||||||
| @ -1984,6 +2032,7 @@ ParseAndPrintString( HANDLE hDev, | |||||||
|       if (c == ESC) |       if (c == ESC) | ||||||
|       { |       { | ||||||
| 	suffix2 = 0; | 	suffix2 = 0; | ||||||
|  | 	ibytes = 0; | ||||||
| 	get_state(); | 	get_state(); | ||||||
| 	state = (pState->crm) ? 7 : 2; | 	state = (pState->crm) ? 7 : 2; | ||||||
|       } |       } | ||||||
| @ -2025,10 +2074,14 @@ ParseAndPrintString( HANDLE hDev, | |||||||
| 	state = 1; | 	state = 1; | ||||||
|       } |       } | ||||||
|       else if (c >= '\x20' && c <= '\x2f') |       else if (c >= '\x20' && c <= '\x2f') | ||||||
| 	suffix2 = c; |  | ||||||
|       else if (suffix2 != 0) |  | ||||||
|       { |       { | ||||||
| 	if (suffix2 == '(')     // SCS - Designate G0 character set
 | 	suffix2 = c; | ||||||
|  | 	++ibytes; | ||||||
|  |       } | ||||||
|  |       else if (ibytes != 0) | ||||||
|  |       { | ||||||
|  | 	if (ibytes == 1 && | ||||||
|  | 	    suffix2 == '(')     // SCS - Designate G0 character set
 | ||||||
| 	{ | 	{ | ||||||
| 	  if (c == '0') | 	  if (c == '0') | ||||||
| 	    shifted = G0_special = TRUE; | 	    shifted = G0_special = TRUE; | ||||||
| @ -2091,6 +2144,10 @@ ParseAndPrintString( HANDLE hDev, | |||||||
| 	} | 	} | ||||||
| 	state = 1; | 	state = 1; | ||||||
|       } |       } | ||||||
|  |       else if (c == 'c')        // RIS Reset to Initial State
 | ||||||
|  |       { | ||||||
|  | 	Reset( TRUE ); | ||||||
|  |       } | ||||||
|       else if (c == '[' ||      // CSI Control Sequence Introducer
 |       else if (c == '[' ||      // CSI Control Sequence Introducer
 | ||||||
| 	       c == ']')        // OSC Operating System Command
 | 	       c == ']')        // OSC Operating System Command
 | ||||||
|       { |       { | ||||||
| @ -2134,15 +2191,16 @@ ParseAndPrintString( HANDLE hDev, | |||||||
|       { |       { | ||||||
| 	// ignore it
 | 	// ignore it
 | ||||||
|       } |       } | ||||||
|       else if (c >= '\x3b' && c <= '\x3f') |       else if (c >= '\x3c' && c <= '\x3f') | ||||||
|       { |       { | ||||||
| 	prefix2 = c; | 	prefix2 = c; | ||||||
|       } |       } | ||||||
|       else if (c >= '\x20' && c <= '\x2f') |       else if (c >= '\x20' && c <= '\x2f') | ||||||
|       { |       { | ||||||
| 	suffix2 = c; | 	suffix2 = c; | ||||||
|  | 	++ibytes; | ||||||
|       } |       } | ||||||
|       else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~')) |       else if (ibytes > 1) | ||||||
|       { |       { | ||||||
| 	state = 1; | 	state = 1; | ||||||
|       } |       } | ||||||
| @ -2175,8 +2233,9 @@ ParseAndPrintString( HANDLE hDev, | |||||||
|       else if (c >= '\x20' && c <= '\x2f') |       else if (c >= '\x20' && c <= '\x2f') | ||||||
|       { |       { | ||||||
| 	suffix2 = c; | 	suffix2 = c; | ||||||
|  | 	++ibytes; | ||||||
|       } |       } | ||||||
|       else if (suffix2 != 0 && suffix2 != '+' && (suffix2 != ',' || c != '~')) |       else if (ibytes > 1) | ||||||
|       { |       { | ||||||
| 	state = 1; | 	state = 1; | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -91,7 +91,7 @@ | |||||||
|     use -pu to unload from the parent. |     use -pu to unload from the parent. | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #define PDATE L"22 December, 2017" | #define PDATE L"23 December, 2017" | ||||||
| 
 | 
 | ||||||
| #include "ansicon.h" | #include "ansicon.h" | ||||||
| #include "version.h" | #include "version.h" | ||||||
|  | |||||||
| @ -191,6 +191,7 @@ Sequences Recognised | |||||||
| 	\e[?5W		DECST8C Set Tab at Every 8 Columns | 	\e[?5W		DECST8C Set Tab at Every 8 Columns | ||||||
| 	\e[?5;#W	DECST8C Set Tab at Every # Columns (ANSICON extension) | 	\e[?5;#W	DECST8C Set Tab at Every # Columns (ANSICON extension) | ||||||
| 	\e[#;#r 	DECSTBM Set Top and Bottom Margins | 	\e[#;#r 	DECSTBM Set Top and Bottom Margins | ||||||
|  | 	\e[!p		DECSTR	Soft Terminal Reset | ||||||
| 	\e[?25h 	DECTCEM Text Cursor Enable Mode (show cursor) | 	\e[?25h 	DECTCEM Text Cursor Enable Mode (show cursor) | ||||||
| 	\e[?25l 	DECTCEM Text Cursor Enable Mode (hide cursor) | 	\e[?25l 	DECTCEM Text Cursor Enable Mode (hide cursor) | ||||||
| 	\e[#M		DL	Delete Line | 	\e[#M		DL	Delete Line | ||||||
| @ -214,6 +215,7 @@ Sequences Recognised | |||||||
| 	\eE		NEL	Next Line | 	\eE		NEL	Next Line | ||||||
| 	\e[#b		REP	Repeat | 	\e[#b		REP	Repeat | ||||||
| 	\eM		RI	Reverse Index | 	\eM		RI	Reverse Index | ||||||
|  | 	\ec		RIS	Reset to Initial State | ||||||
| 	\e(0		SCS	Select Character Set (DEC special graphics) | 	\e(0		SCS	Select Character Set (DEC special graphics) | ||||||
| 	\e(B		SCS	Select Character Set (ASCII) | 	\e(B		SCS	Select Character Set (ASCII) | ||||||
| 	\e[#;#;#m	SGR	Select Graphic Rendition | 	\e[#;#;#m	SGR	Select Graphic Rendition | ||||||
| @ -322,7 +324,7 @@ Version History | |||||||
| 
 | 
 | ||||||
|     Legend: + added, - bug-fixed, * changed. |     Legend: + added, - bug-fixed, * changed. | ||||||
| 
 | 
 | ||||||
|     1.80 - 22 December, 2017: |     1.80 - 23 December, 2017: | ||||||
|     - fix unloading; |     - fix unloading; | ||||||
|     - fix -e et al when redirecting to CON; |     - fix -e et al when redirecting to CON; | ||||||
|     - hook CreateFile and CreateConsoleScreenBuffer to force read/write access |     - hook CreateFile and CreateConsoleScreenBuffer to force read/write access | ||||||
| @ -349,7 +351,8 @@ Version History | |||||||
|     + added SCS, but only for special/ASCII (same as Win10); |     + added SCS, but only for special/ASCII (same as Win10); | ||||||
|     + added tab handling (HT, HTS, TBC & DECST8C); |     + added tab handling (HT, HTS, TBC & DECST8C); | ||||||
|     + added IRM; |     + added IRM; | ||||||
|     + added DECOM, DECSTBM, SD & SU. |     + added DECOM, DECSTBM, SD & SU; | ||||||
|  |     + added DECSTR & RIS. | ||||||
| 
 | 
 | ||||||
|     1.72 - 24 December, 2015: |     1.72 - 24 December, 2015: | ||||||
|     - handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile; |     - handle STD_OUTPUT_HANDLE & STD_ERROR_HANDLE in WriteFile; | ||||||
| @ -578,4 +581,4 @@ Distribution | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ============================== | ============================== | ||||||
| Jason Hood, 22 December, 2017. | Jason Hood, 23 December, 2017. | ||||||
|  | |||||||
| @ -182,6 +182,25 @@ H	set tab stop | |||||||
| [?95h	don't clear screen when changing columns | [?95h	don't clear screen when changing columns | ||||||
| [?95l	clear screen when changing columns | [?95l	clear screen when changing columns | ||||||
| 
 | 
 | ||||||
|  | [!p	soft reset: | ||||||
|  | 	  show cursor | ||||||
|  | 	  perform control functions | ||||||
|  | 	  replace characters | ||||||
|  | 	  set origin to top line | ||||||
|  | 	  wrap lines at screen edge | ||||||
|  | 	  select ASCII | ||||||
|  | 	  remove margins | ||||||
|  | 	  default SGR | ||||||
|  | 	  set the saved cursor to the top-left | ||||||
|  | c	hard reset: | ||||||
|  | 	  as above | ||||||
|  | 	  restore console tab handling | ||||||
|  | 	  restore the entire palette | ||||||
|  | 	  restore original columns | ||||||
|  | 	  clear screen when changing columns | ||||||
|  | 	  clear the buffer | ||||||
|  | 	  home the cursor | ||||||
|  | 
 | ||||||
| [c	sends "\e[?62;1c" to console input (where \e is escape) | [c	sends "\e[?62;1c" to console input (where \e is escape) | ||||||
| [0c	as above | [0c	as above | ||||||
| [5n	sends "\e[0n" to console input | [5n	sends "\e[0n" to console input | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jason Hood
						Jason Hood