ansiprsr.cpp

来自「一个类似windows」· C++ 代码 · 共 1,477 行 · 第 1/3 页

CPP
1,477
字号
		case 'K':
			Console.ClearEOLine();
			break;
		// Scroll Up one line //Reverse index
		case 'M':
			Console.reverse_index();
			break;
		// Direct cursor addressing
		case 'Y':
			if ((pszBufferEnd - pszBuffer) >= 2){
				// if we subtract '\x1F', then we may end up with a negative
				// cursor position! (Paul Brannan 6/26/98)
				ConSetCursorPos(pszBuffer[1] - ' ',	pszBuffer[0] - ' ');
				pszBuffer+=2;
			} else {
				pszBuffer--; // Paul Brannan 6/26/98
			}
			break;
		// Terminal ID Request
		case 'Z':
			{
				const char* szTerminalId = GetTerminalID();
				Network.WriteString(szTerminalId, strlen(szTerminalId));
				break;
			}
		// reset terminal to defaults
		case 'c':
			ResetTerminal();
			break;
		// Enter alternate keypad mode
		case '=':
			KeyTrans.set_ext_mode(APP3_KEY);
			break;
		// Exit alternate keypad mode
		case '>':
			KeyTrans.unset_ext_mode(APP3_KEY);
			break;
		// Enter ANSI mode
		case '<':
			KeyTrans.unset_ext_mode(APP2_KEY); // exit vt52 mode
			break;
		// Graphics processor on (See note 3)
		case '1':
			break;
		// Line size commands
		case '#':        //Line size commands
			// (Paul Brannan 6/26/98)
			if(pszBuffer < pszBufferEnd) {
				switch(*pszBuffer++) {
				case '3': break; // top half of a double-height line
				case '4': break; // bottom half of a double-height line
				case '6': break; // current line becomes double-width
				case '8': Console.ClearScreen('E'); break;
				}
			} else {
				pszBuffer--;
			}			
			break;
		// Graphics processor off (See note 3)
		case '2':
			break;
		// Save cursor and attribs
		case '7':
			SaveCurY(Console.GetRawCursorY());
			SaveCurX(Console.GetRawCursorX());
			iSavedAttributes = Console.GetAttrib();
			break;
			// Restore cursor position and attribs
		case '8':
			Console.SetRawCursorPosition(iSavedCurX, iSavedCurY);
			Console.SetAttrib(iSavedAttributes);
			break;
		// Set G0 map (Paul Brannan 6/25/98)
		case '(':
			if (pszBuffer < pszBufferEnd) {
				map_G0 = *pszBuffer;
				if(current_map == 0) Charmap.setmap(map_G0);
				pszBuffer++;
			} else {
				pszBuffer--;
			}
			break;
		// Set G1 map (Paul Brannan 6/25/98)
		case ')':
			if (pszBuffer < pszBufferEnd) {
				map_G1 = *pszBuffer;
				if(current_map == 1) Charmap.setmap(map_G1);
				pszBuffer++;
			} else {
				pszBuffer--;
			}
			break;
		// This doesn't do anything, as far as I can tell, but it does take
		// a parameter (Paul Brannan 6/27/98)
		case '%':
			if (pszBuffer < pszBufferEnd) {
				pszBuffer++;
			} else {
				pszBuffer--;
			}
			break;
		// ANSI escape sequence
		case '[':
			// Check if we have whole escape sequence in buffer.
			// This should not be isalpha anymore (Paul Brannan 9/1/98)
			pszChar = pszBuffer;
			while ((pszChar < pszBufferEnd) && (*pszChar <= '?'))
				pszChar++;
			if (pszChar == pszBufferEnd)
				pszBuffer -= 2;
			else
				pszBuffer = ParseEscapeANSI(pszBuffer, pszBufferEnd);
			break;
