зеркало из https://github.com/mozilla/gecko-dev.git
1038 строки
32 KiB
C
1038 строки
32 KiB
C
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "MPL"); you may not use this file
|
|
* except in compliance with the MPL. You may obtain a copy of
|
|
* the MPL at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the MPL is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the MPL for the specific language governing
|
|
* rights and limitations under the MPL.
|
|
*
|
|
* The Original Code is lineterm.
|
|
*
|
|
* The Initial Developer of the Original Code is Ramalingam Saravanan.
|
|
* Portions created by Ramalingam Saravanan <svn@xmlterm.org> are
|
|
* Copyright (C) 1999 Ramalingam Saravanan. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License (the "GPL"), in which case
|
|
* the provisions of the GPL are applicable instead of
|
|
* those above. If you wish to allow use of your version of this
|
|
* file only under the terms of the GPL and not to allow
|
|
* others to use your version of this file under the MPL, indicate
|
|
* your decision by deleting the provisions above and replace them
|
|
* with the notice and other provisions required by the GPL.
|
|
* If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
|
|
/* ltermEscape.c: LTERM escape sequence processing
|
|
*/
|
|
|
|
/* public declarations */
|
|
#include "lineterm.h"
|
|
|
|
/* private declarations */
|
|
#include "ltermPrivate.h"
|
|
|
|
|
|
static int ltermProcessCSISequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style, int *consumed, int *opcodes);
|
|
static int ltermProcessDECPrivateMode(struct lterms *lts,
|
|
const int *paramValues, int paramCount, UNICHAR uch, int *opcodes);
|
|
static int ltermProcessXTERMSequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style,int *consumed,int *opcodes);
|
|
static int ltermProcessXMLTermSequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style,int *consumed,int *opcodes);
|
|
|
|
|
|
/** Processes ESCAPE sequence in string BUF containing COUNT characters,
|
|
* returning the number of characters CONSUMED and the OPCODES.
|
|
* Using Extended Backus-Naur Form notation:
|
|
* OPCODES ::= 0 if the sequence was processed without any change of
|
|
* outputMode or terminating condition.
|
|
* OPCODES ::= LINEDATA OUTPUT if a switch from LineMode to ScreenMode
|
|
* or StreamMode was triggered by the ESCAPE sqeuence.
|
|
* OPCODES ::= SCREENDATA OUTPUT if a switch from ScreenMode to StreamMode
|
|
* was triggered by the ESCAPE sequence.
|
|
* (A switch from ScreenMode to LineMode is not considered a terminating
|
|
* condition and occurs transparently.)
|
|
* OPCODES ::= SCREENDATA ( CLEAR
|
|
* | INSERT MOVEDOWN?
|
|
* | DELETE MOVEDOWN? )
|
|
* if the ESCAPE sequence corresponds to the ScreenMode terminal operation.
|
|
* OPCODES ::= LINEDATA CLEAR
|
|
* if the ESCAPE sequence corresponds to the LineMode terminal operation.
|
|
*
|
|
* @return 0 on successful processing of the ESCAPE sequence,
|
|
* 1 if BUF contains an incomplete ESCAPE sequence,
|
|
* -1 if error an error occurred.
|
|
*/
|
|
int ltermProcessEscape(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style, int *consumed, int *opcodes)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
|
|
LTERM_LOG(ltermProcessEscape,50,("count=%d, buf[1]='%c', cursorChar=%d, Chars=%d\n",
|
|
count, buf[1], lto->outputCursorChar, lto->outputChars));
|
|
|
|
if (count < 2) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (buf[1] == U_LBRACKET) {
|
|
/* ESC [ Process CSI sequence */
|
|
return ltermProcessCSISequence(lts, buf, count, style, consumed, opcodes);
|
|
}
|
|
|
|
if (buf[1] == U_RBRACKET) {
|
|
/* ESC ] Process XTERM sequence */
|
|
return ltermProcessXTERMSequence(lts, buf, count, style, consumed,opcodes);
|
|
}
|
|
|
|
if (buf[1] == U_LCURLY) {
|
|
/* ESC { Process XMLTerm sequence */
|
|
return ltermProcessXMLTermSequence(lts, buf, count, style, consumed,opcodes);
|
|
}
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
/* Assume two characters will be consumed at this point */
|
|
*consumed = 2;
|
|
|
|
switch (buf[1]) {
|
|
/* Three character sequences */
|
|
case U_NUMBER: /* ESC # 8 DEC Screen Alignment Test */
|
|
case U_LPAREN: /* ESC ( C Designate G0 Character Set */
|
|
case U_RPAREN: /* ESC ) C Designate G1 Character Set */
|
|
case U_STAR: /* ESC * C Designate G2 Character Set */
|
|
case U_PLUS: /* ESC + C Designate G3 Character Set */
|
|
case U_DOLLAR: /* ESC $ C Designate Kanji Character Set */
|
|
LTERM_LOG(ltermProcessEscape,51,("3 char sequence, buf[1:2]='%c%c'\n",
|
|
buf[1], buf[2]));
|
|
|
|
if (count < 3) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
*consumed = 3;
|
|
|
|
if (buf[1] == U_NUMBER) {
|
|
/* ESC # 8 DEC Screen Alignment Test */
|
|
} else {
|
|
/* ESC ()*+$ C Designate Character Set */
|
|
}
|
|
return 0;
|
|
|
|
/* Two character sequences */
|
|
case U_SEVEN: /* ESC 7 Save Cursor */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_EIGHT: /* ESC 8 Restore Cursor */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_EQUALS: /* ESC = Application Keypad */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_GREATERTHAN: /* ESC > Normal Keypad */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_D_CHAR: /* ESC D Index (IND) */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_E_CHAR: /* ESC E Next Line (NEL) */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_H_CHAR: /* ESC H Tab Set (HTS) */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_M_CHAR: /* ESC M Reverse Index (TI) */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_N_CHAR: /* ESC N Single Shift Select of G2 Character Set */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_O_CHAR: /* ESC O Single Shift Select of G3 Character Set */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_Z_CHAR: /* ESC Z Obsolete form of ESC[c */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_c_CHAR: /* ESC c Full reset (RIS) */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_n_CHAR: /* ESC n Invoke the G2 Character Set */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
case U_o_CHAR: /* ESC o Invoke the G3 Character Set */
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unimplemented %c\n",
|
|
buf[1]);
|
|
return 0;
|
|
|
|
default:
|
|
LTERM_WARNING("ltermProcessEscape: Warning - unknown sequence %x\n",
|
|
buf[1]);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/** Processes CSI sequence (a special case of Escape sequence processing)
|
|
* @return 0 on success and -1 on error.
|
|
*/
|
|
static int ltermProcessCSISequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style, int *consumed, int *opcodes)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
int offset, value, privateMode;
|
|
int paramCount, paramValues[MAXESCAPEPARAMS], param1, param2;
|
|
|
|
if (count < 3) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
LTERM_LOG(ltermProcessCSISequence,50,("buf[2]='%c', cursorChar=%d, Chars=%d\n",
|
|
buf[2], lto->outputCursorChar, lto->outputChars));
|
|
|
|
privateMode = 0;
|
|
offset = 2;
|
|
if (buf[2] == U_QUERYMARK) {
|
|
/* ESC [ ? Process DEC Private Mode */
|
|
privateMode = 1;
|
|
offset = 3;
|
|
}
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
/* Process numerical parameters */
|
|
paramCount = 0;
|
|
while ((offset < count) &&
|
|
((buf[offset] >= U_ZERO) && (buf[offset] <= U_NINE)) ) {
|
|
/* Starts with a digit */
|
|
value = buf[offset] - U_ZERO;
|
|
offset++;
|
|
|
|
/* Process all contiguous digits */
|
|
while ((offset < count) &&
|
|
((buf[offset] >= U_ZERO) && (buf[offset] <= U_NINE)) ) {
|
|
value = value * 10 + buf[offset] - U_ZERO;
|
|
offset++;
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (paramCount < MAXESCAPEPARAMS) {
|
|
/* Store numerical parameter */
|
|
paramValues[paramCount++] = value;
|
|
|
|
} else {
|
|
/* Numeric parameter buffer overflow */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - numeric parameter buffer overflow\n");
|
|
}
|
|
|
|
/* If next character not semicolon, stop processing */
|
|
if (buf[offset] != U_SEMICOLON)
|
|
break;
|
|
|
|
/* Process next argument */
|
|
offset++;
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
/* Assume that all parsed characters will be consumed at this point */
|
|
*consumed = offset+1;
|
|
|
|
LTERM_LOG(ltermProcessCSISequence,51,("paramCount=%d, offset=%d, buf[offset]='%d'\n",
|
|
paramCount, offset, buf[offset]));
|
|
|
|
if (privateMode) {
|
|
/* ESC [ ? Process DEC Private Mode */
|
|
return ltermProcessDECPrivateMode( lts, paramValues, paramCount,
|
|
buf[offset], opcodes);
|
|
}
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
/* Default parameter values: 1, 1 */
|
|
param1 = (paramCount > 0) ? paramValues[0] : 1;
|
|
param2 = (paramCount > 1) ? paramValues[1] : 1;
|
|
|
|
switch (buf[offset]) {
|
|
|
|
case U_ATSIGN: /* Insert Ps (Blank) Character(s) [default: 1] (ICH) */
|
|
if (ltermInsDelEraseChar(lts, param1, LTERM_INSERT_CHAR) != 0)
|
|
return -1;
|
|
return 0;
|
|
|
|
case U_e_CHAR:
|
|
case U_A_CHAR: /* Cursor Up Ps Times [default: 1] (CUU) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_B_CHAR: /* Cursor Down Ps Times [default: 1] (CUD) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_a_CHAR:
|
|
case U_C_CHAR: /* Cursor Forward Ps Times [default: 1] (CUF) */
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Cursor Forward Count = %d\n",
|
|
param1));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
|
|
if (param1 <= (lto->outputChars - lto->outputCursorChar)) {
|
|
lto->outputCursorChar += param1;
|
|
} else {
|
|
lto->outputCursorChar = lto->outputChars;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case U_D_CHAR: /* Cursor Backward Ps Times [default: 1] (CUB) */
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Cursor Back Count = %d\n",
|
|
param1));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
|
|
if (param1 <= lto->outputCursorChar) {
|
|
lto->outputCursorChar -= param1;
|
|
} else {
|
|
lto->outputCursorChar = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case U_E_CHAR: /* Cursor Down Ps Times [default: 1] and to first column */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_F_CHAR: /* Cursor Up Ps Times [default: 1] and to first column */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_SNGLQUOTE:
|
|
case U_G_CHAR: /* Cursor to Column Ps (HPA) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_H_CHAR: /* Cursor Position [row;column] [default: 1;1] (CUP) */
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Cursor Position = (%d, %d)\n",
|
|
param1, param2));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
|
|
if ((param1 > 0) && ((param1-1) <= lto->outputChars)) {
|
|
lto->outputCursorChar = param1-1;
|
|
} else {
|
|
lto->outputCursorChar = 0;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case U_I_CHAR: /* Move forward Ps tab stops [default: 1] */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_J_CHAR: /* Erase in Display (ED)
|
|
* Ps = 0 Clear Below (default)
|
|
* Ps = 1 Clear Above
|
|
* Ps = 2 Clear All
|
|
*/
|
|
param1 = (paramCount > 0) ? paramValues[0] : 0;
|
|
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Erase display code %d\n",
|
|
param1));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
/* Clear line */
|
|
ltermClearOutputLine(lts);
|
|
|
|
/* Set opcodes to return incomplete line */
|
|
*opcodes = LTERM_LINEDATA_CODE|LTERM_CLEAR_CODE;
|
|
}
|
|
return 0;
|
|
|
|
case U_K_CHAR: /* Erase in Line (EL)
|
|
* Ps = 0 Clear to Right (default)
|
|
* Ps = 1 Clear to Left
|
|
* Ps = 2 Clear All
|
|
*/
|
|
param1 = (paramCount > 0) ? paramValues[0] : 0;
|
|
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Line erase code %d\n",
|
|
param1));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
|
|
switch(param1) {
|
|
case 0: /* Clear to Right */
|
|
lto->outputChars = lto->outputCursorChar;
|
|
lto->outputModifiedChar = lto->outputCursorChar;
|
|
break;
|
|
case 1: /* Clear to Left */
|
|
lto->outputChars -= lto->outputCursorChar;
|
|
lto->outputCursorChar = 0;
|
|
lto->outputModifiedChar = 0;
|
|
break;
|
|
case 2: /* Clear All */
|
|
lto->outputChars = 0;
|
|
lto->outputCursorChar = 0;
|
|
lto->outputModifiedChar = 0;
|
|
break;
|
|
default: /* Invalid erase code */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - invalid erase code %d\n", param1);
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
|
|
case U_L_CHAR: /* Insert Ps Line(s) [default: 1] (IL) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_M_CHAR: /* Delete Ps Line(s) [default: 1] (DL) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_P_CHAR: /* Delete Ps Character(s) [default: 1] (DCH) */
|
|
if (ltermInsDelEraseChar(lts, param1, LTERM_DELETE_CHAR) != 0)
|
|
return -1;
|
|
return 0;
|
|
|
|
case U_T_CHAR: /* Initiate hilite mouse tracking. Parameters
|
|
* [func;startx;starty;firstrow;lastrow].
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_W_CHAR: /* Tabulator functions:
|
|
* Ps = 0 Tab Set (HTS)
|
|
* Ps = 2 Tab Clear (TBC), Clear Current Column (default)
|
|
* Ps = 5 Tab Clear (TBC), Clear All
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_X_CHAR: /* Erase Ps Character(s) [default: 1] (ECH) */
|
|
if (ltermInsDelEraseChar(lts, param1, LTERM_ERASE_CHAR) != 0)
|
|
return -1;
|
|
return 0;
|
|
|
|
case U_Z_CHAR: /* Move backward Ps [default: 1] tab stops */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_c_CHAR: /* Send Device Attributes (DA)
|
|
* Ps = 0 (or omitted) : request attributes from terminal
|
|
* returns: ESC[?1;2c
|
|
* (``I am a VT100 with Advanced Video Option'')
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_d_CHAR: /* Cursor to Line Ps (VPA) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_f_CHAR: /* Horizontal and Vertical Position [row;column] (HVP)
|
|
* [default: 1;1]
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_g_CHAR: /* Tab Clear (TBC)
|
|
* Ps = 0 Clear Current Column (default)
|
|
* Ps = 3 Clear All (TBC)
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_i_CHAR: /* Printing
|
|
* Ps = 4 disable transparent print mode (MC4)
|
|
* Ps = 5 enable transparent print mode (MC5)
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_h_CHAR: /* Set Mode (SM)
|
|
* Ps = 4 Insert Mode (SMIR)
|
|
* Ps = 20 Automatic Newline (LNM)
|
|
*/
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Set Mode %d\n",
|
|
param1));
|
|
|
|
if (param1 == 4) {
|
|
lto->insertMode = 1;
|
|
} else if (param1 == 4) {
|
|
lto->automaticNewline = 1;
|
|
}
|
|
return 0;
|
|
|
|
case U_l_CHAR: /* Reset Mode (RM)
|
|
* Ps = 4 Replace Mode (RMIR)
|
|
* Ps = 20 Normal Linefeed (LNM)
|
|
*/
|
|
LTERM_LOG(ltermProcessCSISequence,52,("Reset Mode %d\n",
|
|
param1));
|
|
|
|
if (param1 == 4) {
|
|
lto->insertMode = 0;
|
|
} else if (param1 == 4) {
|
|
lto->automaticNewline = 0;
|
|
}
|
|
return 0;
|
|
|
|
case U_m_CHAR: /* Character Attributes (SGR)
|
|
* Ps = 0 Normal (default)
|
|
* Ps = 1 / 22 On / Off Bold (bright fg)
|
|
* Ps = 4 / 24 On / Off Underline
|
|
* Ps = 5 / 25 On / Off Blink (bright bg)
|
|
* Ps = 7 / 27 On / Off Inverse
|
|
* Ps = 30 / 40 fg/bg Black
|
|
* Ps = 31 / 41 fg/bg Red
|
|
* Ps = 32 / 42 fg/bg Green
|
|
* Ps = 33 / 43 fg/bg Yellow
|
|
* Ps = 34 / 44 fg/bg Blue
|
|
* Ps = 35 / 45 fg/bg Magenta
|
|
* Ps = 36 / 46 fg/bg Cyan
|
|
* Ps = 37 / 47 fg/bg White
|
|
* Ps = 39 / 49 fg/bg Default
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_n_CHAR: /* Device Status Report (DSR)
|
|
* Ps = 5 Status Report ESC [ 0 n (``OK'')
|
|
* Ps = 6 Report Cursor Position (CPR) [row;column]
|
|
* as ESC [ r ; c R
|
|
* Ps = 7 Request Display Name
|
|
* Ps = 8 Request Version Number (place in window title)
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_r_CHAR: /* Set Scrolling Region [top;bottom]
|
|
* [default: full size of window] (CSR)
|
|
*/
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
case U_x_CHAR: /* Request Terminal Parameters (DECREQTPARM) */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
return 0;
|
|
|
|
default: /* Unknown Escape sequence */
|
|
LTERM_WARNING("ltermProcessCSISequence: Warning - unknown sequence %x\n",
|
|
buf[offset]);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/** Processes DEC Private Modes (a special case of CSI sequence processing)
|
|
* ESC [ ? Pm h
|
|
* @return 0 on success and -1 on error.
|
|
*/
|
|
static int ltermProcessDECPrivateMode(struct lterms *lts,
|
|
const int *paramValues, int paramCount, UNICHAR uch, int *opcodes)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
|
|
LTERM_LOG(ltermProcessDECPrivateMode,50,("ch='%c', cursorChar=%d, Chars=%d\n",
|
|
(char) uch, lto->outputCursorChar, lto->outputChars));
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
switch (uch) {
|
|
case U_h_CHAR: /* DEC Private Mode Set (DECSET) */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unimplemented %c\n",
|
|
(char) uch);
|
|
return 0;
|
|
|
|
case U_l_CHAR: /* DEC Private Mode Reset (DECRST) */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unimplemented %c\n",
|
|
(char) uch);
|
|
return 0;
|
|
|
|
case U_r_CHAR: /* Restore previously saved DEC Private Mode Values */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unimplemented %c\n",
|
|
(char) uch);
|
|
return 0;
|
|
|
|
case U_s_CHAR: /* Save DEC Private Mode Values */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unimplemented %c\n",
|
|
(char) uch);
|
|
return 0;
|
|
|
|
case U_t_CHAR: /* Toggle DEC Private Mode Values */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unimplemented %c\n",
|
|
(char) uch);
|
|
return 0;
|
|
|
|
default: /* Unknown escape sequence */
|
|
LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unknown sequence %x\n",
|
|
uch);
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/** Processes XTERM sequence (a special case of Escape sequence processing)
|
|
* ESC ] Ps;Pt BEL
|
|
* @return 0 on success and -1 on error.
|
|
*/
|
|
static int ltermProcessXTERMSequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style,int *consumed,int *opcodes)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
int offset, paramValue, strLength;
|
|
UNICHAR paramString[MAXSTRINGPARAM+1];
|
|
|
|
if (count < 3) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
LTERM_LOG(ltermProcessXTERMSequence,50,("cursorChar=%d, Chars=%d\n",
|
|
lto->outputCursorChar, lto->outputChars));
|
|
|
|
offset = 2;
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
/* Process numerical parameter */
|
|
paramValue = 0;
|
|
while ((offset < count) &&
|
|
((buf[offset] >= U_ZERO) && (buf[offset] <= U_NINE)) ) {
|
|
paramValue = paramValue * 10 + buf[offset] - U_ZERO;
|
|
offset++;
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (buf[offset] != U_SEMICOLON) {
|
|
/* If next character not semicolon, return */
|
|
*consumed = offset;
|
|
return 0;
|
|
}
|
|
|
|
LTERM_LOG(ltermProcessXTERMSequence,51,("paramValue=%d, offset=%d, buf[offset]=%x\n",
|
|
paramValue, offset, buf[offset]));
|
|
|
|
/* Skip the semicolon */
|
|
offset++;
|
|
|
|
/* Process string parameter */
|
|
strLength = 0;
|
|
while ((offset < count) && (buf[offset] != U_BEL)) {
|
|
if (strLength < MAXSTRINGPARAM) {
|
|
paramString[strLength++] = buf[offset];
|
|
offset++;
|
|
|
|
} else {
|
|
LTERM_WARNING("ltermProcessXTERMSequence: Warning - string parameter too long; truncated\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
/* Insert terminating NULL character in string */
|
|
paramString[strLength] = U_NUL;
|
|
|
|
LTERM_LOGUNICODE(ltermProcessXTERMSequence,52,(paramString, strLength));
|
|
|
|
/* All parsed characters have been consumed at this point */
|
|
*consumed = offset+1;
|
|
|
|
LTERM_WARNING("ltermProcessXTERMSequence: Warning - unimplemented %c\n",
|
|
buf[offset]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** Processes XMLTerm sequence (a special case of Escape sequence processing)
|
|
* XMLterm escape sequences are of the form
|
|
* ESC { Pm C Pt BEL
|
|
* where Pm denotes multiple numeric arguments separated by semicolons,
|
|
* character C is a not a digit and not a semicolon, and
|
|
* text parameter Pt may be a null string.
|
|
* Omitted numeric parameters are assumed to be zero.
|
|
* @return 0 on success and -1 on error.
|
|
*/
|
|
static int ltermProcessXMLTermSequence(struct lterms *lts, const UNICHAR *buf,
|
|
int count, const UNISTYLE *style,int *consumed,int *opcodes)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
int offset, value, strLength;
|
|
int paramCount, paramValues[MAXESCAPEPARAMS], param1, param2, param3;
|
|
UNICHAR termChar, paramString[MAXSTRINGPARAM+1];
|
|
char paramCString[MAXSTRINGPARAM+1];
|
|
|
|
if (count < 4) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,50,("cursorChar=%d, Chars=%d\n",
|
|
lto->outputCursorChar, lto->outputChars));
|
|
|
|
offset = 2;
|
|
|
|
/* Set returned opcodes to zero */
|
|
*opcodes = 0;
|
|
|
|
/* Process numerical parameters */
|
|
paramCount = 0;
|
|
while ((offset < count) &&
|
|
((buf[offset] >= U_ZERO) && (buf[offset] <= U_NINE)) ) {
|
|
/* Starts with a digit */
|
|
value = buf[offset] - U_ZERO;
|
|
offset++;
|
|
|
|
/* Process all contiguous digits */
|
|
while ((offset < count) &&
|
|
((buf[offset] >= U_ZERO) && (buf[offset] <= U_NINE)) ) {
|
|
value = value * 10 + buf[offset] - U_ZERO;
|
|
offset++;
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (paramCount < MAXESCAPEPARAMS) {
|
|
/* Store numerical parameter */
|
|
paramValues[paramCount++] = value;
|
|
|
|
} else {
|
|
/* Numeric parameter buffer overflow */
|
|
LTERM_WARNING("ltermProcessXMLTermSequence: Warning - numeric parameter buffer overflow\n");
|
|
}
|
|
|
|
/* If next character not semicolon, stop processing */
|
|
if (buf[offset] != U_SEMICOLON)
|
|
break;
|
|
|
|
/* Process next argument */
|
|
offset++;
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
/* Terminating character */
|
|
termChar = buf[offset];
|
|
|
|
/* Skip terminating character */
|
|
offset++;
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,51,("paramCount=%d, offset=%d, termChar=%x\n",
|
|
paramCount, offset, termChar));
|
|
|
|
/* Process string parameter */
|
|
strLength = 0;
|
|
while ((offset < count) && (buf[offset] != U_BEL)) {
|
|
if (strLength < MAXSTRINGPARAM) {
|
|
paramCString[strLength] = buf[offset];
|
|
paramString[strLength++] = buf[offset];
|
|
offset++;
|
|
|
|
} else {
|
|
LTERM_WARNING("ltermProcessXMLTermSequence: Warning - string parameter too long; truncated\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (offset == count) {
|
|
/* Incomplete Escape sequence */
|
|
*consumed = 0;
|
|
return 1;
|
|
}
|
|
|
|
/* Insert terminating NULL character in string */
|
|
paramCString[strLength] = U_NUL;
|
|
paramString[strLength] = U_NUL;
|
|
|
|
LTERM_LOGUNICODE(ltermProcessXMLTermSequence,52,(paramString, strLength));
|
|
|
|
/* All parsed characters have been consumed at this point (including BEL) */
|
|
*consumed = offset+1;
|
|
|
|
/* Default parameter values: 0, 0, 0 */
|
|
param1 = (paramCount > 0) ? paramValues[0] : 0;
|
|
param2 = (paramCount > 1) ? paramValues[1] : 0;
|
|
param3 = (paramCount > 2) ? paramValues[2] : 0;
|
|
|
|
switch (termChar) {
|
|
int streamOpcodes;
|
|
|
|
case U_D_CHAR: /* Set debugging messageLevel/search-string */
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,("Setting message level etc.\n"));
|
|
if (strLength == 0) {
|
|
tlog_set_level(param1, param2, NULL);
|
|
} else {
|
|
tlog_set_level(param1, param2, paramCString);
|
|
}
|
|
return 0;
|
|
|
|
case U_E_CHAR: /* Enable/disable input echo setting */
|
|
if (param1) {
|
|
/* Enable input echo */
|
|
lts->disabledInputEcho = 0;
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,("Enabled input echo\n"));
|
|
} else {
|
|
/* Disable input echo */
|
|
lts->disabledInputEcho = 1;
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,("Disabled input echo\n"));
|
|
}
|
|
return 0;
|
|
|
|
case U_R_CHAR: /* Enable/disable raw input mode */
|
|
if (param1) {
|
|
/* Switch to raw input mode */
|
|
ltermSwitchToRawMode(lts);
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,("Raw input mode\n"));
|
|
|
|
} else {
|
|
/* Switch to regular input mode */
|
|
ltermClearInputLine(lts);
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,("Line input mode\n"));
|
|
}
|
|
return 0;
|
|
|
|
case U_J_CHAR: /* Switch to null-terminated Javascript stream mode */
|
|
case U_S_CHAR: /* Switch to null-terminated stream mode, with cookie */
|
|
|
|
if (lto->outputMode == LTERM1_SCREEN_MODE) {
|
|
*opcodes = LTERM_SCREENDATA_CODE | LTERM_OUTPUT_CODE;
|
|
} else if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
*opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
|
|
}
|
|
|
|
assert(lto->outputMode != LTERM0_STREAM_MODE);
|
|
|
|
/* Set stream codes */
|
|
streamOpcodes = 0;
|
|
|
|
if (termChar == U_J_CHAR) {
|
|
/* Javascript stream */
|
|
streamOpcodes |= LTERM_JSSTREAM_CODE;
|
|
|
|
} else {
|
|
/* HTML/XML stream */
|
|
if (param1)
|
|
streamOpcodes |= LTERM_DOCSTREAM_CODE;
|
|
|
|
if (param2)
|
|
streamOpcodes |= LTERM_XMLSTREAM_CODE;
|
|
|
|
if (param3)
|
|
streamOpcodes |= LTERM_WINSTREAM_CODE;
|
|
}
|
|
|
|
/* Check if cookie matches */
|
|
if ((strLength > 0) && (strcmp(paramCString, lts->cookie) == 0)) {
|
|
streamOpcodes |= LTERM_COOKIESTR_CODE;
|
|
}
|
|
|
|
LTERM_LOG(ltermProcessXMLTermSequence,52,
|
|
("Switching to stream mode, codes=0x%x\n", streamOpcodes));
|
|
|
|
if (0 != ltermSwitchToStreamMode(lts, streamOpcodes, NULL))
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
default: /* Unknown escape sequence */
|
|
LTERM_WARNING("ltermProcessXMLTermSequence: Warning - unknown sequence %c\n",
|
|
termChar);
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/** Insert/delete/erase COUNT characters at current output cursor position.
|
|
* ACTION = LTERM_INSERT_CHAR (insert)
|
|
* LTERM_DELETE_CHAR (delete)
|
|
* LTERM_ERASE_CHAR (erase)
|
|
* @return 0 on success and -1 on error.
|
|
*/
|
|
int ltermInsDelEraseChar(struct lterms *lts, int count, int action)
|
|
{
|
|
struct LtermOutput *lto = &(lts->ltermOutput);
|
|
int charCount = count;
|
|
int j;
|
|
|
|
assert(count >= 0);
|
|
|
|
LTERM_LOG(ltermInsDelEraseChar,60,("count=%d, action=%d\n",
|
|
count, action));
|
|
|
|
if (lto->outputMode == LTERM2_LINE_MODE) {
|
|
/* Line mode */
|
|
switch (action) {
|
|
|
|
case LTERM_INSERT_CHAR:
|
|
|
|
if (lto->outputChars + charCount > MAXCOLM1) {
|
|
/* Output buffer overflow; ignore extra inserts */
|
|
LTERM_WARNING("ltermInsDelEraseChar: Warning - output line buffer overflow\n");
|
|
charCount = MAXCOLM1 - lto->outputChars;
|
|
}
|
|
|
|
LTERM_LOG(ltermInsDelEraseChar,62,("Line insert %d blank chars\n",
|
|
charCount));
|
|
|
|
/* Shift characters to the right to make room for insertion */
|
|
for (j=lto->outputChars-1; j>=lto->outputCursorChar; j--) {
|
|
lto->outputLine[j+charCount] = lto->outputLine[j];
|
|
lto->outputStyle[j+charCount] = lto->outputStyle[j];
|
|
}
|
|
|
|
/* Insert blank characters */
|
|
for (j=lto->outputCursorChar; j<lto->outputCursorChar+charCount; j++) {
|
|
lto->outputLine[j] = U_SPACE;
|
|
lto->outputStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
|
|
}
|
|
|
|
/* Increment character count */
|
|
lto->outputChars += charCount;
|
|
break;
|
|
|
|
case LTERM_DELETE_CHAR:
|
|
if (lto->outputCursorChar+charCount > lto->outputChars)
|
|
charCount = lto->outputChars - lto->outputCursorChar;
|
|
|
|
LTERM_LOG(ltermInsDelEraseChar,62,("Delete %d chars\n",
|
|
charCount));
|
|
|
|
/* Shift characters to the left */
|
|
for (j=lto->outputCursorChar; j<lto->outputChars-charCount; j++) {
|
|
lto->outputLine[j] = lto->outputLine[j+charCount];
|
|
lto->outputStyle[j] = lto->outputStyle[j+charCount];
|
|
}
|
|
|
|
/* Decrement character count */
|
|
lto->outputChars -= charCount;
|
|
break;
|
|
|
|
case LTERM_ERASE_CHAR:
|
|
if (lto->outputCursorChar+charCount > lto->outputChars)
|
|
charCount = lto->outputChars - lto->outputCursorChar;
|
|
|
|
LTERM_LOG(ltermInsDelEraseChar,62,("Erase %d chars\n",
|
|
charCount));
|
|
|
|
/* Erase characters */
|
|
for (j=lto->outputCursorChar; j<lto->outputCursorChar+charCount; j++) {
|
|
lto->outputLine[j] = U_SPACE;
|
|
lto->outputStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* Note modifications */
|
|
if (lto->outputCursorChar < lto->outputModifiedChar)
|
|
lto->outputModifiedChar = lto->outputCursorChar;
|
|
|
|
} else if (lto->outputMode == LTERM1_SCREEN_MODE) {
|
|
/* Screen mode */
|
|
}
|
|
|
|
return 0;
|
|
}
|