"Fossies" - the Fresh Open Source Software Archive

Member "xterm-379/charproc.c" (15 Feb 2023, 384144 Bytes) of package /linux/misc/xterm-379.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "charproc.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 377_vs_379.

    1 /* $XTermId: charproc.c,v 1.1934 2023/02/15 00:10:20 tom Exp $ */
    2 
    3 /*
    4  * Copyright 1999-2022,2023 by Thomas E. Dickey
    5  *
    6  *                         All Rights Reserved
    7  *
    8  * Permission is hereby granted, free of charge, to any person obtaining a
    9  * copy of this software and associated documentation files (the
   10  * "Software"), to deal in the Software without restriction, including
   11  * without limitation the rights to use, copy, modify, merge, publish,
   12  * distribute, sublicense, and/or sell copies of the Software, and to
   13  * permit persons to whom the Software is furnished to do so, subject to
   14  * the following conditions:
   15  *
   16  * The above copyright notice and this permission notice shall be included
   17  * in all copies or substantial portions of the Software.
   18  *
   19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   22  * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
   23  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   26  *
   27  * Except as contained in this notice, the name(s) of the above copyright
   28  * holders shall not be used in advertising or otherwise to promote the
   29  * sale, use or other dealings in this Software without prior written
   30  * authorization.
   31  *
   32  *
   33  * Copyright 1988  X Consortium
   34  *
   35  * Permission to use, copy, modify, distribute, and sell this software and its
   36  * documentation for any purpose is hereby granted without fee, provided that
   37  * the above copyright notice appear in all copies and that both that
   38  * copyright notice and this permission notice appear in supporting
   39  * documentation.
   40  *
   41  * The above copyright notice and this permission notice shall be included in
   42  * all copies or substantial portions of the Software.
   43  *
   44  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   45  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   46  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   47  * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
   48  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   49  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   50  *
   51  * Except as contained in this notice, the name of the X Consortium shall not be
   52  * used in advertising or otherwise to promote the sale, use or other dealings
   53  * in this Software without prior written authorization from the X Consortium.
   54  *
   55  */
   56 /*
   57  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
   58  *
   59  *                         All Rights Reserved
   60  *
   61  * Permission to use, copy, modify, and distribute this software and its
   62  * documentation for any purpose and without fee is hereby granted,
   63  * provided that the above copyright notice appear in all copies and that
   64  * both that copyright notice and this permission notice appear in
   65  * supporting documentation, and that the name of Digital Equipment
   66  * Corporation not be used in advertising or publicity pertaining to
   67  * distribution of the software without specific, written prior permission.
   68  *
   69  *
   70  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   71  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   72  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   73  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   74  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   75  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   76  * SOFTWARE.
   77  */
   78 
   79 /* charproc.c */
   80 
   81 #include <version.h>
   82 #include <xterm.h>
   83 
   84 #include <X11/Xatom.h>
   85 #include <X11/Xutil.h>
   86 #include <X11/Xmu/Atoms.h>
   87 #include <X11/Xmu/CharSet.h>
   88 #include <X11/Xmu/Converters.h>
   89 
   90 #if OPT_INPUT_METHOD
   91 
   92 #if defined(HAVE_LIB_XAW)
   93 #include <X11/Xaw/XawImP.h>
   94 #elif defined(HAVE_LIB_XAW3D)
   95 #include <X11/Xaw3d/XawImP.h>
   96 #elif defined(HAVE_LIB_XAW3DXFT)
   97 #include <X11/Xaw3dxft/XawImP.h>
   98 #elif defined(HAVE_LIB_NEXTAW)
   99 #include <X11/neXtaw/XawImP.h>
  100 #elif defined(HAVE_LIB_XAWPLUS)
  101 #include <X11/XawPlus/XawImP.h>
  102 #endif
  103 
  104 #endif
  105 
  106 #if OPT_WIDE_CHARS
  107 #include <xutf8.h>
  108 #include <wcwidth.h>
  109 #include <precompose.h>
  110 #ifdef HAVE_LANGINFO_CODESET
  111 #include <langinfo.h>
  112 #endif
  113 #endif
  114 
  115 #if USE_DOUBLE_BUFFER
  116 #include <X11/extensions/Xdbe.h>
  117 #endif
  118 
  119 #include <stdio.h>
  120 #include <ctype.h>
  121 #include <assert.h>
  122 
  123 #if defined(HAVE_SCHED_YIELD)
  124 #include <sched.h>
  125 #endif
  126 
  127 #include <VTparse.h>
  128 #include <data.h>
  129 #include <error.h>
  130 #include <menu.h>
  131 #include <main.h>
  132 #include <fontutils.h>
  133 #include <charclass.h>
  134 #include <xstrings.h>
  135 #include <graphics.h>
  136 
  137 #ifdef NO_LEAKS
  138 #include <xtermcap.h>
  139 #endif
  140 
  141 typedef int (*BitFunc) (unsigned * /* p */ ,
  142             unsigned /* mask */ );
  143 
  144 static IChar doinput(XtermWidget /* xw */ );
  145 static int set_character_class(char * /*s */ );
  146 static void FromAlternate(XtermWidget /* xw */ );
  147 static void ReallyReset(XtermWidget /* xw */ ,
  148             Bool /* full */ ,
  149             Bool /* saved */ );
  150 static void RequestResize(XtermWidget /* xw */ ,
  151               int /* rows */ ,
  152               int /* cols */ ,
  153               Bool /* text */ );
  154 static void SwitchBufs(XtermWidget /* xw */ ,
  155                int /* toBuf */ ,
  156                Bool /* clearFirst */ );
  157 static void ToAlternate(XtermWidget /* xw */ ,
  158             Bool /* clearFirst */ );
  159 static void ansi_modes(XtermWidget /* xw */ ,
  160                BitFunc /* func */ );
  161 static int bitclr(unsigned *p, unsigned mask);
  162 static int bitcpy(unsigned *p, unsigned q, unsigned mask);
  163 static int bitset(unsigned *p, unsigned mask);
  164 static void dpmodes(XtermWidget /* xw */ ,
  165             BitFunc /* func */ );
  166 static void restoremodes(XtermWidget /* xw */ );
  167 static void savemodes(XtermWidget /* xw */ );
  168 static void window_ops(XtermWidget /* xw */ );
  169 
  170 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
  171 #define SettableCursorBlink(screen) \
  172     (((screen)->cursor_blink != cbAlways) && \
  173      ((screen)->cursor_blink != cbNever))
  174 #define UpdateCursorBlink(xw) \
  175      SetCursorBlink(xw, TScreenOf(xw)->cursor_blink)
  176 static void SetCursorBlink(XtermWidget /* xw */ ,
  177                BlinkOps /* enable */ );
  178 static void HandleBlinking(XtPointer /* closure */ ,
  179                XtIntervalId * /* id */ );
  180 static void StartBlinking(XtermWidget /* xw */ );
  181 static void StopBlinking(XtermWidget /* xw */ );
  182 #else
  183 #define StartBlinking(xw)   /* nothing */
  184 #define StopBlinking(xw)    /* nothing */
  185 #endif
  186 
  187 #ifndef NO_ACTIVE_ICON
  188 static Boolean discount_frame_extents(XtermWidget /* xw */ ,
  189                       int * /* height */ ,
  190                       int * /* width */ );
  191 #else
  192 #define discount_frame_extents(xw, height, width)   False
  193 #endif
  194 
  195 #if OPT_INPUT_METHOD
  196 static void PreeditPosition(XtermWidget /* xw */ );
  197 #endif
  198 
  199 #define DEFAULT     -1
  200 #define BELLSUPPRESSMSEC 200
  201 
  202 static ANSI reply;
  203 static PARAMS parms;
  204 
  205 #define nparam parms.count
  206 
  207 #define InitParams()  init_params()
  208 #define GetParam(n)   parms.params[(n)]
  209 #define SetParam(n,v) parms.params[(n)] = v
  210 #define ParamPair(n)  nparam - (n), parms.params + (n)
  211 
  212 static jmp_buf vtjmpbuf;
  213 
  214 /* event handlers */
  215 static void HandleBell PROTO_XT_ACTIONS_ARGS;
  216 static void HandleIgnore PROTO_XT_ACTIONS_ARGS;
  217 static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS;
  218 static void HandleVisualBell PROTO_XT_ACTIONS_ARGS;
  219 #if HANDLE_STRUCT_NOTIFY
  220 static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS;
  221 #endif
  222 
  223 /*
  224  * NOTE: VTInitialize zeros out the entire ".screen" component of the
  225  * XtermWidget, so make sure to add an assignment statement in VTInitialize()
  226  * for each new ".screen" field added to this resource list.
  227  */
  228 
  229 /* Defaults */
  230 #if OPT_ISO_COLORS
  231 
  232 /*
  233  * If we default to colorMode enabled, compile-in defaults for the ANSI colors.
  234  */
  235 #if DFT_COLORMODE
  236 #define DFT_COLOR(name) name
  237 #else
  238 #define DFT_COLOR(name) XtDefaultForeground
  239 #endif
  240 #endif
  241 
  242 static char _Font_Selected_[] = "yes";  /* string is arbitrary */
  243 
  244 static const char *defaultTranslations;
  245 /* *INDENT-OFF* */
  246 static XtActionsRec actionsList[] = {
  247     { "allow-bold-fonts",   HandleAllowBoldFonts },
  248     { "allow-send-events",  HandleAllowSends },
  249     { "bell",           HandleBell },
  250     { "clear-saved-lines",  HandleClearSavedLines },
  251     { "copy-selection",     HandleCopySelection },
  252     { "create-menu",        HandleCreateMenu },
  253     { "delete-is-del",      HandleDeleteIsDEL },
  254     { "dired-button",       DiredButton },
  255     { "hard-reset",     HandleHardReset },
  256     { "ignore",         HandleIgnore },
  257     { "insert",         HandleKeyPressed },  /* alias for insert-seven-bit */
  258     { "insert-eight-bit",   HandleEightBitKeyPressed },
  259     { "insert-selection",   HandleInsertSelection },
  260     { "insert-seven-bit",   HandleKeyPressed },
  261     { "interpret",      HandleInterpret },
  262     { "keymap",         HandleKeymapChange },
  263     { "pointer-motion",     HandlePointerMotion },
  264     { "pointer-button",     HandlePointerButton },
  265     { "popup-menu",     HandlePopupMenu },
  266     { "print",          HandlePrintScreen },
  267     { "print-everything",   HandlePrintEverything },
  268     { "print-redir",        HandlePrintControlMode },
  269     { "quit",           HandleQuit },
  270     { "redraw",         HandleRedraw },
  271     { "scroll-back",        HandleScrollBack },
  272     { "scroll-forw",        HandleScrollForward },
  273     { "scroll-to",      HandleScrollTo },
  274     { "secure",         HandleSecure },
  275     { "select-cursor-end",  HandleKeyboardSelectEnd },
  276     { "select-cursor-extend",   HandleKeyboardSelectExtend },
  277     { "select-cursor-start",    HandleKeyboardSelectStart },
  278     { "select-end",     HandleSelectEnd },
  279     { "select-extend",      HandleSelectExtend },
  280     { "select-set",     HandleSelectSet },
  281     { "select-start",       HandleSelectStart },
  282     { "send-signal",        HandleSendSignal },
  283     { "set-8-bit-control",  Handle8BitControl },
  284     { "set-allow132",       HandleAllow132 },
  285     { "set-altscreen",      HandleAltScreen },
  286     { "set-appcursor",      HandleAppCursor },
  287     { "set-appkeypad",      HandleAppKeypad },
  288     { "set-autolinefeed",   HandleAutoLineFeed },
  289     { "set-autowrap",       HandleAutoWrap },
  290     { "set-backarrow",      HandleBackarrow },
  291     { "set-bellIsUrgent",   HandleBellIsUrgent },
  292     { "set-cursesemul",     HandleCursesEmul },
  293     { "set-jumpscroll",     HandleJumpscroll },
  294     { "set-keep-clipboard", HandleKeepClipboard },
  295     { "set-keep-selection", HandleKeepSelection },
  296     { "set-marginbell",     HandleMarginBell },
  297     { "set-old-function-keys",  HandleOldFunctionKeys },
  298     { "set-pop-on-bell",    HandleSetPopOnBell },
  299     { "set-reverse-video",  HandleReverseVideo },
  300     { "set-reversewrap",    HandleReverseWrap },
  301     { "set-scroll-on-key",  HandleScrollKey },
  302     { "set-scroll-on-tty-output", HandleScrollTtyOutput },
  303     { "set-scrollbar",      HandleScrollbar },
  304     { "set-select",     HandleSetSelect },
  305     { "set-sun-keyboard",   HandleSunKeyboard },
  306     { "set-titeInhibit",    HandleTiteInhibit },
  307     { "set-visual-bell",    HandleSetVisualBell },
  308     { "set-vt-font",        HandleSetFont },
  309     { "soft-reset",     HandleSoftReset },
  310     { "start-cursor-extend",    HandleKeyboardStartExtend },
  311     { "start-extend",       HandleStartExtend },
  312     { "string",         HandleStringEvent },
  313     { "vi-button",      ViButton },
  314     { "visual-bell",        HandleVisualBell },
  315 #ifdef ALLOWLOGGING
  316     { "set-logging",        HandleLogging },
  317 #endif
  318 #if OPT_ALLOW_XXX_OPS
  319     { "allow-color-ops",    HandleAllowColorOps },
  320     { "allow-font-ops",     HandleAllowFontOps },
  321     { "allow-mouse-ops",    HandleAllowMouseOps },
  322     { "allow-tcap-ops",     HandleAllowTcapOps },
  323     { "allow-title-ops",    HandleAllowTitleOps },
  324     { "allow-window-ops",   HandleAllowWindowOps },
  325 #endif
  326 #if OPT_BLINK_CURS
  327     { "set-cursorblink",    HandleCursorBlink },
  328 #endif
  329 #if OPT_BOX_CHARS
  330     { "set-font-linedrawing",   HandleFontBoxChars },
  331     { "set-font-packed",    HandleFontPacked },
  332 #endif
  333 #if OPT_DABBREV
  334     { "dabbrev-expand",     HandleDabbrevExpand },
  335 #endif
  336 #if OPT_DEC_CHRSET
  337     { "set-font-doublesize",    HandleFontDoublesize },
  338 #endif
  339 #if OPT_DEC_SOFTFONT
  340     { "set-font-loading",   HandleFontLoading },
  341 #endif
  342 #if OPT_EXEC_XTERM
  343     { "spawn-new-terminal", HandleSpawnTerminal },
  344 #endif
  345 #if OPT_GRAPHICS
  346     { "set-private-colors", HandleSetPrivateColorRegisters },
  347 #endif
  348 #if OPT_HP_FUNC_KEYS
  349     { "set-hp-function-keys",   HandleHpFunctionKeys },
  350 #endif
  351 #if OPT_LOAD_VTFONTS
  352     { "load-vt-fonts",      HandleLoadVTFonts },
  353 #endif
  354 #if OPT_MAXIMIZE
  355     { "deiconify",      HandleDeIconify },
  356     { "fullscreen",     HandleFullscreen },
  357     { "iconify",        HandleIconify },
  358     { "maximize",       HandleMaximize },
  359     { "restore",        HandleRestoreSize },
  360 #endif
  361 #if OPT_NUM_LOCK
  362     { "alt-sends-escape",   HandleAltEsc },
  363     { "meta-sends-escape",  HandleMetaEsc },
  364     { "set-num-lock",       HandleNumLock },
  365 #endif
  366 #if OPT_PRINT_ON_EXIT
  367     { "print-immediate",    HandlePrintImmediate },
  368     { "print-on-error",     HandlePrintOnError },
  369 #endif
  370 #if OPT_READLINE
  371     { "readline-button",    ReadLineButton },
  372 #endif
  373 #if OPT_RENDERFONT
  374     { "set-render-font",    HandleRenderFont },
  375 #endif
  376 #if OPT_SCO_FUNC_KEYS
  377     { "set-sco-function-keys",  HandleScoFunctionKeys },
  378 #endif
  379 #if OPT_SCREEN_DUMPS
  380     { "dump-html",          HandleDumpHtml },
  381     { "dump-svg",           HandleDumpSvg },
  382 #endif
  383 #if OPT_SCROLL_LOCK
  384     { "scroll-lock",        HandleScrollLock },
  385 #endif
  386 #if OPT_SELECTION_OPS
  387 #if OPT_EXEC_SELECTION
  388     { "exec-formatted",     HandleExecFormatted },
  389     { "exec-selectable",    HandleExecSelectable },
  390 #endif
  391     { "insert-formatted",   HandleInsertFormatted },
  392     { "insert-selectable",  HandleInsertSelectable },
  393 #endif
  394 #if OPT_SHIFT_FONTS
  395     { "larger-vt-font",     HandleLargerFont },
  396     { "smaller-vt-font",    HandleSmallerFont },
  397 #endif
  398 #if OPT_SIXEL_GRAPHICS
  399     { "set-sixel-scrolling",    HandleSixelScrolling },
  400 #endif
  401 #if OPT_SUN_FUNC_KEYS
  402     { "set-sun-function-keys",  HandleSunFunctionKeys },
  403 #endif
  404 #if OPT_TEK4014
  405     { "set-terminal-type",  HandleSetTerminalType },
  406     { "set-visibility",     HandleVisibility },
  407     { "set-tek-text",       HandleSetTekText },
  408     { "tek-page",       HandleTekPage },
  409     { "tek-reset",      HandleTekReset },
  410     { "tek-copy",       HandleTekCopy },
  411 #endif
  412 #if OPT_TOOLBAR
  413     { "set-toolbar",        HandleToolbar },
  414 #endif
  415 #if OPT_WIDE_CHARS
  416     { "set-utf8-mode",      HandleUTF8Mode },
  417     { "set-utf8-fonts",     HandleUTF8Fonts },
  418     { "set-utf8-title",     HandleUTF8Title },
  419 #endif
  420 };
  421 /* *INDENT-ON* */
  422 
  423 #define SPS screen.printer_state
  424 
  425 static XtResource xterm_resources[] =
  426 {
  427     Bres(XtNallowPasteControls, XtCAllowPasteControls,
  428      screen.allowPasteControl0, False),
  429     Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False),
  430     Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR),
  431     Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT),
  432     Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE),
  433     Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP),
  434     Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE),
  435     Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW),
  436     Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False),
  437     Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC),
  438     Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True),
  439     Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False),
  440     Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False),
  441     Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False),
  442     Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False),
  443     Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False),
  444     Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True),
  445     Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False),
  446     Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False),
  447     Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS),
  448     Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False),
  449     Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True),
  450     Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True),
  451     Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False),
  452     Bres(XtNc132, XtCC132, screen.c132, False),
  453     Sres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll_s, DEF_CD_XTRA_SCROLL),
  454     Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False),
  455     Bres(XtNcurses, XtCCurses, screen.curses, False),
  456     Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True),
  457     Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine,
  458      screen.cutToBeginningOfLine, True),
  459     Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL),
  460     Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True),
  461     Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False),
  462     Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True),
  463     Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True),
  464     Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True),
  465     Bres(XtNhighlightSelection, XtCHighlightSelection,
  466      screen.highlight_selection, False),
  467     Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False),
  468     Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False),
  469     Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True),
  470     Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False),
  471     Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True),
  472     Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False),
  473     Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True),
  474     Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False),
  475     Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False),
  476     Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC),
  477     Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False),
  478     Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False),
  479     Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False),
  480     Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False),
  481     Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False),
  482     Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False),
  483     Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True),
  484     Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False),
  485     Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False),
  486     Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False),
  487     Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False),
  488     Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False),
  489     Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False),
  490     Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True),
  491     Bres(XtNselectToClipboard, XtCSelectToClipboard,
  492      screen.selectToClipboard, False),
  493     Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False),
  494     Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False),
  495     Sres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll_s, DEF_TI_XTRA_SCROLL),
  496     Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False),
  497     Bres(XtNunderLine, XtCUnderLine, screen.underline, True),
  498     Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False),
  499     Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False),
  500 
  501     Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"),
  502 
  503     Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC),
  504     Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource),
  505     Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER),
  506     Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1),
  507     Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE),
  508     Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME),
  509     Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL),
  510     Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE),
  511     Ires(XtNprinterControlMode, XtCPrinterControlMode,
  512      SPS.printer_controlmode, 0),
  513     Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES),
  514     Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1),
  515     Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100),
  516     Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES),
  517     Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1),
  518     Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES),
  519 
  520     Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL),
  521     Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL),
  522     Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL),
  523     Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL),
  524     Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL),
  525     Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL),
  526     Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL),
  527     Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL),
  528 
  529     Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""),
  530     Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT),
  531     Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL),
  532     Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID),
  533     Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"),
  534     Sres(XtNdisallowedColorOps, XtCDisallowedColorOps,
  535      screen.disallowedColorOps, DEF_DISALLOWED_COLOR),
  536     Sres(XtNdisallowedFontOps, XtCDisallowedFontOps,
  537      screen.disallowedFontOps, DEF_DISALLOWED_FONT),
  538     Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps,
  539      screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE),
  540     Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls,
  541      screen.disallowedPasteOps, DEF_DISALLOWED_PASTE_CONTROLS),
  542     Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps,
  543      screen.disallowedTcapOps, DEF_DISALLOWED_TCAP),
  544     Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps,
  545      screen.disallowedWinOps, DEF_DISALLOWED_WINDOW),
  546     Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META),
  547     Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes,
  548      screen.eightbit_select_types, NULL),
  549     Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT),
  550     Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL),
  551     Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT),
  552     Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""),
  553     Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL),
  554     Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL),
  555 
  556     Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground),
  557     Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground),
  558     Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground),
  559     Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground),
  560     Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground),
  561 
  562     {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
  563      XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
  564      XtRImmediate, (XtPointer) SouthWestGravity},
  565 
  566     Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"),
  567 
  568 #ifdef ALLOWLOGGING
  569     Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False),
  570     Bres(XtNlogging, XtCLogging, misc.log_on, False),
  571     Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL),
  572 #endif
  573 
  574 #ifndef NO_ACTIVE_ICON
  575     Sres("activeIcon", "ActiveIcon", misc.active_icon_s, "default"),
  576     Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2),
  577     Sres("iconFont", "IconFont", screen.icon_fontname, "nil2"),
  578     Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground),
  579 #endif              /* NO_ACTIVE_ICON */
  580 
  581 #if OPT_BLINK_CURS
  582     Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True),
  583     Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"),
  584 #endif
  585     Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False),
  586     Bres(XtNcursorBar, XtCCursorBar, screen.cursor_bar, False),
  587 
  588 #if OPT_BLINK_TEXT
  589     Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD),
  590 #endif
  591 
  592 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
  593     Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600),
  594     Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300),
  595 #endif
  596 
  597 #if OPT_BOX_CHARS
  598     Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False),
  599     Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True),
  600     Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False),
  601     Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True),
  602 #endif
  603 
  604 #if OPT_BROKEN_OSC
  605     Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True),
  606 #endif
  607 
  608 #if OPT_BROKEN_ST
  609     Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False),
  610 #endif
  611 
  612 #if OPT_C1_PRINT
  613     Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False),
  614 #endif
  615 
  616 #if OPT_CLIP_BOLD
  617     Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True),
  618     Bres(XtNuseBorderClipping, XtCUseBorderClipping,
  619      screen.use_border_clipping, False),
  620 #endif
  621 
  622 #if OPT_DEC_CHRSET
  623     Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True),
  624     Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET),
  625 #endif
  626 
  627 #if OPT_DEC_RECTOPS
  628     Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC),
  629 #endif
  630 
  631 #if OPT_HIGHLIGHT_COLOR
  632     Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground),
  633     Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground),
  634     Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True),
  635     Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe),
  636 #endif              /* OPT_HIGHLIGHT_COLOR */
  637 
  638 #if OPT_INPUT_METHOD
  639     Bres(XtNopenIm, XtCOpenIm, misc.open_im, True),
  640     Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL),
  641     Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type,
  642      "OverTheSpot,Root"),
  643     Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3),
  644 #endif
  645 
  646 #if OPT_ISO_COLORS
  647     Bres(XtNboldColors, XtCColorMode, screen.boldColors, True),
  648     Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0),
  649     Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE),
  650 
  651     Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False),
  652     Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False),
  653     Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False),
  654     Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False),
  655     Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False),
  656     Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False),
  657 #if OPT_WIDE_ATTRS
  658     Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False),
  659 #endif
  660 #if OPT_DIRECT_COLOR
  661     Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True),
  662 #endif
  663 
  664     COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")),
  665     COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")),
  666     COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")),
  667     COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")),
  668     COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)),
  669     COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")),
  670     COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")),
  671     COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")),
  672     COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")),
  673     COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")),
  674     COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")),
  675     COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")),
  676     COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)),
  677     COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")),
  678     COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")),
  679     COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")),
  680     COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)),
  681     COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)),
  682     COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)),
  683     COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)),
  684 
  685 #if OPT_WIDE_ATTRS
  686     COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)),
  687 #endif
  688 
  689 #endif              /* OPT_ISO_COLORS */
  690 
  691     CLICK_RES("2", screen.onClick[1], "word"),
  692     CLICK_RES("3", screen.onClick[2], "line"),
  693     CLICK_RES("4", screen.onClick[3], 0),
  694     CLICK_RES("5", screen.onClick[4], 0),
  695 
  696     Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"),
  697 
  698 #if OPT_MOD_FKEYS
  699     Ires(XtNmodifyKeyboard, XtCModifyKeyboard,
  700      keyboard.modify_1st.allow_keys, 0),
  701     Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys,
  702      keyboard.modify_1st.cursor_keys, 2),
  703     Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys,
  704      keyboard.modify_1st.function_keys, 2),
  705     Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys,
  706      keyboard.modify_1st.keypad_keys, 0),
  707     Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys,
  708      keyboard.modify_1st.other_keys, 0),
  709     Ires(XtNmodifyStringKeys, XtCModifyStringKeys,
  710      keyboard.modify_1st.string_keys, 0),
  711     Ires(XtNformatOtherKeys, XtCFormatOtherKeys,
  712      keyboard.format_keys, 0),
  713 #endif
  714 
  715 #if OPT_NUM_LOCK
  716     Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False),
  717     Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True),
  718 #endif
  719 
  720 #if OPT_PRINT_COLORS
  721     Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1),
  722 #endif
  723 
  724 #if OPT_REGIS_GRAPHICS
  725     Sres(XtNregisDefaultFont, XtCRegisDefaultFont,
  726      screen.graphics_regis_default_font, ""),
  727     Sres(XtNregisScreenSize, XtCRegisScreenSize,
  728      screen.graphics_regis_screensize, "auto"),
  729 #endif
  730 
  731 #if OPT_GRAPHICS
  732     Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID),
  733     Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size,
  734      "1000x1000"),
  735 #endif
  736 
  737 #if OPT_ISO_COLORS && OPT_WIDE_ATTRS && OPT_SGR2_HASH
  738     Bres(XtNfaintIsRelative, XtCFaintIsRelative, screen.faint_relative, False),
  739 #endif
  740 
  741 #if OPT_SHIFT_FONTS
  742     Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True),
  743 #endif
  744 
  745 #if OPT_SIXEL_GRAPHICS
  746     Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, True),
  747     Bres(XtNsixelScrollsRight, XtCSixelScrollsRight,
  748      screen.sixel_scrolls_right, False),
  749 #endif
  750 
  751 #if OPT_GRAPHICS
  752     Ires(XtNnumColorRegisters, XtCNumColorRegisters,
  753      screen.numcolorregisters, 0),
  754     Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters,
  755      screen.privatecolorregisters, True),
  756 #endif
  757 
  758 #if OPT_STATUS_LINE
  759     Sres(XtNindicatorFormat, XtCIndicatorFormat, screen.status_fmt, DEF_SL_FORMAT),
  760 #endif
  761 
  762 #if OPT_SUNPC_KBD
  763     Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10),
  764 #endif
  765 
  766 #if OPT_TEK4014
  767     Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False),
  768     Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False),
  769     Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False),
  770 #endif
  771 
  772 #if OPT_TOOLBAR
  773     Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0),
  774     Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25),
  775 #endif
  776 
  777 #if OPT_WIDE_CHARS
  778     Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False),
  779     Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False),
  780     Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True),
  781     Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False),
  782     Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False),
  783     Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True),
  784     Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False),
  785     Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2),
  786     Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655),
  787     Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536),
  788     Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"),
  789     Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"),
  790     Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"),
  791     Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT),
  792     Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT),
  793     Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL),
  794 #endif
  795 
  796 #if OPT_LUIT_PROG
  797     Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"),
  798     Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER),
  799 #endif
  800 
  801 #if OPT_INPUT_METHOD
  802     Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT),
  803 #endif
  804 
  805 #if OPT_SCROLL_LOCK
  806     Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False),
  807     Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False),
  808 #endif
  809 
  810     /* these are used only for testing ncurses, not in the manual page */
  811 #if OPT_XMC_GLITCH
  812     Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False),
  813     Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True),
  814     Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1),
  815     Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0),
  816 #endif
  817 
  818 #ifdef SCROLLBAR_RIGHT
  819     Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False),
  820 #endif
  821 
  822 #if OPT_RENDERFONT
  823     Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False),
  824     Ires(XtNxftMaxGlyphMemory, XtCXftMaxGlyphMemory,
  825      screen.xft_max_glyph_memory, 0),
  826     Ires(XtNxftMaxUnrefFonts, XtCXftMaxUnrefFonts,
  827      screen.xft_max_unref_fonts, 0),
  828     Bres(XtNxftTrackMemUsage, XtCXftTrackMemUsage,
  829      screen.xft_track_mem_usage, DEF_TRACK_USAGE),
  830 #define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0")
  831     RES_FACESIZE(1),
  832     RES_FACESIZE(2),
  833     RES_FACESIZE(3),
  834     RES_FACESIZE(4),
  835     RES_FACESIZE(5),
  836     RES_FACESIZE(6),
  837     RES_FACESIZE(7),
  838     Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE),
  839     Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME),
  840     Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"),
  841     Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE),
  842     Ires(XtNlimitFontWidth, XtCLimitFontWidth, misc.limit_fontwidth, 10),
  843 #if OPT_RENDERWIDE
  844     Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME),
  845 #endif
  846 #endif
  847 };
  848 
  849 static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg,
  850                ArgList args, Cardinal *num_args);
  851 static void VTClassInit(void);
  852 static void VTDestroy(Widget w);
  853 static void VTExpose(Widget w, XEvent *event, Region region);
  854 static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args,
  855              Cardinal *num_args);
  856 static void VTRealize(Widget w, XtValueMask * valuemask,
  857               XSetWindowAttributes * values);
  858 static void VTResize(Widget w);
  859 
  860 #if OPT_INPUT_METHOD
  861 static void VTInitI18N(XtermWidget);
  862 #endif
  863 
  864 #ifdef VMS
  865 globaldef {
  866     "xtermclassrec"
  867 } noshare
  868 
  869 #else
  870 static
  871 #endif              /* VMS */
  872 WidgetClassRec xtermClassRec =
  873 {
  874     {
  875     /* core_class fields */
  876     (WidgetClass) & widgetClassRec,     /* superclass   */
  877     "VT100",        /* class_name                   */
  878     sizeof(XtermWidgetRec), /* widget_size                  */
  879     VTClassInit,        /* class_initialize             */
  880     NULL,           /* class_part_initialize        */
  881     False,          /* class_inited                 */
  882     VTInitialize,       /* initialize                   */
  883     NULL,           /* initialize_hook              */
  884     VTRealize,      /* realize                      */
  885     actionsList,        /* actions                      */
  886     XtNumber(actionsList),  /* num_actions                  */
  887     xterm_resources,    /* resources                    */
  888     XtNumber(xterm_resources),  /* num_resources        */
  889     NULLQUARK,      /* xrm_class                    */
  890     True,           /* compress_motion              */
  891     False,          /* compress_exposure            */
  892     True,           /* compress_enterleave          */
  893     False,          /* visible_interest             */
  894     VTDestroy,      /* destroy                      */
  895     VTResize,       /* resize                       */
  896     VTExpose,       /* expose                       */
  897     VTSetValues,        /* set_values                   */
  898     NULL,           /* set_values_hook              */
  899     XtInheritSetValuesAlmost,   /* set_values_almost    */
  900     NULL,           /* get_values_hook              */
  901     NULL,           /* accept_focus                 */
  902     XtVersion,      /* version                      */
  903     NULL,           /* callback_offsets             */
  904     0,          /* tm_table                     */
  905     XtInheritQueryGeometry, /* query_geometry               */
  906     XtInheritDisplayAccelerator,    /* display_accelerator  */
  907     NULL            /* extension                    */
  908     }
  909 };
  910 
  911 #ifdef VMS
  912 globaldef {
  913     "xtermwidgetclass"
  914 }
  915 noshare
  916 #endif /* VMS */
  917 WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec;
  918 
  919 /*
  920  * Add input-actions for widgets that are overlooked (scrollbar and toolbar):
  921  *
  922  *  a) Sometimes the scrollbar passes through translations, sometimes it
  923  *     doesn't.  We add the KeyPress translations here, just to be sure.
  924  *  b) In the normal (non-toolbar) configuration, the xterm widget covers
  925  *     almost all of the window.  With a toolbar, there's a relatively
  926  *     large area that the user would expect to enter keystrokes since the
  927  *     program can get the focus.
  928  */
  929 void
  930 xtermAddInput(Widget w)
  931 {
  932     /* *INDENT-OFF* */
  933     XtActionsRec input_actions[] = {
  934     { "insert",         HandleKeyPressed }, /* alias */
  935     { "insert-eight-bit",       HandleEightBitKeyPressed },
  936     { "insert-seven-bit",       HandleKeyPressed },
  937     { "pointer-motion",     HandlePointerMotion },
  938     { "pointer-button",     HandlePointerButton },
  939     { "secure",         HandleSecure },
  940     { "string",         HandleStringEvent },
  941     { "scroll-back",        HandleScrollBack },
  942     { "scroll-forw",        HandleScrollForward },
  943     { "scroll-to",          HandleScrollTo },
  944     { "select-cursor-end",      HandleKeyboardSelectEnd },
  945     { "select-cursor-extend",   HandleKeyboardSelectExtend },
  946     { "select-cursor-start",    HandleKeyboardSelectStart },
  947     { "insert-selection",       HandleInsertSelection },
  948     { "select-start",       HandleSelectStart },
  949     { "select-extend",      HandleSelectExtend },
  950     { "start-extend",       HandleStartExtend },
  951     { "select-end",         HandleSelectEnd },
  952     { "clear-saved-lines",      HandleClearSavedLines },
  953     { "popup-menu",         HandlePopupMenu },
  954     { "bell",           HandleBell },
  955     { "ignore",         HandleIgnore },
  956 #if OPT_DABBREV
  957     { "dabbrev-expand",     HandleDabbrevExpand },
  958 #endif
  959 #if OPT_MAXIMIZE
  960     { "fullscreen",         HandleFullscreen },
  961 #endif
  962 #if OPT_SCROLL_LOCK
  963     { "scroll-lock",        HandleScrollLock },
  964 #endif
  965 #if OPT_SHIFT_FONTS
  966     { "larger-vt-font",     HandleLargerFont },
  967     { "smaller-vt-font",        HandleSmallerFont },
  968 #endif
  969     };
  970     /* *INDENT-ON* */
  971 
  972     TRACE_TRANS("BEFORE", w);
  973     XtAppAddActions(app_con, input_actions, XtNumber(input_actions));
  974     XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations));
  975     TRACE_TRANS("AFTER:", w);
  976 
  977 #if OPT_EXTRA_PASTE
  978     if (term && term->keyboard.extra_translations)
  979     XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations));
  980 #endif
  981 }
  982 
  983 #if OPT_ISO_COLORS
  984 #ifdef EXP_BOGUS_FG
  985 static Bool
  986 CheckBogusForeground(TScreen *screen, const char *tag)
  987 {
  988     int row = -1, col = -1, pass;
  989     Bool isClear = True;
  990 
  991     (void) tag;
  992     for (pass = 0; pass < 2; ++pass) {
  993     row = screen->cur_row;
  994     for (; isClear && (row <= screen->max_row); ++row) {
  995         CLineData *ld = getLineData(screen, row);
  996 
  997         if (ld != 0) {
  998         IAttr *attribs = ld->attribs;
  999 
 1000         col = (row == screen->cur_row) ? screen->cur_col : 0;
 1001         for (; isClear && (col <= screen->max_col); ++col) {
 1002             unsigned flags = attribs[col];
 1003             if (pass) {
 1004             flags &= ~FG_COLOR;
 1005             attribs[col] = (IAttr) flags;
 1006             } else if ((flags & BG_COLOR)) {
 1007             isClear = False;
 1008             } else if ((flags & FG_COLOR)) {
 1009             unsigned ch = ld->charData[col];
 1010             isClear = ((ch == ' ') || (ch == 0));
 1011             } else {
 1012             isClear = False;
 1013             }
 1014         }
 1015         }
 1016     }
 1017     }
 1018     TRACE(("%s checked %d,%d to %d,%d %s pass %d\n",
 1019        tag, screen->cur_row, screen->cur_col,
 1020        row, col,
 1021        isClear && pass ? "cleared" : "unchanged",
 1022        pass));
 1023 
 1024     return isClear;
 1025 }
 1026 #endif
 1027 
 1028 /*
 1029  * The terminal's foreground and background colors are set via two mechanisms:
 1030  *  text (cur_foreground, cur_background values that are passed down to
 1031  *      XDrawImageString and XDrawString)
 1032  *  area (X11 graphics context used in XClearArea and XFillRectangle)
 1033  */
 1034 void
 1035 SGR_Foreground(XtermWidget xw, int color)
 1036 {
 1037     TScreen *screen = TScreenOf(xw);
 1038     Pixel fg;
 1039 
 1040     if (color >= 0) {
 1041     UIntSet(xw->flags, FG_COLOR);
 1042     } else {
 1043     UIntClr(xw->flags, FG_COLOR);
 1044     }
 1045     fg = getXtermFG(xw, xw->flags, color);
 1046     xw->cur_foreground = color;
 1047 
 1048     setCgsFore(xw, WhichVWin(screen), gcNorm, fg);
 1049     setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg);
 1050 
 1051     setCgsFore(xw, WhichVWin(screen), gcBold, fg);
 1052     setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg);
 1053 
 1054 #ifdef EXP_BOGUS_FG
 1055     /*
 1056      * If we've just turned off the foreground color, check for blank cells
 1057      * which have no background color, but do have foreground color.  This
 1058      * could happen due to setting the foreground color just before scrolling.
 1059      *
 1060      * Those cells look uncolored, but will confuse ShowCursor(), which looks
 1061      * for the colors in the current cell, and will see the foreground color.
 1062      * In that case, remove the foreground color from the blank cells.
 1063      */
 1064     if (color < 0) {
 1065     CheckBogusForeground(screen, "SGR_Foreground");
 1066     }
 1067 #endif
 1068 }
 1069 
 1070 void
 1071 SGR_Background(XtermWidget xw, int color)
 1072 {
 1073     TScreen *screen = TScreenOf(xw);
 1074     Pixel bg;
 1075 
 1076     /*
 1077      * An indexing operation may have set screen->scroll_amt, which would
 1078      * normally result in calling FlushScroll() in WriteText().  However,
 1079      * if we're changing the background color now, then the new value
 1080      * should not apply to the pending blank lines.
 1081      */
 1082     if (screen->scroll_amt && (color != xw->cur_background))
 1083     FlushScroll(xw);
 1084 
 1085     if (color >= 0) {
 1086     UIntSet(xw->flags, BG_COLOR);
 1087     } else {
 1088     UIntClr(xw->flags, BG_COLOR);
 1089     }
 1090     bg = getXtermBG(xw, xw->flags, color);
 1091     xw->cur_background = color;
 1092 
 1093     setCgsBack(xw, WhichVWin(screen), gcNorm, bg);
 1094     setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg);
 1095 
 1096     setCgsBack(xw, WhichVWin(screen), gcBold, bg);
 1097     setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg);
 1098 }
 1099 
 1100 /* Invoked after updating bold/underline flags, computes the extended color
 1101  * index to use for foreground.  (See also 'extract_fg()').
 1102  */
 1103 static void
 1104 setExtendedFG(XtermWidget xw)
 1105 {
 1106     int fg = xw->sgr_foreground;
 1107 
 1108     if (TScreenOf(xw)->colorAttrMode
 1109     || (fg < 0)) {
 1110     fg = MapToColorMode(fg, TScreenOf(xw), xw->flags);
 1111     }
 1112 
 1113     /* This implements the IBM PC-style convention of 8-colors, with one
 1114      * bit for bold, thus mapping the 0-7 codes to 8-15.  It won't make
 1115      * much sense for 16-color applications, but we keep it to retain
 1116      * compatibility with ANSI-color applications.
 1117      */
 1118 #if OPT_PC_COLORS       /* XXXJTL should be settable at runtime (resource or OSC?) */
 1119     if (TScreenOf(xw)->boldColors
 1120     && (!xw->sgr_38_xcolors)
 1121     && (fg >= 0)
 1122     && (fg < 8)
 1123     && (xw->flags & BOLD))
 1124     fg |= 8;
 1125 #endif
 1126 
 1127     SGR_Foreground(xw, fg);
 1128 }
 1129 
 1130 /* Invoked after updating inverse flag, computes the extended color
 1131  * index to use for background.  (See also 'extract_bg()').
 1132  */
 1133 static void
 1134 setExtendedBG(XtermWidget xw)
 1135 {
 1136     int bg = xw->sgr_background;
 1137 
 1138     if (TScreenOf(xw)->colorAttrMode
 1139     || (bg < 0)) {
 1140     if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE))
 1141         bg = COLOR_RV;
 1142     }
 1143 
 1144     SGR_Background(xw, bg);
 1145 }
 1146 
 1147 void
 1148 setExtendedColors(XtermWidget xw)
 1149 {
 1150     setExtendedFG(xw);
 1151     setExtendedBG(xw);
 1152 }
 1153 
 1154 static void
 1155 reset_SGR_Foreground(XtermWidget xw)
 1156 {
 1157     xw->sgr_foreground = -1;
 1158     xw->sgr_38_xcolors = False;
 1159     clrDirectFG(xw->flags);
 1160     setExtendedFG(xw);
 1161 }
 1162 
 1163 static void
 1164 reset_SGR_Background(XtermWidget xw)
 1165 {
 1166     xw->sgr_background = -1;
 1167     clrDirectBG(xw->flags);
 1168     setExtendedBG(xw);
 1169 }
 1170 
 1171 static void
 1172 reset_SGR_Colors(XtermWidget xw)
 1173 {
 1174     reset_SGR_Foreground(xw);
 1175     reset_SGR_Background(xw);
 1176 }
 1177 #endif /* OPT_ISO_COLORS */
 1178 
 1179 #if OPT_WIDE_ATTRS
 1180 /*
 1181  * Call this before changing the state of ATR_ITALIC, to update the GC fonts.
 1182  */
 1183 static void
 1184 setItalicFont(XtermWidget xw, Bool enable)
 1185 {
 1186     if (enable) {
 1187     if ((xw->flags & ATR_ITALIC) == 0) {
 1188         xtermLoadItalics(xw);
 1189         TRACE(("setItalicFont: enabling Italics\n"));
 1190         xtermUpdateFontGCs(xw, getItalicFont);
 1191     }
 1192     } else if ((xw->flags & ATR_ITALIC) != 0) {
 1193     TRACE(("setItalicFont: disabling Italics\n"));
 1194     xtermUpdateFontGCs(xw, getNormalFont);
 1195     }
 1196 }
 1197 
 1198 static void
 1199 ResetItalics(XtermWidget xw)
 1200 {
 1201     setItalicFont(xw, False);
 1202     UIntClr(xw->flags, ATR_ITALIC);
 1203 }
 1204 
 1205 #else
 1206 #define ResetItalics(xw)    /* nothing */
 1207 #endif
 1208 
 1209 static void
 1210 initCharset(TScreen *screen, int which, DECNRCM_codes code)
 1211 {
 1212     screen->gsets[which] = code;
 1213 }
 1214 
 1215 void
 1216 saveCharsets(TScreen *screen, DECNRCM_codes * target)
 1217 {
 1218     int g;
 1219     for (g = 0; g < NUM_GSETS; ++g) {
 1220     target[g] = screen->gsets[g];
 1221     }
 1222 }
 1223 
 1224 void
 1225 restoreCharsets(TScreen *screen, DECNRCM_codes * source)
 1226 {
 1227     int g;
 1228     for (g = 0; g < NUM_GSETS; ++g) {
 1229     screen->gsets[g] = source[g];
 1230     }
 1231 }
 1232 
 1233 void
 1234 resetCharsets(TScreen *screen)
 1235 {
 1236     TRACE(("resetCharsets\n"));
 1237 
 1238     initCharset(screen, 0, nrc_ASCII);
 1239     initCharset(screen, 1, nrc_ASCII);
 1240     initCharset(screen, 2, nrc_ASCII);
 1241     initCharset(screen, 3, nrc_ASCII);
 1242 
 1243     screen->curgl = 0;      /* G0 => GL.            */
 1244     screen->curgr = 2;      /* G2 => GR.            */
 1245     screen->curss = 0;      /* No single shift.     */
 1246 
 1247 #if OPT_VT52_MODE
 1248     if (screen->vtXX_level == 0)
 1249     initCharset(screen, 1, nrc_DEC_Spec_Graphic);   /* Graphics */
 1250 #endif
 1251 }
 1252 
 1253 static void
 1254 modified_DECNRCM(XtermWidget xw)
 1255 {
 1256 #if OPT_WIDE_CHARS
 1257     TScreen *screen = TScreenOf(xw);
 1258     if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) {
 1259     int enabled = ((xw->flags & NATIONAL) != 0);
 1260     int modefix;
 1261     EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix);
 1262     switchPtyData(screen, !enabled);
 1263     TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF"));
 1264     }
 1265 #else
 1266     (void) xw;
 1267 #endif
 1268 }
 1269 
 1270 /*
 1271  * VT300 and up support three ANSI conformance levels, defined according to
 1272  * the dpANSI X3.134.1 standard.  DEC's manuals equate levels 1 and 2, and
 1273  * are unclear.  This code is written based on the manuals.
 1274  */
 1275 static void
 1276 set_ansi_conformance(TScreen *screen, int level)
 1277 {
 1278     TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n",
 1279        level,
 1280        screen->vtXX_level * 100,
 1281        screen->terminal_id,
 1282        screen->ansi_level));
 1283     if (screen->vtXX_level >= 3) {
 1284     switch (screen->ansi_level = level) {
 1285     case 1:
 1286         /* FALLTHRU */
 1287     case 2:
 1288         initCharset(screen, 0, nrc_ASCII);  /* G0 is ASCII */
 1289         initCharset(screen, 1, nrc_ASCII);  /* G1 is ISO Latin-1 */
 1290         screen->curgl = 0;
 1291         screen->curgr = 1;
 1292         break;
 1293     case 3:
 1294         initCharset(screen, 0, nrc_ASCII);  /* G0 is ASCII */
 1295         screen->curgl = 0;
 1296         break;
 1297     }
 1298     }
 1299 }
 1300 
 1301 /*
 1302  * Set scrolling margins.  VTxxx terminals require that the top/bottom are
 1303  * different, so we have at least two lines in the scrolling region.
 1304  */
 1305 static void
 1306 set_tb_margins(TScreen *screen, int top, int bottom)
 1307 {
 1308     TRACE(("set_tb_margins %d..%d, prior %d..%d\n",
 1309        top, bottom,
 1310        screen->top_marg,
 1311        screen->bot_marg));
 1312     if (bottom > top) {
 1313     screen->top_marg = top;
 1314     screen->bot_marg = bottom;
 1315     }
 1316     if (screen->top_marg > screen->max_row)
 1317     screen->top_marg = screen->max_row;
 1318     if (screen->bot_marg > screen->max_row)
 1319     screen->bot_marg = screen->max_row;
 1320 }
 1321 
 1322 static void
 1323 set_lr_margins(TScreen *screen, int left, int right)
 1324 {
 1325     TRACE(("set_lr_margins %d..%d, prior %d..%d\n",
 1326        left, right,
 1327        screen->lft_marg,
 1328        screen->rgt_marg));
 1329     if (right > left) {
 1330     screen->lft_marg = left;
 1331     screen->rgt_marg = right;
 1332     }
 1333     if (screen->lft_marg > screen->max_col)
 1334     screen->lft_marg = screen->max_col;
 1335     if (screen->rgt_marg > screen->max_col)
 1336     screen->rgt_marg = screen->max_col;
 1337 }
 1338 
 1339 #define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row)
 1340 #define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col)
 1341 
 1342 void
 1343 resetMargins(XtermWidget xw)
 1344 {
 1345     TScreen *screen = TScreenOf(xw);
 1346 
 1347     reset_tb_margins(screen);
 1348     reset_lr_margins(screen);
 1349 }
 1350 
 1351 static void
 1352 resetMarginMode(XtermWidget xw)
 1353 {
 1354     UIntClr(xw->flags, LEFT_RIGHT);
 1355     resetMargins(xw);
 1356 }
 1357 
 1358 static void
 1359 resetRendition(XtermWidget xw)
 1360 {
 1361     TScreen *screen = TScreenOf(xw);
 1362     (void) screen;
 1363     ResetItalics(xw);
 1364     UIntClr(xw->flags,
 1365         (SGR_MASK | SGR_MASK2 | INVISIBLE));
 1366 }
 1367 
 1368 void
 1369 set_max_col(TScreen *screen, int cols)
 1370 {
 1371     TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col));
 1372     if (cols < 0)
 1373     cols = 0;
 1374     screen->max_col = cols;
 1375 }
 1376 
 1377 void
 1378 set_max_row(TScreen *screen, int rows)
 1379 {
 1380     TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row));
 1381     if (rows < 0)
 1382     rows = 0;
 1383     screen->max_row = rows;
 1384 }
 1385 
 1386 #if OPT_TRACE
 1387 #define DATA(name) { name, #name }
 1388 static const struct {
 1389     Const PARSE_T *table;
 1390     const char *name;
 1391 } all_tables[] = {
 1392 
 1393     DATA(ansi_table)
 1394     ,DATA(cigtable)
 1395     ,DATA(csi2_table)
 1396     ,DATA(csi_ex_table)
 1397     ,DATA(csi_quo_table)
 1398     ,DATA(csi_table)
 1399     ,DATA(dec2_table)
 1400     ,DATA(dec3_table)
 1401     ,DATA(dec_table)
 1402     ,DATA(eigtable)
 1403     ,DATA(esc_sp_table)
 1404     ,DATA(esc_table)
 1405     ,DATA(scrtable)
 1406     ,DATA(scs96table)
 1407     ,DATA(scstable)
 1408     ,DATA(sos_table)
 1409 #if OPT_BLINK_CURS
 1410     ,DATA(csi_sp_table)
 1411 #endif
 1412 #if OPT_DEC_LOCATOR
 1413     ,DATA(csi_tick_table)
 1414 #endif
 1415 #if OPT_DEC_RECTOPS
 1416     ,DATA(csi_dollar_table)
 1417     ,DATA(csi_star_table)
 1418     ,DATA(csi_dec_dollar_table)
 1419 #endif
 1420 #if OPT_WIDE_CHARS
 1421     ,DATA(esc_pct_table)
 1422     ,DATA(scs_amp_table)
 1423     ,DATA(scs_pct_table)
 1424     ,DATA(scs_2qt_table)
 1425 #endif
 1426 #if OPT_VT52_MODE
 1427     ,DATA(vt52_table)
 1428     ,DATA(vt52_esc_table)
 1429     ,DATA(vt52_ignore_table)
 1430 #endif
 1431 #if OPT_XTERM_SGR
 1432     ,DATA(csi_hash_table)
 1433 #endif
 1434 #undef DATA
 1435 };
 1436 
 1437 #define WHICH_TABLE(name) if (table == name) result = #name
 1438 static const char *
 1439 which_table(Const PARSE_T * table)
 1440 {
 1441     const char *result = "?";
 1442     Cardinal n;
 1443     for (n = 0; n < XtNumber(all_tables); ++n) {
 1444     if (table == all_tables[n].table) {
 1445         result = all_tables[n].name;
 1446         break;
 1447     }
 1448     }
 1449 
 1450     return result;
 1451 }
 1452 
 1453 static void
 1454 check_tables(void)
 1455 {
 1456     Cardinal n;
 1457     int ch;
 1458     int total_codes = 0;
 1459     int total_ground = 0;
 1460     int total_ignored = 0;
 1461 
 1462     TRACE(("** check_tables\n"));
 1463     for (n = 0; n < XtNumber(all_tables); ++n) {
 1464     Const PARSE_T *table = all_tables[n].table;
 1465     TRACE(("*** %s\n", all_tables[n].name));
 1466     /*
 1467      * Most of the tables should use the same codes in 0..31, 128..159
 1468      * as the "ansi" table.
 1469      */
 1470     if (strncmp(all_tables[n].name, "ansi", 4) &&
 1471         strncmp(all_tables[n].name, "sos_", 4) &&
 1472         strncmp(all_tables[n].name, "vt52", 4)) {
 1473         for (ch = 0; ch < 32; ++ch) {
 1474         int c1 = ch + 128;
 1475         PARSE_T st_l = table[ch];
 1476         PARSE_T st_r = table[c1];
 1477         if (st_l != ansi_table[ch]) {
 1478             TRACE(("  %3d: %d vs %d\n", ch, st_l, ansi_table[ch]));
 1479         }
 1480         if (st_r != ansi_table[c1]) {
 1481             TRACE(("  %3d: %d vs %d\n", c1, st_r, ansi_table[c1]));
 1482         }
 1483         }
 1484     }
 1485     /*
 1486      * All of the tables should have their GL/GR parts encoded the same.
 1487      */
 1488     for (ch = 32; ch < 127; ++ch) {
 1489         PARSE_T st_l = table[ch];
 1490         PARSE_T st_r = table[ch + 128];
 1491         if (st_l != st_r) {
 1492         if (st_r == CASE_IGNORE &&
 1493             !strncmp(all_tables[n].name, "vt52", 4)) {
 1494             ;
 1495         } else {
 1496             TRACE(("  %3d: %d vs %d\n", ch, st_l, st_r));
 1497         }
 1498         }
 1499     }
 1500     /*
 1501      * Just for amusement, show how sparse the encoding tables are.
 1502      */
 1503     for (ch = 0; ch < 256; ++ch) {
 1504         ++total_codes;
 1505         switch (table[ch]) {
 1506         case CASE_GROUND_STATE:
 1507         total_ground++;
 1508         break;
 1509         case CASE_ESC_IGNORE:
 1510         /* FALLTHRU */
 1511         case CASE_IGNORE:
 1512         /* FALLTHRU */
 1513         case CASE_VT52_IGNORE:
 1514         total_ignored++;
 1515         break;
 1516         }
 1517     }
 1518     }
 1519     TRACE(("VTPrsTbl:\n"));
 1520     TRACE(("%d total codes\n", total_codes));
 1521     TRACE(("%d total ignored\n", total_ignored));
 1522     TRACE(("%d total reset/ground\n", total_ground));
 1523 }
 1524 
 1525 static void
 1526 check_bitmasks(void)
 1527 {
 1528 #define dMSK 0x100
 1529 #define DATA(mode,name) { mode, name, #name }
 1530 #define DMSK(what) (dMSK | (what))
 1531 #define DGRP(offs) (1 << ((offs) - 1))
 1532     static struct {
 1533     int mode;
 1534     int code;
 1535     Const char *name;
 1536     } table[] = {
 1537     DATA(DGRP(1), INVERSE),
 1538         DATA(DGRP(1), UNDERLINE),
 1539         DATA(DGRP(1), BOLD),
 1540         DATA(DGRP(1), BLINK),
 1541         DATA(DMSK(DGRP(1)), SGR_MASK),
 1542         DATA(DGRP(2), BG_COLOR),
 1543         DATA(DGRP(2), FG_COLOR),
 1544         DATA(DGRP(2), PROTECTED),
 1545         DATA(DGRP(4), CHARDRAWN),
 1546 #if OPT_WIDE_ATTRS
 1547         DATA(DGRP(2), ATR_FAINT),
 1548         DATA(DGRP(2), ATR_ITALIC),
 1549         DATA(DGRP(2), ATR_STRIKEOUT),
 1550         DATA(DGRP(2), ATR_DBL_UNDER),
 1551         DATA(DGRP(2), ATR_DIRECT_FG),
 1552         DATA(DGRP(2), ATR_DIRECT_BG),
 1553 #endif
 1554         DATA(DMSK(DGRP(2)), SGR_MASK2),
 1555         DATA(DGRP(3), WRAPAROUND),
 1556         DATA(DGRP(3), REVERSEWRAP),
 1557         DATA(DGRP(3), REVERSE_VIDEO),
 1558         DATA(DGRP(3), LINEFEED),
 1559         DATA(DGRP(3), ORIGIN),
 1560         DATA(DGRP(3), INSERT),
 1561         DATA(DGRP(3), SMOOTHSCROLL),
 1562         DATA(DGRP(3), IN132COLUMNS),
 1563         DATA(DGRP(3), INVISIBLE),
 1564         DATA(DMSK(DGRP(3)), ATTRIBUTES),
 1565         DATA(DGRP(5), NATIONAL),
 1566         DATA(DGRP(5), LEFT_RIGHT),
 1567         DATA(DGRP(5), NOCLEAR_COLM),
 1568         DATA(DGRP(4), NOBACKGROUND),
 1569         DATA(DGRP(4), NOTRANSLATION),
 1570         DATA(DGRP(4), DOUBLEWFONT),
 1571         DATA(DGRP(4), DOUBLEHFONT),
 1572         DATA(DGRP(4), CHARBYCHAR),
 1573         DATA(DGRP(4), NORESOLUTION),
 1574         DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK),
 1575         DATA(-1, EOF)
 1576     };
 1577 #undef DATA
 1578     int j, k;
 1579     TRACE(("** check_bitmasks:\n"));
 1580     for (j = 0; table[j].mode >= 0; ++j) {
 1581     TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name));
 1582     if (table[j].mode & dMSK) {
 1583         int mask = dMSK;
 1584         for (k = 0; table[k].mode >= 0; ++k) {
 1585         if (j == k)
 1586             continue;
 1587         if (table[k].mode & dMSK)
 1588             continue;
 1589         if ((table[j].mode & table[k].mode) != 0)
 1590             mask |= table[k].mode;
 1591         }
 1592         if (mask != table[j].mode) {
 1593         TRACE(("...expected %08X\n", mask));
 1594         }
 1595     } else {
 1596         for (k = 0; table[k].mode >= 0; ++k) {
 1597         if (j == k)
 1598             continue;
 1599         if (table[k].mode & dMSK)
 1600             continue;
 1601         if ((table[j].code & table[k].code) != 0) {
 1602             TRACE(("...same bits %s\n", table[k].name));
 1603         }
 1604         }
 1605     }
 1606     }
 1607 }
 1608 #endif
 1609 
 1610 static int
 1611 init_params(void)
 1612 {
 1613     while (parms.count-- > 0) {
 1614     parms.is_sub[parms.count] = 0;
 1615     parms.params[parms.count] = 0;
 1616     }
 1617     parms.count = 0;
 1618     parms.has_subparams = 0;
 1619     return 0;
 1620 }
 1621 
 1622 #if OPT_TRACE > 0
 1623 static void
 1624 dump_params(void)
 1625 {
 1626     int n;
 1627     int arg;
 1628     TRACE(("params %d (%d)\n", nparam, parms.has_subparams));
 1629     for (arg = 1, n = 0; n < nparam; ++n) {
 1630     TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n]));
 1631     if (!parms.is_sub[n])
 1632         ++arg;
 1633     }
 1634 }
 1635 #define DumpParams() dump_params()
 1636 #else
 1637 #define DumpParams()        /* nothing */
 1638 #endif
 1639 
 1640     /* allocate larger buffer if needed/possible */
 1641 #define SafeAlloc(type, area, used, size) \
 1642         type *new_string = area; \
 1643         size_t new_length = size; \
 1644         if (new_length == 0) { \
 1645             new_length = 1024; \
 1646             new_string = TypeMallocN(type, new_length); \
 1647         } else if (used+1 >= new_length) { \
 1648             new_length = size * 2; \
 1649             new_string = TypeMallocN(type, new_length); \
 1650             if (new_string != 0 \
 1651              && area != 0 \
 1652              && used != 0) { \
 1653             memcpy(new_string, area, used * sizeof(type)); \
 1654              } \
 1655         }
 1656 #define SafeFree(area, size) \
 1657         if (area != new_string) { \
 1658             free(area); \
 1659             area = new_string; \
 1660         } \
 1661         size = new_length
 1662 
 1663 #define WriteNow() {                        \
 1664         unsigned single = 0;                \
 1665                                 \
 1666         if (screen->curss) {                \
 1667         dotext(xw,                  \
 1668                screen->gsets[(int) (screen->curss)],    \
 1669                sp->print_area,              \
 1670                (Cardinal) 1);               \
 1671         screen->curss = 0;              \
 1672         single++;                   \
 1673         }                           \
 1674         if (sp->print_used > single) {          \
 1675         dotext(xw,                  \
 1676                screen->gsets[(int) (screen->curgl)],    \
 1677                sp->print_area + single,         \
 1678                (Cardinal) (sp->print_used - single));   \
 1679         }                           \
 1680         sp->print_used = 0;                 \
 1681     }                           \
 1682 
 1683 #define PARSE_SRM 1
 1684 
 1685 struct ParseState {
 1686     unsigned check_recur;
 1687 #if OPT_VT52_MODE
 1688     Bool vt52_cup;
 1689 #endif
 1690     Const PARSE_T *groundtable;
 1691     Const PARSE_T *parsestate;
 1692     int scstype;
 1693     int scssize;
 1694     Bool private_function;  /* distinguish private-mode from standard */
 1695     int string_mode;        /* nonzero iff we're processing a string */
 1696     int lastchar;       /* positive iff we had a graphic character */
 1697     int nextstate;
 1698 #if OPT_WIDE_CHARS
 1699     int last_was_wide;
 1700 #endif
 1701     /* Buffer for processing printable text */
 1702     IChar *print_area;
 1703     size_t print_size;
 1704     size_t print_used;
 1705     /* Buffer for processing strings (e.g., OSC ... ST) */
 1706     Char *string_area;
 1707     size_t string_size;
 1708     size_t string_used;
 1709     /* Buffer for deferring input */
 1710     Char *defer_area;
 1711     size_t defer_size;
 1712     size_t defer_used;
 1713 };
 1714 
 1715 static struct ParseState myState;
 1716 
 1717 static void
 1718 init_groundtable(TScreen *screen, struct ParseState *sp)
 1719 {
 1720     (void) screen;
 1721 
 1722 #if OPT_VT52_MODE
 1723     if (!(screen->vtXX_level)) {
 1724     sp->groundtable = vt52_table;
 1725     } else if (screen->terminal_id >= 100)
 1726 #endif
 1727     {
 1728     sp->groundtable = ansi_table;
 1729     }
 1730 }
 1731 
 1732 static void
 1733 select_charset(struct ParseState *sp, int type, int size)
 1734 {
 1735     TRACE(("select_charset G%d size %d -> G%d size %d\n",
 1736        sp->scstype, sp->scssize,
 1737        type, size));
 1738 
 1739     sp->scstype = type;
 1740     sp->scssize = size;
 1741     if (size == 94) {
 1742     sp->parsestate = scstable;
 1743     } else {
 1744     sp->parsestate = scs96table;
 1745     }
 1746 }
 1747 /* *INDENT-OFF* */
 1748 static const struct {
 1749     DECNRCM_codes result;
 1750     int prefix;
 1751     int suffix;
 1752     int min_level;
 1753     int max_level;
 1754     int need_nrc;
 1755 } scs_table[] = {
 1756     { nrc_ASCII,             0,   'B', 1, 9, 0 },
 1757     { nrc_British,           0,   'A', 1, 9, 0 },
 1758     { nrc_DEC_Spec_Graphic,  0,   '0', 1, 9, 0 },
 1759     { nrc_DEC_Alt_Chars,     0,   '1', 1, 1, 0 },
 1760     { nrc_DEC_Alt_Graphics,  0,   '2', 1, 1, 0 },
 1761     /* VT2xx */
 1762     { nrc_DEC_Supp,          0,   '<', 2, 9, 0 },
 1763     { nrc_Dutch,             0,   '4', 2, 9, 1 },
 1764     { nrc_Finnish,           0,   '5', 2, 9, 1 },
 1765     { nrc_Finnish2,          0,   'C', 2, 9, 1 },
 1766     { nrc_French,            0,   'R', 2, 9, 1 },
 1767     { nrc_French2,           0,   'f', 2, 9, 1 },
 1768     { nrc_French_Canadian,   0,   'Q', 2, 9, 1 },
 1769     { nrc_German,            0,   'K', 2, 9, 1 },
 1770     { nrc_Italian,           0,   'Y', 2, 9, 1 },
 1771     { nrc_Norwegian_Danish2, 0,   'E', 2, 9, 1 },
 1772     { nrc_Norwegian_Danish3, 0,   '6', 2, 9, 1 },
 1773     { nrc_Spanish,           0,   'Z', 2, 9, 1 },
 1774     { nrc_Swedish,           0,   '7', 2, 9, 1 },
 1775     { nrc_Swedish2,          0,   'H', 2, 9, 1 },
 1776     { nrc_Swiss,             0,   '=', 2, 9, 1 },
 1777     /* VT3xx */
 1778     { nrc_British_Latin_1,   0,   'A', 3, 9, 1 },
 1779     { nrc_DEC_Supp_Graphic,  '%', '5', 3, 9, 0 },
 1780     { nrc_DEC_Technical,     0,   '>', 3, 9, 0 },
 1781     { nrc_French_Canadian2,  0,   '9', 3, 9, 1 },
 1782     { nrc_Norwegian_Danish,  0,   '`', 3, 9, 1 },
 1783     { nrc_Portugese,         '%', '6', 3, 9, 1 },
 1784     { nrc_ISO_Latin_1_Supp,  0,   'A', 3, 9, 0 },
 1785     /* VT5xx */
 1786     { nrc_Greek,             '"', '>', 5, 9, 1 },
 1787     { nrc_Hebrew,            '%', '=', 5, 9, 1 },
 1788     { nrc_Turkish,       '%', '2', 5, 9, 1 },
 1789     { nrc_DEC_Cyrillic,      '&', '4', 5, 9, 0 },
 1790     { nrc_DEC_Greek_Supp,    '"', '?', 5, 9, 0 },
 1791     { nrc_DEC_Hebrew_Supp,   '"', '4', 5, 9, 0 },
 1792     { nrc_DEC_Turkish_Supp,  '%', '0', 5, 9, 0 },
 1793     { nrc_ISO_Greek_Supp,    0,   'F', 5, 9, 0 },
 1794     { nrc_ISO_Hebrew_Supp,   0,   'H', 5, 9, 0 },
 1795     { nrc_ISO_Latin_2_Supp,  0,   'B', 5, 9, 0 },
 1796     { nrc_ISO_Latin_5_Supp,  0,   'M', 5, 9, 0 },
 1797     { nrc_ISO_Latin_Cyrillic,0,   'L', 5, 9, 0 },
 1798     /* VT5xx (not implemented) */
 1799 #if 0
 1800     { nrc_Russian,           '&', '5', 5, 9, 1 },
 1801     { nrc_SCS_NRCS,          '%', '3', 5, 9, 0 },
 1802 #endif
 1803 };
 1804 /* *INDENT-ON* */
 1805 
 1806 #if OPT_DEC_RECTOPS
 1807 static char *
 1808 encode_scs(DECNRCM_codes value)
 1809 {
 1810     static char buffer[3];
 1811     Cardinal n;
 1812     char *result = buffer;
 1813     for (n = 0; n < XtNumber(scs_table); ++n) {
 1814     if (scs_table[n].result == value) {
 1815         if (scs_table[n].prefix)
 1816         *result++ = (char) scs_table[n].prefix;
 1817         if (scs_table[n].suffix)
 1818         *result++ = (char) scs_table[n].suffix;
 1819         break;
 1820     }
 1821     }
 1822     *result = '\0';
 1823     return buffer;
 1824 }
 1825 #endif
 1826 
 1827 void
 1828 xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix)
 1829 {
 1830     TScreen *screen = TScreenOf(xw);
 1831     Cardinal n;
 1832     DECNRCM_codes result = nrc_Unknown;
 1833 
 1834     suffix &= 0x7f;
 1835     for (n = 0; n < XtNumber(scs_table); ++n) {
 1836     if (prefix == scs_table[n].prefix
 1837         && suffix == scs_table[n].suffix
 1838         && sgroup == scs_table[n].min_level
 1839         && screen->vtXX_level >= scs_table[n].min_level
 1840         && screen->vtXX_level <= scs_table[n].max_level
 1841         && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) {
 1842         result = scs_table[n].result;
 1843         break;
 1844     }
 1845     }
 1846     if (result != nrc_Unknown) {
 1847     initCharset(screen, which, result);
 1848     TRACE(("setting G%d to table #%d %s",
 1849            which, n, visibleScsCode((int) result)));
 1850     } else {
 1851     TRACE(("...unknown GSET"));
 1852     initCharset(screen, which, nrc_ASCII);
 1853     }
 1854 #if OPT_TRACE
 1855     TRACE((" ("));
 1856     if (prefix)
 1857     TRACE(("prefix='%c', ", prefix));
 1858     TRACE(("suffix='%c', sgroup=%d", suffix, sgroup));
 1859     TRACE((")\n"));
 1860 #endif
 1861 }
 1862 
 1863 /*
 1864  * Given a parameter number, and subparameter (starting in each case from zero)
 1865  * return the corresponding index into the parameter array.  If the combination
 1866  * is not found, return -1.
 1867  */
 1868 static int
 1869 subparam_index(int p, int s)
 1870 {
 1871     int result = -1;
 1872     int j, p2, s2;
 1873 
 1874     for (j = p2 = 0; j < nparam; ++j, ++p2) {
 1875     if (parms.is_sub[j]) {
 1876         s2 = 0;
 1877 
 1878         do {
 1879         if ((p == p2) && (s == s2)) {
 1880             result = j;
 1881             break;
 1882         }
 1883         ++s2;
 1884         } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j]));
 1885 
 1886         if (result >= 0)
 1887         break;
 1888 
 1889         --j;        /* undo the last "while" */
 1890     } else if (p == p2) {
 1891         if (s == 0) {
 1892         result = j;
 1893         }
 1894         break;
 1895     }
 1896     }
 1897     TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result));
 1898     return result;
 1899 }
 1900 
 1901 /*
 1902  * Check if the given item in the parameter array has subparameters.
 1903  * If so, return the number of subparameters to use as a loop limit, etc.
 1904  */
 1905 static int
 1906 param_has_subparams(int item)
 1907 {
 1908     int result = 0;
 1909     if (parms.has_subparams) {
 1910     int n = subparam_index(item, 0);
 1911     if (n >= 0 && parms.is_sub[n]) {
 1912         while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) {
 1913         result++;
 1914         }
 1915     }
 1916     }
 1917     TRACE(("...param_has_subparams(%d) ->%d\n", item, result));
 1918     return result;
 1919 }
 1920 
 1921 #if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS
 1922 /*
 1923  * Given an index into the parameter array, return the corresponding parameter
 1924  * number (starting from zero).
 1925  */
 1926 static int
 1927 param_number(int item)
 1928 {
 1929     int result = -1;
 1930     int j, p;
 1931 
 1932     for (j = p = 0; j < nparam; ++j, ++p) {
 1933     if (p >= item) {
 1934         result = j;
 1935         break;
 1936     }
 1937     if (parms.is_sub[j]) {
 1938         while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) {
 1939         /* EMPTY */
 1940         }
 1941         --j;
 1942     }
 1943     }
 1944 
 1945     TRACE2(("...param_number(%d) = %d\n", item, result));
 1946     return result;
 1947 }
 1948 
 1949 static int
 1950 get_subparam(int p, int s)
 1951 {
 1952     int item = subparam_index(p, s);
 1953     int result = (item >= 0) ? parms.params[item] : DEFAULT;
 1954     TRACE(("...get_subparam[%d] = %d\n", item, result));
 1955     return result;
 1956 }
 1957 
 1958 /*
 1959  * Some background -
 1960  *
 1961  * Todd Larason provided the initial changes to support 256-colors in July 1999.
 1962  * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and
 1963  * was unsure if there would be some standard using those codes.  His response
 1964  * was that this was documented (it turns out, in equally vague terms) in ITU
 1965  * T.416
 1966  *
 1967  * Discussing this with Todd Larason in mid-1999, my point was that given the
 1968  * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going
 1969  * to be effective (more than $100 then, more than $200 in 2012)
 1970  *
 1971  * We overlooked the detail about ":" as a subparameter delimiter (documented
 1972  * in 5.4.2 in ECMA-48).  Some discussion in KDE in mid-2006 led Lars Doelle
 1973  * to discuss the issue with me.  Lars' initial concern dealt with the fact
 1974  * that a sequence such as
 1975  *  CSI 38 ; 5 ; 1 m
 1976  * violated the principle that SGR parameters could be used in any order.
 1977  * Further discussion (see KDE #107487) resolved that the standard expected
 1978  * that the sequence would look like
 1979  *  CSI 38 ; 5 : 1 m
 1980  * which still violates that principle, since the "5:1" parameter has to
 1981  * follow the "38" to be useful.
 1982  *
 1983  * This function accepts either format (per request by Paul Leonerd Evans).
 1984  * It also accepts
 1985  *  CSI 38 : 5 : 1 m
 1986  * according to Lars' original assumption.  While implementing that, I added
 1987  * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value.
 1988  * ISO-8613-6 documents that as "direct color".
 1989  *
 1990  * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's
 1991  * quirk in the description of direct color:  it mentions a color space
 1992  * identifier parameter which should follow the "2" (as parameter 1).  In the
 1993  * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as
 1994  * well as parameters 7 and 8.  Like parameter 1, parameters 7 and 8 are not
 1995  * defined clearly in the standard, and a close reading indicates they are
 1996  * optional, saying they "may be used".  This implementation ignores parameters
 1997  * 6 (and above), and provides for the color space identifier by checking the
 1998  * number of parameters:
 1999  *  3 after "2" (no color space identifier)
 2000  *  4 or more after "2" (color space identifier)
 2001  *
 2002  * By the way - all of the parameters are decimal integers, and missing
 2003  * parameters represent a default value.  ISO-8613-6 is clear about that.
 2004  *
 2005  * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter.
 2006  * ECMA-48 says only:
 2007  *
 2008  *  5.4.2 Parameter string format
 2009  *
 2010  *  A parameter string which does not start with a bit combination in the
 2011  *  range 03/12 to 03/15 shall have the following format:
 2012  *
 2013  *      a) A parameter string consists of one or more parameter
 2014  *         sub-strings, each of which represents a number in decimal
 2015  *         notation.
 2016  *
 2017  *      b) Each parameter sub-string consists of one or more bit
 2018  *         combinations from 03/00 to 03/10; the bit combinations from
 2019  *         03/00 to 03/09 represent the digits ZERO to NINE; bit
 2020  *         combination 03/10 may be used as a separator in a parameter
 2021  *         sub-string, for example, to separate the fractional part of a
 2022  *         decimal number from the integer part of that number.
 2023  *
 2024  * That is, there is no mention in ECMA-48 of the possibility that a parameter
 2025  * string might be a list of parameters, as done in ISO-8613-3 (nor does
 2026  * ECMA-48 provide an example where the ":" separator might be used).  Because
 2027  * of this, xterm treats other cases than those needed for ISO-8613-3 as an
 2028  * error, and stops interpreting the sequence.
 2029  */
 2030 #define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0))
 2031 static Boolean
 2032 parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended)
 2033 {
 2034     Boolean result = False;
 2035     int item = *itemp;
 2036     int next = item;
 2037     int base = param_number(item);
 2038     int code = -1;
 2039     int values[3];      /* maximum number of subparameters */
 2040     int need = 0;       /* number of subparameters needed */
 2041     int have;
 2042     int n;
 2043 
 2044     /*
 2045      * On entry, 'item' points to the 38/48 code in the parameter array.
 2046      * If that has subparameters, we will expect all of the values to
 2047      * be subparameters of that item.
 2048      */
 2049     if ((have = param_has_subparams(item)) != 0) {
 2050     /* accept CSI 38 : 5 : 1 m */
 2051     /* accept CSI 38 : 2 : 1 : 2 : 3 m */
 2052     code = get_subparam(base, 1);
 2053     need = extended_colors_limit(code);
 2054     next = item + have;
 2055     for (n = 0; n < need && n < 3; ++n) {
 2056         values[n] = get_subparam(base, 2 + n + (have > 4));
 2057     }
 2058     } else if (++item < nparam) {
 2059     ++base;
 2060     if ((have = param_has_subparams(item)) != 0) {
 2061         /* accept CSI 38 ; 5 : 1 m */
 2062         /* accept CSI 38 ; 2 : 1 : 2 : 3 m */
 2063         code = get_subparam(base, 0);
 2064         need = extended_colors_limit(code);
 2065         next = base + have;
 2066         for (n = 0; n < need && n < 3; ++n) {
 2067         values[n] = get_subparam(base, 1 + n + (have > 3));
 2068         }
 2069     } else {
 2070         /* accept CSI 38 ; 5 ; 1 m */
 2071         /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */
 2072         code = GetParam(item);
 2073         need = extended_colors_limit(code);
 2074         next = item + need;
 2075         for (n = 0; n < need && n < 3; ++n) {
 2076         values[n] = GetParam(item + 1 + n);
 2077         }
 2078     }
 2079     }
 2080     item = next;
 2081 
 2082     *extended = False;
 2083     switch (code) {
 2084     case 2:
 2085     /* direct color in rgb space */
 2086     if ((values[0] >= 0 && values[0] < 256) &&
 2087         (values[1] >= 0 && values[1] < 256) &&
 2088         (values[2] >= 0 && values[2] < 256)) {
 2089 #if OPT_DIRECT_COLOR
 2090         if (TScreenOf(xw)->direct_color && xw->has_rgb) {
 2091         *colorp = getDirectColor(xw, values[0], values[1], values[2]);
 2092         result = True;
 2093         *extended = True;
 2094         } else
 2095 #endif
 2096         {
 2097         *colorp = xtermClosestColor(xw, values[0], values[1], values[2]);
 2098         result = okIndexedColor(*colorp);
 2099         }
 2100     } else {
 2101         *colorp = -1;
 2102     }
 2103     break;
 2104     case 5:
 2105     /* indexed color */
 2106     *colorp = values[0];
 2107     result = okIndexedColor(*colorp);
 2108     break;
 2109     default:
 2110     *colorp = -1;
 2111     break;
 2112     }
 2113 
 2114     TRACE(("...resulting color %d/%d %s\n",
 2115        *colorp, NUM_ANSI_COLORS,
 2116        result ? "OK" : "ERR"));
 2117 
 2118     *itemp = item;
 2119     return result;
 2120 }
 2121 #endif /* ...extended_colors */
 2122 
 2123 static int
 2124 optional_param(int which)
 2125 {
 2126     return (nparam > which) ? GetParam(which) : DEFAULT;
 2127 }
 2128 
 2129 static int
 2130 zero_if_default(int which)
 2131 {
 2132     int result = (nparam > which) ? GetParam(which) : 0;
 2133     if (result <= 0)
 2134     result = 0;
 2135     return result;
 2136 }
 2137 
 2138 static int
 2139 one_if_default(int which)
 2140 {
 2141     int result = (nparam > which) ? GetParam(which) : 0;
 2142     if (result <= 0)
 2143     result = 1;
 2144     return result;
 2145 }
 2146 
 2147 /*
 2148  * Color palette changes using the OSC controls require a repaint of the
 2149  * screen - but not immediately.  Do the repaint as soon as we detect a
 2150  * state which will not lead to another color palette change.
 2151  */
 2152 static void
 2153 repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp)
 2154 {
 2155     Boolean ignore = False;
 2156 
 2157     switch (sp->nextstate) {
 2158     case CASE_ESC:
 2159     ignore = ((sp->parsestate == ansi_table) ||
 2160           (sp->parsestate == sos_table));
 2161 #if USE_DOUBLE_BUFFER
 2162     if (resource.buffered && TScreenOf(xw)->needSwap) {
 2163         ignore = False;
 2164     }
 2165 #endif
 2166     break;
 2167     case CASE_OSC:
 2168     ignore = ((sp->parsestate == ansi_table) ||
 2169           (sp->parsestate == esc_table));
 2170     break;
 2171     case CASE_IGNORE:
 2172     ignore = (sp->parsestate == sos_table);
 2173     break;
 2174     case CASE_ST:
 2175     ignore = ((sp->parsestate == esc_table) ||
 2176           (sp->parsestate == sos_table));
 2177     break;
 2178     case CASE_ESC_DIGIT:
 2179     ignore = (sp->parsestate == csi_table);
 2180     break;
 2181     case CASE_ESC_SEMI:
 2182     ignore = (sp->parsestate == csi2_table);
 2183     break;
 2184     }
 2185 
 2186     if (!ignore) {
 2187     TRACE(("repaintWhenPaletteChanged\n"));
 2188     xw->work.palette_changed = False;
 2189     xtermRepaint(xw);
 2190     xtermFlushDbe(xw);
 2191     }
 2192 }
 2193 
 2194 #if OPT_C1_PRINT || OPT_WIDE_CHARS
 2195 #define ParseSOS(screen) ((screen)->c1_printable == 0)
 2196 #else
 2197 #define ParseSOS(screen) 0
 2198 #endif
 2199 
 2200 #define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable
 2201 
 2202 static void
 2203 illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp)
 2204 {
 2205     ResetState(sp);
 2206     sp->nextstate = sp->parsestate[E2A(c)];
 2207     Bell(xw, XkbBI_MinorError, 0);
 2208 }
 2209 
 2210 static void
 2211 init_parser(XtermWidget xw, struct ParseState *sp)
 2212 {
 2213     TScreen *screen = TScreenOf(xw);
 2214 
 2215     free(sp->defer_area);
 2216     free(sp->print_area);
 2217     free(sp->string_area);
 2218     memset(sp, 0, sizeof(*sp));
 2219     sp->scssize = 94;       /* number of printable/nonspace ASCII */
 2220     sp->lastchar = -1;      /* not a legal IChar */
 2221     sp->nextstate = -1;     /* not a legal state */
 2222 
 2223     init_groundtable(screen, sp);
 2224     ResetState(sp);
 2225 }
 2226 
 2227 static void
 2228 init_reply(unsigned type)
 2229 {
 2230     memset(&reply, 0, sizeof(reply));
 2231     reply.a_type = (Char) type;
 2232 }
 2233 
 2234 static void
 2235 deferparsing(unsigned c, struct ParseState *sp)
 2236 {
 2237     SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size);
 2238     if (new_string == 0) {
 2239     xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n",
 2240              (unsigned long) new_length, c);
 2241     return;
 2242     }
 2243     SafeFree(sp->defer_area, sp->defer_size);
 2244     sp->defer_area[(sp->defer_used)++] = CharOf(c);
 2245 }
 2246 
 2247 #if OPT_MOD_FKEYS
 2248 static void
 2249 set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled)
 2250 {
 2251 #define SET_MOD_FKEYS(field) \
 2252     xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \
 2253                      ? xw->keyboard.modify_1st.field \
 2254                      : what; \
 2255     TRACE(("set modify_now.%s to %d\n", #field, \
 2256        xw->keyboard.modify_now.field));
 2257 
 2258     switch (which) {
 2259     case 0:
 2260     SET_MOD_FKEYS(allow_keys);
 2261     break;
 2262     case 1:
 2263     SET_MOD_FKEYS(cursor_keys);
 2264     break;
 2265     case 2:
 2266     SET_MOD_FKEYS(function_keys);
 2267     break;
 2268     case 3:
 2269     SET_MOD_FKEYS(keypad_keys);
 2270     break;
 2271     case 4:
 2272     SET_MOD_FKEYS(other_keys);
 2273     break;
 2274     case 5:
 2275     SET_MOD_FKEYS(string_keys);
 2276     break;
 2277     }
 2278 }
 2279 
 2280 static void
 2281 report_mod_fkeys(XtermWidget xw, int which) /* XTQMODKEYS */
 2282 {
 2283 #define GET_MOD_FKEYS(field) \
 2284     reply.a_param[1] = (ParmType) xw->keyboard.modify_now.field
 2285 
 2286     init_reply(ANSI_CSI);
 2287     reply.a_pintro = '>';   /* replies look like a set-mode */
 2288     reply.a_nparam = 2;
 2289     reply.a_final = 'm';
 2290 
 2291     reply.a_param[1] = DEFAULT;
 2292     switch (reply.a_param[0] = (ParmType) which) {
 2293     case 0:
 2294     GET_MOD_FKEYS(allow_keys);
 2295     break;
 2296     case 1:
 2297     GET_MOD_FKEYS(cursor_keys);
 2298     break;
 2299     case 2:
 2300     GET_MOD_FKEYS(function_keys);
 2301     break;
 2302     case 3:
 2303     GET_MOD_FKEYS(keypad_keys);
 2304     break;
 2305     case 4:
 2306     GET_MOD_FKEYS(other_keys);
 2307     break;
 2308     case 5:
 2309     GET_MOD_FKEYS(string_keys);
 2310     break;
 2311     }
 2312     unparseseq(xw, &reply);
 2313 }
 2314 #endif /* OPT_MOD_FKEYS */
 2315 
 2316 #if OPT_STATUS_LINE
 2317 typedef enum {
 2318     SLnone = 0,         /* no status-line timer needed */
 2319     SLclock = 1,        /* status-line updates once/second */
 2320     SLcoords = 2,       /* status-line shows cursor-position */
 2321     SLwritten = 3       /* status-line may need asynchronous repainting */
 2322 } SL_MODE;
 2323 
 2324 #define SL_BUFSIZ 80
 2325 
 2326 #if OPT_TRACE
 2327 static const char *
 2328 visibleStatusType(int code)
 2329 {
 2330     const char *result = "?";
 2331     switch (code) {
 2332     case 0:
 2333     result = "none";
 2334     break;
 2335     case 1:
 2336     result = "indicator";
 2337     break;
 2338     case 2:
 2339     result = "writable";
 2340     break;
 2341     }
 2342     return result;
 2343 }
 2344 
 2345 static void
 2346 trace_status_line(XtermWidget xw, int lineno, const char *tag)
 2347 {
 2348     TScreen *screen = TScreenOf(xw);
 2349 
 2350     TRACE(("@%d, %s (%s, %s)%s%s @ (%d,%d) vs %d\n",
 2351        lineno,
 2352        tag,
 2353        screen->status_active ? "active" : "inactive",
 2354        visibleStatusType(screen->status_type),
 2355        ((screen->status_type != screen->status_shown)
 2356         ? " vs "
 2357         : ""),
 2358        ((screen->status_type != screen->status_shown)
 2359         ? visibleStatusType(screen->status_shown)
 2360         : ""),
 2361        screen->cur_row,
 2362        screen->cur_col,
 2363        LastRowNumber(screen)));
 2364 }
 2365 
 2366 #define TRACE_SL(tag) trace_status_line(xw, __LINE__, tag)
 2367 #else
 2368 #define TRACE_SL(tag)       /* nothing */
 2369 #endif
 2370 
 2371 static SL_MODE
 2372 find_SL_MODE(XtermWidget xw)
 2373 {
 2374     TScreen *screen = TScreenOf(xw);
 2375     SL_MODE result = SLnone;
 2376     const char *parse;
 2377 
 2378     for (parse = screen->status_fmt; *parse != '\0'; ++parse) {
 2379     const char *found = parse;
 2380     if (*parse == '%') {
 2381         if (*++parse == L_CURL) {
 2382         const char *check = strchr(parse, '%');
 2383         size_t length = 0;
 2384 
 2385         if (check != NULL && check[1] == R_CURL) {
 2386             length = (size_t) (2 + check - found);
 2387         } else {
 2388             length = strlen(found);
 2389         }
 2390 
 2391         if (!strncmp(found, "%{unixtime%}", length)) {
 2392             if (result == SLnone)
 2393             result = SLclock;
 2394         } else if (!strncmp(found, "%{position%}", length)) {
 2395             result = SLcoords;
 2396         }
 2397         parse = found + length - 1;
 2398         }
 2399 #if defined(HAVE_STRFTIME)
 2400         else if (*parse != '\0') {
 2401         if (result == SLnone && strchr("cEgOrsSTX+", *parse) != NULL) {
 2402             result = SLclock;
 2403         }
 2404         }
 2405 #endif
 2406     }
 2407     }
 2408     return result;
 2409 }
 2410 
 2411 static long
 2412 find_SL_Timeout(XtermWidget xw)
 2413 {
 2414     long result = 0;
 2415     switch (find_SL_MODE(xw)) {
 2416     case SLnone:
 2417     case SLwritten:
 2418     break;
 2419     case SLclock:
 2420     result = 1000;
 2421     break;
 2422     case SLcoords:
 2423     result = 80;
 2424     break;
 2425     }
 2426     return result;
 2427 }
 2428 
 2429 static void
 2430 StatusInit(SavedCursor * data)
 2431 {
 2432     memset(data, 0, sizeof(*data));
 2433     data->sgr_foreground = -1;
 2434     data->sgr_background = -1;
 2435 }
 2436 
 2437 /* save the status-line position, restore main display */
 2438 static void
 2439 StatusSave(XtermWidget xw)
 2440 {
 2441     TScreen *screen = TScreenOf(xw);
 2442 
 2443     CursorSave2(xw, &screen->status_data[1]);
 2444     CursorRestore2(xw, &screen->status_data[0]);
 2445 
 2446     TRACE(("...StatusSave %d,%d -> %d,%d (main)\n",
 2447        screen->status_data[1].row,
 2448        screen->status_data[1].col,
 2449        screen->cur_row,
 2450        screen->cur_col));
 2451 }
 2452 
 2453 /* save the main-display position, restore status-line */
 2454 static void
 2455 StatusRestore(XtermWidget xw)
 2456 {
 2457     TScreen *screen = TScreenOf(xw);
 2458 
 2459     CursorSave2(xw, &screen->status_data[0]);
 2460     CursorRestore2(xw, &screen->status_data[1]);
 2461     screen->cur_row = FirstRowNumber(screen);
 2462 
 2463     TRACE(("...StatusRestore %d,%d -> %d,%d (status)\n",
 2464        screen->status_data[0].row,
 2465        screen->status_data[0].col,
 2466        screen->cur_row,
 2467        screen->cur_col));
 2468 }
 2469 
 2470 static void
 2471 StatusPutChars(XtermWidget xw, const char *value, int length)
 2472 {
 2473     TScreen *screen = TScreenOf(xw);
 2474 
 2475     if (length < 0)
 2476     length = (int) strlen(value);
 2477 
 2478     while (length > 0) {
 2479     IChar buffer[SL_BUFSIZ + 1];
 2480     Cardinal n;
 2481     for (n = 0; n < SL_BUFSIZ && length > 0 && *value != '\0'; ++n) {
 2482         buffer[n] = CharOf(*value++);
 2483         if (buffer[n] < 32 || buffer[n] > 126)
 2484         buffer[n] = ' ';    /* FIXME - provide for UTF-8 */
 2485         --length;
 2486     }
 2487     buffer[n] = 0;
 2488     dotext(xw,
 2489            screen->gsets[(int) (screen->curgl)],
 2490            buffer, n);
 2491     }
 2492 }
 2493 
 2494 static void
 2495 show_indicator_status(XtPointer closure, XtIntervalId * id GCC_UNUSED)
 2496 {
 2497     XtermWidget xw = (XtermWidget) closure;
 2498     TScreen *screen = TScreenOf(xw);
 2499     int right_margin;
 2500 
 2501     time_t now;
 2502     const char *parse;
 2503     char buffer[SL_BUFSIZ + 1];
 2504     long interval;
 2505 
 2506     if (screen->status_type != 1) {
 2507     screen->status_timeout = False;
 2508     return;
 2509     }
 2510     if (screen->status_active) {
 2511     return;
 2512     }
 2513 
 2514     screen->status_active = True;
 2515 
 2516     CursorSave2(xw, &screen->status_data[0]);
 2517     screen->cur_row = FirstRowNumber(screen);
 2518     screen->cur_col = 0;
 2519 
 2520     xw->flags |= INVERSE;
 2521     xw->flags &= (IFlags) (~WRAPAROUND);
 2522 
 2523     now = time((time_t *) 0);
 2524 
 2525     for (parse = screen->status_fmt; *parse != '\0'; ++parse) {
 2526     const char *found = parse;
 2527     if (*parse == '%') {
 2528         if (*++parse == L_CURL) {
 2529         const char *check = strchr(parse, '%');
 2530         size_t length = 0;
 2531 
 2532         if (check != NULL && check[1] == R_CURL) {
 2533             length = (size_t) (2 + check - found);
 2534         } else {
 2535             length = strlen(found);
 2536         }
 2537 
 2538         if (!strncmp(found, "%{version%}", length)) {
 2539             StatusPutChars(xw, xtermVersion(), -1);
 2540         } else if (!strncmp(found, "%{unixtime%}", length)) {
 2541             char *t = x_strtrim(ctime(&now));
 2542             if (t != 0) {
 2543             StatusPutChars(xw, t, -1);
 2544             free(t);
 2545             }
 2546         } else if (!strncmp(found, "%{position%}", length)) {
 2547             sprintf(buffer, "(%02d,%03d)",
 2548                 screen->status_data[0].row + 1,
 2549                 screen->status_data[0].col + 1);
 2550             StatusPutChars(xw, buffer, -1);
 2551         } else {
 2552             StatusPutChars(xw, found, (int) length);
 2553         }
 2554         parse = found + length - 1;
 2555         }
 2556 #if defined(HAVE_STRFTIME)
 2557         else if (*parse != '\0') {
 2558         char format[3];
 2559         struct tm *tm = localtime(&now);
 2560 
 2561         format[0] = '%';
 2562         format[1] = *parse;
 2563         format[2] = '\0';
 2564         if (strftime(buffer, sizeof(buffer) - 1, format, tm) != 0) {
 2565             StatusPutChars(xw, buffer, -1);
 2566         } else {
 2567             StatusPutChars(xw, "?", 1);
 2568             StatusPutChars(xw, parse - 1, 2);
 2569         }
 2570         }
 2571 #endif
 2572     } else {
 2573         StatusPutChars(xw, parse, 1);
 2574     }
 2575     }
 2576     right_margin = ScrnRightMargin(xw);
 2577     memset(buffer, ' ', (size_t) SL_BUFSIZ);
 2578     while (screen->cur_col < right_margin) {
 2579     int chunk = Min(SL_BUFSIZ, (right_margin - screen->cur_col));
 2580     StatusPutChars(xw, buffer, chunk);
 2581     }
 2582 
 2583     ScrnRefresh(xw, FirstRowNumber(screen), 0, 1, right_margin, True);
 2584     screen->status_active = False;
 2585 
 2586     CursorRestore2(xw, &screen->status_data[0]);
 2587 
 2588     /* if we processed a position or date/time, repeat */
 2589     interval = find_SL_Timeout(xw);
 2590     if (interval > 0) {
 2591     (void) XtAppAddTimeOut(app_con,
 2592                    (unsigned long) interval,
 2593                    show_indicator_status, xw);
 2594     }
 2595     screen->status_timeout = True;
 2596 }
 2597 
 2598 static void
 2599 clear_status_line(XtermWidget xw)
 2600 {
 2601     TScreen *screen = TScreenOf(xw);
 2602     SavedCursor save_me;
 2603     SavedCursor clearit;
 2604     int save_type = screen->status_type;
 2605 
 2606     TRACE_SL("clear_status_line");
 2607     StatusInit(&clearit);
 2608     CursorSave2(xw, &save_me);
 2609     CursorRestore2(xw, &clearit);
 2610 
 2611     screen->status_type = 2;
 2612     set_cur_row(screen, LastRowNumber(screen));
 2613 #if 1
 2614     ClearLine(xw);
 2615 #else
 2616     if (getLineData(screen, screen->cur_row) != NULL) {
 2617     int n;
 2618     char buffer[SL_BUFSIZ + 1];
 2619     CLineData *ld = getLineData(screen, screen->cur_row);
 2620     int right_margin = ScrnRightMargin(xw);
 2621 
 2622     TRACE(("...text[%d:%d]:%s\n",
 2623            screen->cur_row,
 2624            LastRowNumber(screen),
 2625            visibleIChars(ld->charData, ld->lineSize)));
 2626 
 2627     memset(buffer, '#', SL_BUFSIZ);
 2628     for (n = 0; n < screen->max_col; n += SL_BUFSIZ) {
 2629         StatusPutChars(xw, buffer, right_margin - n);
 2630     }
 2631     }
 2632 #endif
 2633     CursorRestore2(xw, &save_me);
 2634     screen->status_type = save_type;
 2635     TRACE_SL("clear_status_line (done)");
 2636 }
 2637 
 2638 static void
 2639 show_writable_status(XtermWidget xw)
 2640 {
 2641     TScreen *screen = TScreenOf(xw);
 2642 
 2643     TRACE(("show_writable_status (%d:%d) max=%d\n",
 2644        FirstRowNumber(screen),
 2645        LastRowNumber(screen),
 2646        MaxRows(screen)));
 2647     screen->cur_row = FirstRowNumber(screen);
 2648 }
 2649 
 2650 /*
 2651  * Depending the status-type, make the window grow or shrink by one row to
 2652  * show or hide the status-line.  Keep the rest of the window from scrolling
 2653  * by overriding the resize-gravity.
 2654  */
 2655 static void
 2656 resize_status_line(XtermWidget xw)
 2657 {
 2658     TScreen *screen = TScreenOf(xw);
 2659     XtGravity savedGravity = xw->misc.resizeGravity;
 2660 
 2661     TRACE_SL(screen->status_type
 2662          ? "...resize to show status-line"
 2663          : "...resize to hide status-line");
 2664 
 2665     xw->misc.resizeGravity = NorthWestGravity;
 2666 
 2667     RequestResize(xw, MaxRows(screen), MaxCols(screen), True);
 2668 
 2669     xw->misc.resizeGravity = savedGravity;
 2670 }
 2671 
 2672 /*
 2673  * DEC STD 070, chapter 14 "VSRM - Status Display Extension"
 2674  */
 2675 static void
 2676 update_status_line(XtermWidget xw)
 2677 {
 2678     TScreen *screen = TScreenOf(xw);
 2679 
 2680     TRACE_SL("update_status_line");
 2681 
 2682     if (screen->status_type == 1) {
 2683     if (screen->status_type != screen->status_shown) {
 2684         if (screen->status_shown == 0) {
 2685         resize_status_line(xw);
 2686         } else {
 2687         clear_status_line(xw);
 2688         }
 2689         screen->status_shown = screen->status_type;
 2690         TRACE_SL("...updating shown");
 2691     }
 2692     show_indicator_status(xw, NULL);
 2693     } else if (screen->status_active) {
 2694     if (screen->status_type != screen->status_shown) {
 2695         Boolean do_resize = False;
 2696 
 2697         if (screen->status_type == 0) {
 2698         if (screen->status_shown >= 2) {
 2699             StatusSave(xw);
 2700         }
 2701         do_resize = True;   /* shrink... */
 2702         clear_status_line(xw);
 2703         StatusInit(&screen->status_data[1]);
 2704         } else if (screen->status_shown == 0) {
 2705         if (screen->status_type >= 2) {
 2706             StatusRestore(xw);
 2707         }
 2708         do_resize = True;   /* grow... */
 2709         } else {
 2710         clear_status_line(xw);
 2711         }
 2712         if (do_resize) {
 2713         resize_status_line(xw);
 2714         }
 2715         screen->status_shown = screen->status_type;
 2716         TRACE_SL("...updating shown");
 2717     }
 2718     show_writable_status(xw);
 2719     } else {
 2720     if (screen->status_shown) {
 2721         if (screen->status_type != 0 &&
 2722         screen->status_type != screen->status_shown) {
 2723         clear_status_line(xw);
 2724         }
 2725         if (screen->status_shown >= 2) {
 2726         StatusSave(xw);
 2727         }
 2728         if (screen->status_type == 0) {
 2729         screen->status_timeout = False;
 2730         clear_status_line(xw);
 2731         StatusInit(&screen->status_data[1]);
 2732         resize_status_line(xw);     /* shrink... */
 2733         }
 2734         screen->status_shown = screen->status_type;
 2735         TRACE_SL("...updating shown");
 2736     }
 2737     }
 2738     TRACE_SL("update_status_line (done)");
 2739 }
 2740 
 2741 /*
 2742  * If the status-type is "2", we can switch the active status display back and
 2743  * forth between the main-display and the status-line without clearing the
 2744  * status-line (unless the status-line was not shown before).
 2745  *
 2746  * This has no effect if the status-line displays an indicator (type==1).
 2747  */
 2748 static void
 2749 handle_DECSASD(XtermWidget xw, int value)
 2750 {
 2751     TScreen *screen = TScreenOf(xw);
 2752     Boolean updates = value ? True : False;
 2753 
 2754     TRACE(("CASE_DECSASD - select active status display: %s (currently %s)\n",
 2755        BtoS(value),
 2756        BtoS(screen->status_active)));
 2757 
 2758     if (screen->status_active != updates) {
 2759     screen->status_active = updates;
 2760     if (screen->status_type != 1) {
 2761         if (updates) {
 2762         TRACE(("...@%d, saving main position %d,%d\n",
 2763                __LINE__, screen->cur_row, screen->cur_col));
 2764         CursorSave2(xw, &screen->status_data[0]);
 2765         }
 2766         update_status_line(xw);
 2767     }
 2768     }
 2769 }
 2770 
 2771 /*
 2772  * If the status-line is inactive (i.e., only the main-display is used),
 2773  * changing the status-type between none/writable has no immediate effect.
 2774  *
 2775  * But if the status-line is active, setting the status-type reinitializes the
 2776  * status-line.
 2777  *
 2778  * Setting the status-type to indicator overrides the DECSASD active-display
 2779  * mode.
 2780  */
 2781 static void
 2782 handle_DECSSDT(XtermWidget xw, int value)
 2783 {
 2784     TScreen *screen = TScreenOf(xw);
 2785 
 2786     TRACE(("CASE_DECSSDT - select type of status display: %d (currently %d)\n",
 2787        value,
 2788        screen->status_type));
 2789     if (value <= 2) {
 2790     screen->status_type = value;
 2791     if (!screen->status_active) {
 2792         TRACE(("...@%d, saving main position %d,%d\n",
 2793            __LINE__, screen->cur_row, screen->cur_col));
 2794         CursorSave2(xw, &screen->status_data[0]);
 2795     }
 2796     update_status_line(xw);
 2797     }
 2798 }
 2799 #endif
 2800 
 2801 #if OPT_VT52_MODE
 2802 static void
 2803 update_vt52_vt100_settings(void)
 2804 {
 2805     update_autowrap();
 2806     update_reversewrap();
 2807     update_autolinefeed();
 2808     update_appcursor();
 2809     update_appkeypad();
 2810     update_allow132();
 2811 }
 2812 #endif
 2813 
 2814 static Boolean
 2815 doparsing(XtermWidget xw, unsigned c, struct ParseState *sp)
 2816 {
 2817     TScreen *screen = TScreenOf(xw);
 2818     int item;
 2819     int count;
 2820     int value;
 2821     int laststate;
 2822     int thischar = -1;
 2823     XTermRect myRect;
 2824 #if OPT_DEC_RECTOPS
 2825     int thispage = 1;
 2826 #endif
 2827 
 2828     if (sp->check_recur) {
 2829     /* Defer parsing when parser is already running as the parser is not
 2830      * safe to reenter.
 2831      */
 2832     deferparsing(c, sp);
 2833     return True;
 2834     }
 2835     sp->check_recur++;
 2836 
 2837     do {
 2838 #if OPT_WIDE_CHARS
 2839     int this_is_wide = 0;
 2840     int is_formatter = 0;
 2841 
 2842     /*
 2843      * Handle zero-width combining characters.  Make it faster by noting
 2844      * that according to the Unicode charts, the majority of Western
 2845      * character sets do not use this feature.  There are some unassigned
 2846      * codes at 0x242, but no zero-width characters until past 0x300.
 2847      */
 2848     if (c >= 0x300
 2849         && screen->wide_chars
 2850         && CharWidth(screen, c) == 0
 2851         && !(is_formatter = (CharacterClass((int) c) == CNTRL))) {
 2852         int prev, test;
 2853         Boolean used = True;
 2854         int use_row;
 2855         int use_col;
 2856 
 2857         WriteNow();
 2858         use_row = (screen->char_was_written
 2859                ? screen->last_written_row
 2860                : screen->cur_row);
 2861         use_col = (screen->char_was_written
 2862                ? screen->last_written_col
 2863                : screen->cur_col);
 2864 
 2865         /*
 2866          * Check if the latest data can be added to the base character.
 2867          * If there is already a combining character stored for the cell,
 2868          * we cannot, since that would change the order.
 2869          */
 2870         if (screen->normalized_c
 2871         && !IsCellCombined(screen, use_row, use_col)) {
 2872         prev = (int) XTERM_CELL(use_row, use_col);
 2873         test = do_precomposition(prev, (int) c);
 2874         TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n",
 2875                prev, CharWidth(screen, prev),
 2876                (int) c, CharWidth(screen, c),
 2877                test, CharWidth(screen, test)));
 2878         } else {
 2879         prev = -1;
 2880         test = -1;
 2881         }
 2882 
 2883         /* substitute combined character with precomposed character
 2884          * only if it does not change the width of the base character
 2885          */
 2886         if (test != -1
 2887         && CharWidth(screen, test) == CharWidth(screen, prev)) {
 2888         putXtermCell(screen, use_row, use_col, test);
 2889         } else if (screen->char_was_written
 2890                || getXtermCell(screen, use_row, use_col) >= ' ') {
 2891         addXtermCombining(screen, use_row, use_col, c);
 2892         } else {
 2893         /*
 2894          * none of the above... we will add the combining character as
 2895          * a base character.
 2896          */
 2897         used = False;
 2898         }
 2899 
 2900         if (used) {
 2901         if (!screen->scroll_amt)
 2902             ScrnUpdate(xw, use_row, use_col, 1, 1, 1);
 2903         continue;
 2904         }
 2905     }
 2906 #endif
 2907 
 2908     /* Intercept characters for printer controller mode */
 2909     if (PrinterOf(screen).printer_controlmode == 2) {
 2910         if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0)
 2911         continue;
 2912     }
 2913 
 2914     /*
 2915      * VT52 is a little ugly in the one place it has a parameterized
 2916      * control sequence, since the parameter falls after the character
 2917      * that denotes the type of sequence.
 2918      */
 2919 #if OPT_VT52_MODE
 2920     if (sp->vt52_cup) {
 2921         if (nparam < NPARAM - 1) {
 2922         SetParam(nparam++, (int) (c & 0x7f) - 32);
 2923         parms.is_sub[nparam] = 0;
 2924         }
 2925         if (nparam < 2)
 2926         continue;
 2927         sp->vt52_cup = False;
 2928         CursorSet(screen, zero_if_default(0), zero_if_default(1), xw->flags);
 2929         sp->parsestate = vt52_table;
 2930         SetParam(0, 0);
 2931         SetParam(1, 0);
 2932         continue;
 2933     }
 2934 #endif
 2935 
 2936     laststate = sp->nextstate;
 2937     if (c == ANSI_DEL
 2938         && sp->parsestate == sp->groundtable
 2939         && sp->scssize == 96
 2940         && sp->scstype != 0) {
 2941         /*
 2942          * Handle special case of shifts for 96-character sets by checking
 2943          * if we have a DEL.  The other special case for SPACE will always
 2944          * be printable.
 2945          */
 2946         sp->nextstate = CASE_PRINT;
 2947     } else
 2948 #if OPT_WIDE_CHARS
 2949     if (c > 255) {
 2950         /*
 2951          * The parsing tables all have 256 entries.  If we're supporting
 2952          * wide characters, we handle them by treating them the same as
 2953          * printing characters.
 2954          */
 2955         if (sp->parsestate == sp->groundtable) {
 2956         sp->nextstate = is_formatter ? CASE_IGNORE : CASE_PRINT;
 2957         } else if (sp->parsestate == sos_table) {
 2958         c &= WIDEST_ICHAR;
 2959         if (c > 255) {
 2960             TRACE(("Found code > 255 while in SOS state: %04X\n", c));
 2961             c = BAD_ASCII;
 2962         }
 2963         } else {
 2964         sp->nextstate = CASE_GROUND_STATE;
 2965         }
 2966     } else
 2967 #endif
 2968         sp->nextstate = sp->parsestate[E2A(c)];
 2969 
 2970 #if OPT_BROKEN_OSC
 2971     /*
 2972      * Linux console palette escape sequences start with an OSC, but do
 2973      * not terminate correctly.  Some scripts do not check before writing
 2974      * them, making xterm appear to hang (it's awaiting a valid string
 2975      * terminator).  Just ignore these if we see them - there's no point
 2976      * in emulating bad code.
 2977      */
 2978     if (screen->brokenLinuxOSC
 2979         && sp->parsestate == sos_table) {
 2980         if (sp->string_used) {
 2981         switch (sp->string_area[0]) {
 2982         case 'P':
 2983             if (sp->string_used <= 7)
 2984             break;
 2985             /* FALLTHRU */
 2986         case 'R':
 2987             illegal_parse(xw, c, sp);
 2988             TRACE(("Reset to ground state (brokenLinuxOSC)\n"));
 2989             break;
 2990         }
 2991         }
 2992     }
 2993 #endif
 2994 
 2995 #if OPT_BROKEN_ST
 2996     /*
 2997      * Before patch #171, carriage control embedded within an OSC string
 2998      * would terminate it.  Some (buggy, of course) applications rely on
 2999      * this behavior.  Accommodate them by allowing one to compile xterm
 3000      * and emulate the old behavior.
 3001      */
 3002     if (screen->brokenStringTerm
 3003         && sp->parsestate == sos_table
 3004         && c < 32) {
 3005         switch (c) {
 3006         case ANSI_EOT:  /* FALLTHRU */
 3007         case ANSI_BS:   /* FALLTHRU */
 3008         case ANSI_HT:   /* FALLTHRU */
 3009         case ANSI_LF:   /* FALLTHRU */
 3010         case ANSI_VT:   /* FALLTHRU */
 3011         case ANSI_FF:   /* FALLTHRU */
 3012         case ANSI_CR:   /* FALLTHRU */
 3013         case ANSI_SO:   /* FALLTHRU */
 3014         case ANSI_SI:   /* FALLTHRU */
 3015         case ANSI_XON:  /* FALLTHRU */
 3016         case ANSI_CAN:
 3017         illegal_parse(xw, c, sp);
 3018         TRACE(("Reset to ground state (brokenStringTerm)\n"));
 3019         break;
 3020         }
 3021     }
 3022 #endif
 3023 
 3024 #if OPT_C1_PRINT
 3025     /*
 3026      * This is not completely foolproof, but will allow an application
 3027      * with values in the C1 range to use them as printable characters,
 3028      * provided that they are not intermixed with an escape sequence.
 3029      */
 3030     if (screen->c1_printable
 3031         && (c >= 128 && c < 256)) {
 3032         sp->nextstate = (sp->parsestate == esc_table
 3033                  ? CASE_ESC_IGNORE
 3034                  : sp->parsestate[E2A(160)]);
 3035         TRACE(("allowC1Printable %04X %s ->%s\n",
 3036            c, which_table(sp->parsestate),
 3037            visibleVTparse(sp->nextstate)));
 3038     }
 3039 #endif
 3040 
 3041 #if OPT_WIDE_CHARS
 3042     /*
 3043      * If we have a C1 code and the c1_printable flag is not set, simply
 3044      * ignore it when it was translated from UTF-8.  That is because the
 3045      * value could not have been present as-is in the UTF-8.
 3046      *
 3047      * To see that CASE_IGNORE is a consistent value, note that it is
 3048      * always used for NUL and other uninteresting C0 controls.
 3049      */
 3050 #if OPT_C1_PRINT
 3051     if (!screen->c1_printable)
 3052 #endif
 3053         if (screen->wide_chars
 3054         && (c >= 128 && c < 160)) {
 3055         sp->nextstate = CASE_IGNORE;
 3056         }
 3057 
 3058     /*
 3059      * If this character is a different width than the last one, put the
 3060      * previous text into the buffer and draw it now.
 3061      */
 3062     this_is_wide = isWide((int) c);
 3063     if (this_is_wide != sp->last_was_wide) {
 3064         WriteNow();
 3065     }
 3066 #endif
 3067 
 3068     /*
 3069      * Accumulate string for printable text.  This may be 8/16-bit
 3070      * characters.
 3071      */
 3072     if (sp->nextstate == CASE_PRINT) {
 3073         SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size);
 3074         if (new_string == 0) {
 3075         xtermWarning("Cannot allocate %lu bytes for printable text\n",
 3076                  (unsigned long) new_length);
 3077         continue;
 3078         }
 3079         SafeFree(sp->print_area, sp->print_size);
 3080 #if OPT_VT52_MODE
 3081         /*
 3082          * Strip output text to 7-bits for VT52.  We should do this for
 3083          * VT100 also (which is a 7-bit device), but xterm has been
 3084          * doing this for so long we shouldn't change this behavior.
 3085          */
 3086         if (screen->vtXX_level < 1)
 3087         c &= 0x7f;
 3088 #endif
 3089         sp->print_area[sp->print_used++] = (IChar) c;
 3090         sp->lastchar = thischar = (int) c;
 3091 #if OPT_WIDE_CHARS
 3092         sp->last_was_wide = this_is_wide;
 3093 #endif
 3094         if (morePtyData(screen, VTbuffer)) {
 3095         continue;
 3096         }
 3097     }
 3098 
 3099     if (sp->nextstate == CASE_PRINT
 3100         || (laststate == CASE_PRINT && sp->print_used)) {
 3101         WriteNow();
 3102     }
 3103 
 3104     /*
 3105      * Accumulate string for APC, DCS, PM, OSC, SOS controls
 3106      * This should always be 8-bit characters.
 3107      */
 3108     if (sp->parsestate == sos_table) {
 3109         SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size);
 3110         if (new_string == 0) {
 3111         xtermWarning("Cannot allocate %lu bytes for string mode %d\n",
 3112                  (unsigned long) new_length, sp->string_mode);
 3113         continue;
 3114         }
 3115         SafeFree(sp->string_area, sp->string_size);
 3116 #if OPT_WIDE_CHARS
 3117         /*
 3118          * We cannot display codes above 255, but let's try to
 3119          * accommodate the application a little by not aborting the
 3120          * string.
 3121          */
 3122         if ((c & WIDEST_ICHAR) > 255) {
 3123         sp->nextstate = CASE_PRINT;
 3124         c = BAD_ASCII;
 3125         }
 3126 #endif
 3127         sp->string_area[(sp->string_used)++] = CharOf(c);
 3128     } else if (sp->parsestate != esc_table) {
 3129         /* if we were accumulating, we're not any more */
 3130         sp->string_mode = 0;
 3131         sp->string_used = 0;
 3132     }
 3133 
 3134     DumpParams();
 3135     TRACE(("parse %04X -> %s %s (used=%lu)\n",
 3136            c, visibleVTparse(sp->nextstate),
 3137            which_table(sp->parsestate),
 3138            (unsigned long) sp->string_used));
 3139 
 3140     /*
 3141      * If the parameter list has subparameters (tokens separated by ":")
 3142      * reject any controls that do not accept subparameters.
 3143      */
 3144     if (parms.has_subparams) {
 3145         switch (sp->nextstate) {
 3146         case CASE_GROUND_STATE:
 3147         case CASE_CSI_IGNORE:
 3148         /* FALLTHRU */
 3149 
 3150         case CASE_ESC_DIGIT:
 3151         case CASE_ESC_SEMI:
 3152         case CASE_ESC_COLON:
 3153         /* these states are required to parse parameter lists */
 3154         break;
 3155 
 3156         case CASE_SGR:
 3157         TRACE(("...possible subparam usage\n"));
 3158         break;
 3159 
 3160         case CASE_CSI_DEC_DOLLAR_STATE:
 3161         case CASE_CSI_DOLLAR_STATE:
 3162         case CASE_CSI_HASH_STATE:
 3163         case CASE_CSI_EX_STATE:
 3164         case CASE_CSI_QUOTE_STATE:
 3165         case CASE_CSI_SPACE_STATE:
 3166         case CASE_CSI_STAR_STATE:
 3167         case CASE_CSI_TICK_STATE:
 3168         case CASE_DEC2_STATE:
 3169         case CASE_DEC3_STATE:
 3170         case CASE_DEC_STATE:
 3171         /* use this branch when we do not yet have the final character */
 3172         TRACE(("...unexpected subparam usage\n"));
 3173         InitParams();
 3174         sp->nextstate = CASE_CSI_IGNORE;
 3175         break;
 3176 
 3177         default:
 3178         /* use this branch for cases where we have the final character
 3179          * in the table that processed the parameter list.
 3180          */
 3181         TRACE(("...unexpected subparam usage\n"));
 3182         ResetState(sp);
 3183         continue;
 3184         }
 3185     }
 3186 
 3187     if (xw->work.palette_changed) {
 3188         repaintWhenPaletteChanged(xw, sp);
 3189     }
 3190 #if OPT_STATUS_LINE
 3191     /*
 3192      * If we are currently writing to the status-line, ignore controls that
 3193      * apply only to the full screen, or which use features which we will
 3194      * not support in the status-line.
 3195      */
 3196     if (IsStatusShown(screen) && (screen)->status_active) {
 3197         switch (sp->nextstate) {
 3198         case CASE_DECDHL:
 3199         case CASE_DECSWL:
 3200         case CASE_DECDWL:
 3201         case CASE_CUU:
 3202         case CASE_CUD:
 3203         case CASE_VPA:
 3204         case CASE_VPR:
 3205         case CASE_ED:
 3206         case CASE_TRACK_MOUSE:
 3207         case CASE_DECSTBM:
 3208         case CASE_DECALN:
 3209         case CASE_GRAPHICS_ATTRIBUTES:
 3210         case CASE_SPA:
 3211         case CASE_EPA:
 3212         case CASE_SU:
 3213         case CASE_IND:
 3214         case CASE_CPL:
 3215         case CASE_CNL:
 3216         case CASE_NEL:
 3217         case CASE_RI:
 3218 #if OPT_DEC_LOCATOR
 3219         case CASE_DECEFR:
 3220         case CASE_DECELR:
 3221         case CASE_DECSLE:
 3222         case CASE_DECRQLP:
 3223 #endif
 3224 #if OPT_DEC_RECTOPS
 3225         case CASE_DECRQCRA:
 3226         case CASE_DECCRA:
 3227         case CASE_DECERA:
 3228         case CASE_DECFRA:
 3229         case CASE_DECSERA:
 3230         case CASE_DECSACE:
 3231         case CASE_DECCARA:
 3232         case CASE_DECRARA:
 3233 #endif
 3234         ResetState(sp);
 3235         sp->nextstate = -1; /* not a legal state */
 3236         break;
 3237         }
 3238     }
 3239 #endif
 3240 
 3241     switch (sp->nextstate) {
 3242     case CASE_PRINT:
 3243         TRACE(("CASE_PRINT - printable characters\n"));
 3244         break;
 3245 
 3246     case CASE_GROUND_STATE:
 3247         TRACE(("CASE_GROUND_STATE - exit ignore mode\n"));
 3248         ResetState(sp);
 3249         break;
 3250 
 3251     case CASE_IGNORE:
 3252         TRACE(("CASE_IGNORE - Ignore character %02X\n", c));
 3253         break;
 3254 
 3255     case CASE_ENQ:
 3256         TRACE(("CASE_ENQ - answerback\n"));
 3257         if (((xw->keyboard.flags & MODE_SRM) == 0)
 3258         ? (sp->check_recur == 0)
 3259         : (sp->check_recur <= 1)) {
 3260         for (count = 0; screen->answer_back[count] != 0; count++)
 3261             unparseputc(xw, screen->answer_back[count]);
 3262         unparse_end(xw);
 3263         }
 3264         break;
 3265 
 3266     case CASE_BELL:
 3267         TRACE(("CASE_BELL - bell\n"));
 3268         if (sp->string_mode == ANSI_OSC) {
 3269         if (sp->string_used)
 3270             sp->string_area[--(sp->string_used)] = '\0';
 3271         if (sp->check_recur <= 1)
 3272             do_osc(xw, sp->string_area, sp->string_used, (int) c);
 3273         ResetState(sp);
 3274         } else {
 3275         /* bell */
 3276         Bell(xw, XkbBI_TerminalBell, 0);
 3277         }
 3278         break;
 3279 
 3280     case CASE_BS:
 3281         TRACE(("CASE_BS - backspace\n"));
 3282         CursorBack(xw, 1);
 3283         break;
 3284 
 3285     case CASE_CR:
 3286         TRACE(("CASE_CR\n"));
 3287         CarriageReturn(xw);
 3288         break;
 3289 
 3290     case CASE_ESC:
 3291         if_OPT_VT52_MODE(screen, {
 3292         sp->parsestate = vt52_esc_table;
 3293         break;
 3294         });
 3295         sp->parsestate = esc_table;
 3296         break;
 3297 
 3298 #if OPT_VT52_MODE
 3299     case CASE_VT52_CUP:
 3300         TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n"));
 3301         sp->vt52_cup = True;
 3302         ResetState(sp);
 3303         break;
 3304 
 3305     case CASE_VT52_IGNORE:
 3306         TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n"));
 3307         sp->parsestate = vt52_ignore_table;
 3308         break;
 3309 #endif
 3310 
 3311     case CASE_VMOT:
 3312         TRACE(("CASE_VMOT\n"));
 3313         /*
 3314          * form feed, line feed, vertical tab
 3315          */
 3316         xtermAutoPrint(xw, c);
 3317         xtermIndex(xw, 1);
 3318         if (xw->flags & LINEFEED)
 3319         CarriageReturn(xw);
 3320         else
 3321         do_xevents(xw);
 3322         break;
 3323 
 3324     case CASE_CBT:
 3325         TRACE(("CASE_CBT\n"));
 3326         /* cursor backward tabulation */
 3327         count = one_if_default(0);
 3328         while ((count-- > 0)
 3329            && (TabToPrevStop(xw))) ;
 3330         ResetState(sp);
 3331         break;
 3332 
 3333     case CASE_CHT:
 3334         TRACE(("CASE_CHT\n"));
 3335         /* cursor forward tabulation */
 3336         count = one_if_default(0);
 3337         while ((count-- > 0)
 3338            && (TabToNextStop(xw))) ;
 3339         ResetState(sp);
 3340         break;
 3341 
 3342     case CASE_TAB:
 3343         /* tab */
 3344         TabToNextStop(xw);
 3345         break;
 3346 
 3347     case CASE_SI:
 3348         screen->curgl = 0;
 3349         if_OPT_VT52_MODE(screen, {
 3350         ResetState(sp);
 3351         });
 3352         break;
 3353 
 3354     case CASE_SO:
 3355         screen->curgl = 1;
 3356         if_OPT_VT52_MODE(screen, {
 3357         ResetState(sp);
 3358         });
 3359         break;
 3360 
 3361     case CASE_DECDHL:
 3362         xterm_DECDHL(xw, c == '3');
 3363         ResetState(sp);
 3364         break;
 3365 
 3366     case CASE_DECSWL:
 3367         xterm_DECSWL(xw);
 3368         ResetState(sp);
 3369         break;
 3370 
 3371     case CASE_DECDWL:
 3372         xterm_DECDWL(xw);
 3373         ResetState(sp);
 3374         break;
 3375 
 3376     case CASE_SCR_STATE:
 3377         /* enter scr state */
 3378         sp->parsestate = scrtable;
 3379         break;
 3380 
 3381     case CASE_SCS0_STATE:
 3382         /* enter scs state 0 */
 3383         select_charset(sp, 0, 94);
 3384         break;
 3385 
 3386     case CASE_SCS1_STATE:
 3387         /* enter scs state 1 */
 3388         select_charset(sp, 1, 94);
 3389         break;
 3390 
 3391     case CASE_SCS2_STATE:
 3392         /* enter scs state 2 */
 3393         select_charset(sp, 2, 94);
 3394         break;
 3395 
 3396     case CASE_SCS3_STATE:
 3397         /* enter scs state 3 */
 3398         select_charset(sp, 3, 94);
 3399         break;
 3400 
 3401     case CASE_SCS1A_STATE:
 3402         /* enter scs state 1 */
 3403         select_charset(sp, 1, 96);
 3404         break;
 3405 
 3406     case CASE_SCS2A_STATE:
 3407         /* enter scs state 2 */
 3408         select_charset(sp, 2, 96);
 3409         break;
 3410 
 3411     case CASE_SCS3A_STATE:
 3412         /* enter scs state 3 */
 3413         select_charset(sp, 3, 96);
 3414         break;
 3415 
 3416     case CASE_ESC_IGNORE:
 3417         /* unknown escape sequence */
 3418         sp->parsestate = eigtable;
 3419         break;
 3420 
 3421     case CASE_ESC_DIGIT:
 3422         /* digit in csi or dec mode */
 3423         if (nparam > 0) {
 3424         value = zero_if_default(nparam - 1);
 3425         SetParam(nparam - 1, (10 * value) + ((int) c - '0'));
 3426         if (GetParam(nparam - 1) > MAX_I_PARAM)
 3427             SetParam(nparam - 1, MAX_I_PARAM);
 3428         if (sp->parsestate == csi_table)
 3429             sp->parsestate = csi2_table;
 3430         }
 3431         break;
 3432 
 3433     case CASE_ESC_SEMI:
 3434         /* semicolon in csi or dec mode */
 3435         if (nparam < NPARAM) {
 3436         parms.is_sub[nparam] = 0;
 3437         SetParam(nparam++, DEFAULT);
 3438         }
 3439         if (sp->parsestate == csi_table)
 3440         sp->parsestate = csi2_table;
 3441         break;
 3442 
 3443         /*
 3444          * A _few_ commands accept colon-separated subparameters.
 3445          * Mark the parameter list so that we can exclude (most) bogus
 3446          * commands with simple/fast checks.
 3447          */
 3448     case CASE_ESC_COLON:
 3449         if (nparam < NPARAM) {
 3450         parms.has_subparams = 1;
 3451         if (nparam == 0) {
 3452             parms.is_sub[nparam] = 1;
 3453             SetParam(nparam++, DEFAULT);
 3454         } else if (parms.is_sub[nparam - 1] == 0) {
 3455             parms.is_sub[nparam - 1] = 1;
 3456             parms.is_sub[nparam] = 2;
 3457             parms.params[nparam] = 0;
 3458             ++nparam;
 3459         } else {
 3460             parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1];
 3461             parms.params[nparam] = 0;
 3462             ++nparam;
 3463         }
 3464         }
 3465         break;
 3466 
 3467     case CASE_DEC_STATE:
 3468         /* enter dec mode */
 3469         sp->parsestate = dec_table;
 3470         break;
 3471 
 3472     case CASE_DEC2_STATE:
 3473         /* enter dec2 mode */
 3474         sp->parsestate = dec2_table;
 3475         break;
 3476 
 3477     case CASE_DEC3_STATE:
 3478         /* enter dec3 mode */
 3479         sp->parsestate = dec3_table;
 3480         break;
 3481 
 3482     case CASE_ICH:
 3483         TRACE(("CASE_ICH - insert char\n"));
 3484         InsertChar(xw, (unsigned) one_if_default(0));
 3485         ResetState(sp);
 3486         break;
 3487 
 3488     case CASE_CUU:
 3489         TRACE(("CASE_CUU - cursor up\n"));
 3490         CursorUp(screen, one_if_default(0));
 3491         ResetState(sp);
 3492         break;
 3493 
 3494     case CASE_CUD:
 3495         TRACE(("CASE_CUD - cursor down\n"));
 3496         CursorDown(screen, one_if_default(0));
 3497         ResetState(sp);
 3498         break;
 3499 
 3500     case CASE_CUF:
 3501         TRACE(("CASE_CUF - cursor forward\n"));
 3502         CursorForward(xw, one_if_default(0));
 3503         ResetState(sp);
 3504         break;
 3505 
 3506     case CASE_CUB:
 3507         TRACE(("CASE_CUB - cursor backward\n"));
 3508         CursorBack(xw, one_if_default(0));
 3509         ResetState(sp);
 3510         break;
 3511 
 3512     case CASE_CUP:
 3513         TRACE(("CASE_CUP - cursor position\n"));
 3514         if_OPT_XMC_GLITCH(screen, {
 3515         Jump_XMC(xw);
 3516         });
 3517         CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags);
 3518         ResetState(sp);
 3519         break;
 3520 
 3521     case CASE_VPA:
 3522         TRACE(("CASE_VPA - vertical position absolute\n"));
 3523         CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags);
 3524         ResetState(sp);
 3525         break;
 3526 
 3527     case CASE_HPA:
 3528         TRACE(("CASE_HPA - horizontal position absolute\n"));
 3529         CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags);
 3530         ResetState(sp);
 3531         break;
 3532 
 3533     case CASE_VPR:
 3534         TRACE(("CASE_VPR - vertical position relative\n"));
 3535         CursorSet(screen,
 3536               CursorRow(xw) + one_if_default(0),
 3537               CursorCol(xw),
 3538               xw->flags);
 3539         ResetState(sp);
 3540         break;
 3541 
 3542     case CASE_HPR:
 3543         TRACE(("CASE_HPR - horizontal position relative\n"));
 3544         CursorSet(screen,
 3545               CursorRow(xw),
 3546               CursorCol(xw) + one_if_default(0),
 3547               xw->flags);
 3548         ResetState(sp);
 3549         break;
 3550 
 3551     case CASE_HP_BUGGY_LL:
 3552         TRACE(("CASE_HP_BUGGY_LL\n"));
 3553         /* Some HP-UX applications have the bug that they
 3554            assume ESC F goes to the lower left corner of
 3555            the screen, regardless of what terminfo says. */
 3556         if (screen->hp_ll_bc)
 3557         CursorSet(screen, screen->max_row, 0, xw->flags);
 3558         ResetState(sp);
 3559         break;
 3560 
 3561     case CASE_ED:
 3562         TRACE(("CASE_ED - erase display\n"));
 3563         do_cd_xtra_scroll(xw, zero_if_default(0));
 3564         do_erase_display(xw, zero_if_default(0), OFF_PROTECT);
 3565         ResetState(sp);
 3566         break;
 3567 
 3568     case CASE_EL:
 3569         TRACE(("CASE_EL - erase line\n"));
 3570         do_erase_line(xw, zero_if_default(0), OFF_PROTECT);
 3571         ResetState(sp);
 3572         break;
 3573 
 3574     case CASE_ECH:
 3575         TRACE(("CASE_ECH - erase char\n"));
 3576         /* ECH */
 3577         do_erase_char(xw, one_if_default(0), OFF_PROTECT);
 3578         ResetState(sp);
 3579         break;
 3580 
 3581     case CASE_IL:
 3582         TRACE(("CASE_IL - insert line\n"));
 3583         InsertLine(xw, one_if_default(0));
 3584         ResetState(sp);
 3585         break;
 3586 
 3587     case CASE_DL:
 3588         TRACE(("CASE_DL - delete line\n"));
 3589         DeleteLine(xw, one_if_default(0), True);
 3590         ResetState(sp);
 3591         break;
 3592 
 3593     case CASE_DCH:
 3594         TRACE(("CASE_DCH - delete char\n"));
 3595         DeleteChar(xw, (unsigned) one_if_default(0));
 3596         ResetState(sp);
 3597         break;
 3598 
 3599     case CASE_TRACK_MOUSE:
 3600         /*
 3601          * A single parameter other than zero is always scroll-down.
 3602          * A zero-parameter is used to reset the mouse mode, and is
 3603          * not useful for scrolling anyway.
 3604          */
 3605         if (nparam > 1 || GetParam(0) == 0) {
 3606         CELL start;
 3607 
 3608         TRACE(("CASE_TRACK_MOUSE\n"));
 3609         /* Track mouse as long as in window and between
 3610          * specified rows
 3611          */
 3612         start.row = one_if_default(2) - 1;
 3613         start.col = GetParam(1) - 1;
 3614         TrackMouse(xw,
 3615                GetParam(0),
 3616                &start,
 3617                GetParam(3) - 1, GetParam(4) - 2);
 3618         } else {
 3619         TRACE(("CASE_SD - scroll down\n"));
 3620         /* SD */
 3621         RevScroll(xw, one_if_default(0));
 3622         do_xevents(xw);
 3623         }
 3624         ResetState(sp);
 3625         break;
 3626 
 3627     case CASE_SD:
 3628         /*
 3629          * Cater to ECMA-48's typographical error...
 3630          */
 3631         TRACE(("CASE_SD - scroll down\n"));
 3632         RevScroll(xw, one_if_default(0));
 3633         do_xevents(xw);
 3634         ResetState(sp);
 3635         break;
 3636 
 3637     case CASE_DECID:
 3638         TRACE(("CASE_DECID\n"));
 3639         if_OPT_VT52_MODE(screen, {
 3640         unparseputc(xw, ANSI_ESC);
 3641         unparseputc(xw, '/');
 3642         unparseputc(xw, 'Z');
 3643         unparse_end(xw);
 3644         ResetState(sp);
 3645         break;
 3646         });
 3647         SetParam(0, DEFAULT);   /* Default ID parameter */
 3648         /* FALLTHRU */
 3649     case CASE_DA1:
 3650         TRACE(("CASE_DA1\n"));
 3651         if (GetParam(0) <= 0) { /* less than means DEFAULT */
 3652         count = 0;
 3653         init_reply(ANSI_CSI);
 3654         reply.a_pintro = '?';
 3655 
 3656         /*
 3657          * The first parameter corresponds to the highest operating
 3658          * level (i.e., service level) of the emulation.  A DEC
 3659          * terminal can be setup to respond with a different DA
 3660          * response, but there's no control sequence that modifies
 3661          * this.  We set it via a resource.
 3662          */
 3663         if (screen->terminal_id < 200) {
 3664             switch (screen->terminal_id) {
 3665             case 132:
 3666             reply.a_param[count++] = 4; /* VT132 */
 3667 #if OPT_REGIS_GRAPHICS
 3668             reply.a_param[count++] = 6; /* no STP, AVO, GPO (ReGIS) */
 3669 #else
 3670             reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */
 3671 #endif
 3672             break;
 3673             case 131:
 3674             reply.a_param[count++] = 7; /* VT131 */
 3675             break;
 3676             case 125:
 3677             reply.a_param[count++] = 12;    /* VT125 */
 3678 #if OPT_REGIS_GRAPHICS
 3679             reply.a_param[count++] = 0 | 2 | 1; /* no STP, AVO, GPO (ReGIS) */
 3680 #else
 3681             reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */
 3682 #endif
 3683             reply.a_param[count++] = 0; /* no printer */
 3684             reply.a_param[count++] = XTERM_PATCH;   /* ROM version */
 3685             break;
 3686             case 102:
 3687             reply.a_param[count++] = 6; /* VT102 */
 3688             break;
 3689             case 101:
 3690             reply.a_param[count++] = 1; /* VT101 */
 3691             reply.a_param[count++] = 0; /* no options */
 3692             break;
 3693             default:    /* VT100 */
 3694             reply.a_param[count++] = 1; /* VT100 */
 3695             reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */
 3696             break;
 3697             }
 3698         } else {
 3699             reply.a_param[count++] = (ParmType) (60
 3700                              + screen->terminal_id
 3701                              / 100);
 3702             reply.a_param[count++] = 1;     /* 132-columns */
 3703             reply.a_param[count++] = 2;     /* printer */
 3704 #if OPT_REGIS_GRAPHICS
 3705             if (optRegisGraphics(screen)) {
 3706             reply.a_param[count++] = 3; /* ReGIS graphics */
 3707             }
 3708 #endif
 3709 #if OPT_SIXEL_GRAPHICS
 3710             if (optSixelGraphics(screen)) {
 3711             reply.a_param[count++] = 4; /* sixel graphics */
 3712             }
 3713 #endif
 3714             reply.a_param[count++] = 6;     /* selective-erase */
 3715 #if OPT_SUNPC_KBD
 3716             if (xw->keyboard.type == keyboardIsVT220)
 3717 #endif
 3718             reply.a_param[count++] = 8; /* user-defined-keys */
 3719             reply.a_param[count++] = 9;     /* national replacement charsets */
 3720             reply.a_param[count++] = 15;    /* technical characters */
 3721             reply.a_param[count++] = 16;    /* locator port */
 3722             if (screen->terminal_id >= 400) {
 3723             reply.a_param[count++] = 17;    /* terminal state interrogation */
 3724             reply.a_param[count++] = 18;    /* windowing extension */
 3725             reply.a_param[count++] = 21;    /* horizontal scrolling */
 3726             }
 3727             if_OPT_ISO_COLORS(screen, {
 3728             reply.a_param[count++] = 22;    /* ANSI color, VT525 */
 3729             });
 3730             reply.a_param[count++] = 28;    /* rectangular editing */
 3731 #if OPT_DEC_LOCATOR
 3732             reply.a_param[count++] = 29;    /* ANSI text locator */
 3733 #endif
 3734         }
 3735         reply.a_nparam = (ParmType) count;
 3736         reply.a_final = 'c';
 3737         unparseseq(xw, &reply);
 3738         }
 3739         ResetState(sp);
 3740         break;
 3741 
 3742     case CASE_DA2:
 3743         TRACE(("CASE_DA2\n"));
 3744         if (GetParam(0) <= 0) { /* less than means DEFAULT */
 3745         count = 0;
 3746         init_reply(ANSI_CSI);
 3747         reply.a_pintro = '>';
 3748 
 3749         if (screen->terminal_id >= 200) {
 3750             switch (screen->terminal_id) {
 3751             case 220:
 3752             default:
 3753             reply.a_param[count++] = 1; /* VT220 */
 3754             break;
 3755             case 240:
 3756             case 241:
 3757             /* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */
 3758             reply.a_param[count++] = 2; /* VT240 */
 3759             break;
 3760             case 320:
 3761             /* http://www.vt100.net/docs/vt320-uu/appendixe.html */
 3762             reply.a_param[count++] = 24;    /* VT320 */
 3763             break;
 3764             case 330:
 3765             reply.a_param[count++] = 18;    /* VT330 */
 3766             break;
 3767             case 340:
 3768             reply.a_param[count++] = 19;    /* VT340 */
 3769             break;
 3770             case 382:
 3771             reply.a_param[count++] = 32;    /* VT382 */
 3772             break;
 3773             case 420:
 3774             reply.a_param[count++] = 41;    /* VT420 */
 3775             break;
 3776             case 510:
 3777             /* http://www.vt100.net/docs/vt510-rm/DA2 */
 3778             reply.a_param[count++] = 61;    /* VT510 */
 3779             break;
 3780             case 520:
 3781             reply.a_param[count++] = 64;    /* VT520 */
 3782             break;
 3783             case 525:
 3784             reply.a_param[count++] = 65;    /* VT525 */
 3785             break;
 3786             }
 3787         } else {
 3788             reply.a_param[count++] = 0;     /* VT100 (nonstandard) */
 3789         }
 3790         reply.a_param[count++] = XTERM_PATCH;   /* Version */
 3791         reply.a_param[count++] = 0; /* options (none) */
 3792         reply.a_nparam = (ParmType) count;
 3793         reply.a_final = 'c';
 3794         unparseseq(xw, &reply);
 3795         }
 3796         ResetState(sp);
 3797         break;
 3798 
 3799     case CASE_DECRPTUI:
 3800         TRACE(("CASE_DECRPTUI\n"));
 3801         if ((screen->vtXX_level >= 4)
 3802         && (GetParam(0) <= 0)) {    /* less than means DEFAULT */
 3803         unparseputc1(xw, ANSI_DCS);
 3804         unparseputc(xw, '!');
 3805         unparseputc(xw, '|');
 3806         /* report the "terminal unit id" as 4 pairs of hexadecimal
 3807          * digits -- meaningless for a terminal emulator, but some
 3808          * host may care about the format.
 3809          */
 3810         for (count = 0; count < 8; ++count) {
 3811             unparseputc(xw, '0');
 3812         }
 3813         unparseputc1(xw, ANSI_ST);
 3814         unparse_end(xw);
 3815         }
 3816         ResetState(sp);
 3817         break;
 3818 
 3819     case CASE_TBC:
 3820         TRACE(("CASE_TBC - tab clear\n"));
 3821         if ((value = GetParam(0)) <= 0) /* less than means default */
 3822         TabClear(xw->tabs, screen->cur_col);
 3823         else if (value == 3)
 3824         TabZonk(xw->tabs);
 3825         ResetState(sp);
 3826         break;
 3827 
 3828     case CASE_SET:
 3829         TRACE(("CASE_SET - set mode\n"));
 3830         ansi_modes(xw, bitset);
 3831         ResetState(sp);
 3832         break;
 3833 
 3834     case CASE_RST:
 3835         TRACE(("CASE_RST - reset mode\n"));
 3836         ansi_modes(xw, bitclr);
 3837         ResetState(sp);
 3838         break;
 3839 
 3840     case CASE_SGR:
 3841         for (item = 0; item < nparam; ++item) {
 3842         int op = GetParam(item);
 3843         int skip;
 3844 
 3845         if_OPT_XMC_GLITCH(screen, {
 3846             Mark_XMC(xw, op);
 3847         });
 3848         TRACE(("CASE_SGR %d\n", op));
 3849 
 3850         /*
 3851          * Only SGR 38/48 accept subparameters, and in those cases
 3852          * the values will not be seen at this point.
 3853          */
 3854         if ((skip = param_has_subparams(item))) {
 3855             switch (op) {
 3856             case 38:
 3857             /* FALLTHRU */
 3858             case 48:
 3859             if_OPT_ISO_COLORS(screen, {
 3860                 break;
 3861             });
 3862             /* FALLTHRU */
 3863             default:
 3864             TRACE(("...unexpected subparameter in SGR\n"));
 3865             item += skip;   /* ignore this */
 3866             op = NPARAM;    /* will never use this, anyway */
 3867             break;
 3868             }
 3869         }
 3870 
 3871         switch (op) {
 3872         case DEFAULT:
 3873             /* FALLTHRU */
 3874         case 0:
 3875             resetRendition(xw);
 3876             if_OPT_ISO_COLORS(screen, {
 3877             reset_SGR_Colors(xw);
 3878             });
 3879             break;
 3880         case 1: /* Bold                 */
 3881             UIntSet(xw->flags, BOLD);
 3882             if_OPT_ISO_COLORS(screen, {
 3883             setExtendedFG(xw);
 3884             });
 3885             break;
 3886 #if OPT_WIDE_ATTRS
 3887         case 2: /* faint, decreased intensity or second colour */
 3888             UIntSet(xw->flags, ATR_FAINT);
 3889             if_OPT_ISO_COLORS(screen, {
 3890             setExtendedFG(xw);
 3891             });
 3892             break;
 3893         case 3: /* italicized */
 3894             setItalicFont(xw, UseItalicFont(screen));
 3895             UIntSet(xw->flags, ATR_ITALIC);
 3896             if_OPT_ISO_COLORS(screen, {
 3897             setExtendedFG(xw);
 3898             });
 3899             break;
 3900 #endif
 3901         case 4: /* Underscore           */
 3902             UIntSet(xw->flags, UNDERLINE);
 3903             if_OPT_ISO_COLORS(screen, {
 3904             setExtendedFG(xw);
 3905             });
 3906             break;
 3907         case 5: /* Blink (less than 150 per minute) */
 3908             /* FALLTHRU */
 3909         case 6: /* Blink (150 per minute, or more) */
 3910             UIntSet(xw->flags, BLINK);
 3911             StartBlinking(xw);
 3912             if_OPT_ISO_COLORS(screen, {
 3913             setExtendedFG(xw);
 3914             });
 3915             break;
 3916         case 7:
 3917             UIntSet(xw->flags, INVERSE);
 3918             if_OPT_ISO_COLORS(screen, {
 3919             setExtendedBG(xw);
 3920             });
 3921             break;
 3922         case 8:
 3923             UIntSet(xw->flags, INVISIBLE);
 3924             break;
 3925 #if OPT_WIDE_ATTRS
 3926         case 9: /* crossed-out characters */
 3927             UIntSet(xw->flags, ATR_STRIKEOUT);
 3928             break;
 3929 #endif
 3930 #if OPT_WIDE_ATTRS
 3931         case 21:    /* doubly-underlined */
 3932             UIntSet(xw->flags, ATR_DBL_UNDER);
 3933             break;
 3934 #endif
 3935         case 22:    /* reset 'bold' */
 3936             UIntClr(xw->flags, BOLD);
 3937 #if OPT_WIDE_ATTRS
 3938             UIntClr(xw->flags, ATR_FAINT);
 3939 #endif
 3940             if_OPT_ISO_COLORS(screen, {
 3941             setExtendedFG(xw);
 3942             });
 3943             break;
 3944 #if OPT_WIDE_ATTRS
 3945         case 23:    /* not italicized */
 3946             ResetItalics(xw);
 3947             if_OPT_ISO_COLORS(screen, {
 3948             setExtendedFG(xw);
 3949             });
 3950             break;
 3951 #endif
 3952         case 24:
 3953             UIntClr(xw->flags, UNDERLINE);
 3954 #if OPT_WIDE_ATTRS
 3955             UIntClr(xw->flags, ATR_DBL_UNDER);
 3956 #endif
 3957             if_OPT_ISO_COLORS(screen, {
 3958             setExtendedFG(xw);
 3959             });
 3960             break;
 3961         case 25:    /* reset 'blink' */
 3962             UIntClr(xw->flags, BLINK);
 3963             if_OPT_ISO_COLORS(screen, {
 3964             setExtendedFG(xw);
 3965             });
 3966             break;
 3967         case 27:
 3968             UIntClr(xw->flags, INVERSE);
 3969             if_OPT_ISO_COLORS(screen, {
 3970             setExtendedBG(xw);
 3971             });
 3972             break;
 3973         case 28:
 3974             UIntClr(xw->flags, INVISIBLE);
 3975             break;
 3976 #if OPT_WIDE_ATTRS
 3977         case 29:    /* not crossed out */
 3978             UIntClr(xw->flags, ATR_STRIKEOUT);
 3979             break;
 3980 #endif
 3981         case 30:
 3982             /* FALLTHRU */
 3983         case 31:
 3984             /* FALLTHRU */
 3985         case 32:
 3986             /* FALLTHRU */
 3987         case 33:
 3988             /* FALLTHRU */
 3989         case 34:
 3990             /* FALLTHRU */
 3991         case 35:
 3992             /* FALLTHRU */
 3993         case 36:
 3994             /* FALLTHRU */
 3995         case 37:
 3996             if_OPT_ISO_COLORS(screen, {
 3997             xw->sgr_foreground = (op - 30);
 3998             xw->sgr_38_xcolors = False;
 3999             clrDirectFG(xw->flags);
 4000             setExtendedFG(xw);
 4001             });
 4002             break;
 4003         case 38:
 4004             /* This is more complicated than I'd like, but it should
 4005              * properly eat all the parameters for unsupported modes.
 4006              */
 4007             if_OPT_ISO_COLORS(screen, {
 4008             Boolean extended;
 4009             if (parse_extended_colors(xw, &value, &item,
 4010                           &extended)) {
 4011                 xw->sgr_foreground = value;
 4012                 xw->sgr_38_xcolors = True;
 4013                 setDirectFG(xw->flags, extended);
 4014                 setExtendedFG(xw);
 4015             }
 4016             });
 4017             break;
 4018         case 39:
 4019             if_OPT_ISO_COLORS(screen, {
 4020             reset_SGR_Foreground(xw);
 4021             });
 4022             break;
 4023         case 40:
 4024             /* FALLTHRU */
 4025         case 41:
 4026             /* FALLTHRU */
 4027         case 42:
 4028             /* FALLTHRU */
 4029         case 43:
 4030             /* FALLTHRU */
 4031         case 44:
 4032             /* FALLTHRU */
 4033         case 45:
 4034             /* FALLTHRU */
 4035         case 46:
 4036             /* FALLTHRU */
 4037         case 47:
 4038             if_OPT_ISO_COLORS(screen, {
 4039             xw->sgr_background = (op - 40);
 4040             clrDirectBG(xw->flags);
 4041             setExtendedBG(xw);
 4042             });
 4043             break;
 4044         case 48:
 4045             if_OPT_ISO_COLORS(screen, {
 4046             Boolean extended;
 4047             if (parse_extended_colors(xw, &value, &item,
 4048                           &extended)) {
 4049                 xw->sgr_background = value;
 4050                 setDirectBG(xw->flags, extended);
 4051                 setExtendedBG(xw);
 4052             }
 4053             });
 4054             break;
 4055         case 49:
 4056             if_OPT_ISO_COLORS(screen, {
 4057             reset_SGR_Background(xw);
 4058             });
 4059             break;
 4060         case 90:
 4061             /* FALLTHRU */
 4062         case 91:
 4063             /* FALLTHRU */
 4064         case 92:
 4065             /* FALLTHRU */
 4066         case 93:
 4067             /* FALLTHRU */
 4068         case 94:
 4069             /* FALLTHRU */
 4070         case 95:
 4071             /* FALLTHRU */
 4072         case 96:
 4073             /* FALLTHRU */
 4074         case 97:
 4075             if_OPT_AIX_COLORS(screen, {
 4076             xw->sgr_foreground = (op - 90 + 8);
 4077             clrDirectFG(xw->flags);
 4078             setExtendedFG(xw);
 4079             });
 4080             break;
 4081         case 100:
 4082 #if !OPT_AIX_COLORS
 4083             if_OPT_ISO_COLORS(screen, {
 4084             reset_SGR_Foreground(xw);
 4085             reset_SGR_Background(xw);
 4086             });
 4087             break;
 4088 #endif
 4089         case 101:
 4090             /* FALLTHRU */
 4091         case 102:
 4092             /* FALLTHRU */
 4093         case 103:
 4094             /* FALLTHRU */
 4095         case 104:
 4096             /* FALLTHRU */
 4097         case 105:
 4098             /* FALLTHRU */
 4099         case 106:
 4100             /* FALLTHRU */
 4101         case 107:
 4102             if_OPT_AIX_COLORS(screen, {
 4103             xw->sgr_background = (op - 100 + 8);
 4104             clrDirectBG(xw->flags);
 4105             setExtendedBG(xw);
 4106             });
 4107             break;
 4108         default:
 4109             /* later: skip += NPARAM; */
 4110             break;
 4111         }
 4112         }
 4113         ResetState(sp);
 4114         break;
 4115 
 4116         /* DSR (except for the '?') is a superset of CPR */
 4117     case CASE_DSR:
 4118         sp->private_function = True;
 4119 
 4120         /* FALLTHRU */
 4121     case CASE_CPR:
 4122         TRACE(("CASE_DSR - device status report\n"));
 4123         count = 0;
 4124         init_reply(ANSI_CSI);
 4125         reply.a_pintro = CharOf(sp->private_function ? '?' : 0);
 4126         reply.a_final = 'n';
 4127 
 4128         switch (GetParam(0)) {
 4129         case 5:
 4130         TRACE(("...request operating status\n"));
 4131         /* operating status */
 4132         reply.a_param[count++] = 0; /* (no malfunction ;-) */
 4133         break;
 4134         case 6:
 4135         TRACE(("...request %s\n",
 4136                (sp->private_function
 4137             ? "DECXCPR"
 4138             : "CPR")));
 4139         /* CPR */
 4140         /* DECXCPR (with page=1) */
 4141         value = screen->cur_row;
 4142         if ((xw->flags & ORIGIN) != 0) {
 4143             value -= screen->top_marg;
 4144         }
 4145         if_STATUS_LINE(screen, {
 4146             if ((value -= LastRowNumber(screen)) < 0)
 4147             value = 0;
 4148         });
 4149         reply.a_param[count++] = (ParmType) (value + 1);
 4150 
 4151         value = (screen->cur_col + 1);
 4152         if ((xw->flags & ORIGIN) != 0) {
 4153             value -= screen->lft_marg;
 4154         }
 4155         reply.a_param[count++] = (ParmType) value;
 4156 
 4157         if (sp->private_function &&
 4158             (screen->vtXX_level >= 4 ||
 4159              (screen->terminal_id >= 330 &&
 4160               screen->vtXX_level >= 3))) {
 4161             /* VT330 (not VT320) and VT420 */
 4162             reply.a_param[count++] = 1;
 4163         }
 4164         reply.a_final = 'R';
 4165         break;
 4166         case 15:
 4167         TRACE(("...request printer status\n"));
 4168         if (sp->private_function
 4169             && screen->vtXX_level >= 2) {   /* VT220 */
 4170             reply.a_param[count++] = 13;    /* no printer detected */
 4171         }
 4172         break;
 4173         case 25:
 4174         TRACE(("...request UDK status\n"));
 4175         if (sp->private_function
 4176             && screen->vtXX_level >= 2) {   /* VT220 */
 4177             reply.a_param[count++] = 20;    /* UDK always unlocked */
 4178         }
 4179         break;
 4180         case 26:
 4181         TRACE(("...request keyboard status\n"));
 4182         if (sp->private_function
 4183             && screen->vtXX_level >= 2) {   /* VT220 */
 4184             reply.a_param[count++] = 27;
 4185             reply.a_param[count++] = 1;     /* North American */
 4186             if (screen->vtXX_level >= 3) {  /* VT320 */
 4187             reply.a_param[count++] = 0; /* ready */
 4188             }
 4189             if (screen->vtXX_level >= 4) {  /* VT420 */
 4190             reply.a_param[count++] = 0; /* LK201 */
 4191             }
 4192         }
 4193         break;
 4194         case 53:        /* according to existing xterm handling */
 4195         /* FALLTHRU */
 4196         case 55:        /* according to the VT330/VT340 Text Programming Manual */
 4197         TRACE(("...request locator status\n"));
 4198         if (sp->private_function
 4199             && screen->vtXX_level >= 3) {   /* VT330 */
 4200 #if OPT_DEC_LOCATOR
 4201             reply.a_param[count++] = 50;    /* locator ready */
 4202 #else
 4203             reply.a_param[count++] = 53;    /* no locator */
 4204 #endif
 4205         }
 4206         break;
 4207         case 56:
 4208         TRACE(("...request locator type\n"));
 4209         if (sp->private_function
 4210             && screen->vtXX_level >= 3) {   /* VT330 */
 4211             reply.a_param[count++] = 57;
 4212 #if OPT_DEC_LOCATOR
 4213             reply.a_param[count++] = 1;     /* mouse */
 4214 #else
 4215             reply.a_param[count++] = 0;     /* unknown */
 4216 #endif
 4217         }
 4218         break;
 4219         case 62:
 4220         TRACE(("...request DECMSR - macro space\n"));
 4221         if (sp->private_function
 4222             && screen->vtXX_level >= 4) {   /* VT420 */
 4223             reply.a_pintro = 0;
 4224             reply.a_radix[count] = 16;  /* no data */
 4225             reply.a_param[count++] = 0;     /* no space for macros */
 4226             reply.a_inters = '*';
 4227             reply.a_final = L_CURL;
 4228         }
 4229         break;
 4230         case 63:
 4231         TRACE(("...request DECCKSR - memory checksum\n"));
 4232         /* DECCKSR - Memory checksum */
 4233         if (sp->private_function
 4234             && screen->vtXX_level >= 4) {   /* VT420 */
 4235             init_reply(ANSI_DCS);
 4236             reply.a_param[count++] = (ParmType) GetParam(1);    /* PID */
 4237             reply.a_delim = "!~";   /* delimiter */
 4238             reply.a_radix[count] = 16;  /* use hex */
 4239             reply.a_param[count++] = 0;     /* no data */
 4240         }
 4241         break;
 4242         case 75:
 4243         TRACE(("...request data integrity\n"));
 4244         if (sp->private_function
 4245             && screen->vtXX_level >= 4) {   /* VT420 */
 4246             reply.a_param[count++] = 70;    /* no errors */
 4247         }
 4248         break;
 4249         case 85:
 4250         TRACE(("...request multi-session configuration\n"));
 4251         if (sp->private_function
 4252             && screen->vtXX_level >= 4) {   /* VT420 */
 4253             reply.a_param[count++] = 83;    /* not configured */
 4254         }
 4255         break;
 4256         default:
 4257         break;
 4258         }
 4259 
 4260         if ((reply.a_nparam = (ParmType) count) != 0)
 4261         unparseseq(xw, &reply);
 4262 
 4263         ResetState(sp);
 4264         sp->private_function = False;
 4265         break;
 4266 
 4267     case CASE_MC:
 4268         TRACE(("CASE_MC - media control\n"));
 4269         xtermMediaControl(xw, GetParam(0), False);
 4270         ResetState(sp);
 4271         break;
 4272 
 4273     case CASE_DEC_MC:
 4274         TRACE(("CASE_DEC_MC - DEC media control\n"));
 4275         xtermMediaControl(xw, GetParam(0), True);
 4276         ResetState(sp);
 4277         break;
 4278 
 4279     case CASE_HP_MEM_LOCK:
 4280         /* FALLTHRU */
 4281     case CASE_HP_MEM_UNLOCK:
 4282         TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK)
 4283                 ? "CASE_HP_MEM_LOCK"
 4284                 : "CASE_HP_MEM_UNLOCK")));
 4285         if (screen->scroll_amt)
 4286         FlushScroll(xw);
 4287         if (sp->parsestate[c] == CASE_HP_MEM_LOCK)
 4288         set_tb_margins(screen, screen->cur_row, screen->bot_marg);
 4289         else
 4290         set_tb_margins(screen, 0, screen->bot_marg);
 4291         ResetState(sp);
 4292         break;
 4293 
 4294     case CASE_DECSTBM:
 4295         TRACE(("CASE_DECSTBM - set scrolling region\n"));
 4296         {
 4297         int top;
 4298         int bot;
 4299         top = one_if_default(0);
 4300         if (nparam < 2 || (bot = GetParam(1)) == DEFAULT
 4301             || bot > MaxRows(screen)
 4302             || bot == 0)
 4303             bot = MaxRows(screen);
 4304         if (bot > top) {
 4305             if (screen->scroll_amt)
 4306             FlushScroll(xw);
 4307             set_tb_margins(screen, top - 1, bot - 1);
 4308             CursorSet(screen, 0, 0, xw->flags);
 4309         }
 4310         ResetState(sp);
 4311         }
 4312         break;
 4313 
 4314     case CASE_DECREQTPARM:
 4315         TRACE(("CASE_DECREQTPARM\n"));
 4316         if (screen->terminal_id < 200) {    /* VT102 */
 4317         value = zero_if_default(0);
 4318         if (value == 0 || value == 1) {
 4319             init_reply(ANSI_CSI);
 4320             reply.a_nparam = 7;
 4321             reply.a_param[0] = (ParmType) (value + 2);
 4322             reply.a_param[1] = 1;   /* no parity */
 4323             reply.a_param[2] = 1;   /* eight bits */
 4324             reply.a_param[3] = 128; /* transmit 38.4k baud */
 4325             reply.a_param[4] = 128; /* receive 38.4k baud */
 4326             reply.a_param[5] = 1;   /* clock multiplier ? */
 4327             reply.a_param[6] = 0;   /* STP flags ? */
 4328             reply.a_final = 'x';
 4329             unparseseq(xw, &reply);
 4330         }
 4331         }
 4332         ResetState(sp);
 4333         break;
 4334 
 4335     case CASE_DECSET:
 4336         /* DECSET */
 4337 #if OPT_VT52_MODE
 4338         if (screen->vtXX_level != 0)
 4339 #endif
 4340         dpmodes(xw, bitset);
 4341         ResetState(sp);
 4342 #if OPT_TEK4014
 4343         if (TEK4014_ACTIVE(xw)) {
 4344         TRACE(("Tek4014 is now active...\n"));
 4345         if (sp->check_recur)
 4346             sp->check_recur--;
 4347         return False;
 4348         }
 4349 #endif
 4350         break;
 4351 
 4352     case CASE_DECRST:
 4353         /* DECRST */
 4354         dpmodes(xw, bitclr);
 4355         init_groundtable(screen, sp);
 4356         ResetState(sp);
 4357         break;
 4358 
 4359     case CASE_DECALN:
 4360         TRACE(("CASE_DECALN - alignment test\n"));
 4361         if (screen->cursor_state)
 4362         HideCursor(xw);
 4363         /*
 4364          * DEC STD 070 (see pages D-19 to D-20) does not mention left/right
 4365          * margins.  The section is dated March 1985, not updated for the
 4366          * VT420 (introduced in 1990).
 4367          */
 4368         UIntClr(xw->flags, ORIGIN);
 4369         screen->do_wrap = False;
 4370         resetRendition(xw);
 4371         resetMargins(xw);
 4372         xterm_ResetDouble(xw);
 4373         CursorSet(screen, 0, 0, xw->flags);
 4374         xtermParseRect(xw, 0, 0, &myRect);
 4375         ScrnFillRectangle(xw, &myRect, 'E', 0, False);
 4376         ResetState(sp);
 4377         break;
 4378 
 4379     case CASE_GSETS5:
 4380         if (screen->vtXX_level >= 5) {
 4381         TRACE(("CASE_GSETS5(%d) = '%c'\n", sp->scstype, c));
 4382         xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c);
 4383         }
 4384         ResetState(sp);
 4385         break;
 4386 
 4387     case CASE_GSETS3:
 4388         if (screen->vtXX_level >= 3) {
 4389         TRACE(("CASE_GSETS3(%d) = '%c'\n", sp->scstype, c));
 4390         xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c);
 4391         }
 4392         ResetState(sp);
 4393         break;
 4394 
 4395     case CASE_GSETS:
 4396         if (strchr("012AB", (int) c) != 0) {
 4397         TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
 4398         xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c);
 4399         } else if (screen->vtXX_level >= 2) {
 4400         TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
 4401         xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c);
 4402         }
 4403         ResetState(sp);
 4404         break;
 4405 
 4406     case CASE_ANSI_SC:
 4407         if (IsLeftRightMode(xw)) {
 4408         int left;
 4409         int right;
 4410 
 4411         TRACE(("CASE_DECSLRM - set left and right margin\n"));
 4412         left = one_if_default(0);
 4413         if (nparam < 2 || (right = GetParam(1)) == DEFAULT
 4414             || right > MaxCols(screen)
 4415             || right == 0)
 4416             right = MaxCols(screen);
 4417         if (right > left) {
 4418             set_lr_margins(screen, left - 1, right - 1);
 4419             CursorSet(screen, 0, 0, xw->flags);
 4420         }
 4421         } else {
 4422         TRACE(("CASE_ANSI_SC - save cursor\n"));
 4423         CursorSave(xw);
 4424         }
 4425         ResetState(sp);
 4426         break;
 4427 
 4428     case CASE_DECSC:
 4429         TRACE(("CASE_DECSC - save cursor\n"));
 4430         CursorSave(xw);
 4431         ResetState(sp);
 4432         break;
 4433 
 4434     case CASE_ANSI_RC:
 4435         /* FALLTHRU */
 4436     case CASE_DECRC:
 4437         TRACE(("CASE_%sRC - restore cursor\n",
 4438            (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_"));
 4439         CursorRestore(xw);
 4440         if_OPT_ISO_COLORS(screen, {
 4441         setExtendedFG(xw);
 4442         });
 4443         ResetState(sp);
 4444         break;
 4445 
 4446     case CASE_DECKPAM:
 4447         TRACE(("CASE_DECKPAM\n"));
 4448         xw->keyboard.flags |= MODE_DECKPAM;
 4449         update_appkeypad();
 4450         ResetState(sp);
 4451         break;
 4452 
 4453     case CASE_DECKPNM:
 4454         TRACE(("CASE_DECKPNM\n"));
 4455         UIntClr(xw->keyboard.flags, MODE_DECKPAM);
 4456         update_appkeypad();
 4457         ResetState(sp);
 4458         break;
 4459 
 4460     case CASE_CSI_QUOTE_STATE:
 4461         sp->parsestate = csi_quo_table;
 4462         break;
 4463 
 4464 #if OPT_BLINK_CURS
 4465     case CASE_CSI_SPACE_STATE:
 4466         sp->parsestate = csi_sp_table;
 4467         break;
 4468 
 4469     case CASE_DECSCUSR:
 4470         TRACE(("CASE_DECSCUSR\n"));
 4471         {
 4472         Boolean change = True;
 4473         int blinks = screen->cursor_blink_esc;
 4474 
 4475         HideCursor(xw);
 4476 
 4477         switch (GetParam(0)) {
 4478         case DEFAULT:
 4479             /* FALLTHRU */
 4480         case DEFAULT_STYLE:
 4481             /* FALLTHRU */
 4482         case BLINK_BLOCK:
 4483             blinks = True;
 4484             screen->cursor_shape = CURSOR_BLOCK;
 4485             break;
 4486         case STEADY_BLOCK:
 4487             blinks = False;
 4488             screen->cursor_shape = CURSOR_BLOCK;
 4489             break;
 4490         case BLINK_UNDERLINE:
 4491             blinks = True;
 4492             screen->cursor_shape = CURSOR_UNDERLINE;
 4493             break;
 4494         case STEADY_UNDERLINE:
 4495             blinks = False;
 4496             screen->cursor_shape = CURSOR_UNDERLINE;
 4497             break;
 4498         case BLINK_BAR:
 4499             blinks = True;
 4500             screen->cursor_shape = CURSOR_BAR;
 4501             break;
 4502         case STEADY_BAR:
 4503             blinks = False;
 4504             screen->cursor_shape = CURSOR_BAR;
 4505             break;
 4506         default:
 4507             change = False;
 4508             break;
 4509         }
 4510         TRACE(("cursor_shape:%d blinks:%s\n",
 4511                screen->cursor_shape, BtoS(blinks)));
 4512         if (change) {
 4513             xtermSetCursorBox(screen);
 4514             if (SettableCursorBlink(screen)) {
 4515             screen->cursor_blink_esc = blinks;
 4516             UpdateCursorBlink(xw);
 4517             }
 4518         }
 4519         }
 4520         ResetState(sp);
 4521         break;
 4522 #endif
 4523 
 4524 #if OPT_SCROLL_LOCK
 4525     case CASE_DECLL:
 4526         TRACE(("CASE_DECLL\n"));
 4527         if (nparam > 0) {
 4528         for (count = 0; count < nparam; ++count) {
 4529             int op = zero_if_default(count);
 4530             switch (op) {
 4531             case 0:
 4532             case DEFAULT:
 4533             xtermClearLEDs(screen);
 4534             break;
 4535             case 1:
 4536             /* FALLTHRU */
 4537             case 2:
 4538             /* FALLTHRU */
 4539             case 3:
 4540             xtermShowLED(screen,
 4541                      (Cardinal) op,
 4542                      True);
 4543             break;
 4544             case 21:
 4545             /* FALLTHRU */
 4546             case 22:
 4547             /* FALLTHRU */
 4548             case 23:
 4549             xtermShowLED(screen,
 4550                      (Cardinal) (op - 20),
 4551                      True);
 4552             break;
 4553             }
 4554         }
 4555         } else {
 4556         xtermClearLEDs(screen);
 4557         }
 4558         ResetState(sp);
 4559         break;
 4560 #endif
 4561 
 4562 #if OPT_VT52_MODE
 4563     case CASE_VT52_FINISH:
 4564         TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n",
 4565            screen->terminal_id,
 4566            screen->vtXX_level));
 4567         if (screen->terminal_id >= 100
 4568         && screen->vtXX_level == 0) {
 4569         sp->groundtable =
 4570             sp->parsestate = ansi_table;
 4571         /*
 4572          * On restore, the terminal does not recognize DECRQSS for
 4573          * DECSCL (per vttest).
 4574          */
 4575         screen->vtXX_level = 1;
 4576         xw->flags = screen->vt52_save_flags;
 4577         screen->curgl = screen->vt52_save_curgl;
 4578         screen->curgr = screen->vt52_save_curgr;
 4579         screen->curss = screen->vt52_save_curss;
 4580         restoreCharsets(screen, screen->vt52_save_gsets);
 4581         update_vt52_vt100_settings();
 4582         }
 4583         break;
 4584 #endif
 4585 
 4586     case CASE_ANSI_LEVEL_1:
 4587         TRACE(("CASE_ANSI_LEVEL_1\n"));
 4588         set_ansi_conformance(screen, 1);
 4589         ResetState(sp);
 4590         break;
 4591 
 4592     case CASE_ANSI_LEVEL_2:
 4593         TRACE(("CASE_ANSI_LEVEL_2\n"));
 4594         set_ansi_conformance(screen, 2);
 4595         ResetState(sp);
 4596         break;
 4597 
 4598     case CASE_ANSI_LEVEL_3:
 4599         TRACE(("CASE_ANSI_LEVEL_3\n"));
 4600         set_ansi_conformance(screen, 3);
 4601         ResetState(sp);
 4602         break;
 4603 
 4604     case CASE_DECSCL:
 4605         TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1)));
 4606         /*
 4607          * This changes the emulation level, and is not recognized by
 4608          * VT100s.  However, a VT220 or above can be set to conformance
 4609          * level 1 to act like a VT100.
 4610          */
 4611         if (screen->terminal_id >= 200) {
 4612         /*
 4613          * Disallow unrecognized parameters, as well as attempts to set
 4614          * the operating level higher than the given terminal-id.
 4615          */
 4616         if (GetParam(0) >= 61
 4617             && GetParam(0) <= 60 + (screen->terminal_id / 100)) {
 4618             int new_vtXX_level = GetParam(0) - 60;
 4619             int case_value = zero_if_default(1);
 4620             /*
 4621              * Note:
 4622              *
 4623              * The VT300, VT420, VT520 manuals claim that DECSCL does a
 4624              * hard reset (RIS).
 4625              *
 4626              * Both the VT220 manual and DEC STD 070 (which documents
 4627              * levels 1-4 in detail) state that it is a soft reset.
 4628              *
 4629              * Perhaps both sets of manuals are right (unlikely).
 4630              * Kermit says it's soft.
 4631              */
 4632             ReallyReset(xw, False, False);
 4633             init_parser(xw, sp);
 4634             screen->vtXX_level = new_vtXX_level;
 4635             if (new_vtXX_level > 1) {
 4636             switch (case_value) {
 4637             case 1:
 4638                 show_8bit_control(False);
 4639                 break;
 4640             case 0:
 4641             case 2:
 4642                 show_8bit_control(True);
 4643                 break;
 4644             }
 4645             }
 4646         }
 4647         }
 4648         ResetState(sp);
 4649         break;
 4650 
 4651     case CASE_DECSCA:
 4652         TRACE(("CASE_DECSCA\n"));
 4653         screen->protected_mode = DEC_PROTECT;
 4654         if (GetParam(0) <= 0 || GetParam(0) == 2) {
 4655         UIntClr(xw->flags, PROTECTED);
 4656         TRACE(("...clear PROTECTED\n"));
 4657         } else if (GetParam(0) == 1) {
 4658         xw->flags |= PROTECTED;
 4659         TRACE(("...set PROTECTED\n"));
 4660         }
 4661         ResetState(sp);
 4662         break;
 4663 
 4664     case CASE_DECSED:
 4665         TRACE(("CASE_DECSED\n"));
 4666         do_erase_display(xw, zero_if_default(0), DEC_PROTECT);
 4667         ResetState(sp);
 4668         break;
 4669 
 4670     case CASE_DECSEL:
 4671         TRACE(("CASE_DECSEL\n"));
 4672         do_erase_line(xw, zero_if_default(0), DEC_PROTECT);
 4673         ResetState(sp);
 4674         break;
 4675 
 4676     case CASE_GRAPHICS_ATTRIBUTES:
 4677 #if OPT_GRAPHICS
 4678         TRACE(("CASE_GRAPHICS_ATTRIBUTES\n"));
 4679         {
 4680         /* request: item, action, value */
 4681         /* reply: item, status, value */
 4682         if (nparam != 3) {
 4683             TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam));
 4684         } else {
 4685             int status = 3; /* assume failure */
 4686             int result = 0;
 4687             int result2 = 0;
 4688 
 4689             TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n",
 4690                GetParam(0), GetParam(1), GetParam(2)));
 4691             switch (GetParam(0)) {
 4692             case 1: /* color register count */
 4693             switch (GetParam(1)) {
 4694             case 1: /* read */
 4695                 status = 0;     /* success */
 4696                 result = (int) get_color_register_count(screen);
 4697                 break;
 4698             case 2: /* reset */
 4699                 screen->numcolorregisters = 0;
 4700                 status = 0;     /* success */
 4701                 result = (int) get_color_register_count(screen);
 4702                 break;
 4703             case 3: /* set */
 4704                 if (GetParam(2) > 1 &&
 4705                 (unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) {
 4706                 screen->numcolorregisters = GetParam(2);
 4707                 status = 0; /* success */
 4708                 result = (int) get_color_register_count(screen);
 4709                 }
 4710                 break;
 4711             case 4: /* read maximum */
 4712                 status = 0;     /* success */
 4713                 result = MAX_COLOR_REGISTERS;
 4714                 break;
 4715             default:
 4716                 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n",
 4717                    GetParam(1)));
 4718                 status = 2;     /* error in Pa */
 4719                 break;
 4720             }
 4721             if (status == 0 && !(optSixelGraphics(screen)
 4722                          || optRegisGraphics(screen)))
 4723                 status = 3;
 4724             break;
 4725 # if OPT_SIXEL_GRAPHICS
 4726             case 2: /* graphics geometry */
 4727             switch (GetParam(1)) {
 4728             case 1: /* read */
 4729                 TRACE(("Get sixel graphics geometry\n"));
 4730                 status = 0;     /* success */
 4731                 result = Min(Width(screen), (int) screen->graphics_max_wide);
 4732                 result2 = Min(Height(screen), (int) screen->graphics_max_high);
 4733                 break;
 4734             case 2: /* reset */
 4735                 /* FALLTHRU */
 4736             case 3: /* set */
 4737                 break;
 4738             case 4: /* read maximum */
 4739                 status = 0;     /* success */
 4740                 result = screen->graphics_max_wide;
 4741                 result2 = screen->graphics_max_high;
 4742                 break;
 4743             default:
 4744                 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n",
 4745                    GetParam(1)));
 4746                 status = 2;     /* error in Pa */
 4747                 break;
 4748             }
 4749             if (status == 0 && !optSixelGraphics(screen))
 4750                 status = 3;
 4751             break;
 4752 #endif
 4753 # if OPT_REGIS_GRAPHICS
 4754             case 3: /* ReGIS geometry */
 4755             switch (GetParam(1)) {
 4756             case 1: /* read */
 4757                 status = 0;     /* success */
 4758                 result = screen->graphics_regis_def_wide;
 4759                 result2 = screen->graphics_regis_def_high;
 4760                 break;
 4761             case 2: /* reset */
 4762                 /* FALLTHRU */
 4763             case 3: /* set */
 4764                 /* FALLTHRU */
 4765             case 4: /* read maximum */
 4766                 /* not implemented */
 4767                 break;
 4768             default:
 4769                 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n",
 4770                    GetParam(1)));
 4771                 status = 2;     /* error in Pa */
 4772                 break;
 4773             }
 4774             if (status == 0 && !optRegisGraphics(screen))
 4775                 status = 3;
 4776             break;
 4777 #endif
 4778             default:
 4779             TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n",
 4780                    GetParam(0)));
 4781             status = 1;
 4782             break;
 4783             }
 4784 
 4785             init_reply(ANSI_CSI);
 4786             reply.a_pintro = '?';
 4787             count = 0;
 4788             reply.a_param[count++] = (ParmType) GetParam(0);
 4789             reply.a_param[count++] = (ParmType) status;
 4790             if (status == 0) {
 4791             reply.a_param[count++] = (ParmType) result;
 4792             if (GetParam(0) >= 2)
 4793                 reply.a_param[count++] = (ParmType) result2;
 4794             }
 4795             reply.a_nparam = (ParmType) count;
 4796             reply.a_final = 'S';
 4797             unparseseq(xw, &reply);
 4798         }
 4799         }
 4800 #endif
 4801         ResetState(sp);
 4802         break;
 4803 
 4804     case CASE_ST:
 4805         TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n",
 4806            (unsigned long) sp->string_used,
 4807            sp->string_mode));
 4808         ResetState(sp);
 4809         if (!sp->string_used)
 4810         break;
 4811         sp->string_area[--(sp->string_used)] = '\0';
 4812         if (sp->check_recur <= 1)
 4813         switch (sp->string_mode) {
 4814         case ANSI_APC:
 4815             /* ignored */
 4816             break;
 4817         case ANSI_DCS:
 4818             do_dcs(xw, sp->string_area, sp->string_used);
 4819             break;
 4820         case ANSI_OSC:
 4821             do_osc(xw, sp->string_area, sp->string_used, ANSI_ST);
 4822             break;
 4823         case ANSI_PM:
 4824             /* ignored */
 4825             break;
 4826         case ANSI_SOS:
 4827             /* ignored */
 4828             break;
 4829         default:
 4830             TRACE(("unknown mode\n"));
 4831             break;
 4832         }
 4833         break;
 4834 
 4835     case CASE_SOS:
 4836         TRACE(("CASE_SOS: Start of String\n"));
 4837         if (ParseSOS(screen)) {
 4838         sp->string_mode = ANSI_SOS;
 4839         sp->parsestate = sos_table;
 4840         } else {
 4841         illegal_parse(xw, c, sp);
 4842         }
 4843         break;
 4844 
 4845     case CASE_PM:
 4846         TRACE(("CASE_PM: Privacy Message\n"));
 4847         if (ParseSOS(screen)) {
 4848         sp->string_mode = ANSI_PM;
 4849         sp->parsestate = sos_table;
 4850         } else {
 4851         illegal_parse(xw, c, sp);
 4852         }
 4853         break;
 4854 
 4855     case CASE_DCS:
 4856         TRACE(("CASE_DCS: Device Control String\n"));
 4857         sp->string_mode = ANSI_DCS;
 4858         sp->parsestate = sos_table;
 4859         break;
 4860 
 4861     case CASE_APC:
 4862         TRACE(("CASE_APC: Application Program Command\n"));
 4863         if (ParseSOS(screen)) {
 4864         sp->string_mode = ANSI_APC;
 4865         sp->parsestate = sos_table;
 4866         } else {
 4867         illegal_parse(xw, c, sp);
 4868         }
 4869         break;
 4870 
 4871     case CASE_SPA:
 4872         TRACE(("CASE_SPA - start protected area\n"));
 4873         screen->protected_mode = ISO_PROTECT;
 4874         xw->flags |= PROTECTED;
 4875         ResetState(sp);
 4876         break;
 4877 
 4878     case CASE_EPA:
 4879         TRACE(("CASE_EPA - end protected area\n"));
 4880         UIntClr(xw->flags, PROTECTED);
 4881         ResetState(sp);
 4882         break;
 4883 
 4884     case CASE_SU:
 4885         TRACE(("CASE_SU - scroll up\n"));
 4886         xtermScroll(xw, one_if_default(0));
 4887         ResetState(sp);
 4888         break;
 4889 
 4890     case CASE_SL:       /* ISO 6429, non-DEC */
 4891         TRACE(("CASE_SL - scroll left\n"));
 4892         xtermScrollLR(xw, one_if_default(0), True);
 4893         ResetState(sp);
 4894         break;
 4895 
 4896     case CASE_SR:       /* ISO 6429, non-DEC */
 4897         TRACE(("CASE_SR - scroll right\n"));
 4898         xtermScrollLR(xw, one_if_default(0), False);
 4899         ResetState(sp);
 4900         break;
 4901 
 4902     case CASE_DECDC:
 4903         TRACE(("CASE_DC - delete column\n"));
 4904         if (screen->vtXX_level >= 4) {
 4905         xtermColScroll(xw, one_if_default(0), True, screen->cur_col);
 4906         }
 4907         ResetState(sp);
 4908         break;
 4909 
 4910     case CASE_DECIC:
 4911         TRACE(("CASE_IC - insert column\n"));
 4912         if (screen->vtXX_level >= 4) {
 4913         xtermColScroll(xw, one_if_default(0), False, screen->cur_col);
 4914         }
 4915         ResetState(sp);
 4916         break;
 4917 
 4918     case CASE_DECBI:
 4919         TRACE(("CASE_BI - back index\n"));
 4920         if (screen->vtXX_level >= 4) {
 4921         xtermColIndex(xw, True);
 4922         }
 4923         ResetState(sp);
 4924         break;
 4925 
 4926     case CASE_DECFI:
 4927         TRACE(("CASE_FI - forward index\n"));
 4928         if (screen->vtXX_level >= 4) {
 4929         xtermColIndex(xw, False);
 4930         }
 4931         ResetState(sp);
 4932         break;
 4933 
 4934     case CASE_IND:
 4935         TRACE(("CASE_IND - index\n"));
 4936         xtermIndex(xw, 1);
 4937         do_xevents(xw);
 4938         ResetState(sp);
 4939         break;
 4940 
 4941     case CASE_CPL:
 4942         TRACE(("CASE_CPL - cursor prev line\n"));
 4943         CursorPrevLine(xw, one_if_default(0));
 4944         ResetState(sp);
 4945         break;
 4946 
 4947     case CASE_CNL:
 4948         TRACE(("CASE_CNL - cursor next line\n"));
 4949         CursorNextLine(xw, one_if_default(0));
 4950         ResetState(sp);
 4951         break;
 4952 
 4953     case CASE_NEL:
 4954         TRACE(("CASE_NEL\n"));
 4955         xtermIndex(xw, 1);
 4956         CarriageReturn(xw);
 4957         ResetState(sp);
 4958         break;
 4959 
 4960     case CASE_HTS:
 4961         TRACE(("CASE_HTS - horizontal tab set\n"));
 4962         TabSet(xw->tabs, screen->cur_col);
 4963         ResetState(sp);
 4964         break;
 4965 
 4966     case CASE_REPORT_VERSION:
 4967         TRACE(("CASE_REPORT_VERSION - report terminal version\n"));
 4968         if (GetParam(0) <= 0) {
 4969         unparseputc1(xw, ANSI_DCS);
 4970         unparseputc(xw, '>');
 4971         unparseputc(xw, '|');
 4972         unparseputs(xw, xtermVersion());
 4973         unparseputc1(xw, ANSI_ST);
 4974         unparse_end(xw);
 4975         }
 4976         ResetState(sp);
 4977         break;
 4978 
 4979     case CASE_RI:
 4980         TRACE(("CASE_RI - reverse index\n"));
 4981         RevIndex(xw, 1);
 4982         ResetState(sp);
 4983         break;
 4984 
 4985     case CASE_SS2:
 4986         TRACE(("CASE_SS2\n"));
 4987         screen->curss = 2;
 4988         ResetState(sp);
 4989         break;
 4990 
 4991     case CASE_SS3:
 4992         TRACE(("CASE_SS3\n"));
 4993         screen->curss = 3;
 4994         ResetState(sp);
 4995         break;
 4996 
 4997     case CASE_CSI_STATE:
 4998         /* enter csi state */
 4999         InitParams();
 5000         SetParam(nparam++, DEFAULT);
 5001         sp->parsestate = csi_table;
 5002         break;
 5003 
 5004     case CASE_ESC_SP_STATE:
 5005         /* esc space */
 5006         sp->parsestate = esc_sp_table;
 5007         break;
 5008 
 5009     case CASE_CSI_EX_STATE:
 5010         /* csi exclamation */
 5011         sp->parsestate = csi_ex_table;
 5012         break;
 5013 
 5014     case CASE_CSI_TICK_STATE:
 5015         /* csi tick (') */
 5016         sp->parsestate = csi_tick_table;
 5017         break;
 5018 
 5019 #if OPT_DEC_LOCATOR
 5020     case CASE_DECEFR:
 5021         TRACE(("CASE_DECEFR - Enable Filter Rectangle\n"));
 5022         if (okSendMousePos(xw) == DEC_LOCATOR) {
 5023         MotionOff(screen, xw);
 5024         if ((screen->loc_filter_top = GetParam(0)) < 1)
 5025             screen->loc_filter_top = LOC_FILTER_POS;
 5026         if (nparam < 2
 5027             || (screen->loc_filter_left = GetParam(1)) < 1)
 5028             screen->loc_filter_left = LOC_FILTER_POS;
 5029         if (nparam < 3
 5030             || (screen->loc_filter_bottom = GetParam(2)) < 1)
 5031             screen->loc_filter_bottom = LOC_FILTER_POS;
 5032         if (nparam < 4
 5033             || (screen->loc_filter_right = GetParam(3)) < 1)
 5034             screen->loc_filter_right = LOC_FILTER_POS;
 5035         InitLocatorFilter(xw);
 5036         }
 5037         ResetState(sp);
 5038         break;
 5039 
 5040     case CASE_DECELR:
 5041         MotionOff(screen, xw);
 5042         if (GetParam(0) <= 0 || GetParam(0) > 2) {
 5043         screen->send_mouse_pos = MOUSE_OFF;
 5044         TRACE(("DECELR - Disable Locator Reports\n"));
 5045         } else {
 5046         TRACE(("DECELR - Enable Locator Reports\n"));
 5047         screen->send_mouse_pos = DEC_LOCATOR;
 5048         xtermShowPointer(xw, True);
 5049         if (GetParam(0) == 2) {
 5050             screen->locator_reset = True;
 5051         } else {
 5052             screen->locator_reset = False;
 5053         }
 5054         if (nparam < 2 || GetParam(1) != 1) {
 5055             screen->locator_pixels = False;
 5056         } else {
 5057             screen->locator_pixels = True;
 5058         }
 5059         screen->loc_filter = False;
 5060         }
 5061         ResetState(sp);
 5062         break;
 5063 
 5064     case CASE_DECSLE:
 5065         TRACE(("DECSLE - Select Locator Events\n"));
 5066         for (count = 0; count < nparam; ++count) {
 5067         switch (zero_if_default(count)) {
 5068         case 0:
 5069             MotionOff(screen, xw);
 5070             screen->loc_filter = False;
 5071             screen->locator_events = 0;
 5072             break;
 5073         case 1:
 5074             screen->locator_events |= LOC_BTNS_DN;
 5075             break;
 5076         case 2:
 5077             UIntClr(screen->locator_events, LOC_BTNS_DN);
 5078             break;
 5079         case 3:
 5080             screen->locator_events |= LOC_BTNS_UP;
 5081             break;
 5082         case 4:
 5083             UIntClr(screen->locator_events, LOC_BTNS_UP);
 5084             break;
 5085         }
 5086         }
 5087         ResetState(sp);
 5088         break;
 5089 
 5090     case CASE_DECRQLP:
 5091         TRACE(("DECRQLP - Request Locator Position\n"));
 5092         if (GetParam(0) < 2) {
 5093         /* Issue DECLRP Locator Position Report */
 5094         GetLocatorPosition(xw);
 5095         }
 5096         ResetState(sp);
 5097         break;
 5098 #endif /* OPT_DEC_LOCATOR */
 5099 
 5100 #if OPT_DEC_RECTOPS
 5101     case CASE_CSI_DOLLAR_STATE:
 5102         TRACE(("CASE_CSI_DOLLAR_STATE\n"));
 5103         /* csi dollar ($) */
 5104         if (screen->vtXX_level >= 3)
 5105         sp->parsestate = csi_dollar_table;
 5106         else
 5107         sp->parsestate = eigtable;
 5108         break;
 5109 
 5110     case CASE_CSI_STAR_STATE:
 5111         TRACE(("CASE_CSI_STAR_STATE\n"));
 5112         /* csi star (*) */
 5113         if (screen->vtXX_level >= 4)
 5114         sp->parsestate = csi_star_table;
 5115         else
 5116         sp->parsestate = eigtable;
 5117         break;
 5118 
 5119     case CASE_DECRQCRA:
 5120         if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) {
 5121         int checksum;
 5122         int pid;
 5123 
 5124         TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n"));
 5125         xtermCheckRect(xw, ParamPair(0), &checksum);
 5126         init_reply(ANSI_DCS);
 5127         count = 0;
 5128         checksum &= 0xffff;
 5129         pid = GetParam(0);
 5130         reply.a_param[count++] = (ParmType) pid;
 5131         reply.a_delim = "!~";   /* delimiter */
 5132         reply.a_radix[count] = 16;
 5133         reply.a_param[count++] = (ParmType) checksum;
 5134         reply.a_nparam = (ParmType) count;
 5135         TRACE(("...checksum(%d) = %04X\n", pid, checksum));
 5136         unparseseq(xw, &reply);
 5137         }
 5138         ResetState(sp);
 5139         break;
 5140 
 5141     case CASE_DECCRA:
 5142         if (screen->vtXX_level >= 4) {
 5143         TRACE(("CASE_DECCRA - Copy rectangular area\n"));
 5144         xtermParseRect(xw, ParamPair(0), &myRect);
 5145         ScrnCopyRectangle(xw, &myRect, ParamPair(5));
 5146         }
 5147         ResetState(sp);
 5148         break;
 5149