#ifdef MTE_SUPPORT
		case '~':
			// Frediano Ziglio, 5/31/2000
			// Meridian Terminal Emulator extension
			// !!! same as ANSI
			// !!! should put in MTE procedure
			pszChar = pszBuffer;
			while ((pszChar < pszBufferEnd) && (*pszChar <= '?'))
				pszChar++;
			if (pszChar == pszBufferEnd)
				pszBuffer -= 2;
			else
				pszBuffer = ParseEscapeMTE(pszBuffer, pszBufferEnd);
			break;
#endif
		default:
#ifdef DEBUG
			Console.Beep();
#endif
			break;
	}

	return pszBuffer;
}

// This function now only parses the ANSI buffer and does not do anything
// with IAC sequences.  That code has been moved to TTelHndl.cpp.
// The scroller update routines have been moved to TScroll.cpp.
// (Paul Brannan 6/15/98)
char* TANSIParser::ParseBuffer(char* pszHead, char* pszTail){
	// copy into ANSI buffer
	char * pszResult;
	
	// Parse the buffer for ANSI or display
	while (pszHead < pszTail) {
		if(!ini.get_output_redir()) {
			pszResult = ParseANSIBuffer(pszHead, pszTail);
		} else {
			// Output is being redirected
			if(ini.get_strip_redir()) {
				// Skip the WriteFile() altogether and pass the buffer to a filter
				// Mark Miesfield 09/24/2000
				pszResult = PrintGoodChars(pszHead, pszTail);
			} else {
				DWORD Result;
				// Paul Brannan 7/29/98
				// Note that this has the unforunate effect of printing out
				// NULL (ascii 0) characters onto the screen
				if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),	pszHead,
					pszTail - pszHead, &Result,	NULL)) pszResult = pszHead;
				pszResult = pszHead + Result;
			}
		}
		if (dumpfile)
			fwrite( pszHead, sizeof (char), pszResult-pszHead, dumpfile);
		if(ini.get_scroll_enable()) Scroller.update(pszHead, pszResult);
		if (pszResult == pszHead) break;
		pszHead = pszResult;
	}
	// return the new head to the buffer
	return pszHead;
}

// A simple routine to strip ANSI sequences
// This isn't perfect, but it does an okay job (Paul Brannan 7/5/98)
// Fixed a line counting bug (Paul Brannan 12/4/98)
int TANSIParser::StripBuffer(char* pszHead, char* pszTail, int width) {
	int lines = 0, c = 0;
	char *pszBuf = pszHead;

	while(pszHead < pszTail) {
		if(iscntrl(*pszHead)) {
			switch(*(pszHead++)) {
			case 8:
			case 127:
				if(c>0) {
					if(!(c%width)) lines--;
					c--;
					pszBuf--;
				}
				break;
			case 10: lines++;
			case 13:
				*(pszBuf++) = *(pszHead - 1);
				c = 0;
				break;
			case 27:
				switch(*(pszHead++)) {
				case 'Y': pszHead += 2; break;
				case '#':
				case '(':
				case ')':
				case '%': pszHead++; break;
				case '[':
					while((pszHead < pszTail) && (*pszHead < '?'))
						pszHead++;
					pszHead++;
					break;
				}
			}
		} else {
			*(pszBuf++) = *(pszHead++);
			c++;
		}
		if(c != 0 && !(c%width))
			lines++;
	}
	
	// Fill in the end of the buffer with blanks
	while(pszBuf <= pszTail) *pszBuf++ = ' ';

	return lines;
}

