Back to index

lightning-sunbird  0.9+nobinonly
ltermEscape.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is lineterm.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Ramalingam Saravanan.
00018  * Portions created by the Initial Developer are Copyright (C) 1999
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /* ltermEscape.c: LTERM escape sequence processing
00038  */
00039 
00040 /* public declarations */
00041 #include "lineterm.h"
00042 
00043 /* private declarations */
00044 #include "ltermPrivate.h"
00045 
00046 
00047 static int ltermProcessCSISequence(struct lterms *lts, const UNICHAR *buf,
00048                                    int count, const UNISTYLE *style,
00049                                    int *consumed, int *opcodes,
00050                                    int *opvals, int *oprow);
00051 static int ltermProcessDECPrivateMode(struct lterms *lts,
00052             const int *paramValues, int paramCount, UNICHAR uch, int *opcodes);
00053 static int ltermProcessXTERMSequence(struct lterms *lts, const UNICHAR *buf,
00054                   int count, const UNISTYLE *style,int *consumed,int *opcodes);
00055 static int ltermProcessXMLTermSequence(struct lterms *lts, const UNICHAR *buf,
00056                   int count, const UNISTYLE *style,int *consumed,int *opcodes);
00057 
00058 
00085 int ltermProcessEscape(struct lterms *lts, const UNICHAR *buf,
00086                        int count, const UNISTYLE *style, int *consumed,
00087                        int *opcodes, int *opvals, int *oprow)
00088 {
00089   struct LtermOutput *lto = &(lts->ltermOutput);
00090 
00091   LTERM_LOG(ltermProcessEscape,50,("count=%d, buf[1]=0x%x, cursorChar=%d, Chars=%d\n",
00092                 count, buf[1], lto->outputCursorChar, lto->outputChars));
00093 
00094   if (count < 2) {
00095     /* Incomplete Escape sequence */
00096     *consumed = 0;
00097     return 1;
00098   }
00099 
00100   if (buf[1] == U_LBRACKET) {
00101     /* ESC [ Process CSI sequence */
00102     return ltermProcessCSISequence(lts, buf, count, style, consumed,
00103                                    opcodes, opvals, oprow);
00104   }
00105 
00106   if (buf[1] == U_RBRACKET) {
00107     /* ESC ] Process XTERM sequence */
00108     return ltermProcessXTERMSequence(lts, buf, count, style, consumed,
00109                                      opcodes);
00110   }
00111 
00112   if (buf[1] == U_LCURLY) {
00113     /* ESC { Process XMLTerm sequence */
00114     return ltermProcessXMLTermSequence(lts, buf, count, style, consumed,
00115                                        opcodes);
00116   }
00117 
00118   /* Assume two characters will be consumed at this point */
00119   *consumed = 2;
00120 
00121   switch (buf[1]) {
00122 
00123   /* Three character sequences */
00124   case U_NUMBER:            /* ESC # 8 DEC Screen Alignment Test */
00125   case U_LPAREN:            /* ESC ( C Designate G0 Character Set */
00126   case U_RPAREN:            /* ESC ) C Designate G1 Character Set */
00127   case U_STAR:              /* ESC * C Designate G2 Character Set */
00128   case U_PLUS:              /* ESC + C Designate G3 Character Set */
00129   case U_DOLLAR:            /* ESC $ C Designate Kanji Character Set */
00130     LTERM_LOG(ltermProcessEscape,51,("3 char sequence, buf[1:2]=0x%x,0x%x\n",
00131                   buf[1], buf[2]));
00132 
00133     if (count < 3) {
00134       /* Incomplete Escape sequence */
00135       *consumed = 0;
00136       return 1;
00137     }
00138     *consumed = 3;
00139 
00140     if (buf[1] == U_NUMBER) {
00141       /* ESC # 8 DEC Screen Alignment Test */
00142     } else {
00143       /* ESC ()*+$ C Designate Character Set */
00144     }
00145     return 0;
00146 
00147   /* Two character sequences */
00148   case U_SEVEN:             /* ESC 7 Save Cursor */
00149     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00150     return 0;
00151 
00152   case U_EIGHT:             /* ESC 8 Restore Cursor */
00153     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00154     return 0;
00155 
00156   case U_EQUALS:            /* ESC = Application Keypad */
00157     LTERM_LOG(ltermProcessEscape,52,("Application Keypad\n"));
00158     if (lto->outputMode == LTERM2_LINE_MODE) {
00159       ltermSwitchToScreenMode(lts);
00160       *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
00161     }
00162     return 0;
00163 
00164   case U_GREATERTHAN:       /* ESC > Normal Keypad */
00165     LTERM_LOG(ltermProcessEscape,52,("Normal Keypad\n"));
00166     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00167       ltermSwitchToLineMode(lts);
00168       *opcodes = LTERM_SCREENDATA_CODE | LTERM_CLEAR_CODE;
00169     }
00170     return 0;
00171 
00172   case U_D_CHAR:            /* ESC D Index (IND) */
00173     LTERM_LOG(ltermProcessEscape,52,("Index\n"));
00174     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00175       /* Scroll up */
00176       if (ltermInsDelEraseLine(lts, 1, lto->topScrollRow, LTERM_DELETE_ACTION) != 0)
00177         return -1;
00178       *opcodes = LTERM_SCREENDATA_CODE | LTERM_DELETE_CODE;
00179       *opvals = 1;
00180       *oprow = lto->topScrollRow;
00181     }
00182     return 0;
00183 
00184   case U_E_CHAR:            /* ESC E Next Line (NEL) */
00185     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00186       if (lto->cursorRow > 0)
00187         lto->cursorRow--;
00188     }
00189     return 0;
00190 
00191   case U_H_CHAR:            /* ESC H Tab Set (HTS) */
00192     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00193     return 0;
00194 
00195   case U_M_CHAR:            /* ESC M Reverse Index (TI) */
00196     LTERM_LOG(ltermProcessEscape,52,("Reverse Index\n"));
00197     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00198       /* Scroll down */
00199       if (ltermInsDelEraseLine(lts, 1, lto->topScrollRow, LTERM_INSERT_ACTION) != 0)
00200         return -1;
00201       *opcodes = LTERM_SCREENDATA_CODE | LTERM_INSERT_CODE;
00202       *opvals = 1;
00203       *oprow = lto->topScrollRow;
00204     }
00205     return 0;
00206 
00207   case U_N_CHAR:            /* ESC N Single Shift Select of G2 Character Set */
00208     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00209     return 0;
00210 
00211   case U_O_CHAR:            /* ESC O Single Shift Select of G3 Character Set */
00212     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00213     return 0;
00214 
00215   case U_Z_CHAR:            /* ESC Z Obsolete form of ESC[c */
00216     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00217     return 0;
00218 
00219   case U_c_CHAR:            /* ESC c Full reset (RIS)  */
00220     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00221     return 0;
00222 
00223   case U_n_CHAR:            /* ESC n Invoke the G2 Character Set  */
00224     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00225     return 0;
00226 
00227   case U_o_CHAR:            /* ESC o Invoke the G3 Character Set */
00228     LTERM_LOG(ltermProcessEscape,2,("Unimplemented 0x%x\n", buf[1]));
00229     return 0;
00230 
00231   default:
00232     LTERM_WARNING("ltermProcessEscape: Warning - unknown sequence 0x%x\n",
00233                   buf[1]);
00234     return 0;
00235   }
00236 }
00237 
00238 
00242 static int ltermProcessCSISequence(struct lterms *lts, const UNICHAR *buf,
00243                                    int count, const UNISTYLE *style,
00244                                    int *consumed, int *opcodes,
00245                                    int *opvals, int *oprow)
00246 {
00247   struct LtermOutput *lto = &(lts->ltermOutput);
00248   int offset, value, privateMode;
00249   int paramCount, paramValues[MAXESCAPEPARAMS], param1, param2;
00250 
00251   if (count < 3) {
00252     /* Incomplete Escape sequence */
00253     *consumed = 0;
00254     return 1;
00255   }
00256 
00257   LTERM_LOG(ltermProcessCSISequence,50,("buf[2]=0x%x, cursorChar=%d, Chars=%d\n",
00258                 buf[2], lto->outputCursorChar, lto->outputChars));
00259 
00260   privateMode = 0;
00261   offset = 2;
00262   if (buf[2] == U_QUERYMARK) {
00263     /* ESC [ ? Process DEC Private Mode */
00264     privateMode = 1;
00265     offset = 3;
00266   }
00267 
00268   /* Process numerical parameters */
00269   paramCount = 0;
00270   while ((offset < count) &&
00271          ((buf[offset] >= (UNICHAR)U_ZERO) &&
00272           (buf[offset] <= (UNICHAR)U_NINE)) ) {
00273     /* Starts with a digit */
00274     value = buf[offset] - U_ZERO;
00275     offset++;
00276 
00277     /* Process all contiguous digits */
00278     while ((offset < count) &&
00279        ((buf[offset] >= (UNICHAR)U_ZERO) &&
00280         (buf[offset] <= (UNICHAR)U_NINE)) ) {
00281       value = value * 10 + buf[offset] - U_ZERO;
00282       offset++;
00283     }
00284 
00285     if (offset == count) {
00286       /* Incomplete Escape sequence */
00287       *consumed = 0;
00288       return 1;
00289     }
00290 
00291     if (paramCount < MAXESCAPEPARAMS) {
00292       /* Store numerical parameter */
00293       paramValues[paramCount++] = value;
00294 
00295     } else {
00296       /* Numeric parameter buffer overflow */
00297       LTERM_WARNING("ltermProcessCSISequence: Warning - numeric parameter buffer overflow\n");
00298     }
00299 
00300     /* If next character not semicolon, stop processing */
00301     if (buf[offset] != U_SEMICOLON)
00302       break;
00303 
00304     /* Process next argument */
00305     offset++;
00306   }
00307 
00308   if (offset == count) {
00309     /* Incomplete Escape sequence */
00310     *consumed = 0;
00311     return 1;
00312   }
00313 
00314   /* Assume that all parsed characters will be consumed at this point */
00315   *consumed = offset+1;
00316 
00317   LTERM_LOG(ltermProcessCSISequence,51,("paramCount=%d, offset=%d, buf[offset]='%d'\n",
00318                  paramCount, offset, buf[offset]));
00319 
00320   if (privateMode) {
00321     /* ESC [ ? Process DEC Private Mode */
00322     return ltermProcessDECPrivateMode( lts, paramValues, paramCount,
00323                                        buf[offset], opcodes);
00324   }
00325 
00326   /* Set returned opcodes to zero */
00327   *opcodes = 0;
00328 
00329   /* Default parameter values: 1, 1 */
00330   param1 = (paramCount > 0) ? paramValues[0] : 1;
00331   param2 = (paramCount > 1) ? paramValues[1] : 1;
00332 
00333   switch (buf[offset]) {
00334 
00335   case U_ATSIGN:    /* Insert Ps (Blank) Character(s) [default: 1] (ICH) */
00336     if (ltermInsDelEraseChar(lts, param1, LTERM_INSERT_ACTION) != 0)
00337       return -1;
00338     return 0;
00339 
00340   case U_e_CHAR:
00341   case U_A_CHAR:    /* Cursor Up Ps Times [default: 1] (CUU) */
00342     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Up Count = %d\n", param1));
00343 
00344     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00345       lto->cursorRow += param1;
00346       if (lto->cursorRow >= lts->nRows)
00347         lto->cursorRow = lts->nRows - 1;
00348     }
00349     return 0;
00350 
00351   case U_B_CHAR:    /* Cursor Down Ps Times [default: 1] (CUD) */
00352     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Down Count = %d\n", param1));
00353 
00354     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00355       lto->cursorRow -= param1;
00356       if (lto->cursorRow < 0)
00357         lto->cursorRow = 0;
00358     }
00359     return 0;
00360 
00361   case U_a_CHAR:
00362   case U_C_CHAR:    /* Cursor Forward Ps Times [default: 1] (CUF) */
00363     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Forward Count = %d\n",
00364                    param1));
00365 
00366     if (lto->outputMode == LTERM2_LINE_MODE) {
00367 
00368       if (param1 <= (lto->outputChars - lto->outputCursorChar)) {
00369         lto->outputCursorChar += param1;
00370       } else {
00371         lto->outputCursorChar = lto->outputChars;
00372       }
00373 
00374     } else {
00375       lto->cursorCol += param1;
00376       if (lto->cursorCol >= lts->nCols)
00377         lto->cursorCol = lts->nCols-1;
00378     }
00379     return 0;
00380 
00381   case U_D_CHAR:    /* Cursor Backward Ps Times [default: 1] (CUB) */
00382     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Back Count = %d\n", param1));
00383 
00384     if (lto->outputMode == LTERM2_LINE_MODE) {
00385 
00386       if (param1 <= lto->outputCursorChar) {
00387         lto->outputCursorChar -= param1;
00388       } else {
00389         lto->outputCursorChar = 0;
00390       }
00391 
00392     } else {
00393       lto->cursorCol -= param1;
00394       if (lto->cursorCol < 0)
00395         lto->cursorCol = 0;
00396     }
00397     return 0;
00398 
00399   case U_E_CHAR:    /* Cursor Down Ps Times [default: 1] and to first column */
00400     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Down and First Count = %d\n",
00401                    param1));
00402 
00403     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00404       lto->cursorCol = 0;
00405       lto->cursorRow -= param1;
00406       if (lto->cursorRow < 0)
00407         lto->cursorRow = 0;
00408     }
00409     return 0;
00410 
00411   case U_F_CHAR:    /* Cursor Up Ps Times [default: 1] and to first column */
00412     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Up and First Count = %d\n",
00413                    param1));
00414 
00415     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00416       lto->cursorCol = 0;
00417       lto->cursorRow += param1;
00418       if (lto->cursorRow >= lts->nRows)
00419         lto->cursorRow = lts->nRows - 1;
00420     }
00421     return 0;
00422 
00423   case U_SNGLQUOTE:
00424   case U_G_CHAR:    /* Cursor to Column Ps (HPA) */
00425     LTERM_LOG(ltermProcessCSISequence,52,("Cursor to Column = %d\n", param1));
00426 
00427     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00428       lto->cursorCol = param1-1;
00429       if (lto->cursorCol < 0) {
00430         lto->cursorCol = 0;
00431       } else if (lto->cursorCol >= lts->nCols) {
00432         lto->cursorCol = lts->nCols - 1;
00433       }
00434     }
00435     return 0;
00436 
00437   case U_H_CHAR:    /* Cursor Position [row;column] [default: 1;1] (CUP) */
00438     LTERM_LOG(ltermProcessCSISequence,52,("Cursor Position = (%d, %d)\n",
00439                    param1, param2));
00440 
00441     if (lto->outputMode == LTERM2_LINE_MODE) {
00442       /* Line mode */
00443       if ((param1 > 0) && ((param1-1) <= lto->outputChars)) {
00444         lto->outputCursorChar = param1-1;
00445       } else {
00446         lto->outputCursorChar = 0;
00447       }
00448 
00449     } else {
00450       /* Screen mode */
00451       lto->cursorRow = lts->nRows - param1;
00452       if (lto->cursorRow < 0) {
00453         lto->cursorRow = 0;
00454       } else if (lto->cursorRow >= lts->nRows) {
00455         lto->cursorRow = lts->nRows - 1;
00456       }
00457 
00458       lto->cursorCol = param2 - 1;
00459       if (lto->cursorCol < 0) {
00460         lto->cursorCol = 0;
00461       } else if (lto->cursorCol >= lts->nCols) {
00462         lto->cursorCol = lts->nCols - 1;
00463       }
00464     }
00465     return 0;
00466 
00467   case U_I_CHAR:    /* Move forward Ps tab stops [default: 1] */
00468     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00469     return 0;
00470 
00471   case U_J_CHAR:    /* Erase in Display (ED)
00472                      * Ps = 0 Clear Below (default) 
00473                      * Ps = 1 Clear Above
00474                      * Ps = 2 Clear All 
00475                      */
00476     param1 = (paramCount > 0) ? paramValues[0] : 0;
00477 
00478     LTERM_LOG(ltermProcessCSISequence,52,("Erase display code %d\n", param1));
00479 
00480     if (lto->outputMode == LTERM2_LINE_MODE) {
00481       /* Clear line */
00482       ltermClearOutputLine(lts);
00483 
00484       /* Set opcodes to return incomplete line */
00485       *opcodes = LTERM_LINEDATA_CODE;
00486 
00487     } else {
00488       /* Screen mode */
00489       int eraseLines, j;
00490 
00491       if ((param1 == 0) && (lto->cursorRow == lts->nRows-1))
00492         param1 = 2;
00493 
00494       switch (param1) {
00495       case 0:          /* Clear below */
00496         eraseLines = lto->cursorRow + 1;
00497         if (ltermInsDelEraseLine(lts, eraseLines, lto->cursorRow, LTERM_ERASE_ACTION) != 0)
00498           return -1;
00499 
00500         /* Set line modification flags */
00501         for (j=0; j<=lto->cursorRow; j++) {
00502           lto->modifiedCol[j] = lts->nCols-1;
00503         }
00504         break;
00505 
00506       case 1:          /* Clear above */
00507         eraseLines = lts->nRows - lto->cursorRow - 1;
00508         if (ltermInsDelEraseLine(lts, eraseLines, lts->nRows-1, LTERM_ERASE_ACTION) != 0)
00509           return -1;
00510 
00511         /* Set line modification flags */
00512         for (j=lto->cursorRow; j<lts->nRows; j++) {
00513           lto->modifiedCol[j] = lts->nCols-1;
00514         }
00515         break;
00516 
00517       case 2:          /* Clear all */
00518         eraseLines = lts->nRows;
00519         if (ltermInsDelEraseLine(lts, eraseLines, lts->nRows-1, LTERM_ERASE_ACTION) != 0)
00520           return -1;
00521 
00522         /* Clear screen */
00523         *opcodes = LTERM_SCREENDATA_CODE|LTERM_CLEAR_CODE;
00524         break;
00525 
00526       default:         /* Invalid line erase code */
00527         LTERM_WARNING("ltermProcessCSISequence: Warning - invalid line erase code %d\n", param1);
00528       }
00529     }
00530     return 0;
00531 
00532   case U_K_CHAR:    /* Erase in Line (EL)
00533                      * Ps = 0 Clear to Right (default) 
00534                      * Ps = 1 Clear to Left
00535                      * Ps = 2 Clear All 
00536                      */
00537     param1 = (paramCount > 0) ? paramValues[0] : 0;
00538 
00539     LTERM_LOG(ltermProcessCSISequence,52,("Line erase code %d\n", param1));
00540 
00541     if (lto->outputMode == LTERM2_LINE_MODE) {
00542       /* Line mode */
00543       switch(param1) {
00544       case 0:        /* Clear to Right */
00545         lto->outputChars = lto->outputCursorChar;
00546         lto->outputModifiedChar = lto->outputCursorChar;
00547         break;
00548       case 1:        /* Clear to Left */
00549         lto->outputChars -= lto->outputCursorChar;
00550         lto->outputCursorChar = 0;
00551         lto->outputModifiedChar = 0;
00552         break;
00553       case 2:        /* Clear All */
00554         lto->outputChars = 0;
00555         lto->outputCursorChar = 0;
00556         lto->outputModifiedChar = 0;
00557         break;
00558       default:       /* Invalid char erase code */
00559         LTERM_WARNING("ltermProcessCSISequence: Warning - invalid char erase code %d\n", param1);
00560       }
00561 
00562     } else {
00563       /* Screen mode */
00564       int eraseCount = 0;
00565 
00566       switch(param1) {
00567       case 0:        /* Clear to Right */
00568         eraseCount = lts->nCols - lto->cursorCol;
00569         if (ltermInsDelEraseChar(lts, eraseCount, LTERM_ERASE_ACTION) != 0)
00570           return -1;
00571         break;
00572 
00573       case 1:        /* Clear to Left */
00574         eraseCount = lto->cursorCol;
00575         lto->cursorCol = 0;
00576         if (ltermInsDelEraseChar(lts, eraseCount, LTERM_ERASE_ACTION) != 0)
00577           return -1;
00578         lto->cursorCol = eraseCount;
00579         break;
00580 
00581       case 2:        /* Clear All */
00582         eraseCount = lts->nCols;
00583         lto->cursorCol = 0;
00584         if (ltermInsDelEraseChar(lts, eraseCount, LTERM_ERASE_ACTION) != 0)
00585           return -1;
00586         lto->cursorCol = eraseCount;
00587         break;
00588 
00589       default:       /* Invalid erase code */
00590         LTERM_WARNING("ltermProcessCSISequence: Warning - invalid erase code %d\n", param1);
00591       }
00592 
00593     }
00594     return 0;
00595 
00596   case U_L_CHAR:    /* Insert Ps Line(s) [default: 1] (IL) */
00597     LTERM_LOG(ltermProcessCSISequence,52,("Insert Line Count = %d\n", param1));
00598 
00599     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00600       if (ltermInsDelEraseLine(lts, param1, lto->cursorRow, LTERM_INSERT_ACTION) != 0)
00601         return -1;
00602       *opcodes = LTERM_SCREENDATA_CODE|LTERM_INSERT_CODE;
00603       *opvals = param1;
00604       *oprow = lto->cursorRow;
00605     }
00606     return 0;
00607 
00608   case U_M_CHAR:    /* Delete Ps Line(s) [default: 1] (DL) */
00609     LTERM_LOG(ltermProcessCSISequence,52,("Delete Line Count = %d\n", param1));
00610 
00611     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00612       if (ltermInsDelEraseLine(lts, param1, lto->cursorRow, LTERM_DELETE_ACTION) != 0)
00613         return -1;
00614       *opcodes = LTERM_SCREENDATA_CODE|LTERM_DELETE_CODE;
00615       *opvals = param1;
00616       *oprow = lto->cursorRow;
00617     }
00618     return 0;
00619 
00620   case U_P_CHAR:    /* Delete Ps Character(s) [default: 1] (DCH) */
00621     if (ltermInsDelEraseChar(lts, param1, LTERM_DELETE_ACTION) != 0)
00622       return -1;
00623     return 0;
00624 
00625   case U_T_CHAR:    /* Initiate hilite mouse tracking. Parameters
00626                      * [func;startx;starty;firstrow;lastrow]. 
00627                      */
00628     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00629     return 0;
00630 
00631   case U_W_CHAR:    /* Tabulator functions:
00632                      *  Ps = 0  Tab Set (HTS)
00633                      *  Ps = 2  Tab Clear (TBC), Clear Current Column (default)
00634                      *  Ps = 5  Tab Clear (TBC), Clear All 
00635                      */
00636     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00637     return 0;
00638 
00639   case U_X_CHAR:    /* Erase Ps Character(s) [default: 1] (ECH) */
00640     if (ltermInsDelEraseChar(lts, param1, LTERM_ERASE_ACTION) != 0)
00641       return -1;
00642     return 0;
00643 
00644   case U_Z_CHAR:    /* Move backward Ps [default: 1] tab stops */
00645     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00646     return 0;
00647 
00648   case U_c_CHAR:    /* Send Device Attributes (DA)
00649                      * Ps = 0 (or omitted) : request attributes from terminal 
00650                      * returns: ESC[?1;2c
00651                      *          (``I am a VT100 with Advanced Video Option'') 
00652                      */
00653     LTERM_LOG(ltermProcessCSISequence,52,("Device Attr %d\n", param1));
00654     {
00655       char deviceAttr[] = "\033[?1;2c";
00656       if (ltermSendChar(lts, deviceAttr, strlen(deviceAttr)) != 0)
00657         return -1;
00658     }
00659 
00660     return 0;
00661 
00662   case U_d_CHAR:    /* Cursor to Line Ps (VPA) */
00663     LTERM_LOG(ltermProcessCSISequence,52,("Cursor to Line = %d\n", param1));
00664     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00665       lto->cursorRow = lts->nRows - param1;
00666       if (lto->cursorRow < 0) {
00667         lto->cursorRow = 0;
00668       } else if (lto->cursorRow >= lts->nRows) {
00669         lto->cursorRow = lts->nRows - 1;
00670       }
00671     }
00672     return 0;
00673 
00674   case U_f_CHAR:    /* Horizontal and Vertical Position [row;column] (HVP)
00675                      * [default: 1;1]
00676                      */
00677     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00678     return 0;
00679 
00680   case U_g_CHAR:    /* Tab Clear (TBC) 
00681                      * Ps = 0 Clear Current Column (default) 
00682                      * Ps = 3 Clear All (TBC)
00683                      */
00684     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00685     return 0;
00686 
00687   case U_i_CHAR:    /* Printing 
00688                      * Ps = 4 disable transparent print mode (MC4) 
00689                      * Ps = 5 enable transparent print mode (MC5)
00690                      */
00691     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00692     return 0;
00693 
00694   case U_h_CHAR:    /* Set Mode (SM)
00695                      * Ps =  4 Insert Mode (SMIR)
00696                      * Ps = 20 Automatic Newline (LNM)
00697                      */
00698     LTERM_LOG(ltermProcessCSISequence,52,("Set Mode %d\n", param1));
00699 
00700     if (param1 == 4) {
00701       lto->insertMode = 1;
00702     } else if (param1 == 4) {
00703       lto->automaticNewline = 1;
00704     } if ((param1 % 100) == 47) {
00705       /* Switch to alternate buffer */
00706       if (lto->outputMode == LTERM2_LINE_MODE) {
00707         ltermSwitchToScreenMode(lts);
00708         *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
00709       }
00710     }
00711     return 0;
00712 
00713   case U_l_CHAR:    /* Reset Mode (RM)
00714                      * Ps =  4 Replace Mode (RMIR)
00715                      * Ps = 20 Normal Linefeed (LNM)
00716                      */
00717     LTERM_LOG(ltermProcessCSISequence,52,("Reset Mode %d\n", param1));
00718 
00719     if (param1 == 4) {
00720       lto->insertMode = 0;
00721     } else if (param1 == 4) {
00722       lto->automaticNewline = 0;
00723     } if ((param1 % 100) == 47) {
00724       /* Switch to regular buffer */
00725       if (lto->outputMode == LTERM1_SCREEN_MODE) {
00726         ltermSwitchToLineMode(lts);
00727         *opcodes = LTERM_SCREENDATA_CODE | LTERM_CLEAR_CODE;
00728       }
00729     }
00730     return 0;
00731 
00732   case U_m_CHAR:    /* Character Attributes (SGR) 
00733                      * Ps = 0 Normal (default) 
00734                      * Ps = 1 / 22 On / Off Bold (bright fg) 
00735                      * Ps = 4 / 24 On / Off Underline 
00736                      * Ps = 5 / 25 On / Off Blink (bright bg) 
00737                      * Ps = 7 / 27 On / Off Inverse 
00738                      * Ps = 30 / 40 fg/bg Black 
00739                      * Ps = 31 / 41 fg/bg Red 
00740                      * Ps = 32 / 42 fg/bg Green 
00741                      * Ps = 33 / 43 fg/bg Yellow 
00742                      * Ps = 34 / 44 fg/bg Blue 
00743                      * Ps = 35 / 45 fg/bg Magenta 
00744                      * Ps = 36 / 46 fg/bg Cyan 
00745                      * Ps = 37 / 47 fg/bg White 
00746                      * Ps = 39 / 49 fg/bg Default
00747                      */
00748 
00749     /* Enforce default value for parameter (hack!) */
00750     if (paramCount == 0)
00751       param1 = 0;
00752 
00753     LTERM_LOG(ltermProcessCSISequence,52,("Character Attr %d\n", param1));
00754     switch (param1) {
00755     case 0:
00756       lto->styleMask = 0;
00757       break;
00758     case 1:
00759       lto->styleMask |= LTERM_BOLD_STYLE;
00760       break;
00761     case 22:
00762       lto->styleMask &= ~LTERM_BOLD_STYLE;
00763       break;
00764     case 4:
00765       lto->styleMask |= LTERM_ULINE_STYLE;
00766       break;
00767     case 24:
00768       lto->styleMask &= ~LTERM_ULINE_STYLE;
00769       break;
00770     case 5:
00771       lto->styleMask |= LTERM_BLINK_STYLE;
00772       break;
00773     case 25:
00774       lto->styleMask &= ~LTERM_BLINK_STYLE;
00775       break;
00776     case 7:
00777       lto->styleMask |= LTERM_INVERSE_STYLE;
00778       break;
00779     case 27:
00780       lto->styleMask &= ~LTERM_INVERSE_STYLE;
00781       break;
00782     default:
00783       break;
00784     }
00785     return 0;
00786 
00787   case U_n_CHAR:    /* Device Status Report (DSR) 
00788                      * Ps = 5 Status Report ESC [ 0 n (``OK'') 
00789                      * Ps = 6 Report Cursor Position (CPR) [row;column]
00790                      *         as ESC [ r ; c R 
00791                      * Ps = 7 Request Display Name 
00792                      * Ps = 8 Request Version Number (place in window title)
00793                      */
00794     LTERM_LOG(ltermProcessCSISequence,52,("Status Report %d\n", param1));
00795     switch (param1) {
00796     case 5:
00797       {
00798         char statusReport[] = "\033[01";
00799         if (ltermSendChar(lts, statusReport, strlen(statusReport)) != 0)
00800           return -1;
00801       }
00802       break;
00803 
00804     case 6:
00805       if (lto->outputMode == LTERM1_SCREEN_MODE) {
00806         int iRow = lts->nRows-lto->cursorRow;
00807         int iCol = lto->cursorCol+1;
00808         char cursorPos[13];
00809 
00810         if ((iRow > 0) && (iRow < 10000) && (iCol > 0) && (iCol < 10000)) {
00811           if (sprintf(cursorPos, "\033[%d;%dR", iRow, iCol) > 12) {
00812             LTERM_ERROR("ltermProcessCSISequence: Error - DSR buffer overflow\n");
00813           }
00814           if (ltermSendChar(lts, cursorPos, strlen(cursorPos)) != 0)
00815             return -1;
00816         }
00817       }
00818       break;
00819     default:
00820       break;
00821     }
00822     return 0;
00823 
00824   case U_r_CHAR:    /* Set Scrolling Region [top;bottom] 
00825                      * [default: full size of window] (CSR) 
00826                      */
00827 
00828     if (lto->outputMode == LTERM1_SCREEN_MODE) {
00829 
00830       if (paramCount == 0) {
00831         param1 = 1;
00832         param2 = lts->nRows;
00833       }
00834 
00835       LTERM_LOG(ltermProcessCSISequence,52,("Scrolling Region (%d, %d)\n",
00836                                             param1, param2));
00837 
00838       lto->topScrollRow = (param1 > 0) ? lts->nRows - param1 : lts->nRows - 1;
00839       if (lto->topScrollRow < 0)
00840         lto->topScrollRow = 0;
00841 
00842       lto->botScrollRow = (param2 > 0) ? lts->nRows - param2 : lts->nRows - 1;
00843       if (lto->botScrollRow < 0)
00844         lto->botScrollRow = 0;
00845 
00846       if (lto->topScrollRow < lto->botScrollRow) {
00847         int temRow = lto->topScrollRow;
00848         lto->topScrollRow = lto->botScrollRow;
00849         lto->botScrollRow = temRow;
00850       }
00851 
00852       *opcodes = LTERM_SCREENDATA_CODE|LTERM_SCROLL_CODE;
00853       *opvals = lto->topScrollRow;
00854       *oprow = lto->botScrollRow;
00855     }
00856 
00857     return 0;
00858 
00859   case U_x_CHAR:    /* Request Terminal Parameters (DECREQTPARM) */
00860     LTERM_LOG(ltermProcessCSISequence,2,("Unimplemented 0x%x\n", buf[offset]));
00861     return 0;
00862 
00863   default:          /* Unknown Escape sequence */
00864     LTERM_WARNING("ltermProcessCSISequence: Warning - unknown sequence 0x%x\n",
00865                   buf[offset]);
00866     return 0;
00867   }
00868 
00869 }
00870 
00871 
00876 static int ltermProcessDECPrivateMode(struct lterms *lts,
00877             const int *paramValues, int paramCount, UNICHAR uch, int *opcodes)
00878 {
00879   struct LtermOutput *lto = &(lts->ltermOutput);
00880   int param1, param2;
00881 
00882   LTERM_LOG(ltermProcessDECPrivateMode,50,("ch=0x%x, cursorChar=%d, Chars=%d\n",
00883                 uch, lto->outputCursorChar, lto->outputChars));
00884 
00885   /* Set returned opcodes to zero */
00886   *opcodes = 0;
00887 
00888   /* Default parameter values: 1, 1 */
00889   param1 = (paramCount > 0) ? paramValues[0] : 1;
00890   param2 = (paramCount > 1) ? paramValues[1] : 1;
00891 
00892   switch (uch) {
00893   case U_h_CHAR:    /* DEC Private Mode Set (DECSET) */
00894     LTERM_LOG(ltermProcessDECPrivateMode,2,("Unimplemented 0x%x\n", uch));
00895     if ((param1 % 100) == 47) {
00896       /* Switch to screen mode */
00897       if (lto->outputMode == LTERM2_LINE_MODE) {
00898         ltermSwitchToScreenMode(lts);
00899         *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
00900       }
00901     }
00902     return 0;
00903 
00904   case U_l_CHAR:    /* DEC Private Mode Reset (DECRST) */
00905     LTERM_LOG(ltermProcessDECPrivateMode,2,("Unimplemented 0x%x\n", uch));
00906     if ((param1 % 100) == 47) {
00907       /* Switch to line mode */
00908       if (lto->outputMode == LTERM1_SCREEN_MODE) {
00909         ltermSwitchToLineMode(lts);
00910         *opcodes = LTERM_SCREENDATA_CODE | LTERM_CLEAR_CODE;
00911       }
00912     }
00913     return 0;
00914 
00915   case U_r_CHAR:    /* Restore previously saved DEC Private Mode Values */
00916     LTERM_LOG(ltermProcessDECPrivateMode,2,("Unimplemented 0x%x\n", uch));
00917     return 0;
00918 
00919   case U_s_CHAR:    /* Save DEC Private Mode Values */
00920     LTERM_LOG(ltermProcessDECPrivateMode,2,("Unimplemented 0x%x\n", uch));
00921     return 0;
00922 
00923   case U_t_CHAR:    /* Toggle DEC Private Mode Values */
00924     LTERM_LOG(ltermProcessDECPrivateMode,2,("Unimplemented 0x%x\n", uch));
00925     return 0;
00926 
00927   default:          /* Unknown escape sequence */
00928     LTERM_WARNING("ltermProcessDECPrivateMode: Warning - unknown sequence 0x%x\n",
00929                   uch);
00930     return 0;
00931   }
00932 
00933 }
00934 
00935 
00940 static int ltermProcessXTERMSequence(struct lterms *lts, const UNICHAR *buf,
00941                   int count, const UNISTYLE *style,int *consumed,int *opcodes)
00942 {
00943   struct LtermOutput *lto = &(lts->ltermOutput);
00944   int offset, paramValue, strLength;
00945   UNICHAR paramString[MAXSTRINGPARAM+1];
00946 
00947   if (count < 3) {
00948     /* Incomplete Escape sequence */
00949     *consumed = 0;
00950     return 1;
00951   }
00952 
00953   LTERM_LOG(ltermProcessXTERMSequence,50,("cursorChar=%d, Chars=%d\n",
00954                 lto->outputCursorChar, lto->outputChars));
00955 
00956   offset = 2;
00957 
00958   /* Set returned opcodes to zero */
00959   *opcodes = 0;
00960 
00961   /* Process numerical parameter */
00962   paramValue = 0;
00963   while ((offset < count) &&
00964          ((buf[offset] >= (UNICHAR)U_ZERO) &&
00965           (buf[offset] <= (UNICHAR)U_NINE)) ) {
00966     paramValue = paramValue * 10 + buf[offset] - U_ZERO;
00967     offset++;
00968   }
00969 
00970   if (offset == count) {
00971     /* Incomplete Escape sequence */
00972     *consumed = 0;
00973     return 1;
00974   }
00975 
00976   if (buf[offset] != U_SEMICOLON) {
00977     /* If next character not semicolon, return */
00978     *consumed = offset;
00979     return 0;
00980   }
00981 
00982   LTERM_LOG(ltermProcessXTERMSequence,51,("paramValue=%d, offset=%d, buf[offset]=0x%x\n",
00983                  paramValue, offset, buf[offset]));
00984 
00985   /* Skip the semicolon */
00986   offset++;
00987 
00988   /* Process string parameter */
00989   strLength = 0;
00990   while ((offset < count) && (buf[offset] != U_BEL)) {
00991     if (strLength < MAXSTRINGPARAM) {
00992       paramString[strLength++] = buf[offset];
00993       offset++;
00994 
00995     } else {
00996       LTERM_WARNING("ltermProcessXTERMSequence: Warning - string parameter too long; truncated\n");
00997       break;
00998     }
00999   }
01000 
01001   if (offset == count) {
01002     /* Incomplete Escape sequence */
01003     *consumed = 0;
01004     return 1;
01005   }
01006 
01007   /* Insert terminating NULL character in string */
01008   paramString[strLength] = U_NUL;
01009 
01010   LTERM_LOGUNICODE(ltermProcessXTERMSequence,52,(paramString, strLength));
01011 
01012   /* All parsed characters have been consumed at this point */
01013   *consumed = offset+1;
01014 
01015   LTERM_WARNING("ltermProcessXTERMSequence: Warning - unimplemented 0x%x\n",
01016                 buf[offset]);
01017 
01018   return 0;
01019 }
01020 
01021 
01033 static int ltermProcessXMLTermSequence(struct lterms *lts, const UNICHAR *buf,
01034                   int count, const UNISTYLE *style,int *consumed,int *opcodes)
01035 {
01036   struct LtermOutput *lto = &(lts->ltermOutput);
01037   int offset, value, strLength;
01038   int paramCount, paramValues[MAXESCAPEPARAMS], param1, param2, param3;
01039   UNICHAR termChar, paramString[MAXSTRINGPARAM+1];
01040   char paramCString[MAXSTRINGPARAM+1];
01041 
01042   if (count < 4) {
01043     /* Incomplete Escape sequence */
01044     *consumed = 0;
01045     return 1;
01046   }
01047 
01048   LTERM_LOG(ltermProcessXMLTermSequence,50,("cursorChar=%d, Chars=%d\n",
01049                 lto->outputCursorChar, lto->outputChars));
01050 
01051   offset = 2;
01052 
01053   /* Set returned opcodes to zero */
01054   *opcodes = 0;
01055 
01056   /* Process numerical parameters */
01057   paramCount = 0;
01058   while ((offset < count) &&
01059          ((buf[offset] >= (UNICHAR)U_ZERO) &&
01060           (buf[offset] <= (UNICHAR)U_NINE)) ) {
01061     /* Starts with a digit */
01062     value = buf[offset] - U_ZERO;
01063     offset++;
01064 
01065     /* Process all contiguous digits */
01066     while ((offset < count) &&
01067            ((buf[offset] >= (UNICHAR)U_ZERO) &&
01068             (buf[offset] <= (UNICHAR)U_NINE)) ) {
01069       value = value * 10 + buf[offset] - U_ZERO;
01070       offset++;
01071     }
01072 
01073     if (offset == count) {
01074       /* Incomplete Escape sequence */
01075       *consumed = 0;
01076       return 1;
01077     }
01078 
01079     if (paramCount < MAXESCAPEPARAMS) {
01080       /* Store numerical parameter */
01081       paramValues[paramCount++] = value;
01082 
01083     } else {
01084       /* Numeric parameter buffer overflow */
01085       LTERM_WARNING("ltermProcessXMLTermSequence: Warning - numeric parameter buffer overflow\n");
01086     }
01087 
01088     /* If next character not semicolon, stop processing */
01089     if (buf[offset] != U_SEMICOLON)
01090       break;
01091 
01092     /* Process next argument */
01093     offset++;
01094   }
01095 
01096   if (offset == count) {
01097     /* Incomplete Escape sequence */
01098     *consumed = 0;
01099     return 1;
01100   }
01101 
01102   /* Terminating character */
01103   termChar = buf[offset];
01104 
01105   /* Skip terminating character */
01106   offset++;
01107 
01108   LTERM_LOG(ltermProcessXMLTermSequence,51,("paramCount=%d, offset=%d, termChar=0x%x\n",
01109                  paramCount, offset, termChar));
01110 
01111   /* Process string parameter */
01112   strLength = 0;
01113   while ((offset < count) && (buf[offset] != U_LINEFEED)) {
01114     if (strLength < MAXSTRINGPARAM) {
01115       paramCString[strLength] = buf[offset];
01116       paramString[strLength++] = buf[offset];
01117       offset++;
01118 
01119     } else {
01120       LTERM_WARNING("ltermProcessXMLTermSequence: Warning - string parameter too long; truncated\n");
01121       break;
01122     }
01123   }
01124 
01125   if (offset == count) {
01126     /* Incomplete Escape sequence */
01127     *consumed = 0;
01128     return 1;
01129   }
01130 
01131   /* Discard any CR character preceding the terminating LF character */
01132   if ((strLength > 0) && (paramString[strLength-1] == U_CRETURN))
01133     strLength--;
01134 
01135   /* Insert terminating NULL character in string */
01136   paramCString[strLength] = U_NUL;
01137   paramString[strLength] = U_NUL;
01138 
01139   LTERM_LOGUNICODE(ltermProcessXMLTermSequence,52,(paramString, strLength));
01140 
01141   /* All parsed characters have been consumed at this point (including BEL) */
01142   *consumed = offset+1;
01143 
01144   /* Default parameter values: 0, 0, 0 */
01145   param1 = (paramCount > 0) ? paramValues[0] : 0;
01146   param2 = (paramCount > 1) ? paramValues[1] : 0;
01147   param3 = (paramCount > 2) ? paramValues[2] : 0;
01148 
01149   switch (termChar) {
01150     int streamOpcodes, nRows, nCols, sprint_len;
01151     char sprint_buf[81];
01152 
01153   case U_A_CHAR:    /* Send XMLterm device attributes */
01154   case U_B_CHAR:    /* Send XMLterm device attributes (Bourne shell format) */
01155   case U_C_CHAR:    /* Send XMLterm device attributes (C shell format) */
01156     LTERM_LOG(ltermProcessXMLTermSequence,52,("Sending device attributes\n"));
01157 
01158 
01159     nRows = lts->nRows;
01160     nCols = lts->nCols;
01161 
01162     if ((nRows >= 0) && (nRows < 10000) && (nCols >= 0) && (nCols < 10000)) {
01163 
01164       if (termChar == U_C_CHAR) {
01165         /* C shell format */
01166 
01167         sprint_len = sprintf(sprint_buf, "setenv LINES %d;setenv COLUMNS %d;setenv LTERM_COOKIE ", nRows, nCols);
01168 
01169       } else {
01170 
01171         sprint_len = sprintf(sprint_buf, "LINES=%d;COLUMNS=%d;LTERM_COOKIE=", nRows, nCols);
01172       }
01173 
01174       if (sprint_len > 80) {
01175         LTERM_ERROR("ltermProcessXMLTermSequence: Error - sprintf buffer overflow\n");
01176       }
01177 
01178       if (ltermSendChar(lts, sprint_buf, strlen(sprint_buf)) != 0)
01179         return -1;
01180     }
01181 
01182     if (*lts->cookie) {
01183       if (ltermSendChar(lts, lts->cookie, strlen(lts->cookie)) != 0)
01184         return -1;
01185     }
01186 
01187     if (termChar == U_B_CHAR) {
01188       const char exportStr[] = ";export LINES COLUMNS LTERM_COOKIE";
01189       if (ltermSendChar(lts, exportStr, strlen(exportStr)) != 0)
01190         return -1;
01191     }
01192 
01193     if (ltermSendChar(lts, "\n", 1) != 0)
01194       return -1;
01195     return 0;
01196 
01197   case U_D_CHAR:    /* Set debugging messageLevel/search-string */
01198     LTERM_LOG(ltermProcessXMLTermSequence,52,("Setting message level etc.\n"));
01199     if (strLength == 0) {
01200       tlog_set_level(param1, param2, NULL);
01201     } else {
01202       tlog_set_level(param1, param2, paramCString);
01203     }
01204     return 0;
01205 
01206   case U_E_CHAR:    /* Enable/disable input echo setting */
01207     if (param1) {
01208       /* Enable input echo */
01209       lts->disabledInputEcho = 0;
01210 
01211       LTERM_LOG(ltermProcessXMLTermSequence,52,("Enabled input echo\n"));
01212     } else {
01213       /* Disable input echo */
01214       lts->disabledInputEcho = 1;
01215 
01216       LTERM_LOG(ltermProcessXMLTermSequence,52,("Disabled input echo\n"));
01217     }
01218     return 0;
01219 
01220   case U_F_CHAR:    /* Enable/disable full screen mode */
01221     if (param1) {
01222       /* Enable full screen mode */
01223       if (lto->outputMode == LTERM2_LINE_MODE) {
01224         ltermSwitchToScreenMode(lts);
01225         *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
01226       }
01227 
01228       LTERM_LOG(ltermProcessXMLTermSequence,52,("Enabled full screen mode\n"));
01229 
01230     } else {
01231       /* Disable full screen mode */
01232       if (lto->outputMode == LTERM1_SCREEN_MODE) {
01233         ltermSwitchToLineMode(lts);
01234         *opcodes = LTERM_SCREENDATA_CODE | LTERM_CLEAR_CODE;
01235       }
01236 
01237       LTERM_LOG(ltermProcessXMLTermSequence,52,("Disabled full screen mode\n"));
01238     }
01239     return 0;
01240 
01241   case U_R_CHAR:    /* Enable/disable raw input mode */
01242     if (param1) {
01243       /* Switch to raw input mode */
01244       ltermSwitchToRawMode(lts);
01245 
01246       LTERM_LOG(ltermProcessXMLTermSequence,52,("Raw input mode\n"));
01247 
01248     } else {
01249       /* Switch to regular input mode */
01250       ltermClearInputLine(lts);
01251 
01252       LTERM_LOG(ltermProcessXMLTermSequence,52,("Line input mode\n"));
01253     }
01254     return 0;
01255 
01256   case U_J_CHAR:    /* Switch to null-terminated Javascript stream mode */
01257   case U_S_CHAR:    /* Switch to null-terminated stream mode, with cookie */
01258 
01259     if (lto->outputMode == LTERM1_SCREEN_MODE) {
01260       *opcodes = LTERM_SCREENDATA_CODE;
01261     } else if (lto->outputMode == LTERM2_LINE_MODE) {
01262       *opcodes = LTERM_LINEDATA_CODE | LTERM_OUTPUT_CODE;
01263     }
01264 
01265     assert(lto->outputMode != LTERM0_STREAM_MODE);
01266 
01267     /* Set stream codes */
01268     streamOpcodes = 0;
01269 
01270     if (termChar == U_J_CHAR) {
01271       /* Javascript stream */
01272       streamOpcodes |= LTERM_JSSTREAM_CODE;
01273 
01274     } else {
01275       /* HTML/XML stream */
01276       if (param1)
01277         streamOpcodes |= LTERM_DOCSTREAM_CODE;
01278 
01279       if (param2)
01280         streamOpcodes |= LTERM_XMLSTREAM_CODE;
01281 
01282       if (param3)
01283         streamOpcodes |= LTERM_WINSTREAM_CODE;
01284     }
01285 
01286     /* Check if cookie matches */
01287     if ((strLength > 0) && (strcmp(paramCString, lts->cookie) == 0)) {
01288       streamOpcodes |= LTERM_COOKIESTR_CODE;
01289     }
01290 
01291     LTERM_LOG(ltermProcessXMLTermSequence,52,
01292               ("Switching to stream mode, codes=0x%x\n", streamOpcodes));
01293 
01294     if (0 != ltermSwitchToStreamMode(lts, streamOpcodes, NULL))
01295       return -1;
01296 
01297     return 0;
01298 
01299   default:          /* Unknown escape sequence */
01300     LTERM_WARNING("ltermProcessXMLTermSequence: Warning - unknown sequence 0x%x\n",
01301                    termChar);
01302     return 0;
01303   }
01304 
01305   return 0;
01306 }
01307 
01308 
01315 int ltermInsDelEraseChar(struct lterms *lts, int count, int action)
01316 {
01317   struct LtermOutput *lto = &(lts->ltermOutput);
01318   int charCount = count;
01319   int j;
01320 
01321   assert(count >= 0);
01322 
01323   LTERM_LOG(ltermInsDelEraseChar,60,("count=%d, action=%d\n",
01324                  count, action));
01325 
01326   if (lto->outputMode == LTERM2_LINE_MODE) {
01327     /* Line mode */
01328     switch (action) {
01329 
01330     case LTERM_INSERT_ACTION:
01331 
01332       if (lto->outputChars + charCount > MAXCOLM1) {
01333         /* Output buffer overflow; ignore extra inserts */
01334         LTERM_WARNING("ltermInsDelEraseChar: Warning - output line buffer overflow\n");
01335         charCount = MAXCOLM1 - lto->outputChars;
01336       }
01337 
01338       LTERM_LOG(ltermInsDelEraseChar,62,("Line insert %d blank chars\n",
01339                      charCount));
01340 
01341       /* Shift characters to the right to make room for insertion */
01342       for (j=lto->outputChars-1; j>=lto->outputCursorChar; j--) {
01343         lto->outputLine[j+charCount] = lto->outputLine[j];
01344         lto->outputStyle[j+charCount] = lto->outputStyle[j];
01345       }
01346 
01347       /* Insert blank characters */
01348       for (j=lto->outputCursorChar; j<lto->outputCursorChar+charCount; j++) {
01349         lto->outputLine[j] = U_SPACE;
01350         lto->outputStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
01351       }
01352 
01353       /* Increment character count */
01354       lto->outputChars += charCount;
01355       break;
01356 
01357     case LTERM_DELETE_ACTION:
01358       if (lto->outputCursorChar+charCount > lto->outputChars)
01359         charCount = lto->outputChars - lto->outputCursorChar;
01360 
01361       LTERM_LOG(ltermInsDelEraseChar,62,("Line delete %d chars\n",
01362                      charCount));
01363 
01364       /* Shift characters to the left */
01365       for (j=lto->outputCursorChar; j<lto->outputChars-charCount; j++) {
01366         lto->outputLine[j] = lto->outputLine[j+charCount];
01367         lto->outputStyle[j] = lto->outputStyle[j+charCount];
01368       }
01369 
01370       /* Decrement character count */
01371       lto->outputChars -= charCount;
01372       break;
01373 
01374     case LTERM_ERASE_ACTION:
01375       if (lto->outputCursorChar+charCount > lto->outputChars)
01376         charCount = lto->outputChars - lto->outputCursorChar;
01377 
01378       LTERM_LOG(ltermInsDelEraseChar,62,("Line erase %d chars\n",
01379                      charCount));
01380 
01381       /* Erase characters */
01382       for (j=lto->outputCursorChar; j<lto->outputCursorChar+charCount; j++) {
01383         lto->outputLine[j] = U_SPACE;
01384         lto->outputStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
01385       }
01386 
01387       break;
01388     }
01389 
01390     /* Note modifications */
01391     if (lto->outputCursorChar < lto->outputModifiedChar)
01392       lto->outputModifiedChar = lto->outputCursorChar;
01393 
01394   } else if (lto->outputMode == LTERM1_SCREEN_MODE) {
01395     /* Screen mode */
01396     int j0 = lto->cursorRow*lts->nCols;
01397 
01398     switch (action) {
01399 
01400     case LTERM_INSERT_ACTION:
01401       if (lto->cursorCol+charCount > lts->nCols) {
01402         /* Ignore inserts beyond screen width */
01403         LTERM_WARNING("ltermInsDelEraseChar: Warning - screen insert overflow\n");
01404         charCount = lts->nCols - lto->cursorCol;
01405       }
01406 
01407       LTERM_LOG(ltermInsDelEraseChar,62,
01408                 ("Screen insert %d blank chars at column %d\n",
01409                  charCount, lto->cursorCol));
01410 
01411       if (charCount > 0) {
01412         /* Shift characters to the right to make room for insertion */
01413         for (j=lts->nCols-1+j0; j>=lto->cursorCol+charCount+j0; j--) {
01414           lto->screenChar[j] = lto->screenChar[j-charCount];
01415           lto->screenStyle[j] = lto->screenStyle[j-charCount];
01416         }
01417 
01418         /* Insert blank characters */
01419         for (j=lto->cursorCol+j0; j<lto->cursorCol+charCount+j0; j++) {
01420           lto->screenChar[j] = U_SPACE;
01421           lto->screenStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
01422         }
01423 
01424         /* Note modified column */
01425         lto->modifiedCol[lto->cursorRow] = lts->nCols-1;
01426       }
01427       break;
01428 
01429     case LTERM_DELETE_ACTION:
01430       if (lto->cursorCol+charCount > lts->nCols)
01431         charCount = lts->nCols - lto->cursorCol;
01432 
01433       LTERM_LOG(ltermInsDelEraseChar,62,
01434                 ("Screen delete %d chars at column %d\n",
01435                  charCount, lto->cursorCol));
01436 
01437       if (charCount > 0) {
01438         /* Shift characters to the left */
01439         for (j=lto->cursorCol+j0; j<lts->nCols-charCount+j0; j++) {
01440           lto->screenChar[j] = lto->screenChar[j+charCount];
01441           lto->screenStyle[j] = lto->screenStyle[j+charCount];
01442         }
01443 
01444         /* Note modified column */
01445         lto->modifiedCol[lto->cursorRow] = lts->nCols-1;
01446       }
01447 
01448       break;
01449 
01450     case LTERM_ERASE_ACTION:
01451       if (lto->cursorCol+charCount > lts->nCols)
01452         charCount = lts->nCols - lto->cursorCol;
01453 
01454       LTERM_LOG(ltermInsDelEraseChar,62,
01455                 ("Screen erase %d chars at column %d\n",
01456                  charCount, lto->cursorCol));
01457 
01458       if (charCount > 0) {
01459         /* Erase characters */
01460         for (j=lto->cursorCol+j0; j<lto->cursorCol+charCount+j0; j++) {
01461           lto->screenChar[j] = U_SPACE;
01462           lto->screenStyle[j] = LTERM_STDOUT_STYLE | lto->styleMask;
01463         }
01464 
01465         /* Note modified column */
01466         if (lto->modifiedCol[lto->cursorRow] < lto->cursorCol+charCount-1)
01467           lto->modifiedCol[lto->cursorRow] = lto->cursorCol+charCount-1;
01468       }
01469 
01470       break;
01471     }
01472   }
01473 
01474   return 0;
01475 }
01476 
01477 
01490 int ltermInsDelEraseLine(struct lterms *lts, int count, int row, int action)
01491 {
01492   struct LtermOutput *lto = &(lts->ltermOutput);
01493   int lineCount, kblank1, kblank2;
01494   int joffset, jscroll, j, k;
01495 
01496   LTERM_LOG(ltermInsDelEraseLine,60, ("count=%d, row=%d, action=%d\n",
01497                                       count, row, action));
01498 
01499   lineCount = count;
01500 
01501   switch (action) {
01502 
01503   case LTERM_ERASE_ACTION:
01504     /* Erase lines down; no scrolling */
01505     if (lineCount > row + 1)
01506       lineCount = row + 1;
01507 
01508     kblank1 = row-lineCount+1;
01509     kblank2 = row;
01510     break;
01511 
01512   case LTERM_INSERT_ACTION:
01513     /* Scroll down for insertion */
01514     if ( (row < lto->botScrollRow) ||
01515          (row > lto->topScrollRow) ) {
01516       /* Cursor located outside scrollable region */
01517       return 0;
01518     }
01519 
01520     if (lineCount > row - lto->botScrollRow + 1)
01521       lineCount = row - lto->botScrollRow + 1;
01522 
01523     kblank1 = row-lineCount+1;
01524     kblank2 = row;
01525 
01526     for (k=lto->botScrollRow; k<=row-lineCount; k++) {
01527       joffset = k*lts->nCols;
01528       jscroll = lineCount*lts->nCols;
01529 
01530       lto->modifiedCol[k] = lto->modifiedCol[k+lineCount];
01531 
01532       for (j=0+joffset; j<=lts->nCols-1+joffset; j++) {
01533         lto->screenChar[j] = lto->screenChar[j+jscroll];
01534         lto->screenStyle[j] = lto->screenStyle[j+jscroll];
01535       }
01536     }
01537 
01538     break;
01539 
01540   case LTERM_DELETE_ACTION:
01541     /* Scroll up for deletion */
01542     if ( (row < lto->botScrollRow) ||
01543          (row > lto->topScrollRow) ) {
01544       /* Cursor located outside scrollable region */
01545       return 0;
01546     }
01547 
01548     if (lineCount > row - lto->botScrollRow + 1)
01549       lineCount = row - lto->botScrollRow + 1;
01550 
01551     kblank1 = lto->botScrollRow;
01552     kblank2 = lto->botScrollRow + lineCount-1;
01553 
01554     /* Scroll up */
01555     for (k=row; k>=lto->botScrollRow+lineCount; k--) {
01556       joffset = k*lts->nCols;
01557       jscroll = lineCount*lts->nCols;
01558 
01559       lto->modifiedCol[k] = lto->modifiedCol[k-lineCount];
01560 
01561       for (j=0+joffset; j<=lts->nCols-1+joffset; j++) {
01562         lto->screenChar[j] = lto->screenChar[j-jscroll];
01563         lto->screenStyle[j] = lto->screenStyle[j-jscroll];
01564       }
01565     }
01566 
01567     break;
01568 
01569   default:
01570     kblank1 = 0;
01571     kblank2 = -1;
01572     break;
01573   }
01574 
01575   /* Blank out lines (assumed to be displayed already) */
01576   for (k=kblank1; k<=kblank2; k++) {
01577     joffset = k*lts->nCols;
01578 
01579     lto->modifiedCol[k] = -1;
01580 
01581     for (j=0+joffset; j<=lts->nCols-1+joffset; j++) {
01582       lto->screenChar[j] = U_SPACE;
01583       lto->screenStyle[j] = LTERM_STDOUT_STYLE;
01584     }
01585   }
01586 
01587   return 0;
01588 }