char* TANSIParser::ParseANSIBuffer(char* pszBuffer, char* pszBufferEnd)
{
	if(InPrintMode) {
		return PrintBuffer(pszBuffer, pszBufferEnd);
	}
	
	unsigned char tmpc = *(unsigned char *)pszBuffer;

	if(tmpc == 27) {
		return ParseEscape(pszBuffer, pszBufferEnd);
	}
	
//	if((fast_write && tmpc < 32) ||
//		!print_ctrl && (tmpc < 32 || (EightBit_Ansi &&
//		(tmpc > 128 && tmpc < 128 + ' ')))) {

	// We shouldn't print ctrl characters when fast write is enabled
	// and ctrl chars are disabled (Paul Brannan 9/1/98)
	if(tmpc < 32) {
		// From the Linux kernel (Paul Brannan 12/5/98):
		/* A bitmap for codes <32. A bit of 1 indicates that the code
		 * corresponding to that bit number invokes some special action
		 * (such as cursor movement) and should not be displayed as a
		 * glyph unless the disp_ctrl mode is explicitly enabled.
		 */
		const long CTRL_ACTION = 0x0d00ff81;
		const long CTRL_ALWAYS = 0x0800f501;
		if(!(((print_ctrl?CTRL_ALWAYS:CTRL_ACTION)>>tmpc)&1)) {
			
			Console.WriteString((char *)&tmpc, 1);
			pszBuffer++;
			return pszBuffer;
		}

		switch (tmpc) {
		case 0:
			pszBuffer++;
			break;
		
		// I.Ioannou 5/30/98
		case 7:
			Console.Beep();
			pszBuffer++;
			break;
		
		// destructive backspace
		case 8:
			// Added option for destructive backspace (Paul Brannan 5/13/98)
			// Changed to ConWriteCtrlString so that the cursor position can be
			// updated (Paul Brannan 5/25/98)
			if(ini.get_dstrbksp()) {
				Console.WriteCtrlChar('\b');
				Console.WriteString(" ", 1);
				Console.WriteCtrlChar('\b');
			}
			else Console.WriteCtrlChar('\b');
			pszBuffer++;
			break;
		
		// horizontal tab
		case 9:
			{
				pszBuffer++;
				int x = Console.GetCursorX();
				if(x != -1)
					Console.SetCursorPosition(tab_stops[x], Console.GetCursorY());
			}
			break;
		
		// Line Feed Char
		case 10:
			// Test for local echo (Paul Brannan 8/25/98)
			if(Network.get_local_echo() || newline_mode) // &&
				Console.WriteCtrlChar('\x0d');
			Console.WriteCtrlChar('\x0a');
			pszBuffer++;
			break;
		
		// form feed
		case 12:
			pszBuffer++;
			Console.ClearScreen();
			Console.SetRawCursorPosition(Console.GetCursorX(), 1); // changed fm 1
			break;
		
		case 13:
			Console.WriteCtrlChar('\x0d');
			pszBuffer++;

			break;

		case 14:  // shift out of alternate chararcter set
			pszBuffer++;
			Charmap.setmap(map_G1); // Paul Brannan 6/25/98
			current_map = 1;
			break;
	
		case 15:  // shift in
			pszBuffer++;
			Charmap.setmap(map_G0); // Paul Brannan 6/25/98
			current_map = 0;
			break;
		
		// Paul Brannan 9/1/98 - Is this okay?
		default:
			pszBuffer++;
		}

		return pszBuffer;
	}

	//  added by I.Ioannou 06 April, 1997
	//  In 8 bit systems the server may send 0x9b instead of ESC[
	//  Well, this will produce troubles in Greek 737 Code page
	//  which uses 0x9b as the small "delta" - and I thing that there
	//  is another European country with the same problem.
	//  If we have to stay 8-bit clean we may have to
	//  give the ability of ROM characters (ESC[11m),
	//  for striped 8'th bit (ESC[12m) as SCO does,
	//  or a parameter at compile (or run ?) time.
	// We now check for a flag in the ini file (Paul Brannan 5/13/98)
	// We also handle any 8-bit ESC sequence (Paul Brannan 6/28/98)
	if(ini.get_eightbit_ansi() && (tmpc > 128 && tmpc < 128 + ' ')) {
		// There's a chance the sequence might not parse.  If this happens
		// then pszBuffer will be one character too far back, since
		// ParseEscape is expecting two characters, not one.
		// In that case we must handle it.
		char *pszCurrent = pszBuffer;
		pszBuffer = ParseEscape(pszBuffer, pszBufferEnd);
		if(pszBuffer < pszCurrent) pszBuffer = pszCurrent;
	}

	char* pszCurrent = pszBuffer + 1;
	// I.Ioannou 04 Sep 1997 FIXME with ESC[11m must show chars < 32
	// Fixed (Paul Brannan 6/28/98)
	while ((pszCurrent < pszBufferEnd) && (!iscntrl(*pszCurrent))) {
		// I.Ioannou 04 Sep 1997 strip on high bit
		if ( (inGraphMode) && (*pszCurrent > (char)32) )
			*pszCurrent |= 0x80 ;
		pszCurrent++;
	}
	
	// Note that this may break dumpfiles slightly.
	// If 'B' is set to anything other than ASCII, this will cause problems
	// (Paul Brannan 6/28/98)
	if(current_map != 'B' && Charmap.enabled)
		Charmap.translate_buffer(pszBuffer, pszCurrent);    
	
	last_char = *(pszCurrent-1);    // TITUS++: Remember last char

	if(fast_write) {
		pszBuffer += Console.WriteStringFast(pszBuffer,
			pszCurrent - pszBuffer);
	} else {
		pszBuffer += Console.WriteString(pszBuffer,
			pszCurrent - pszBuffer);
	}

	return pszBuffer;
}

// Added by I.Ioannou 06 April, 1997
// Print the buffer until you reach ESC[4i
char* TANSIParser::PrintBuffer(char* pszBuffer, char* pszBufferEnd) {
	// Check if we have enough characters in buffer.
	if ((pszBufferEnd - pszBuffer) < 4)
		return pszBuffer;
	char *tmpChar;
	
	tmpChar = pszBuffer;
	if ( *tmpChar == 27 ) {
		tmpChar++;
		if ( *tmpChar == '[' ) {
			tmpChar++;
			if ( *tmpChar == '4' ) {
				tmpChar++;
				if ( *tmpChar == 'i' ) {
					InPrintMode = 0; // Stop Print Log
					if ( printfile != NULL )
						fclose(printfile);
					pszBuffer += 4;
					return pszBuffer;
				}
			}
		}
	}
	
	if (printfile != NULL) {
		fputc( *pszBuffer, printfile);
		pszBuffer++;
	} else
		InPrintMode = 0;
	
	return pszBuffer;
}

/* - PrintGoodChars( pszHead, pszTail ) - - - - - - - - - - - - - - - - - - -
-*

  Mark Miesfield 09/24/2000

  Prints the characters in a buffer, from the specified head to the specified
  tail, to standard out, skipping any control characters or ANSI escape
  sequences.

  Parameters on entry:
    pszHead  ->  Starting point in buffer.

    pszTail  ->  Ending point in buffer.

  Returns:
    Pointer to the first character in the buffer that was not output to
    standard out.  (Since no error checking is done, this is in effect
    pszTail.)

  Side Effects:
    None.
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
char * TANSIParser::PrintGoodChars( char * pszHead, char * pszTail )  {

  while ( pszHead < pszTail )  {
    if ( iscntrl( *pszHead ) )  {
      switch ( *(pszHead++) )  {
        case 10 :
          putc( 10, stdout );
          break;

        case 13 :
          putc( 13, stdout );
          break;

        case 27:
          switch ( *(pszHead++) )  {
            case 'Y':
              pszHead += 2;
              break;

            case '#':
            case '(':
            case ')':
            case '%': pszHead++; break;
            case '[':
              while ( (pszHead < pszTail) && (*pszHead < '?') )
                pszHead++;
              pszHead++;
              break;

            default :
              break;
          }
          break;

        default :
          break;
      }
    }
    else
      putc( *(pszHead++), stdout );
  }
  return ( pszTail );
}
// End of function:  PrintGoodChars( pszHead, pszTail )

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?