Home | History | Annotate | Line # | Download | only in dist
      1 /* $XTermId: charproc.c,v 1.2060 2025/01/05 20:45:50 tom Exp $ */
      2 
      3 /*
      4  * Copyright 1999-2024,2025 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 #include <graphics_sixel.h>
    137 
    138 #ifdef NO_LEAKS
    139 #include <xtermcap.h>
    140 #endif
    141 
    142 typedef int (*BitFunc) (unsigned * /* p */ ,
    143 			unsigned /* mask */ );
    144 
    145 static IChar doinput(XtermWidget /* xw */ );
    146 static int set_character_class(char * /*s */ );
    147 static void FromAlternate(XtermWidget /* xw */ ,
    148 			  Bool /* clearFirst */ );
    149 static void ReallyReset(XtermWidget /* xw */ ,
    150 			Bool /* full */ ,
    151 			Bool /* saved */ );
    152 static void RequestResize(XtermWidget /* xw */ ,
    153 			  int /* rows */ ,
    154 			  int /* cols */ ,
    155 			  Bool /* text */ );
    156 static void SwitchBufs(XtermWidget /* xw */ ,
    157 		       int /* toBuf */ ,
    158 		       Bool /* clearFirst */ );
    159 static void ToAlternate(XtermWidget /* xw */ ,
    160 			Bool /* clearFirst */ );
    161 static void ansi_modes(XtermWidget /* xw */ ,
    162 		       BitFunc /* func */ );
    163 static int bitclr(unsigned *p, unsigned mask);
    164 static int bitcpy(unsigned *p, unsigned q, unsigned mask);
    165 static int bitset(unsigned *p, unsigned mask);
    166 static void dpmodes(XtermWidget /* xw */ ,
    167 		    BitFunc /* func */ );
    168 static void restoremodes(XtermWidget /* xw */ );
    169 static void savemodes(XtermWidget /* xw */ );
    170 static void window_ops(XtermWidget /* xw */ );
    171 
    172 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
    173 #define SettableCursorBlink(screen) \
    174 	(((screen)->cursor_blink != cbAlways) && \
    175 	 ((screen)->cursor_blink != cbNever))
    176 #define UpdateCursorBlink(xw) \
    177 	 SetCursorBlink(xw, TScreenOf(xw)->cursor_blink)
    178 static void SetCursorBlink(XtermWidget /* xw */ ,
    179 			   BlinkOps /* enable */ );
    180 static void HandleBlinking(XtPointer /* closure */ ,
    181 			   XtIntervalId * /* id */ );
    182 static void StartBlinking(XtermWidget /* xw */ );
    183 static void StopBlinking(XtermWidget /* xw */ );
    184 #else
    185 #define StartBlinking(xw)	/* nothing */
    186 #define StopBlinking(xw)	/* nothing */
    187 #endif
    188 
    189 #ifndef NO_ACTIVE_ICON
    190 static Boolean discount_frame_extents(XtermWidget /* xw */ ,
    191 				      int * /* height */ ,
    192 				      int * /* width */ );
    193 #else
    194 #define discount_frame_extents(xw, height, width)	False
    195 #endif
    196 
    197 #if OPT_INPUT_METHOD
    198 static void PreeditPosition(XtermWidget /* xw */ );
    199 #endif
    200 
    201 #define	DEFAULT		-1
    202 #define BELLSUPPRESSMSEC 200
    203 
    204 static ANSI reply;
    205 static PARAMS parms;
    206 
    207 #define nparam parms.count
    208 
    209 #define InitParams()  init_params()
    210 #define GetParam(n)   parms.params[(n)]
    211 #define SetParam(n,v) parms.params[(n)] = v
    212 #define ParamPair(n)  nparam - (n), parms.params + (n)
    213 
    214 static jmp_buf vtjmpbuf;
    215 
    216 /* event handlers */
    217 static void HandleBell PROTO_XT_ACTIONS_ARGS;
    218 static void HandleIgnore PROTO_XT_ACTIONS_ARGS;
    219 static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS;
    220 static void HandleVisualBell PROTO_XT_ACTIONS_ARGS;
    221 #if HANDLE_STRUCT_NOTIFY
    222 static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS;
    223 #endif
    224 
    225 /*
    226  * NOTE: VTInitialize zeros out the entire ".screen" component of the
    227  * XtermWidget, so make sure to add an assignment statement in VTInitialize()
    228  * for each new ".screen" field added to this resource list.
    229  */
    230 
    231 /* Defaults */
    232 #if OPT_ISO_COLORS
    233 
    234 /*
    235  * If we default to colorMode enabled, compile-in defaults for the ANSI colors.
    236  */
    237 #if DFT_COLORMODE
    238 #define DFT_COLOR(name) name
    239 #else
    240 #define DFT_COLOR(name) XtDefaultForeground
    241 #endif
    242 #endif
    243 
    244 static char _Font_Selected_[] = "yes";	/* string is arbitrary */
    245 
    246 static const char *defaultTranslations;
    247 /* *INDENT-OFF* */
    248 static XtActionsRec actionsList[] = {
    249     { "allow-bold-fonts",	HandleAllowBoldFonts },
    250     { "allow-send-events",	HandleAllowSends },
    251     { "bell",			HandleBell },
    252     { "clear-saved-lines",	HandleClearSavedLines },
    253     { "copy-selection",		HandleCopySelection },
    254     { "create-menu",		HandleCreateMenu },
    255     { "delete-is-del",		HandleDeleteIsDEL },
    256     { "dired-button",		DiredButton },
    257     { "hard-reset",		HandleHardReset },
    258     { "ignore",			HandleIgnore },
    259     { "insert",			HandleKeyPressed },  /* alias for insert-seven-bit */
    260     { "insert-eight-bit",	HandleEightBitKeyPressed },
    261     { "insert-selection",	HandleInsertSelection },
    262     { "insert-seven-bit",	HandleKeyPressed },
    263     { "interpret",		HandleInterpret },
    264     { "keymap",			HandleKeymapChange },
    265     { "pointer-motion",		HandlePointerMotion },
    266     { "pointer-button",		HandlePointerButton },
    267     { "popup-menu",		HandlePopupMenu },
    268     { "print",			HandlePrintScreen },
    269     { "print-everything",	HandlePrintEverything },
    270     { "print-redir",		HandlePrintControlMode },
    271     { "quit",			HandleQuit },
    272     { "redraw",			HandleRedraw },
    273     { "scroll-back",		HandleScrollBack },
    274     { "scroll-forw",		HandleScrollForward },
    275     { "scroll-to",		HandleScrollTo },
    276     { "secure",			HandleSecure },
    277     { "select-cursor-end",	HandleKeyboardSelectEnd },
    278     { "select-cursor-extend",   HandleKeyboardSelectExtend },
    279     { "select-cursor-start",	HandleKeyboardSelectStart },
    280     { "select-end",		HandleSelectEnd },
    281     { "select-extend",		HandleSelectExtend },
    282     { "select-set",		HandleSelectSet },
    283     { "select-start",		HandleSelectStart },
    284     { "send-signal",		HandleSendSignal },
    285     { "set-8-bit-control",	Handle8BitControl },
    286     { "set-allow132",		HandleAllow132 },
    287     { "set-altscreen",		HandleAltScreen },
    288     { "set-appcursor",		HandleAppCursor },
    289     { "set-appkeypad",		HandleAppKeypad },
    290     { "set-autolinefeed",	HandleAutoLineFeed },
    291     { "set-autowrap",		HandleAutoWrap },
    292     { "set-backarrow",		HandleBackarrow },
    293     { "set-bellIsUrgent",	HandleBellIsUrgent },
    294     { "set-cursesemul",		HandleCursesEmul },
    295     { "set-jumpscroll",		HandleJumpscroll },
    296     { "set-keep-clipboard",	HandleKeepClipboard },
    297     { "set-keep-selection",	HandleKeepSelection },
    298     { "set-marginbell",		HandleMarginBell },
    299     { "set-old-function-keys",	HandleOldFunctionKeys },
    300     { "set-pop-on-bell",	HandleSetPopOnBell },
    301     { "set-reverse-video",	HandleReverseVideo },
    302     { "set-reversewrap",	HandleReverseWrap },
    303     { "set-scroll-on-key",	HandleScrollKey },
    304     { "set-scroll-on-tty-output", HandleScrollTtyOutput },
    305     { "set-scrollbar",		HandleScrollbar },
    306     { "set-select",		HandleSetSelect },
    307     { "set-sun-keyboard",	HandleSunKeyboard },
    308     { "set-titeInhibit",	HandleTiteInhibit },
    309     { "set-visual-bell",	HandleSetVisualBell },
    310     { "set-vt-font",		HandleSetFont },
    311     { "soft-reset",		HandleSoftReset },
    312     { "start-cursor-extend",	HandleKeyboardStartExtend },
    313     { "start-extend",		HandleStartExtend },
    314     { "string",			HandleStringEvent },
    315     { "vi-button",		ViButton },
    316     { "visual-bell",		HandleVisualBell },
    317 #ifdef ALLOWLOGGING
    318     { "set-logging",		HandleLogging },
    319 #endif
    320 #if OPT_ALLOW_XXX_OPS
    321     { "allow-color-ops",	HandleAllowColorOps },
    322     { "allow-font-ops",		HandleAllowFontOps },
    323     { "allow-mouse-ops",	HandleAllowMouseOps },
    324     { "allow-tcap-ops",		HandleAllowTcapOps },
    325     { "allow-title-ops",	HandleAllowTitleOps },
    326     { "allow-window-ops",	HandleAllowWindowOps },
    327 #endif
    328 #if OPT_BLINK_CURS
    329     { "set-cursorblink",	HandleCursorBlink },
    330 #endif
    331 #if OPT_BOX_CHARS
    332     { "set-font-linedrawing",	HandleFontBoxChars },
    333     { "set-font-packed",	HandleFontPacked },
    334 #endif
    335 #if OPT_DABBREV
    336     { "dabbrev-expand",		HandleDabbrevExpand },
    337 #endif
    338 #if OPT_DEC_CHRSET
    339     { "set-font-doublesize",	HandleFontDoublesize },
    340 #endif
    341 #if OPT_DEC_SOFTFONT
    342     { "set-font-loading",	HandleFontLoading },
    343 #endif
    344 #if OPT_EXEC_XTERM
    345     { "spawn-new-terminal",	HandleSpawnTerminal },
    346 #endif
    347 #if OPT_GRAPHICS
    348     { "set-private-colors",	HandleSetPrivateColorRegisters },
    349 #endif
    350 #if OPT_HP_FUNC_KEYS
    351     { "set-hp-function-keys",	HandleHpFunctionKeys },
    352 #endif
    353 #if OPT_LOAD_VTFONTS
    354     { "load-vt-fonts",		HandleLoadVTFonts },
    355 #endif
    356 #if OPT_MAXIMIZE
    357     { "deiconify",		HandleDeIconify },
    358     { "fullscreen",		HandleFullscreen },
    359     { "iconify",		HandleIconify },
    360     { "maximize",		HandleMaximize },
    361     { "restore",		HandleRestoreSize },
    362 #endif
    363 #if OPT_NUM_LOCK
    364     { "alt-sends-escape",	HandleAltEsc },
    365     { "meta-sends-escape",	HandleMetaEsc },
    366     { "set-num-lock",		HandleNumLock },
    367 #endif
    368 #if OPT_PRINT_ON_EXIT
    369     { "print-immediate",	HandlePrintImmediate },
    370     { "print-on-error",		HandlePrintOnError },
    371 #endif
    372 #if OPT_READLINE
    373     { "readline-button",	ReadLineButton },
    374 #endif
    375 #if OPT_RENDERFONT
    376     { "set-render-font",	HandleRenderFont },
    377 #endif
    378 #if OPT_SCO_FUNC_KEYS
    379     { "set-sco-function-keys",	HandleScoFunctionKeys },
    380 #endif
    381 #if OPT_SCREEN_DUMPS
    382     { "dump-html",	        HandleDumpHtml },
    383     { "dump-svg",	        HandleDumpSvg },
    384 #endif
    385 #if OPT_SCROLL_LOCK
    386     { "scroll-lock",		HandleScrollLock },
    387 #endif
    388 #if OPT_SELECTION_OPS
    389 #if OPT_EXEC_SELECTION
    390     { "exec-formatted",		HandleExecFormatted },
    391     { "exec-selectable",	HandleExecSelectable },
    392 #endif
    393     { "insert-formatted",	HandleInsertFormatted },
    394     { "insert-selectable",	HandleInsertSelectable },
    395 #endif
    396 #if OPT_SHIFT_FONTS
    397     { "larger-vt-font",		HandleLargerFont },
    398     { "smaller-vt-font",	HandleSmallerFont },
    399 #endif
    400 #if OPT_SIXEL_GRAPHICS
    401     { "set-sixel-scrolling",	HandleSixelScrolling },
    402 #endif
    403 #if OPT_SUN_FUNC_KEYS
    404     { "set-sun-function-keys",	HandleSunFunctionKeys },
    405 #endif
    406 #if OPT_TEK4014
    407     { "set-terminal-type",	HandleSetTerminalType },
    408     { "set-visibility",		HandleVisibility },
    409     { "set-tek-text",		HandleSetTekText },
    410     { "tek-page",		HandleTekPage },
    411     { "tek-reset",		HandleTekReset },
    412     { "tek-copy",		HandleTekCopy },
    413 #endif
    414 #if OPT_TOOLBAR
    415     { "set-toolbar",		HandleToolbar },
    416 #endif
    417 #if OPT_WIDE_CHARS
    418     { "set-utf8-mode",		HandleUTF8Mode },
    419     { "set-utf8-fonts",		HandleUTF8Fonts },
    420     { "set-utf8-title",		HandleUTF8Title },
    421 #endif
    422 };
    423 /* *INDENT-ON* */
    424 
    425 #define SPS screen.printer_state
    426 
    427 static XtResource xterm_resources[] =
    428 {
    429     Bres(XtNallowPasteControls, XtCAllowPasteControls,
    430 	 screen.allowPasteControl0, False),
    431     Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False),
    432     Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR),
    433     Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT),
    434     Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE),
    435     Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP),
    436     Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE),
    437     Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW),
    438     Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False),
    439     Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC),
    440     Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True),
    441     Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False),
    442     Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False),
    443     Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False),
    444     Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False),
    445     Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False),
    446     Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True),
    447     Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False),
    448     Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False),
    449     Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS),
    450     Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False),
    451     Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True),
    452     Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True),
    453     Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False),
    454     Bres(XtNc132, XtCC132, screen.c132, False),
    455     Sres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll_s, DEF_CD_XTRA_SCROLL),
    456     Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False),
    457     Bres(XtNcurses, XtCCurses, screen.curses, False),
    458     Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True),
    459     Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine,
    460 	 screen.cutToBeginningOfLine, True),
    461     Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL),
    462     Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True),
    463     Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False),
    464     Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True),
    465     Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True),
    466     Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True),
    467     Bres(XtNhighlightSelection, XtCHighlightSelection,
    468 	 screen.highlight_selection, False),
    469     Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False),
    470     Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False),
    471     Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True),
    472     Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, True),
    473     Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True),
    474     Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False),
    475     Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True),
    476     Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False),
    477     Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False),
    478     Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC),
    479     Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False),
    480     Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False),
    481     Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False),
    482     Bres(XtNpreferLatin1, XtCPreferLatin1, screen.prefer_latin1, True),
    483     Bres(XtNprintRawChars, XtCPrintRawChars, screen.print_rawchars, False),
    484     Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False),
    485     Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False),
    486     Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False),
    487     Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True),
    488     Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False),
    489     Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False),
    490     Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False),
    491     Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False),
    492     Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False),
    493     Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False),
    494     Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True),
    495     Bres(XtNselectToClipboard, XtCSelectToClipboard,
    496 	 screen.selectToClipboard, False),
    497     Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False),
    498     Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False),
    499     Sres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll_s, DEF_TI_XTRA_SCROLL),
    500     Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False),
    501     Bres(XtNunderLine, XtCUnderLine, screen.underline, True),
    502     Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False),
    503     Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False),
    504 
    505     Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"),
    506 
    507     Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC),
    508     Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource),
    509     Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER),
    510     Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1),
    511     Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE),
    512     Ires(XtNmaxStringParse, XtCMaxStringParse, screen.strings_max, DEF_STRINGS_MAX),
    513     Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME),
    514     Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL),
    515     Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE),
    516     Ires(XtNprinterControlMode, XtCPrinterControlMode,
    517 	 SPS.printer_controlmode, 0),
    518     Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES),
    519     Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1),
    520     Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100),
    521     Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES),
    522     Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1),
    523     Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES),
    524 
    525     Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL),
    526     Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL),
    527     Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL),
    528     Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL),
    529     Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL),
    530     Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL),
    531     Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL),
    532     Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL),
    533 
    534     Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""),
    535     Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT),
    536     Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL),
    537     Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID),
    538     Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"),
    539     Sres(XtNdisallowedColorOps, XtCDisallowedColorOps,
    540 	 screen.disallowedColorOps, DEF_DISALLOWED_COLOR),
    541     Sres(XtNdisallowedFontOps, XtCDisallowedFontOps,
    542 	 screen.disallowedFontOps, DEF_DISALLOWED_FONT),
    543     Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps,
    544 	 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE),
    545     Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls,
    546 	 screen.disallowedPasteOps, DEF_DISALLOWED_PASTE_CONTROLS),
    547     Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps,
    548 	 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP),
    549     Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps,
    550 	 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW),
    551     Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META),
    552     Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes,
    553 	 screen.eightbit_select_types, NULL),
    554     Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT),
    555     Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL),
    556     Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT),
    557     Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""),
    558     Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL),
    559     Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL),
    560 
    561     Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground),
    562     Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground),
    563     Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground),
    564     Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground),
    565     Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground),
    566 
    567     {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
    568      XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
    569      XtRImmediate, (XtPointer) SouthWestGravity},
    570 
    571     Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"),
    572 
    573 #ifdef ALLOWLOGGING
    574     Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False),
    575     Bres(XtNlogging, XtCLogging, misc.log_on, False),
    576     Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL),
    577 #endif
    578 
    579 #ifndef NO_ACTIVE_ICON
    580     Sres(XtNactiveIcon, XtCActiveIcon, misc.active_icon_s, "default"),
    581     Ires(XtNiconBorderWidth, XtCBorderWidth, misc.icon_border_width, 2),
    582     Sres(XtNiconFont, XtCIconFont, screen.icon_fontname, "nil2"),
    583     Cres(XtNiconBorderColor, XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground),
    584 #endif				/* NO_ACTIVE_ICON */
    585 
    586 #if OPT_BLINK_CURS
    587     Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True),
    588     Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"),
    589 #endif
    590     Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False),
    591     Bres(XtNcursorBar, XtCCursorBar, screen.cursor_bar, False),
    592 
    593 #if OPT_BLINK_TEXT
    594     Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD),
    595 #endif
    596 
    597 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
    598     Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600),
    599     Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300),
    600 #endif
    601 
    602 #if OPT_BOX_CHARS
    603     Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False),
    604     Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True),
    605     Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True),
    606 #endif
    607 #if OPT_BOX_CHARS || OPT_WIDE_CHARS
    608     Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, True),
    609 #endif
    610 
    611 #if OPT_BROKEN_OSC
    612     Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True),
    613 #endif
    614 
    615 #if OPT_BROKEN_ST
    616     Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False),
    617 #endif
    618 
    619 #if OPT_C1_PRINT
    620     Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False),
    621 #endif
    622 
    623 #if OPT_CLIP_BOLD
    624     Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True),
    625     Bres(XtNuseBorderClipping, XtCUseBorderClipping,
    626 	 screen.use_border_clipping, False),
    627 #endif
    628 
    629 #if OPT_DEC_CHRSET
    630     Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True),
    631     Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET),
    632 #endif
    633 
    634 #if OPT_DEC_RECTOPS
    635     Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC),
    636 #endif
    637 
    638 #if OPT_HIGHLIGHT_COLOR
    639     Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground),
    640     Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground),
    641     Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True),
    642     Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe),
    643 #endif				/* OPT_HIGHLIGHT_COLOR */
    644 
    645 #if OPT_INPUT_METHOD
    646     Bres(XtNopenIm, XtCOpenIm, misc.open_im, True),
    647     Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL),
    648     Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type,
    649 	 "OverTheSpot,Root"),
    650     Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3),
    651 #endif
    652 
    653 #if OPT_ISO_COLORS
    654     Bres(XtNboldColors, XtCColorMode, screen.boldColors, True),
    655     Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0),
    656     Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE),
    657 
    658     Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False),
    659     Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False),
    660     Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False),
    661     Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False),
    662     Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False),
    663     Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False),
    664 #if OPT_WIDE_ATTRS
    665     Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False),
    666 #endif
    667 #if OPT_DIRECT_COLOR
    668     Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True),
    669 #endif
    670 
    671     COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")),
    672     COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")),
    673     COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")),
    674     COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")),
    675     COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)),
    676     COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")),
    677     COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")),
    678     COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")),
    679     COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")),
    680     COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")),
    681     COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")),
    682     COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")),
    683     COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)),
    684     COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")),
    685     COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")),
    686     COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")),
    687     COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)),
    688     COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)),
    689     COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)),
    690     COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)),
    691 
    692 #if OPT_WIDE_ATTRS
    693     COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)),
    694 #endif
    695 
    696 #endif				/* OPT_ISO_COLORS */
    697 
    698     CLICK_RES("2", screen.onClick[1], "word"),
    699     CLICK_RES("3", screen.onClick[2], "line"),
    700     CLICK_RES("4", screen.onClick[3], 0),
    701     CLICK_RES("5", screen.onClick[4], 0),
    702 
    703     Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"),
    704 
    705 #if OPT_MOD_FKEYS
    706     Ires(XtNmodifyKeyboard, XtCModifyKeyboard,
    707 	 keyboard.modify_1st.allow_keys, 0),
    708     Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys,
    709 	 keyboard.modify_1st.cursor_keys, 2),
    710     Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys,
    711 	 keyboard.modify_1st.function_keys, 2),
    712     Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys,
    713 	 keyboard.modify_1st.keypad_keys, 0),
    714     Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys,
    715 	 keyboard.modify_1st.other_keys, 0),
    716     Ires(XtNmodifyStringKeys, XtCModifyStringKeys,
    717 	 keyboard.modify_1st.string_keys, 0),
    718     Ires(XtNformatOtherKeys, XtCFormatOtherKeys,
    719 	 keyboard.format_keys, 0),
    720 #endif
    721 
    722 #if OPT_NUM_LOCK
    723     Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False),
    724     Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True),
    725 #endif
    726 
    727 #if OPT_PRINT_COLORS
    728     Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1),
    729 #endif
    730 
    731 #if OPT_REGIS_GRAPHICS
    732     Sres(XtNregisDefaultFont, XtCRegisDefaultFont,
    733 	 screen.graphics_regis_default_font, ""),
    734     Sres(XtNregisScreenSize, XtCRegisScreenSize,
    735 	 screen.graphics_regis_screensize, "auto"),
    736 #endif
    737 
    738 #if OPT_GRAPHICS
    739     Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID),
    740     Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size,
    741 	 "1000x1000"),
    742 #endif
    743 
    744 #if OPT_ISO_COLORS && OPT_WIDE_ATTRS && OPT_SGR2_HASH
    745     Bres(XtNfaintIsRelative, XtCFaintIsRelative, screen.faint_relative, False),
    746 #endif
    747 
    748 #if OPT_SHIFT_FONTS
    749     Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True),
    750 #endif
    751 
    752 #if OPT_SIXEL_GRAPHICS
    753     Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, True),
    754     Bres(XtNsixelScrollsRight, XtCSixelScrollsRight,
    755 	 screen.sixel_scrolls_right, False),
    756 #endif
    757 
    758 #if OPT_GRAPHICS
    759     Ires(XtNnumColorRegisters, XtCNumColorRegisters,
    760 	 screen.numcolorregisters, 0),
    761     Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters,
    762 	 screen.privatecolorregisters, True),
    763     Bres(XtNincrementalGraphics, XtCIncrementalGraphics,
    764 	 screen.incremental_graphics, False),
    765 #endif
    766 
    767 #if OPT_STATUS_LINE
    768     Sres(XtNindicatorFormat, XtCIndicatorFormat, screen.status_fmt, DEF_SL_FORMAT),
    769 #endif
    770 
    771 #if OPT_SUNPC_KBD
    772     Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10),
    773 #endif
    774 
    775 #if OPT_TEK4014
    776     Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False),
    777     Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False),
    778     Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False),
    779 #endif
    780 
    781 #if OPT_TOOLBAR
    782     Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0),
    783     Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25),
    784 #endif
    785 
    786 #if OPT_WIDE_CHARS
    787     Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False),
    788     Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False),
    789     Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True),
    790     Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False),
    791     Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False),
    792     Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True),
    793     Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False),
    794     Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2),
    795     Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655),
    796     Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536),
    797     Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"),
    798     Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"),
    799     Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"),
    800     Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT),
    801     Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT),
    802     Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL),
    803 #endif
    804 
    805 #if OPT_LUIT_PROG
    806     Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"),
    807     Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER),
    808 #endif
    809 
    810 #if OPT_INPUT_METHOD
    811     Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT),
    812 #endif
    813 
    814 #if OPT_SCROLL_LOCK
    815     Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False),
    816     Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False),
    817 #endif
    818 
    819     /* these are used only for testing ncurses, not in the manual page */
    820 #if OPT_XMC_GLITCH
    821     Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False),
    822     Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True),
    823     Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1),
    824     Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0),
    825 #endif
    826 
    827 #ifdef SCROLLBAR_RIGHT
    828     Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False),
    829 #endif
    830 
    831 #if OPT_RENDERFONT
    832     Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False),
    833     Ires(XtNxftMaxGlyphMemory, XtCXftMaxGlyphMemory,
    834 	 screen.xft_max_glyph_memory, 0),
    835     Ires(XtNxftMaxUnrefFonts, XtCXftMaxUnrefFonts,
    836 	 screen.xft_max_unref_fonts, 0),
    837     Bres(XtNxftTrackMemUsage, XtCXftTrackMemUsage,
    838 	 screen.xft_track_mem_usage, DEF_TRACK_USAGE),
    839 #define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0")
    840     RES_FACESIZE(1),
    841     RES_FACESIZE(2),
    842     RES_FACESIZE(3),
    843     RES_FACESIZE(4),
    844     RES_FACESIZE(5),
    845     RES_FACESIZE(6),
    846     RES_FACESIZE(7),
    847     Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE),
    848     Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME),
    849     Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"),
    850     Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE),
    851     Ires(XtNlimitFontHeight, XtCLimitFontHeight, misc.limit_fontheight, 10),
    852     Ires(XtNlimitFontWidth, XtCLimitFontWidth, misc.limit_fontwidth, 10),
    853 #if OPT_RENDERWIDE
    854     Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME),
    855 #endif
    856 #endif
    857 };
    858 
    859 static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg,
    860 			   ArgList args, Cardinal *num_args);
    861 static void VTClassInit(void);
    862 static void VTDestroy(Widget w);
    863 static void VTExpose(Widget w, XEvent *event, Region region);
    864 static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args,
    865 			 Cardinal *num_args);
    866 static void VTRealize(Widget w, XtValueMask * valuemask,
    867 		      XSetWindowAttributes * values);
    868 static void VTResize(Widget w);
    869 
    870 #if OPT_INPUT_METHOD
    871 static void VTInitI18N(XtermWidget);
    872 #endif
    873 
    874 static
    875 WidgetClassRec xtermClassRec =
    876 {
    877     {
    878 	/* core_class fields */
    879 	(WidgetClass) & widgetClassRec,		/* superclass   */
    880 	"VT100",		/* class_name                   */
    881 	sizeof(XtermWidgetRec),	/* widget_size                  */
    882 	VTClassInit,		/* class_initialize             */
    883 	NULL,			/* class_part_initialize        */
    884 	False,			/* class_inited                 */
    885 	VTInitialize,		/* initialize                   */
    886 	NULL,			/* initialize_hook              */
    887 	VTRealize,		/* realize                      */
    888 	actionsList,		/* actions                      */
    889 	XtNumber(actionsList),	/* num_actions                  */
    890 	xterm_resources,	/* resources                    */
    891 	XtNumber(xterm_resources),	/* num_resources        */
    892 	NULLQUARK,		/* xrm_class                    */
    893 	True,			/* compress_motion              */
    894 	False,			/* compress_exposure            */
    895 	True,			/* compress_enterleave          */
    896 	False,			/* visible_interest             */
    897 	VTDestroy,		/* destroy                      */
    898 	VTResize,		/* resize                       */
    899 	VTExpose,		/* expose                       */
    900 	VTSetValues,		/* set_values                   */
    901 	NULL,			/* set_values_hook              */
    902 	XtInheritSetValuesAlmost,	/* set_values_almost    */
    903 	NULL,			/* get_values_hook              */
    904 	NULL,			/* accept_focus                 */
    905 	XtVersion,		/* version                      */
    906 	NULL,			/* callback_offsets             */
    907 	NULL,			/* tm_table                     */
    908 	XtInheritQueryGeometry,	/* query_geometry               */
    909 	XtInheritDisplayAccelerator,	/* display_accelerator  */
    910 	NULL			/* extension                    */
    911     }
    912 };
    913 
    914 WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec;
    915 
    916 /*
    917  * Add input-actions for widgets that are overlooked (scrollbar and toolbar):
    918  *
    919  *	a) Sometimes the scrollbar passes through translations, sometimes it
    920  *	   doesn't.  We add the KeyPress translations here, just to be sure.
    921  *	b) In the normal (non-toolbar) configuration, the xterm widget covers
    922  *	   almost all of the window.  With a toolbar, there's a relatively
    923  *	   large area that the user would expect to enter keystrokes since the
    924  *	   program can get the focus.
    925  */
    926 void
    927 xtermAddInput(Widget w)
    928 {
    929     /* *INDENT-OFF* */
    930     XtActionsRec input_actions[] = {
    931 	{ "insert",		    HandleKeyPressed }, /* alias */
    932 	{ "insert-eight-bit",	    HandleEightBitKeyPressed },
    933 	{ "insert-seven-bit",	    HandleKeyPressed },
    934 	{ "pointer-motion",	    HandlePointerMotion },
    935 	{ "pointer-button",	    HandlePointerButton },
    936 	{ "secure",		    HandleSecure },
    937 	{ "string",		    HandleStringEvent },
    938 	{ "scroll-back",	    HandleScrollBack },
    939 	{ "scroll-forw",	    HandleScrollForward },
    940 	{ "scroll-to",		    HandleScrollTo },
    941 	{ "select-cursor-end",	    HandleKeyboardSelectEnd },
    942 	{ "select-cursor-extend",   HandleKeyboardSelectExtend },
    943 	{ "select-cursor-start",    HandleKeyboardSelectStart },
    944 	{ "insert-selection",	    HandleInsertSelection },
    945 	{ "select-start",	    HandleSelectStart },
    946 	{ "select-extend",	    HandleSelectExtend },
    947 	{ "start-extend",	    HandleStartExtend },
    948 	{ "select-end",		    HandleSelectEnd },
    949 	{ "clear-saved-lines",	    HandleClearSavedLines },
    950 	{ "popup-menu",		    HandlePopupMenu },
    951 	{ "bell",		    HandleBell },
    952 	{ "ignore",		    HandleIgnore },
    953 #if OPT_DABBREV
    954 	{ "dabbrev-expand",	    HandleDabbrevExpand },
    955 #endif
    956 #if OPT_MAXIMIZE
    957 	{ "fullscreen",		    HandleFullscreen },
    958 #endif
    959 #if OPT_SCROLL_LOCK
    960 	{ "scroll-lock",	    HandleScrollLock },
    961 #endif
    962 #if OPT_SHIFT_FONTS
    963 	{ "larger-vt-font",	    HandleLargerFont },
    964 	{ "smaller-vt-font",	    HandleSmallerFont },
    965 #endif
    966     };
    967     /* *INDENT-ON* */
    968 
    969     TRACE_TRANS("BEFORE", w);
    970     XtAppAddActions(app_con, input_actions, XtNumber(input_actions));
    971     XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations));
    972     TRACE_TRANS("AFTER:", w);
    973 
    974 #if OPT_EXTRA_PASTE
    975     if (term && term->keyboard.extra_translations)
    976 	XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations));
    977 #endif
    978 }
    979 
    980 #if OPT_ISO_COLORS
    981 #ifdef EXP_BOGUS_FG
    982 static Bool
    983 CheckBogusForeground(TScreen *screen, const char *tag)
    984 {
    985     int row = -1, col = -1, pass;
    986     Bool isClear = True;
    987 
    988     (void) tag;
    989     for (pass = 0; pass < 2; ++pass) {
    990 	row = screen->cur_row;
    991 	for (; isClear && (row <= screen->max_row); ++row) {
    992 	    CLineData *ld = getLineData(screen, row);
    993 
    994 	    if (ld != 0) {
    995 		IAttr *attribs = ld->attribs;
    996 
    997 		col = (row == screen->cur_row) ? screen->cur_col : 0;
    998 		for (; isClear && (col <= screen->max_col); ++col) {
    999 		    unsigned flags = attribs[col];
   1000 		    if (pass) {
   1001 			flags &= ~FG_COLOR;
   1002 			attribs[col] = (IAttr) flags;
   1003 		    } else if ((flags & BG_COLOR)) {
   1004 			isClear = False;
   1005 		    } else if ((flags & FG_COLOR)) {
   1006 			unsigned ch = ld->charData[col];
   1007 			isClear = ((ch == ' ') || (ch == 0));
   1008 		    } else {
   1009 			isClear = False;
   1010 		    }
   1011 		}
   1012 	    }
   1013 	}
   1014     }
   1015     TRACE(("%s checked %d,%d to %d,%d %s pass %d\n",
   1016 	   tag, screen->cur_row, screen->cur_col,
   1017 	   row, col,
   1018 	   isClear && pass ? "cleared" : "unchanged",
   1019 	   pass));
   1020 
   1021     return isClear;
   1022 }
   1023 #endif
   1024 
   1025 /*
   1026  * The terminal's foreground and background colors are set via two mechanisms:
   1027  *	text (cur_foreground, cur_background values that are passed down to
   1028  *		XDrawImageString and XDrawString)
   1029  *	area (X11 graphics context used in XClearArea and XFillRectangle)
   1030  */
   1031 void
   1032 SGR_Foreground(XtermWidget xw, int color)
   1033 {
   1034     TScreen *screen = TScreenOf(xw);
   1035     Pixel fg;
   1036 
   1037     if (color >= 0) {
   1038 	UIntSet(xw->flags, FG_COLOR);
   1039     } else {
   1040 	UIntClr(xw->flags, FG_COLOR);
   1041     }
   1042     fg = getXtermFG(xw, xw->flags, color);
   1043     xw->cur_foreground = color;
   1044 
   1045     setCgsFore(xw, WhichVWin(screen), gcNorm, fg);
   1046     setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg);
   1047 
   1048     setCgsFore(xw, WhichVWin(screen), gcBold, fg);
   1049     setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg);
   1050 
   1051 #ifdef EXP_BOGUS_FG
   1052     /*
   1053      * If we've just turned off the foreground color, check for blank cells
   1054      * which have no background color, but do have foreground color.  This
   1055      * could happen due to setting the foreground color just before scrolling.
   1056      *
   1057      * Those cells look uncolored, but will confuse ShowCursor(), which looks
   1058      * for the colors in the current cell, and will see the foreground color.
   1059      * In that case, remove the foreground color from the blank cells.
   1060      */
   1061     if (color < 0) {
   1062 	CheckBogusForeground(screen, "SGR_Foreground");
   1063     }
   1064 #endif
   1065 }
   1066 
   1067 void
   1068 SGR_Background(XtermWidget xw, int color)
   1069 {
   1070     TScreen *screen = TScreenOf(xw);
   1071     Pixel bg;
   1072 
   1073     /*
   1074      * An indexing operation may have set screen->scroll_amt, which would
   1075      * normally result in calling FlushScroll() in WriteText().  However,
   1076      * if we're changing the background color now, then the new value
   1077      * should not apply to the pending blank lines.
   1078      */
   1079     if (screen->scroll_amt && (color != xw->cur_background))
   1080 	FlushScroll(xw);
   1081 
   1082     if (color >= 0) {
   1083 	UIntSet(xw->flags, BG_COLOR);
   1084     } else {
   1085 	UIntClr(xw->flags, BG_COLOR);
   1086     }
   1087     bg = getXtermBG(xw, xw->flags, color);
   1088     xw->cur_background = color;
   1089 
   1090     setCgsBack(xw, WhichVWin(screen), gcNorm, bg);
   1091     setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg);
   1092 
   1093     setCgsBack(xw, WhichVWin(screen), gcBold, bg);
   1094     setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg);
   1095 }
   1096 
   1097 /* Invoked after updating bold/underline flags, computes the extended color
   1098  * index to use for foreground.  (See also 'extract_fg()').
   1099  */
   1100 static void
   1101 setExtendedFG(XtermWidget xw)
   1102 {
   1103     int fg = xw->sgr_foreground;
   1104 
   1105     if (TScreenOf(xw)->colorAttrMode
   1106 	|| (fg < 0)) {
   1107 	fg = MapToColorMode(fg, TScreenOf(xw), xw->flags);
   1108     }
   1109 
   1110     /* This implements the IBM PC-style convention of 8-colors, with one
   1111      * bit for bold, thus mapping the 0-7 codes to 8-15.  It won't make
   1112      * much sense for 16-color applications, but we keep it to retain
   1113      * compatibility with ANSI-color applications.
   1114      */
   1115 #if OPT_PC_COLORS		/* XXXJTL should be settable at runtime (resource or OSC?) */
   1116     if (TScreenOf(xw)->boldColors
   1117 	&& (!xw->sgr_38_xcolors)
   1118 	&& (fg >= 0)
   1119 	&& (fg < 8)
   1120 	&& (xw->flags & BOLD))
   1121 	fg |= 8;
   1122 #endif
   1123 
   1124     SGR_Foreground(xw, fg);
   1125 }
   1126 
   1127 /* Invoked after updating inverse flag, computes the extended color
   1128  * index to use for background.  (See also 'extract_bg()').
   1129  */
   1130 static void
   1131 setExtendedBG(XtermWidget xw)
   1132 {
   1133     int bg = xw->sgr_background;
   1134 
   1135     if (TScreenOf(xw)->colorAttrMode
   1136 	|| (bg < 0)) {
   1137 	if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE))
   1138 	    bg = COLOR_RV;
   1139     }
   1140 
   1141     SGR_Background(xw, bg);
   1142 }
   1143 
   1144 void
   1145 setExtendedColors(XtermWidget xw)
   1146 {
   1147     setExtendedFG(xw);
   1148     setExtendedBG(xw);
   1149 }
   1150 
   1151 static void
   1152 reset_SGR_Foreground(XtermWidget xw)
   1153 {
   1154     xw->sgr_foreground = -1;
   1155     xw->sgr_38_xcolors = False;
   1156     clrDirectFG(xw->flags);
   1157     setExtendedFG(xw);
   1158 }
   1159 
   1160 static void
   1161 reset_SGR_Background(XtermWidget xw)
   1162 {
   1163     xw->sgr_background = -1;
   1164     clrDirectBG(xw->flags);
   1165     setExtendedBG(xw);
   1166 }
   1167 
   1168 static void
   1169 reset_SGR_Colors(XtermWidget xw)
   1170 {
   1171     reset_SGR_Foreground(xw);
   1172     reset_SGR_Background(xw);
   1173 }
   1174 #endif /* OPT_ISO_COLORS */
   1175 
   1176 #if OPT_WIDE_ATTRS
   1177 /*
   1178  * Call this before changing the state of ATR_ITALIC, to update the GC fonts.
   1179  */
   1180 static void
   1181 setItalicFont(XtermWidget xw, Bool enable)
   1182 {
   1183     if (enable) {
   1184 	if ((xw->flags & ATR_ITALIC) == 0) {
   1185 	    xtermLoadItalics(xw);
   1186 	    TRACE(("setItalicFont: enabling Italics\n"));
   1187 	    xtermUpdateFontGCs(xw, getItalicFont);
   1188 	}
   1189     } else if ((xw->flags & ATR_ITALIC) != 0) {
   1190 	TRACE(("setItalicFont: disabling Italics\n"));
   1191 	xtermUpdateFontGCs(xw, getNormalFont);
   1192     }
   1193 }
   1194 
   1195 static void
   1196 ResetItalics(XtermWidget xw)
   1197 {
   1198     setItalicFont(xw, False);
   1199     UIntClr(xw->flags, ATR_ITALIC);
   1200 }
   1201 
   1202 #else
   1203 #define ResetItalics(xw)	/* nothing */
   1204 #endif
   1205 
   1206 static void
   1207 initCharset(TScreen *screen, int which, DECNRCM_codes code)
   1208 {
   1209     screen->gsets[which] = code;
   1210 }
   1211 
   1212 void
   1213 saveCharsets(TScreen *screen, DECNRCM_codes * target)
   1214 {
   1215     int g;
   1216     for (g = 0; g < NUM_GSETS2; ++g) {
   1217 	target[g] = screen->gsets[g];
   1218     }
   1219 }
   1220 
   1221 void
   1222 restoreCharsets(TScreen *screen, const DECNRCM_codes * source)
   1223 {
   1224     int g;
   1225     for (g = 0; g < NUM_GSETS2; ++g) {
   1226 	screen->gsets[g] = source[g];
   1227     }
   1228 }
   1229 
   1230 void
   1231 resetCharsets(TScreen *screen)
   1232 {
   1233     int dft_upss = ((screen->ansi_level >= 2)
   1234 		    ? PreferredUPSS(screen)
   1235 		    : nrc_ASCII);
   1236 
   1237 #if OPT_WIDE_CHARS
   1238     /*
   1239      * User-preferred selection set makes a choice between ISO-8859-1 and
   1240      * a precursor to it.  Those are both single-byte encodings.  Because the
   1241      * multibyte UTF-8 equates to ISO-8859-1, the default (DEC Supplemental)
   1242      * cannot be used as a default in UTF-8 mode.  But we cannot use ISO-8859-1
   1243      * either, because that would break the special case in decodeUtf8() that
   1244      * checks if NRCS is being used, passing 8-bit characters as is.
   1245      *
   1246      * In short, UPSS is not available with UTF-8, but DECRQUPSS will say that
   1247      * ISO-Latin1 is selected.
   1248      */
   1249     if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) {
   1250 	dft_upss = nrc_ASCII;
   1251     }
   1252 #endif
   1253 
   1254     TRACE(("resetCharsets: UPSS=%s\n", visibleScsCode(dft_upss)));
   1255 
   1256     /*
   1257      * The assignments for G2/G3 to ASCII differ from the documented DEC
   1258      * terminal, because xterm also checks GR to decide whether or not to
   1259      * handle non-Unicode character sets, e.g., NRCS.
   1260      */
   1261     initCharset(screen, 0, nrc_ASCII);
   1262     initCharset(screen, 1, nrc_ASCII);
   1263     initCharset(screen, 2, dft_upss);
   1264     initCharset(screen, 3, dft_upss);
   1265     initCharset(screen, 4, dft_upss);	/* gsets_upss */
   1266 
   1267     screen->curgl = 0;		/* G0 => GL.            */
   1268     screen->curgr = 2;		/* G2 => GR.            */
   1269     screen->curss = 0;		/* No single shift.     */
   1270 
   1271 #if OPT_VT52_MODE
   1272     if (screen->vtXX_level == 0)
   1273 	initCharset(screen, 1, nrc_DEC_Spec_Graphic);	/* Graphics */
   1274 #endif
   1275 }
   1276 
   1277 static void
   1278 modified_DECNRCM(XtermWidget xw)
   1279 {
   1280 #if OPT_WIDE_CHARS
   1281     TScreen *screen = TScreenOf(xw);
   1282     if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) {
   1283 	int enabled = ((xw->flags & NATIONAL) != 0);
   1284 	int modefix;
   1285 	EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix);
   1286 	switchPtyData(screen, !enabled);
   1287 	TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF"));
   1288     }
   1289 #else
   1290     (void) xw;
   1291 #endif
   1292 }
   1293 
   1294 /*
   1295  * VT300 and up support three ANSI conformance levels, defined according to
   1296  * ECMA-43 (originally dpANSI X3.134.1).
   1297  *
   1298  * VSRM - Documented Exceptions EL-00070-D
   1299  */
   1300 static void
   1301 set_ansi_conformance(TScreen *screen, int level)
   1302 {
   1303     TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n",
   1304 	   level,
   1305 	   screen->vtXX_level * 100,
   1306 	   screen->terminal_id,
   1307 	   screen->ansi_level));
   1308     if (screen->vtXX_level >= 3) {
   1309 	screen->ansi_level = level;
   1310     }
   1311 }
   1312 
   1313 static void
   1314 set_vtXX_level(TScreen *screen, int level)
   1315 {
   1316     screen->vtXX_level = level;
   1317     screen->ansi_level = (level > 1) ? 3 : 1;
   1318 }
   1319 
   1320 /*
   1321  * Set scrolling margins.  VTxxx terminals require that the top/bottom are
   1322  * different, so we have at least two lines in the scrolling region.
   1323  */
   1324 static void
   1325 set_tb_margins(TScreen *screen, int top, int bottom)
   1326 {
   1327     TRACE(("set_tb_margins %d..%d, prior %d..%d\n",
   1328 	   top, bottom,
   1329 	   screen->top_marg,
   1330 	   screen->bot_marg));
   1331     if (bottom > top) {
   1332 	screen->top_marg = top;
   1333 	screen->bot_marg = bottom;
   1334     }
   1335     if (screen->top_marg > screen->max_row)
   1336 	screen->top_marg = screen->max_row;
   1337     if (screen->bot_marg > screen->max_row)
   1338 	screen->bot_marg = screen->max_row;
   1339 }
   1340 
   1341 static void
   1342 set_lr_margins(TScreen *screen, int left, int right)
   1343 {
   1344     TRACE(("set_lr_margins %d..%d, prior %d..%d\n",
   1345 	   left, right,
   1346 	   screen->lft_marg,
   1347 	   screen->rgt_marg));
   1348     if (right > left) {
   1349 	screen->lft_marg = left;
   1350 	screen->rgt_marg = right;
   1351     }
   1352     if (screen->lft_marg > screen->max_col)
   1353 	screen->lft_marg = screen->max_col;
   1354     if (screen->rgt_marg > screen->max_col)
   1355 	screen->rgt_marg = screen->max_col;
   1356 }
   1357 
   1358 #define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row)
   1359 #define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col)
   1360 
   1361 void
   1362 resetMargins(XtermWidget xw)
   1363 {
   1364     TScreen *screen = TScreenOf(xw);
   1365 
   1366     reset_tb_margins(screen);
   1367     reset_lr_margins(screen);
   1368 }
   1369 
   1370 static void
   1371 resetMarginMode(XtermWidget xw)
   1372 {
   1373     UIntClr(xw->flags, LEFT_RIGHT);
   1374     resetMargins(xw);
   1375 }
   1376 
   1377 static void
   1378 resetRendition(XtermWidget xw)
   1379 {
   1380     TScreen *screen = TScreenOf(xw);
   1381     (void) screen;
   1382     ResetItalics(xw);
   1383     UIntClr(xw->flags,
   1384 	    (SGR_MASK | SGR_MASK2 | INVISIBLE));
   1385 }
   1386 
   1387 void
   1388 set_max_col(TScreen *screen, int cols)
   1389 {
   1390     TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col));
   1391     if (cols < 0)
   1392 	cols = 0;
   1393     screen->max_col = cols;
   1394 }
   1395 
   1396 void
   1397 set_max_row(TScreen *screen, int rows)
   1398 {
   1399     TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row));
   1400     if (rows < 0)
   1401 	rows = 0;
   1402     screen->max_row = rows;
   1403 }
   1404 
   1405 #if OPT_TRACE
   1406 #define DATA(name) { name, #name }
   1407 static const struct {
   1408     const PARSE_T *table;
   1409     const char *name;
   1410 } all_tables[] = {
   1411 
   1412     DATA(ansi_table)
   1413 	,DATA(cigtable)
   1414 	,DATA(csi2_table)
   1415 	,DATA(csi_ex_table)
   1416 	,DATA(csi_amp_table)
   1417 	,DATA(csi_quo_table)
   1418 	,DATA(csi_table)
   1419 	,DATA(dec2_table)
   1420 	,DATA(dec3_table)
   1421 	,DATA(dec_table)
   1422 	,DATA(eigtable)
   1423 	,DATA(esc_sp_table)
   1424 	,DATA(esc_table)
   1425 	,DATA(scrtable)
   1426 	,DATA(scs96table)
   1427 	,DATA(scstable)
   1428 	,DATA(sos_table)
   1429 #if OPT_BLINK_CURS
   1430 	,DATA(csi_sp_table)
   1431 #endif
   1432 #if OPT_DEC_LOCATOR
   1433 	,DATA(csi_tick_table)
   1434 #endif
   1435 #if OPT_DEC_RECTOPS
   1436 	,DATA(csi_dollar_table)
   1437 	,DATA(csi_star_table)
   1438 	,DATA(csi_dec_dollar_table)
   1439 #endif
   1440 #if OPT_VT52_MODE
   1441 	,DATA(vt52_table)
   1442 	,DATA(vt52_esc_table)
   1443 	,DATA(vt52_ignore_table)
   1444 #endif
   1445 #if OPT_VT525_COLORS
   1446 	,DATA(csi_comma_table)
   1447 #endif
   1448 #if OPT_WIDE_CHARS
   1449 	,DATA(esc_pct_table)
   1450 	,DATA(scs_amp_table)
   1451 	,DATA(scs_pct_table)
   1452 	,DATA(scs_2qt_table)
   1453 #endif
   1454 #if OPT_XTERM_SGR
   1455 	,DATA(csi_hash_table)
   1456 #endif
   1457 #undef DATA
   1458 };
   1459 
   1460 #define WHICH_TABLE(name) if (table == name) result = #name
   1461 static const char *
   1462 which_table(const PARSE_T * table)
   1463 {
   1464     const char *result = "?";
   1465     Cardinal n;
   1466     for (n = 0; n < XtNumber(all_tables); ++n) {
   1467 	if (table == all_tables[n].table) {
   1468 	    result = all_tables[n].name;
   1469 	    break;
   1470 	}
   1471     }
   1472 
   1473     return result;
   1474 }
   1475 
   1476 static void
   1477 check_tables(void)
   1478 {
   1479     Cardinal n;
   1480     int ch;
   1481     int total_codes = 0;
   1482     int total_ground = 0;
   1483     int total_ignored = 0;
   1484 
   1485     TRACE(("** check_tables\n"));
   1486     for (n = 0; n < XtNumber(all_tables); ++n) {
   1487 	const PARSE_T *table = all_tables[n].table;
   1488 	TRACE(("*** %s\n", all_tables[n].name));
   1489 	/*
   1490 	 * Most of the tables should use the same codes in 0..31, 128..159
   1491 	 * as the "ansi" table.
   1492 	 */
   1493 	if (strncmp(all_tables[n].name, "ansi", 4) &&
   1494 	    strncmp(all_tables[n].name, "sos_", 4) &&
   1495 	    strncmp(all_tables[n].name, "vt52", 4)) {
   1496 	    for (ch = 0; ch < 32; ++ch) {
   1497 		int c1 = ch + 128;
   1498 		PARSE_T st_l = table[ch];
   1499 		PARSE_T st_r = table[c1];
   1500 		if (st_l != ansi_table[ch]) {
   1501 		    TRACE(("  %3d: %d vs %d\n", ch, st_l, ansi_table[ch]));
   1502 		}
   1503 		if (st_r != ansi_table[c1]) {
   1504 		    TRACE(("  %3d: %d vs %d\n", c1, st_r, ansi_table[c1]));
   1505 		}
   1506 	    }
   1507 	}
   1508 	/*
   1509 	 * All of the tables should have their GL/GR parts encoded the same.
   1510 	 *
   1511 	 * Originally reported by Paul Williams (patch #171), this is a
   1512 	 * standard feature of DEC's terminals, documented in DEC 070 section
   1513 	 * 3.5.4.5 "GR Graphic Characters Within Control Strings".
   1514 	 */
   1515 	for (ch = 32; ch < 127; ++ch) {
   1516 	    PARSE_T st_l = table[ch];
   1517 	    PARSE_T st_r = table[ch + 128];
   1518 	    if (st_l != st_r) {
   1519 		if (st_r == CASE_IGNORE &&
   1520 		    !strncmp(all_tables[n].name, "vt52", 4)) {
   1521 		    ;
   1522 		} else {
   1523 		    TRACE(("  %3d: %d vs %d\n", ch, st_l, st_r));
   1524 		}
   1525 	    }
   1526 	}
   1527 	/*
   1528 	 * Just for amusement, show how sparse the encoding tables are.
   1529 	 */
   1530 	for (ch = 0; ch < 256; ++ch) {
   1531 	    ++total_codes;
   1532 	    switch (table[ch]) {
   1533 	    case CASE_GROUND_STATE:
   1534 		total_ground++;
   1535 		break;
   1536 	    case CASE_ESC_IGNORE:
   1537 		/* FALLTHRU */
   1538 	    case CASE_IGNORE:
   1539 		/* FALLTHRU */
   1540 	    case CASE_VT52_IGNORE:
   1541 		total_ignored++;
   1542 		break;
   1543 	    }
   1544 	}
   1545     }
   1546     TRACE(("VTPrsTbl:\n"));
   1547     TRACE(("%d total codes\n", total_codes));
   1548     TRACE(("%d total ignored\n", total_ignored));
   1549     TRACE(("%d total reset/ground\n", total_ground));
   1550 }
   1551 
   1552 static void
   1553 check_bitmasks(void)
   1554 {
   1555 #define dMSK 0x100
   1556 #define DATA(mode,name) { mode, name, #name }
   1557 #define DMSK(what) (dMSK | (what))
   1558 #define DGRP(offs) (1 << ((offs) - 1))
   1559     static struct {
   1560 	int mode;
   1561 	int code;
   1562 	const char *name;
   1563     } table[] = {
   1564 	DATA(DGRP(1), INVERSE),
   1565 	    DATA(DGRP(1), UNDERLINE),
   1566 	    DATA(DGRP(1), BOLD),
   1567 	    DATA(DGRP(1), BLINK),
   1568 	    DATA(DMSK(DGRP(1)), SGR_MASK),
   1569 	    DATA(DGRP(2), BG_COLOR),
   1570 	    DATA(DGRP(2), FG_COLOR),
   1571 	    DATA(DGRP(2), PROTECTED),
   1572 	    DATA(DGRP(4), CHARDRAWN),
   1573 	    DATA(DGRP(2), INVISIBLE),
   1574 #if OPT_WIDE_ATTRS
   1575 	    DATA(DGRP(2), ATR_FAINT),
   1576 	    DATA(DGRP(2), ATR_ITALIC),
   1577 	    DATA(DGRP(2), ATR_STRIKEOUT),
   1578 	    DATA(DGRP(2), ATR_DBL_UNDER),
   1579 	    DATA(DGRP(2), ATR_DIRECT_FG),
   1580 	    DATA(DGRP(2), ATR_DIRECT_BG),
   1581 #endif
   1582 	    DATA(DMSK(DGRP(2)), SGR_MASK2),
   1583 	    DATA(DMSK(DGRP(3)), ATTRIBUTES),
   1584 	    DATA(DGRP(3), REVERSE_VIDEO),
   1585 	    DATA(DGRP(3), WRAPAROUND),
   1586 	    DATA(DGRP(3), REVERSEWRAP),
   1587 	    DATA(DGRP(3), REVERSEWRAP2),
   1588 	    DATA(DGRP(3), LINEFEED),
   1589 	    DATA(DGRP(3), ORIGIN),
   1590 	    DATA(DGRP(3), INSERT),
   1591 	    DATA(DGRP(3), SMOOTHSCROLL),
   1592 	    DATA(DGRP(3), IN132COLUMNS),
   1593 	    DATA(DGRP(5), NATIONAL),
   1594 	    DATA(DGRP(5), LEFT_RIGHT),
   1595 	    DATA(DGRP(5), NOCLEAR_COLM),
   1596 	    DATA(DGRP(4), NOBACKGROUND),
   1597 	    DATA(DGRP(4), NOTRANSLATION),
   1598 	    DATA(DGRP(4), DOUBLEWFONT),
   1599 	    DATA(DGRP(4), DOUBLEHFONT),
   1600 	    DATA(DGRP(4), CHARBYCHAR),
   1601 	    DATA(DGRP(4), NORESOLUTION),
   1602 	    DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK),
   1603 	    DATA(-1, EOF)
   1604     };
   1605 #undef DATA
   1606     int j, k;
   1607     TRACE(("** check_bitmasks:\n"));
   1608     for (j = 0; table[j].mode >= 0; ++j) {
   1609 	TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name));
   1610 	if (table[j].mode & dMSK) {
   1611 	    int mask = dMSK;
   1612 	    for (k = 0; table[k].mode >= 0; ++k) {
   1613 		if (j == k)
   1614 		    continue;
   1615 		if (table[k].mode & dMSK)
   1616 		    continue;
   1617 		if ((table[j].mode & table[k].mode) != 0)
   1618 		    mask |= table[k].mode;
   1619 	    }
   1620 	    if (mask != table[j].mode) {
   1621 		TRACE(("...expected %08X\n", mask));
   1622 	    }
   1623 	} else {
   1624 	    for (k = 0; table[k].mode >= 0; ++k) {
   1625 		if (j == k)
   1626 		    continue;
   1627 		if (table[k].mode & dMSK)
   1628 		    continue;
   1629 		if ((table[j].code & table[k].code) != 0) {
   1630 		    TRACE(("...same bits %s\n", table[k].name));
   1631 		}
   1632 	    }
   1633 	}
   1634     }
   1635 }
   1636 #endif
   1637 
   1638 static int
   1639 init_params(void)
   1640 {
   1641     while (parms.count-- > 0) {
   1642 	parms.is_sub[parms.count] = 0;
   1643 	parms.params[parms.count] = 0;
   1644     }
   1645     parms.count = 0;
   1646     parms.has_subparams = 0;
   1647     return 0;
   1648 }
   1649 
   1650 #if OPT_TRACE > 0
   1651 static void
   1652 dump_params(void)
   1653 {
   1654     int n;
   1655     int arg;
   1656     TRACE(("params %d (%d)\n", nparam, parms.has_subparams));
   1657     for (arg = 1, n = 0; n < nparam; ++n) {
   1658 	TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n]));
   1659 	if (!parms.is_sub[n])
   1660 	    ++arg;
   1661     }
   1662 }
   1663 #define DumpParams() dump_params()
   1664 #else
   1665 #define DumpParams()		/* nothing */
   1666 #endif
   1667 
   1668 	/* allocate larger buffer if needed/possible */
   1669 #define SafeAlloc(type, area, used, size) \
   1670 		type *new_string = area; \
   1671 		size_t new_length = size; \
   1672 		if (new_length == 0) { \
   1673 		    new_length = 1024; \
   1674 		    new_string = TypeMallocN(type, new_length); \
   1675 		} else if (used+1 >= new_length) { \
   1676 		    new_length = size * 2; \
   1677 		    new_string = TypeMallocN(type, new_length); \
   1678 		    if (new_string != NULL \
   1679 		     && area != NULL \
   1680 		     && used != 0) { \
   1681 			memcpy(new_string, area, used * sizeof(type)); \
   1682 		     } \
   1683 		}
   1684 #define SafeFree(area, size) \
   1685 		if (area != new_string) { \
   1686 		    free(area); \
   1687 		    area = new_string; \
   1688 		} \
   1689 		size = new_length
   1690 
   1691 #define WriteNow() {							\
   1692 	    unsigned single = 0;					\
   1693 									\
   1694 	    if (screen->curss) {					\
   1695 		if (sp->print_area != NULL) {				\
   1696 		    dotext(xw,						\
   1697 			   screen->gsets[(int) (screen->curss)],	\
   1698 			   sp->print_area,				\
   1699 			   (Cardinal) 1);				\
   1700 		    single++;						\
   1701 		}							\
   1702 		screen->curss = 0;					\
   1703 	    }								\
   1704 	    if (sp->print_used > single) {				\
   1705 		if (sp->print_area != NULL) {				\
   1706 		    dotext(xw,						\
   1707 			   screen->gsets[(int) (screen->curgl)],	\
   1708 			   sp->print_area + single,			\
   1709 			   (Cardinal) (sp->print_used - single));	\
   1710 		}							\
   1711 	    }								\
   1712 	    sp->print_used = 0;						\
   1713 	}								\
   1714 
   1715 typedef enum {
   1716     sa_INIT
   1717     ,sa_LAST
   1718     ,sa_REGIS
   1719     ,sa_SIXEL
   1720 } StringArgs;
   1721 
   1722 struct ParseState {
   1723     unsigned check_recur;
   1724 #if OPT_VT52_MODE
   1725     Bool vt52_cup;
   1726 #endif
   1727     const PARSE_T *groundtable;
   1728     const PARSE_T *parsestate;
   1729     int scstype;
   1730     int scssize;
   1731     Bool private_function;	/* distinguish private-mode from standard */
   1732     int string_mode;		/* nonzero iff we're processing a string */
   1733     StringArgs string_args;	/* parse-state within string processing */
   1734     Bool string_skip;		/* true if we will ignore the string */
   1735     int lastchar;		/* positive iff we had a graphic character */
   1736     int nextstate;
   1737 #if OPT_WIDE_CHARS
   1738     int last_was_wide;
   1739 #endif
   1740     /* Buffer for processing printable text */
   1741     IChar *print_area;
   1742     size_t print_size;
   1743     size_t print_used;
   1744     /* Buffer for processing strings (e.g., OSC ... ST) */
   1745     Char *string_area;
   1746     size_t string_size;
   1747     size_t string_used;
   1748     /* Buffer for deferring input */
   1749     Char *defer_area;
   1750     size_t defer_size;
   1751     size_t defer_used;
   1752 };
   1753 
   1754 static struct ParseState myState;
   1755 
   1756 static void
   1757 init_groundtable(TScreen *screen, struct ParseState *sp)
   1758 {
   1759     (void) screen;
   1760 
   1761 #if OPT_VT52_MODE
   1762     if (!(screen->vtXX_level)) {
   1763 	sp->groundtable = vt52_table;
   1764     } else if (screen->terminal_id >= 100)
   1765 #endif
   1766     {
   1767 	sp->groundtable = ansi_table;
   1768     }
   1769 }
   1770 
   1771 static void
   1772 select_charset(struct ParseState *sp, int type, int size)
   1773 {
   1774     TRACE(("select_charset G%d size %d -> G%d size %d\n",
   1775 	   sp->scstype, sp->scssize,
   1776 	   type, size));
   1777 
   1778     sp->scstype = type;
   1779     sp->scssize = size;
   1780     if (size == 94) {
   1781 	sp->parsestate = scstable;
   1782     } else {
   1783 	sp->parsestate = scs96table;
   1784     }
   1785 }
   1786 /* *INDENT-OFF* */
   1787 static const struct {
   1788     DECNRCM_codes result;
   1789     int prefix;
   1790     int suffix;
   1791     int min_level;
   1792     int max_level;
   1793     int need_nrc;
   1794     int sized_96;
   1795 } scs_table[] = {
   1796     { nrc_ASCII,             0,   'B', 1, 9, 0, 0 },
   1797     { nrc_British,           0,   'A', 1, 9, 0, 0 },
   1798     { nrc_DEC_Spec_Graphic,  0,   '0', 1, 9, 0, 0 },
   1799     { nrc_DEC_Alt_Chars,     0,   '1', 1, 1, 0, 0 },
   1800     { nrc_DEC_Alt_Graphics,  0,   '2', 1, 1, 0, 0 },
   1801     /* VT2xx */
   1802     { nrc_DEC_Supp,          0,   '<', 2, 2, 0, 0 },
   1803     { nrc_Dutch,             0,   '4', 2, 9, 1, 0 },
   1804     { nrc_Finnish,           0,   '5', 2, 9, 1, 0 },
   1805     { nrc_Finnish2,          0,   'C', 2, 9, 1, 0 },
   1806     { nrc_French,            0,   'R', 2, 9, 1, 0 },
   1807     { nrc_French2,           0,   'f', 2, 9, 1, 0 },
   1808     { nrc_French_Canadian,   0,   'Q', 2, 9, 1, 0 },
   1809     { nrc_German,            0,   'K', 2, 9, 1, 0 },
   1810     { nrc_Italian,           0,   'Y', 2, 9, 1, 0 },
   1811     { nrc_Norwegian_Danish2, 0,   'E', 2, 9, 1, 0 },
   1812     { nrc_Norwegian_Danish3, 0,   '6', 2, 9, 1, 0 },
   1813     { nrc_Spanish,           0,   'Z', 2, 9, 1, 0 },
   1814     { nrc_Swedish,           0,   '7', 2, 9, 1, 0 },
   1815     { nrc_Swedish2,          0,   'H', 2, 9, 1, 0 },
   1816     { nrc_Swiss,             0,   '=', 2, 9, 1, 0 },
   1817     /* VT3xx */
   1818     { nrc_DEC_UPSS,          0,   '<', 3, 9, 0, 1 },
   1819     { nrc_British_Latin_1,   0,   'A', 3, 9, 1, 0 },
   1820     { nrc_DEC_Supp_Graphic,  '%', '5', 3, 9, 0, 0 },
   1821     { nrc_DEC_Technical,     0,   '>', 3, 9, 0, 0 },
   1822     { nrc_French_Canadian2,  0,   '9', 3, 9, 1, 0 },
   1823     { nrc_Norwegian_Danish,  0,   '`', 3, 9, 1, 0 },
   1824     { nrc_Portugese,         '%', '6', 3, 9, 1, 0 },
   1825     { nrc_ISO_Latin_1_Supp,  0,   'A', 3, 9, 0, 1 },
   1826     { nrc_JIS_Katakana,      0,   'I', 3, 3, 0, 0 },
   1827     { nrc_JIS_Roman,         0,   'J', 3, 3, 0, 0 },
   1828     /* VT5xx */
   1829     { nrc_Greek,             '"', '>', 5, 9, 1, 0 },
   1830     { nrc_Hebrew,            '%', '=', 5, 9, 1, 0 },
   1831     { nrc_Russian,	     '&', '5', 5, 9, 1, 0 },
   1832     { nrc_SCS_NRCS,	     '%', '3', 5, 9, 1, 0 },
   1833     { nrc_Turkish,	     '%', '2', 5, 9, 1, 0 },
   1834     { nrc_DEC_Cyrillic,      '&', '4', 5, 9, 0, 0 },
   1835     { nrc_DEC_Greek_Supp,    '"', '?', 5, 9, 0, 0 },
   1836     { nrc_DEC_Hebrew_Supp,   '"', '4', 5, 9, 0, 0 },
   1837     { nrc_DEC_Turkish_Supp,  '%', '0', 5, 9, 0, 0 },
   1838     { nrc_ISO_Greek_Supp,    0,   'F', 5, 9, 0, 1 },
   1839     { nrc_ISO_Hebrew_Supp,   0,   'H', 5, 9, 0, 1 },
   1840     { nrc_ISO_Latin_2_Supp,  0,   'B', 5, 9, 0, 1 },
   1841     { nrc_ISO_Latin_5_Supp,  0,   'M', 5, 9, 0, 1 },
   1842     { nrc_ISO_Latin_Cyrillic,0,   'L', 5, 9, 0, 1 },
   1843 };
   1844 /* *INDENT-ON* */
   1845 
   1846 #if OPT_DEC_RECTOPS
   1847 static char *
   1848 encode_scs(DECNRCM_codes value, int *psize)
   1849 {
   1850     static char buffer[3];
   1851     Cardinal n;
   1852     char *result = buffer;
   1853 
   1854     for (n = 0; n < XtNumber(scs_table); ++n) {
   1855 	if (scs_table[n].result == value) {
   1856 	    if (scs_table[n].prefix)
   1857 		*result++ = (char) scs_table[n].prefix;
   1858 	    if (scs_table[n].suffix)
   1859 		*result++ = (char) scs_table[n].suffix;
   1860 	    *psize = scs_table[n].sized_96;
   1861 	    break;
   1862 	}
   1863     }
   1864     *result = '\0';
   1865     return buffer;
   1866 }
   1867 
   1868 static int
   1869 is_96charset(DECNRCM_codes value)
   1870 {
   1871     Cardinal n;
   1872     int result = 0;
   1873 
   1874     for (n = 0; n < XtNumber(scs_table); ++n) {
   1875 	if (scs_table[n].result == value) {
   1876 	    result = scs_table[n].sized_96 ? 1 : 0;
   1877 	    break;
   1878 	}
   1879     }
   1880     return result;
   1881 }
   1882 #endif
   1883 
   1884 void
   1885 xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix)
   1886 {
   1887     TScreen *screen = TScreenOf(xw);
   1888     Cardinal n;
   1889     DECNRCM_codes result = nrc_Unknown;
   1890 
   1891     prefix = AsciiOf(prefix);
   1892     suffix = AsciiOf(suffix);
   1893     for (n = 0; n < XtNumber(scs_table); ++n) {
   1894 	if (prefix == scs_table[n].prefix
   1895 	    && suffix == scs_table[n].suffix
   1896 	    && sgroup <= scs_table[n].min_level
   1897 	    && screen->vtXX_level >= scs_table[n].min_level
   1898 	    && screen->vtXX_level <= scs_table[n].max_level
   1899 	    && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) {
   1900 	    result = scs_table[n].result;
   1901 	    break;
   1902 	}
   1903     }
   1904     if (result != nrc_Unknown) {
   1905 	initCharset(screen, which, result);
   1906 	TRACE(("setting G%d to table #%d %s",
   1907 	       which, n, visibleScsCode((int) result)));
   1908     } else {
   1909 	TRACE(("...unknown GSET"));
   1910 	initCharset(screen, which, nrc_ASCII);
   1911     }
   1912 #if OPT_TRACE
   1913     TRACE((" ("));
   1914     if (prefix)
   1915 	TRACE(("prefix='%c', ", prefix));
   1916     TRACE(("suffix='%c', sgroup=%d", suffix, sgroup));
   1917     TRACE((")\n"));
   1918 #endif
   1919 }
   1920 
   1921 /*
   1922  * Given a parameter number, and subparameter (starting in each case from zero)
   1923  * return the corresponding index into the parameter array.  If the combination
   1924  * is not found, return -1.
   1925  */
   1926 static int
   1927 subparam_index(int p, int s)
   1928 {
   1929     int result = -1;
   1930     int j, p2, s2;
   1931 
   1932     for (j = p2 = 0; j < nparam; ++j, ++p2) {
   1933 	if (parms.is_sub[j]) {
   1934 	    s2 = 0;
   1935 
   1936 	    do {
   1937 		if ((p == p2) && (s == s2)) {
   1938 		    result = j;
   1939 		    break;
   1940 		}
   1941 		++s2;
   1942 	    } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j]));
   1943 
   1944 	    if (result >= 0)
   1945 		break;
   1946 
   1947 	    --j;		/* undo the last "while" */
   1948 	} else if (p == p2) {
   1949 	    if (s == 0) {
   1950 		result = j;
   1951 	    }
   1952 	    break;
   1953 	}
   1954     }
   1955     TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result));
   1956     return result;
   1957 }
   1958 
   1959 /*
   1960  * Given an index into the parameter array, return the corresponding parameter
   1961  * number (starting from zero).
   1962  */
   1963 static int
   1964 param_number(int item)
   1965 {
   1966     int result = -1;
   1967     int j, p;
   1968 
   1969     for (j = p = 0; j < nparam; ++j, ++p) {
   1970 	if (j >= item) {
   1971 	    result = p;
   1972 	    break;
   1973 	}
   1974 	if (parms.is_sub[j]) {
   1975 	    while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) {
   1976 		/* EMPTY */
   1977 	    }
   1978 	    --j;
   1979 	}
   1980     }
   1981 
   1982     TRACE2(("...param_number(%d) = %d\n", item, result));
   1983     return result;
   1984 }
   1985 
   1986 /*
   1987  * Check if the given index in the parameter array has subparameters.
   1988  * If so, return the number of subparameters to use as a loop limit, etc.
   1989  */
   1990 static int
   1991 param_has_subparams(int item)
   1992 {
   1993     int result = 0;
   1994     if (parms.has_subparams) {
   1995 	int p = param_number(item);
   1996 	int n = subparam_index(p, 0);
   1997 	if (n >= 0 && parms.is_sub[n]) {
   1998 	    while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) {
   1999 		result++;
   2000 	    }
   2001 	}
   2002     }
   2003     TRACE(("...param_has_subparams(%d) ->%d\n", item, result));
   2004     return result;
   2005 }
   2006 
   2007 #if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS
   2008 
   2009 static int
   2010 get_subparam(int p, int s)
   2011 {
   2012     int item = subparam_index(p, s);
   2013     int result = (item >= 0) ? parms.params[item] : DEFAULT;
   2014     TRACE(("...get_subparam[%d] = %d\n", item, result));
   2015     return result;
   2016 }
   2017 
   2018 /*
   2019  * Some background -
   2020  *
   2021  * Todd Larason provided the initial changes to support 256-colors in July 1999.
   2022  * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and
   2023  * was unsure if there would be some standard using those codes.  His response
   2024  * was that this was documented (it turns out, in equally vague terms) in ITU
   2025  * T.416
   2026  *
   2027  * Discussing this with Todd Larason in mid-1999, my point was that given the
   2028  * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going
   2029  * to be effective (more than $100 then, more than $200 in 2012)
   2030  *
   2031  * We overlooked the detail about ":" as a subparameter delimiter (documented
   2032  * in 5.4.2 in ECMA-48).  Some discussion in KDE in mid-2006 led Lars Doelle
   2033  * to discuss the issue with me.  Lars' initial concern dealt with the fact
   2034  * that a sequence such as
   2035  *	CSI 38 ; 5 ; 1 m
   2036  * violated the principle that SGR parameters could be used in any order.
   2037  * Further discussion (see KDE #107487) resolved that the standard expected
   2038  * that the sequence would look like
   2039  *	CSI 38 ; 5 : 1 m
   2040  * which still violates that principle, since the "5:1" parameter has to
   2041  * follow the "38" to be useful.
   2042  *
   2043  * This function accepts either format (per request by Paul Leonerd Evans).
   2044  * It also accepts
   2045  *	CSI 38 : 5 : 1 m
   2046  * according to Lars' original assumption.  While implementing that, I added
   2047  * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value.
   2048  * ISO-8613-6 documents that as "direct color".
   2049  *
   2050  * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's
   2051  * quirk in the description of direct color:  it mentions a color space
   2052  * identifier parameter which should follow the "2" (as parameter 1).  In the
   2053  * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as
   2054  * well as parameters 7 and 8.  Like parameter 1, parameters 7 and 8 are not
   2055  * defined clearly in the standard, and a close reading indicates they are
   2056  * optional, saying they "may be used".  This implementation ignores parameters
   2057  * 6 (and above), and provides for the color space identifier by checking the
   2058  * number of parameters:
   2059  *	3 after "2" (no color space identifier)
   2060  *	4 or more after "2" (color space identifier)
   2061  *
   2062  * By the way - all of the parameters are decimal integers, and missing
   2063  * parameters represent a default value.  ISO-8613-6 is clear about that.
   2064  *
   2065  * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter.
   2066  * ECMA-48 says only:
   2067  *
   2068  *	5.4.2 Parameter string format
   2069  *
   2070  *	A parameter string which does not start with a bit combination in the
   2071  *	range 03/12 to 03/15 shall have the following format:
   2072  *
   2073  *	    a) A parameter string consists of one or more parameter
   2074  *	       sub-strings, each of which represents a number in decimal
   2075  *	       notation.
   2076  *
   2077  *	    b) Each parameter sub-string consists of one or more bit
   2078  *	       combinations from 03/00 to 03/10; the bit combinations from
   2079  *	       03/00 to 03/09 represent the digits ZERO to NINE; bit
   2080  *	       combination 03/10 may be used as a separator in a parameter
   2081  *	       sub-string, for example, to separate the fractional part of a
   2082  *	       decimal number from the integer part of that number.
   2083  *
   2084  * That is, there is no mention in ECMA-48 of the possibility that a parameter
   2085  * string might be a list of parameters, as done in ISO-8613-3 (nor does
   2086  * ECMA-48 provide an example where the ":" separator might be used).  Because
   2087  * of this, xterm treats other cases than those needed for ISO-8613-3 as an
   2088  * error, and stops interpreting the sequence.
   2089  */
   2090 #define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0))
   2091 static Boolean
   2092 parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended)
   2093 {
   2094     Boolean result = False;
   2095     int item = *itemp;
   2096     int next = item;
   2097     int base = param_number(item);
   2098     int code = -1;
   2099     int values[3];		/* maximum number of subparameters */
   2100     int need = 0;		/* number of subparameters needed */
   2101     int have;
   2102     int n;
   2103 
   2104     /*
   2105      * On entry, 'item' points to the 38/48 code in the parameter array.
   2106      * If that has subparameters, we will expect all of the values to
   2107      * be subparameters of that item.
   2108      */
   2109     if ((have = param_has_subparams(item)) != 0) {
   2110 	/* accept CSI 38 : 5 : 1 m */
   2111 	/* accept CSI 38 : 2 : 1 : 2 : 3 m */
   2112 	code = get_subparam(base, 1);
   2113 	need = extended_colors_limit(code);
   2114 	next = item + have;
   2115 	for (n = 0; n < need && n < 3; ++n) {
   2116 	    values[n] = get_subparam(base, 2 + n + (have > 4));
   2117 	}
   2118     } else if (++item < nparam) {
   2119 	++base;
   2120 	if ((have = param_has_subparams(item)) != 0) {
   2121 	    /* accept CSI 38 ; 5 : 1 m */
   2122 	    /* accept CSI 38 ; 2 : 1 : 2 : 3 m */
   2123 	    code = get_subparam(base, 0);
   2124 	    need = extended_colors_limit(code);
   2125 	    next = base + have;
   2126 	    for (n = 0; n < need && n < 3; ++n) {
   2127 		values[n] = get_subparam(base, 1 + n + (have > 3));
   2128 	    }
   2129 	} else {
   2130 	    /* accept CSI 38 ; 5 ; 1 m */
   2131 	    /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */
   2132 	    code = GetParam(item);
   2133 	    need = extended_colors_limit(code);
   2134 	    next = item + need;
   2135 	    for (n = 0; n < need && n < 3; ++n) {
   2136 		values[n] = GetParam(item + 1 + n);
   2137 	    }
   2138 	}
   2139     }
   2140     item = next;
   2141 
   2142     *extended = False;
   2143     switch (code) {
   2144     case 2:
   2145 	/* direct color in rgb space */
   2146 	if ((values[0] >= 0 && values[0] < 256) &&
   2147 	    (values[1] >= 0 && values[1] < 256) &&
   2148 	    (values[2] >= 0 && values[2] < 256)) {
   2149 #if OPT_DIRECT_COLOR
   2150 	    if (TScreenOf(xw)->direct_color && xw->has_rgb) {
   2151 		*colorp = getDirectColor(xw, values[0], values[1], values[2]);
   2152 		result = True;
   2153 		*extended = True;
   2154 	    } else
   2155 #endif
   2156 	    {
   2157 		*colorp = xtermClosestColor(xw, values[0], values[1], values[2]);
   2158 		result = okIndexedColor(*colorp);
   2159 	    }
   2160 	} else {
   2161 	    *colorp = -1;
   2162 	}
   2163 	break;
   2164     case 5:
   2165 	/* indexed color */
   2166 	*colorp = values[0];
   2167 	result = okIndexedColor(*colorp);
   2168 	break;
   2169     default:
   2170 	*colorp = -1;
   2171 	break;
   2172     }
   2173 
   2174     TRACE(("...resulting color %d/%d %s\n",
   2175 	   *colorp, NUM_ANSI_COLORS,
   2176 	   result ? "OK" : "ERR"));
   2177 
   2178     *itemp = item;
   2179     return result;
   2180 }
   2181 #endif /* ...extended_colors */
   2182 
   2183 static int
   2184 optional_param(int which)
   2185 {
   2186     return (nparam > which) ? GetParam(which) : DEFAULT;
   2187 }
   2188 
   2189 static int
   2190 only_default(void)
   2191 {
   2192     return (nparam <= 1) && (GetParam(0) == DEFAULT);
   2193 }
   2194 
   2195 static int
   2196 use_default_value(int which, int default_value)
   2197 {
   2198     int result = (nparam > which) ? GetParam(which) : default_value;
   2199     if (result <= 0)
   2200 	result = default_value;
   2201     return result;
   2202 }
   2203 
   2204 #define zero_if_default(which) use_default_value(which, 0)
   2205 
   2206 #define one_if_default(which) use_default_value(which, 1)
   2207 
   2208 #define BeginString(mode) \
   2209 	do { \
   2210 	    sp->string_mode = mode; \
   2211 	    sp->string_args = sa_LAST; \
   2212 	    sp->parsestate = sos_table; \
   2213 	} while (0)
   2214 
   2215 #define BeginString2(mode) \
   2216 	do { \
   2217 	    sp->string_mode = mode; \
   2218 	    sp->string_args = sa_INIT; \
   2219 	    sp->parsestate = sos_table; \
   2220 	} while (0)
   2221 
   2222 static void
   2223 begin_sixel(XtermWidget xw, struct ParseState *sp)
   2224 {
   2225     TScreen *screen = TScreenOf(xw);
   2226 
   2227     sp->string_args = sa_LAST;
   2228     if (optSixelGraphics(screen)) {
   2229 #if OPT_SIXEL_GRAPHICS
   2230 	ANSI params;
   2231 	const char *cp;
   2232 
   2233 	cp = (const char *) sp->string_area;
   2234 	sp->string_area[sp->string_used] = '\0';
   2235 	parse_ansi_params(&params, &cp);
   2236 	parse_sixel_init(xw, &params);
   2237 	sp->string_args = sa_SIXEL;
   2238 	sp->string_used = 0;
   2239 #else
   2240 	(void) screen;
   2241 	TRACE(("ignoring sixel graphic (compilation flag not enabled)\n"));
   2242 #endif
   2243     }
   2244 }
   2245 
   2246 /*
   2247  * Color palette changes using the OSC controls require a repaint of the
   2248  * screen - but not immediately.  Do the repaint as soon as we detect a
   2249  * state which will not lead to another color palette change.
   2250  */
   2251 static void
   2252 repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp)
   2253 {
   2254     Boolean ignore = False;
   2255 
   2256     switch (sp->nextstate) {
   2257     case CASE_ESC:
   2258 	ignore = ((sp->parsestate == ansi_table) ||
   2259 		  (sp->parsestate == sos_table));
   2260 #if USE_DOUBLE_BUFFER
   2261 	if (resource.buffered && TScreenOf(xw)->needSwap) {
   2262 	    ignore = False;
   2263 	}
   2264 #endif
   2265 	break;
   2266     case CASE_OSC:
   2267 	ignore = ((sp->parsestate == ansi_table) ||
   2268 		  (sp->parsestate == esc_table));
   2269 	break;
   2270     case CASE_IGNORE:
   2271 	ignore = (sp->parsestate == sos_table);
   2272 	break;
   2273     case CASE_ST:
   2274 	ignore = ((sp->parsestate == esc_table) ||
   2275 		  (sp->parsestate == sos_table));
   2276 	break;
   2277     case CASE_ESC_DIGIT:
   2278 	ignore = (sp->parsestate == csi_table);
   2279 	break;
   2280     case CASE_ESC_SEMI:
   2281 	ignore = (sp->parsestate == csi2_table);
   2282 	break;
   2283     }
   2284 
   2285     if (!ignore) {
   2286 	TRACE(("repaintWhenPaletteChanged\n"));
   2287 	xw->work.palette_changed = False;
   2288 	xtermRepaint(xw);
   2289 	xtermFlushDbe(xw);
   2290     }
   2291 }
   2292 
   2293 #if OPT_C1_PRINT || OPT_WIDE_CHARS
   2294 #define ParseSOS(screen) ((screen)->c1_printable == 0)
   2295 #else
   2296 #define ParseSOS(screen) 0
   2297 #endif
   2298 
   2299 #define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable
   2300 
   2301 static void
   2302 illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp)
   2303 {
   2304     ResetState(sp);
   2305     sp->nextstate = sp->parsestate[c];
   2306     Bell(xw, XkbBI_MinorError, 0);
   2307 }
   2308 
   2309 static void
   2310 init_parser(XtermWidget xw, struct ParseState *sp)
   2311 {
   2312     TScreen *screen = TScreenOf(xw);
   2313 
   2314     free(sp->defer_area);
   2315     free(sp->print_area);
   2316     free(sp->string_area);
   2317     memset(sp, 0, sizeof(*sp));
   2318     sp->scssize = 94;		/* number of printable/nonspace ASCII */
   2319     sp->lastchar = -1;		/* not a legal IChar */
   2320     sp->nextstate = -1;		/* not a legal state */
   2321 
   2322     init_groundtable(screen, sp);
   2323     ResetState(sp);
   2324 }
   2325 
   2326 static void
   2327 init_reply(unsigned type)
   2328 {
   2329     memset(&reply, 0, sizeof(reply));
   2330     reply.a_type = (Char) type;
   2331 }
   2332 
   2333 static void
   2334 deferparsing(unsigned c, struct ParseState *sp)
   2335 {
   2336     SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size);
   2337     if (new_string == NULL) {
   2338 	xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n",
   2339 		     (unsigned long) new_length, c);
   2340 	return;
   2341     }
   2342     SafeFree(sp->defer_area, sp->defer_size);
   2343     sp->defer_area[(sp->defer_used)++] = CharOf(c);
   2344 }
   2345 
   2346 #if OPT_MOD_FKEYS
   2347 static void
   2348 set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled)
   2349 {
   2350 #define SET_MOD_FKEYS(field) \
   2351     xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \
   2352 				     ? xw->keyboard.modify_1st.field \
   2353 				     : what; \
   2354     TRACE(("set modify_now.%s to %d\n", #field, \
   2355 	   xw->keyboard.modify_now.field));
   2356 
   2357     switch (which) {
   2358     case 0:
   2359 	SET_MOD_FKEYS(allow_keys);
   2360 	break;
   2361     case 1:
   2362 	SET_MOD_FKEYS(cursor_keys);
   2363 	break;
   2364     case 2:
   2365 	SET_MOD_FKEYS(function_keys);
   2366 	break;
   2367     case 3:
   2368 	SET_MOD_FKEYS(keypad_keys);
   2369 	break;
   2370     case 4:
   2371 	SET_MOD_FKEYS(other_keys);
   2372 	break;
   2373     case 5:
   2374 	SET_MOD_FKEYS(string_keys);
   2375 	break;
   2376     }
   2377 }
   2378 
   2379 static void
   2380 report_mod_fkeys(XtermWidget xw, int which)	/* XTQMODKEYS */
   2381 {
   2382 #define GET_MOD_FKEYS(field) \
   2383     reply.a_param[1] = (ParmType) xw->keyboard.modify_now.field
   2384 
   2385     init_reply(ANSI_CSI);
   2386     reply.a_pintro = '>';	/* replies look like a set-mode */
   2387     reply.a_nparam = 2;
   2388     reply.a_final = 'm';
   2389 
   2390     reply.a_param[1] = DEFAULT;
   2391     switch (reply.a_param[0] = (ParmType) which) {
   2392     case 0:
   2393 	GET_MOD_FKEYS(allow_keys);
   2394 	break;
   2395     case 1:
   2396 	GET_MOD_FKEYS(cursor_keys);
   2397 	break;
   2398     case 2:
   2399 	GET_MOD_FKEYS(function_keys);
   2400 	break;
   2401     case 3:
   2402 	GET_MOD_FKEYS(keypad_keys);
   2403 	break;
   2404     case 4:
   2405 	GET_MOD_FKEYS(other_keys);
   2406 	break;
   2407     case 5:
   2408 	GET_MOD_FKEYS(string_keys);
   2409 	break;
   2410     }
   2411     unparseseq(xw, &reply);
   2412 }
   2413 #endif /* OPT_MOD_FKEYS */
   2414 
   2415 #if OPT_STATUS_LINE
   2416 typedef enum {
   2417     SLnone = 0,			/* no status-line timer needed */
   2418     SLclock = 1,		/* status-line updates once/second */
   2419     SLcoords = 2,		/* status-line shows cursor-position */
   2420     SLwritten = 3		/* status-line may need asynchronous repainting */
   2421 } SL_MODE;
   2422 
   2423 #define SL_BUFSIZ 80
   2424 
   2425 #if OPT_TRACE
   2426 static const char *
   2427 visibleStatusType(int code)
   2428 {
   2429     const char *result = "?";
   2430     switch (code) {
   2431     case 0:
   2432 	result = "none";
   2433 	break;
   2434     case 1:
   2435 	result = "indicator";
   2436 	break;
   2437     case 2:
   2438 	result = "writable";
   2439 	break;
   2440     }
   2441     return result;
   2442 }
   2443 
   2444 static void
   2445 trace_status_line(XtermWidget xw, int lineno, const char *tag)
   2446 {
   2447     TScreen *screen = TScreenOf(xw);
   2448 
   2449     TRACE(("@%d, %s (%s, %s)%s%s @ (%d,%d) vs %d\n",
   2450 	   lineno,
   2451 	   tag,
   2452 	   screen->status_active ? "active" : "inactive",
   2453 	   visibleStatusType(screen->status_type),
   2454 	   ((screen->status_type != screen->status_shown)
   2455 	    ? " vs "
   2456 	    : ""),
   2457 	   ((screen->status_type != screen->status_shown)
   2458 	    ? visibleStatusType(screen->status_shown)
   2459 	    : ""),
   2460 	   screen->cur_row,
   2461 	   screen->cur_col,
   2462 	   LastRowNumber(screen)));
   2463 }
   2464 
   2465 #define TRACE_SL(tag) trace_status_line(xw, __LINE__, tag)
   2466 #else
   2467 #define TRACE_SL(tag)		/* nothing */
   2468 #endif
   2469 
   2470 static SL_MODE
   2471 find_SL_MODE(XtermWidget xw)
   2472 {
   2473     TScreen *screen = TScreenOf(xw);
   2474     SL_MODE result = SLnone;
   2475     const char *parse;
   2476 
   2477     for (parse = screen->status_fmt; *parse != '\0'; ++parse) {
   2478 	const char *found = parse;
   2479 	if (*parse == '%') {
   2480 	    if (*++parse == L_CURL) {
   2481 		const char *check = strchr(parse, '%');
   2482 		size_t length = 0;
   2483 
   2484 		if (check != NULL && check[1] == R_CURL) {
   2485 		    length = (size_t) (2 + check - found);
   2486 		} else {
   2487 		    length = strlen(found);
   2488 		}
   2489 
   2490 		if (!strncmp(found, "%{unixtime%}", length)) {
   2491 		    if (result == SLnone)
   2492 			result = SLclock;
   2493 		} else if (!strncmp(found, "%{position%}", length)) {
   2494 		    result = SLcoords;
   2495 		}
   2496 		parse = found + length - 1;
   2497 	    }
   2498 #if defined(HAVE_STRFTIME)
   2499 	    else if (*parse != '\0') {
   2500 		if (result == SLnone && strchr("cEgOrsSTX+", *parse) != NULL) {
   2501 		    result = SLclock;
   2502 		}
   2503 	    }
   2504 #endif
   2505 	}
   2506     }
   2507     return result;
   2508 }
   2509 
   2510 static long
   2511 find_SL_Timeout(XtermWidget xw)
   2512 {
   2513     long result = 0;
   2514     switch (find_SL_MODE(xw)) {
   2515     case SLnone:
   2516     case SLwritten:
   2517 	break;
   2518     case SLclock:
   2519 	result = DEF_SL_CLOCK;
   2520 	break;
   2521     case SLcoords:
   2522 	result = DEF_SL_COORDS;
   2523 	break;
   2524     }
   2525     return result;
   2526 }
   2527 
   2528 static void
   2529 StatusInit(SavedCursor * data)
   2530 {
   2531     memset(data, 0, sizeof(*data));
   2532     data->sgr_foreground = -1;
   2533     data->sgr_background = -1;
   2534 }
   2535 
   2536 #define SL_SAVE(n) \
   2537 	do { \
   2538 	    TRACE(("@%d saving %s to %d,%d\n", __LINE__, \
   2539 		  (n) ? "status" : "main", \
   2540 		  screen->cur_row, \
   2541 		  screen->cur_col)); \
   2542 	    CursorSave2(xw, &screen->status_data[n]); \
   2543 	} while (0)
   2544 #define SL_RESTORE(n) \
   2545 	do { \
   2546 	    CursorRestore2(xw, &screen->status_data[n]); \
   2547 	    TRACE(("@%d restored %s to %d,%d\n", __LINE__, \
   2548 		  (n) ? "status" : "main", \
   2549 		  screen->status_data[n].row, \
   2550 		  screen->status_data[n].col)); \
   2551 	} while (0)
   2552 
   2553 /* save the status-line position, restore main display */
   2554 #define SL_SAVE2() \
   2555 	do { \
   2556 	    SL_SAVE(1); \
   2557 	    SL_RESTORE(0); \
   2558 	} while (0)
   2559 
   2560 /* save the main-display position, restore status-line */
   2561 #define SL_RESTORE2() \
   2562 	do { \
   2563 	    SL_SAVE(0); \
   2564 	    SL_RESTORE(1); \
   2565 	    screen->cur_row = FirstRowNumber(screen); \
   2566 	} while (0)
   2567 
   2568 static void
   2569 StatusPutChars(XtermWidget xw, const char *value, int length)
   2570 {
   2571     TScreen *screen = TScreenOf(xw);
   2572 
   2573     if (length < 0)
   2574 	length = (int) strlen(value);
   2575 
   2576     while (length > 0) {
   2577 	IChar buffer[SL_BUFSIZ + 1];
   2578 	Cardinal n;
   2579 	for (n = 0; n < SL_BUFSIZ && length > 0 && *value != '\0'; ++n) {
   2580 	    buffer[n] = CharOf(*value++);
   2581 	    if (buffer[n] < 32 || buffer[n] > 126)
   2582 		buffer[n] = ' ';	/* FIXME - provide for UTF-8 */
   2583 	    --length;
   2584 	}
   2585 	buffer[n] = 0;
   2586 	dotext(xw,
   2587 	       screen->gsets[(int) (screen->curgl)],
   2588 	       buffer, n);
   2589     }
   2590 }
   2591 
   2592 static void
   2593 show_indicator_status(XtPointer closure, XtIntervalId * id GCC_UNUSED)
   2594 {
   2595     XtermWidget xw = (XtermWidget) closure;
   2596     TScreen *screen = TScreenOf(xw);
   2597     int right_margin;
   2598 
   2599     time_t now;
   2600     const char *parse;
   2601     char buffer[SL_BUFSIZ + 1];
   2602     long interval;
   2603 
   2604     if (screen->status_type != 1) {
   2605 	screen->status_timeout = False;
   2606 	return;
   2607     }
   2608     if (screen->status_active && (screen->status_type == screen->status_shown)) {
   2609 	return;
   2610     }
   2611 
   2612     screen->status_active = True;
   2613 
   2614     if (screen->status_shown <= 1) {
   2615 	SL_SAVE(0);
   2616     }
   2617     screen->cur_row = FirstRowNumber(screen);
   2618     screen->cur_col = 0;
   2619 
   2620     xw->flags |= INVERSE;
   2621     xw->flags &= (IFlags) (~WRAPAROUND);
   2622 
   2623     now = time((time_t *) 0);
   2624 
   2625     for (parse = screen->status_fmt; *parse != '\0'; ++parse) {
   2626 	const char *found = parse;
   2627 	if (*parse == '%') {
   2628 	    if (*++parse == L_CURL) {
   2629 		const char *check = strchr(parse, '%');
   2630 		size_t length = 0;
   2631 
   2632 		if (check != NULL && check[1] == R_CURL) {
   2633 		    length = (size_t) (2 + check - found);
   2634 		} else {
   2635 		    length = strlen(found);
   2636 		}
   2637 
   2638 		if (!strncmp(found, "%{version%}", length)) {
   2639 		    StatusPutChars(xw, xtermVersion(), -1);
   2640 		} else if (!strncmp(found, "%{unixtime%}", length)) {
   2641 		    char *t = x_strtrim(ctime(&now));
   2642 		    if (t != NULL) {
   2643 			StatusPutChars(xw, t, -1);
   2644 			free(t);
   2645 		    }
   2646 		} else if (!strncmp(found, "%{position%}", length)) {
   2647 		    sprintf(buffer, "(%02d,%03d)",
   2648 			    screen->status_data[0].row + 1,
   2649 			    screen->status_data[0].col + 1);
   2650 		    StatusPutChars(xw, buffer, -1);
   2651 		} else {
   2652 		    StatusPutChars(xw, found, (int) length);
   2653 		}
   2654 		parse = found + length - 1;
   2655 	    }
   2656 #if defined(HAVE_STRFTIME)
   2657 	    else if (*parse != '\0') {
   2658 		char format[3];
   2659 		struct tm *tm = localtime(&now);
   2660 
   2661 		format[0] = '%';
   2662 		format[1] = *parse;
   2663 		format[2] = '\0';
   2664 		if (strftime(buffer, sizeof(buffer) - 1, format, tm) != 0) {
   2665 		    StatusPutChars(xw, buffer, -1);
   2666 		} else {
   2667 		    StatusPutChars(xw, "?", 1);
   2668 		    StatusPutChars(xw, parse - 1, 2);
   2669 		}
   2670 	    }
   2671 #endif
   2672 	} else {
   2673 	    StatusPutChars(xw, parse, 1);
   2674 	}
   2675     }
   2676     right_margin = ScrnRightMargin(xw);
   2677     memset(buffer, ' ', (size_t) SL_BUFSIZ);
   2678     while (screen->cur_col < right_margin) {
   2679 	int chunk = Min(SL_BUFSIZ, (right_margin - screen->cur_col));
   2680 	StatusPutChars(xw, buffer, chunk);
   2681     }
   2682 
   2683     ScrnRefresh(xw, FirstRowNumber(screen), 0, 1, right_margin, True);
   2684     screen->status_active = False;
   2685 
   2686     SL_RESTORE(0);
   2687 
   2688     /* if we processed a position or date/time, repeat */
   2689     interval = find_SL_Timeout(xw);
   2690     if (interval > 0) {
   2691 	(void) XtAppAddTimeOut(app_con,
   2692 			       (unsigned long) interval,
   2693 			       show_indicator_status, xw);
   2694     }
   2695     screen->status_timeout = True;
   2696 }
   2697 
   2698 static void
   2699 clear_status_line(XtermWidget xw)
   2700 {
   2701     TScreen *screen = TScreenOf(xw);
   2702     SavedCursor save_me;
   2703     SavedCursor clearit;
   2704     int save_type = screen->status_type;
   2705 
   2706     TRACE_SL("clear_status_line");
   2707     StatusInit(&clearit);
   2708     CursorSave2(xw, &save_me);
   2709     CursorRestore2(xw, &clearit);
   2710 
   2711     screen->status_type = 2;
   2712     set_cur_row(screen, LastRowNumber(screen));
   2713 #if 1
   2714     ClearLine(xw);
   2715 #else
   2716     if (getLineData(screen, screen->cur_row) != NULL) {
   2717 	int n;
   2718 	char buffer[SL_BUFSIZ + 1];
   2719 	CLineData *ld = getLineData(screen, screen->cur_row);
   2720 	int right_margin = ScrnRightMargin(xw);
   2721 
   2722 	TRACE(("...text[%d:%d]:%s\n",
   2723 	       screen->cur_row,
   2724 	       LastRowNumber(screen),
   2725 	       visibleIChars(ld->charData, ld->lineSize)));
   2726 
   2727 	memset(buffer, '#', SL_BUFSIZ);
   2728 	for (n = 0; n < screen->max_col; n += SL_BUFSIZ) {
   2729 	    StatusPutChars(xw, buffer, right_margin - n);
   2730 	}
   2731     }
   2732 #endif
   2733     CursorRestore2(xw, &save_me);
   2734     screen->status_type = save_type;
   2735     TRACE_SL("clear_status_line (done)");
   2736 }
   2737 
   2738 static void
   2739 show_writable_status(XtermWidget xw)
   2740 {
   2741     TScreen *screen = TScreenOf(xw);
   2742 
   2743     TRACE(("show_writable_status (%d:%d) max=%d\n",
   2744 	   FirstRowNumber(screen),
   2745 	   LastRowNumber(screen),
   2746 	   MaxRows(screen)));
   2747     screen->cur_row = FirstRowNumber(screen);
   2748 }
   2749 
   2750 /*
   2751  * Depending the status-type, make the window grow or shrink by one row to
   2752  * show or hide the status-line.  Keep the rest of the window from scrolling
   2753  * by overriding the resize-gravity.
   2754  */
   2755 static void
   2756 resize_status_line(XtermWidget xw)
   2757 {
   2758     TScreen *screen = TScreenOf(xw);
   2759     XtGravity savedGravity = xw->misc.resizeGravity;
   2760 
   2761     TRACE_SL(screen->status_type
   2762 	     ? "...resize to show status-line"
   2763 	     : "...resize to hide status-line");
   2764 
   2765     xw->misc.resizeGravity = NorthWestGravity;
   2766 
   2767     RequestResize(xw, MaxRows(screen), MaxCols(screen), True);
   2768 
   2769     xw->misc.resizeGravity = savedGravity;
   2770 }
   2771 
   2772 /*
   2773  * DEC STD 070, chapter 14 "VSRM - Status Display Extension"
   2774  */
   2775 static void
   2776 update_status_line(XtermWidget xw, int new_active, int new_type)
   2777 {
   2778     /* *INDENT-EQLS* */
   2779     TScreen *screen = TScreenOf(xw);
   2780     int old_active  = screen->status_active;
   2781     int old_type    = screen->status_type;
   2782     int old_shown   = screen->status_shown;
   2783 
   2784     TRACE_SL("update_status_line");
   2785 
   2786     if (new_active >= 0 && new_active <= 1) {
   2787 	screen->status_active = new_active;
   2788 	if (old_active == new_active) {
   2789 	    goto finish;
   2790 	}
   2791 	if (old_type < 2) {
   2792 	    goto finish;
   2793 	}
   2794 	if (new_active && !old_active) {
   2795 	    SL_SAVE(0);
   2796 	}
   2797     } else if (new_type >= 0 && new_type <= 2) {
   2798 	screen->status_type = new_type;
   2799     } else {
   2800 	goto finish;
   2801     }
   2802 
   2803     if (screen->status_type == 1) {
   2804 	int next_shown = screen->status_type;
   2805 	if (screen->status_type != screen->status_shown) {
   2806 	    if (screen->status_shown == 0) {
   2807 		resize_status_line(xw);
   2808 	    } else {
   2809 		clear_status_line(xw);
   2810 	    }
   2811 	}
   2812 	show_indicator_status(xw, NULL);
   2813 	if (screen->status_shown != next_shown) {
   2814 	    screen->status_shown = next_shown;
   2815 	    TRACE_SL("...updating shown");
   2816 	}
   2817 	if (old_shown == 2) {
   2818 	    SL_RESTORE(0);
   2819 	}
   2820     } else if (screen->status_active) {
   2821 	if (screen->status_type != screen->status_shown) {
   2822 	    Boolean do_resize = False;
   2823 
   2824 	    if (screen->status_type == 0) {
   2825 		if (screen->status_shown >= 2) {
   2826 		    SL_SAVE2();
   2827 		}
   2828 		do_resize = True;	/* shrink... */
   2829 		clear_status_line(xw);
   2830 		StatusInit(&screen->status_data[1]);
   2831 	    } else if (screen->status_shown == 0) {
   2832 		if (screen->status_type >= 2) {
   2833 		    SL_RESTORE2();
   2834 		}
   2835 		do_resize = True;	/* grow... */
   2836 	    } else {
   2837 		clear_status_line(xw);
   2838 	    }
   2839 	    if (do_resize) {
   2840 		resize_status_line(xw);
   2841 	    }
   2842 	    screen->status_shown = screen->status_type;
   2843 	    TRACE_SL("...updating shown");
   2844 	}
   2845 	show_writable_status(xw);
   2846     } else {
   2847 	if (screen->status_shown) {
   2848 	    if (screen->status_type != 0 &&
   2849 		screen->status_type != screen->status_shown) {
   2850 		clear_status_line(xw);
   2851 	    }
   2852 	    if (screen->status_shown >= 2) {
   2853 		SL_SAVE2();
   2854 	    }
   2855 	    if (screen->status_type == 0) {
   2856 		screen->status_timeout = False;
   2857 		clear_status_line(xw);
   2858 		StatusInit(&screen->status_data[1]);
   2859 		resize_status_line(xw);		/* shrink... */
   2860 	    }
   2861 	    screen->status_shown = screen->status_type;
   2862 	    TRACE_SL("...updating shown");
   2863 	}
   2864     }
   2865   finish:
   2866     TRACE_SL("update_status_line (done)");
   2867     return;
   2868 }
   2869 
   2870 /*
   2871  * If the status-type is "2", we can switch the active status display back and
   2872  * forth between the main-display and the status-line without clearing the
   2873  * status-line (unless the status-line was not shown before).
   2874  *
   2875  * This has no effect if the status-line displays an indicator (type==1),
   2876  * or if no status-line type was selected (type==0).
   2877  */
   2878 static void
   2879 handle_DECSASD(XtermWidget xw, int value)
   2880 {
   2881     TRACE(("CASE_DECSASD - select active status display: %s (currently %s)\n",
   2882 	   BtoS(value),
   2883 	   BtoS(TScreenOf(xw)->status_active)));
   2884 
   2885     update_status_line(xw, value, -1);
   2886 }
   2887 
   2888 /*
   2889  * If the status-line is inactive (i.e., only the main-display is used),
   2890  * changing the status-type between none/writable has no immediate effect.
   2891  *
   2892  * But if the status-line is active, setting the status-type reinitializes the
   2893  * status-line.
   2894  *
   2895  * Setting the status-type to indicator overrides the DECSASD active-display
   2896  * mode.
   2897  */
   2898 static void
   2899 handle_DECSSDT(XtermWidget xw, int value)
   2900 {
   2901     TRACE(("CASE_DECSSDT - select type of status display: %d (currently %d)\n",
   2902 	   value,
   2903 	   TScreenOf(xw)->status_type));
   2904 
   2905     update_status_line(xw, -1, value);
   2906 }
   2907 
   2908 #else
   2909 #define clear_status_line(xw)	/* nothing */
   2910 #endif /* OPT_STATUS_LINE */
   2911 
   2912 #if OPT_VT52_MODE
   2913 static void
   2914 update_vt52_vt100_settings(void)
   2915 {
   2916     update_autowrap();
   2917     update_reversewrap();
   2918     update_autolinefeed();
   2919     update_appcursor();
   2920     update_appkeypad();
   2921     update_allow132();
   2922 }
   2923 #endif
   2924 
   2925 #define TRACE_GSETS(name) TRACE(("CASE_GSETS%s(%d) = '%c'\n", name, sp->scstype, AsciiOf(c)))
   2926 
   2927 static Boolean
   2928 doparsing(XtermWidget xw, unsigned c, struct ParseState *sp)
   2929 {
   2930     TScreen *screen = TScreenOf(xw);
   2931     int item;
   2932     int count;
   2933     int value;
   2934     int laststate;
   2935     int thischar = -1;
   2936     XTermRect myRect;
   2937 #if OPT_DEC_RECTOPS
   2938     int thispage = 1;
   2939 #endif
   2940 
   2941     if (sp->check_recur) {
   2942 	/* Defer parsing when parser is already running as the parser is not
   2943 	 * safe to reenter.
   2944 	 */
   2945 	deferparsing(c, sp);
   2946 	return True;
   2947     }
   2948     sp->check_recur++;
   2949 
   2950     do {
   2951 #if OPT_WIDE_CHARS
   2952 	int this_is_wide = 0;
   2953 	int is_formatter = 0;
   2954 
   2955 	/*
   2956 	 * Handle zero-width combining characters.  Make it faster by noting
   2957 	 * that according to the Unicode charts, the majority of Western
   2958 	 * character sets do not use this feature.  There are some unassigned
   2959 	 * codes at 0x242, but no zero-width characters until past 0x300.
   2960 	 */
   2961 	if (c >= 0x300
   2962 	    && screen->wide_chars
   2963 	    && CharWidth(screen, c) == 0
   2964 	    && !(is_formatter = (CharacterClass((int) c) == CNTRL))) {
   2965 	    int prev, test;
   2966 	    Boolean used = True;
   2967 	    int use_row;
   2968 	    int use_col;
   2969 
   2970 	    WriteNow();
   2971 	    use_row = (screen->char_was_written
   2972 		       ? screen->last_written_row
   2973 		       : screen->cur_row);
   2974 	    use_col = (screen->char_was_written
   2975 		       ? screen->last_written_col
   2976 		       : screen->cur_col);
   2977 
   2978 	    /*
   2979 	     * Check if the latest data can be added to the base character.
   2980 	     * If there is already a combining character stored for the cell,
   2981 	     * we cannot, since that would change the order.
   2982 	     */
   2983 	    if (screen->normalized_c
   2984 		&& !IsCellCombined(screen, use_row, use_col)) {
   2985 		prev = (int) XTERM_CELL(use_row, use_col);
   2986 		test = do_precomposition(prev, (int) c);
   2987 		TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n",
   2988 		       prev, CharWidth(screen, prev),
   2989 		       (int) c, CharWidth(screen, c),
   2990 		       test, CharWidth(screen, test)));
   2991 	    } else {
   2992 		prev = -1;
   2993 		test = -1;
   2994 	    }
   2995 
   2996 	    /* substitute combined character with precomposed character
   2997 	     * only if it does not change the width of the base character
   2998 	     */
   2999 	    if (test != -1
   3000 		&& CharWidth(screen, test) == CharWidth(screen, prev)) {
   3001 		putXtermCell(screen, use_row, use_col, test);
   3002 	    } else if (screen->char_was_written
   3003 		       || getXtermCell(screen, use_row, use_col) >= ' ') {
   3004 		addXtermCombining(screen, use_row, use_col, c);
   3005 	    } else {
   3006 		/*
   3007 		 * none of the above... we will add the combining character as
   3008 		 * a base character.
   3009 		 */
   3010 		used = False;
   3011 	    }
   3012 
   3013 	    if (used) {
   3014 		if (!screen->scroll_amt)
   3015 		    ScrnUpdate(xw, use_row, use_col, 1, 1, 1);
   3016 		break;
   3017 	    }
   3018 	}
   3019 #endif
   3020 
   3021 	/* Intercept characters for printer controller mode */
   3022 	if (PrinterOf(screen).printer_controlmode == 2) {
   3023 	    if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0)
   3024 		break;
   3025 	}
   3026 
   3027 	/*
   3028 	 * VT52 is a little ugly in the one place it has a parameterized
   3029 	 * control sequence, since the parameter falls after the character
   3030 	 * that denotes the type of sequence.
   3031 	 */
   3032 #if OPT_VT52_MODE
   3033 	if (sp->vt52_cup) {
   3034 	    int row, col;
   3035 	    if (nparam < NPARAM - 1) {
   3036 		SetParam(nparam++, (int) AsciiOf(c) - 32);
   3037 		parms.is_sub[nparam] = 0;
   3038 	    }
   3039 	    if (nparam < 2)
   3040 		break;
   3041 	    sp->vt52_cup = False;
   3042 	    /*
   3043 	     * According to EK-VT5X-OP-001 DECscope User's Guide, if the row
   3044 	     * is out of range, no vertical movement occurs, while if the
   3045 	     * column is out of range, it is set to the rightmost column.
   3046 	     *
   3047 	     * However, DEC 070 (VSRM - VT52 Emulation EL-00070-0A, page A-28)
   3048 	     * differs from that, updating the column only when the parameter
   3049 	     * is in range, i.e., not mentioning the rightmost column.
   3050 	     */
   3051 	    if ((row = GetParam(0)) > screen->max_row)
   3052 		row = screen->cur_row;
   3053 	    if ((col = GetParam(1)) > screen->max_col)
   3054 		col = ((screen->terminal_id < 100)
   3055 		       ? screen->max_col	/* real VT52 */
   3056 		       : screen->cur_col);	/* emulated VT52 */
   3057 	    CursorSet(screen, row, col, xw->flags);
   3058 	    sp->parsestate = vt52_table;
   3059 	    SetParam(0, 0);
   3060 	    SetParam(1, 0);
   3061 	    break;
   3062 	}
   3063 #endif
   3064 
   3065 	laststate = sp->nextstate;
   3066 	if (c == ANSI_DEL
   3067 	    && sp->parsestate == sp->groundtable
   3068 	    && sp->scssize == 96
   3069 	    && sp->scstype != 0) {
   3070 	    /*
   3071 	     * Handle special case of shifts for 96-character sets by checking
   3072 	     * if we have a DEL.  The other special case for SPACE will always
   3073 	     * be printable.
   3074 	     */
   3075 	    sp->nextstate = CASE_PRINT;
   3076 	} else
   3077 #if OPT_WIDE_CHARS
   3078 	if (c > 255) {
   3079 	    /*
   3080 	     * The parsing tables all have 256 entries.  If we're supporting
   3081 	     * wide characters, we handle them by treating them the same as
   3082 	     * printing characters.
   3083 	     */
   3084 	    if (sp->parsestate == sp->groundtable) {
   3085 		sp->nextstate = is_formatter ? CASE_IGNORE : CASE_PRINT;
   3086 	    } else if (sp->parsestate == sos_table) {
   3087 		if ((c & WIDEST_ICHAR) > 255) {
   3088 		    TRACE(("Found code > 255 while in SOS state: %04X\n", c));
   3089 		    c = BAD_ASCII;
   3090 		}
   3091 	    } else {
   3092 		sp->nextstate = CASE_GROUND_STATE;
   3093 	    }
   3094 	} else
   3095 #endif
   3096 	    sp->nextstate = sp->parsestate[c];
   3097 
   3098 #if OPT_BROKEN_OSC
   3099 	/*
   3100 	 * Linux console palette escape sequences start with an OSC, but do
   3101 	 * not terminate correctly.  Some scripts do not check before writing
   3102 	 * them, making xterm appear to hang (it's awaiting a valid string
   3103 	 * terminator).  Just ignore these if we see them - there's no point
   3104 	 * in emulating bad code.
   3105 	 */
   3106 	if (screen->brokenLinuxOSC
   3107 	    && sp->parsestate == sos_table) {
   3108 	    if (sp->string_used && sp->string_area) {
   3109 		switch (sp->string_area[0]) {
   3110 		case 'P':
   3111 		    if (sp->string_used <= 7)
   3112 			break;
   3113 		    /* FALLTHRU */
   3114 		case 'R':
   3115 		    illegal_parse(xw, c, sp);
   3116 		    TRACE(("Reset to ground state (brokenLinuxOSC)\n"));
   3117 		    break;
   3118 		}
   3119 	    }
   3120 	}
   3121 #endif
   3122 
   3123 #if OPT_BROKEN_ST
   3124 	/*
   3125 	 * Before patch #171, carriage control embedded within an OSC string
   3126 	 * would terminate it.  Some (buggy, of course) applications rely on
   3127 	 * this behavior.  Accommodate them by allowing one to compile xterm
   3128 	 * and emulate the old behavior.
   3129 	 */
   3130 	if (screen->brokenStringTerm
   3131 	    && sp->parsestate == sos_table
   3132 	    && c < 32) {
   3133 	    switch (c) {
   3134 	    case ANSI_EOT:	/* FALLTHRU */
   3135 	    case ANSI_BS:	/* FALLTHRU */
   3136 	    case ANSI_HT:	/* FALLTHRU */
   3137 	    case ANSI_LF:	/* FALLTHRU */
   3138 	    case ANSI_VT:	/* FALLTHRU */
   3139 	    case ANSI_FF:	/* FALLTHRU */
   3140 	    case ANSI_CR:	/* FALLTHRU */
   3141 	    case ANSI_SO:	/* FALLTHRU */
   3142 	    case ANSI_SI:	/* FALLTHRU */
   3143 	    case ANSI_XON:	/* FALLTHRU */
   3144 	    case ANSI_CAN:
   3145 		illegal_parse(xw, c, sp);
   3146 		TRACE(("Reset to ground state (brokenStringTerm)\n"));
   3147 		break;
   3148 	    }
   3149 	}
   3150 #endif
   3151 
   3152 #if OPT_C1_PRINT
   3153 	/*
   3154 	 * This is not completely foolproof, but will allow an application
   3155 	 * with values in the C1 range to use them as printable characters,
   3156 	 * provided that they are not intermixed with an escape sequence.
   3157 	 */
   3158 #if OPT_WIDE_CHARS
   3159 	if (!screen->wide_chars)
   3160 #endif
   3161 	    if (screen->c1_printable
   3162 		&& (c >= 128 && c < 256)) {
   3163 		sp->nextstate = (sp->parsestate == esc_table
   3164 				 ? CASE_ESC_IGNORE
   3165 				 : sp->parsestate[160]);
   3166 		TRACE(("allowC1Printable %04X %s ->%s\n",
   3167 		       c, which_table(sp->parsestate),
   3168 		       visibleVTparse(sp->nextstate)));
   3169 	    }
   3170 #endif
   3171 
   3172 #if OPT_WIDE_CHARS
   3173 	/*
   3174 	 * If we have a C1 code and the c1_printable flag is not set, simply
   3175 	 * ignore it when it was translated from UTF-8, unless the parse-state
   3176 	 * tells us that a C1 would be legal.
   3177 	 */
   3178 #if OPT_C1_PRINT
   3179 	if (!screen->c1_printable)
   3180 #endif
   3181 	    if (screen->wide_chars
   3182 		&& (c >= 128 && c < 160)) {
   3183 		if (sp->parsestate != ansi_table)
   3184 		    sp->nextstate = CASE_IGNORE;
   3185 	    }
   3186 
   3187 	/*
   3188 	 * If this character is a different width than the last one, put the
   3189 	 * previous text into the buffer and draw it now.
   3190 	 */
   3191 	this_is_wide = isWide((int) c);
   3192 	if (this_is_wide != sp->last_was_wide) {
   3193 	    WriteNow();
   3194 	}
   3195 #endif
   3196 
   3197 	/*
   3198 	 * Accumulate string for printable text.  This may be 8/16-bit
   3199 	 * characters.
   3200 	 */
   3201 	if (sp->nextstate == CASE_PRINT) {
   3202 	    SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size);
   3203 	    if (new_string == NULL) {
   3204 		xtermWarning("Cannot allocate %lu bytes for printable text\n",
   3205 			     (unsigned long) new_length);
   3206 		break;
   3207 	    }
   3208 	    SafeFree(sp->print_area, sp->print_size);
   3209 #if OPT_VT52_MODE
   3210 	    /*
   3211 	     * Strip output text to 7-bits for VT52.  We should do this for
   3212 	     * VT100 also (which is a 7-bit device), but xterm has been
   3213 	     * doing this for so long we shouldn't change this behavior.
   3214 	     */
   3215 	    if (screen->vtXX_level < 1)
   3216 		c = AsciiOf(c);
   3217 #endif
   3218 	    sp->print_area[sp->print_used++] = (IChar) c;
   3219 	    sp->lastchar = thischar = (int) c;
   3220 #if OPT_WIDE_CHARS
   3221 	    sp->last_was_wide = this_is_wide;
   3222 #endif
   3223 	    if (morePtyData(screen, VTbuffer)) {
   3224 		break;
   3225 	    }
   3226 	}
   3227 
   3228 	if (sp->nextstate == CASE_PRINT
   3229 	    || (laststate == CASE_PRINT && sp->print_used)) {
   3230 	    WriteNow();
   3231 	}
   3232 
   3233 	/*
   3234 	 * Accumulate string for DCS, OSC controls
   3235 	 * The string content should always be 8-bit characters.
   3236 	 *
   3237 	 * APC, PM and SOS are ignored; xterm currently does not use those.
   3238 	 */
   3239 	if (sp->parsestate == sos_table) {
   3240 #if OPT_WIDE_CHARS
   3241 	    /*
   3242 	     * We cannot display codes above 255, but let's try to
   3243 	     * accommodate the application a little by not aborting the
   3244 	     * string.
   3245 	     */
   3246 	    if ((c & WIDEST_ICHAR) > 255) {
   3247 		sp->nextstate = CASE_PRINT;
   3248 		c = BAD_ASCII;
   3249 	    }
   3250 #endif
   3251 	    if (sp->string_mode == ANSI_APC ||
   3252 		sp->string_mode == ANSI_PM ||
   3253 		sp->string_mode == ANSI_SOS) {
   3254 		/* EMPTY */
   3255 	    }
   3256 #if OPT_SIXEL_GRAPHICS
   3257 	    else if (sp->string_args == sa_SIXEL) {
   3258 		/* avoid adding the string-terminator */
   3259 		if (sos_table[CharOf(c)] == CASE_IGNORE)
   3260 		    parse_sixel_char(AsciiOf(c));
   3261 	    }
   3262 #endif
   3263 	    else if (sp->string_skip) {
   3264 		sp->string_used++;
   3265 	    } else if (sp->string_used > screen->strings_max) {
   3266 		sp->string_skip = True;
   3267 		sp->string_used++;
   3268 		FreeAndNull(sp->string_area);
   3269 		sp->string_size = 0;
   3270 	    } else {
   3271 		Boolean utf8Title;
   3272 
   3273 		SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size);
   3274 		if (new_string == NULL) {
   3275 		    xtermWarning("Cannot allocate %lu bytes for string mode %#02x\n",
   3276 				 (unsigned long) new_length, sp->string_mode);
   3277 		    break;
   3278 		}
   3279 		SafeFree(sp->string_area, sp->string_size);
   3280 
   3281 		/*
   3282 		 * Provide for special case where xterm allows an OSC string to
   3283 		 * contain 8-bit data.  Otherwise, ECMA-48 section 9 recommends
   3284 		 * parsing controls with a 7-bit table, precluding the use of
   3285 		 * 8-bit data.
   3286 		 */
   3287 #if OPT_WIDE_CHARS
   3288 		utf8Title = (sp->string_mode == ANSI_OSC
   3289 			     && IsSetUtf8Title(xw)
   3290 			     && (sp->string_used >= 2)
   3291 			     && (sp->string_area[0] == '0'
   3292 				 || sp->string_area[0] == '2')
   3293 			     && sp->string_area[1] == ';');
   3294 #else
   3295 		utf8Title = False;
   3296 #endif
   3297 
   3298 		/*
   3299 		 * ReGIS and SIXEL data can be detected by skipping over (only)
   3300 		 * parameters to the first non-parameter character and
   3301 		 * inspecting it.  Since both are DCS, we can also ignore OSC.
   3302 		 */
   3303 		sp->string_area[(sp->string_used)++] = (utf8Title
   3304 							? CharOf(c)
   3305 							: AsciiOf(c));
   3306 		if (sp->string_args < sa_LAST) {
   3307 		    switch (c) {
   3308 		    case ':':
   3309 		    case ';':
   3310 		    case '0':
   3311 		    case '1':
   3312 		    case '2':
   3313 		    case '3':
   3314 		    case '4':
   3315 		    case '5':
   3316 		    case '6':
   3317 		    case '7':
   3318 		    case '8':
   3319 		    case '9':
   3320 			break;
   3321 		    case 'p':
   3322 			sp->string_args = sa_REGIS;
   3323 			break;
   3324 		    case 'q':
   3325 			begin_sixel(xw, sp);
   3326 			break;
   3327 		    default:
   3328 			sp->string_args = sa_LAST;
   3329 			break;
   3330 		    }
   3331 		}
   3332 	    }
   3333 	} else if (sp->parsestate != esc_table) {
   3334 	    /* if we were accumulating, we're not any more */
   3335 	    sp->string_mode = 0;
   3336 	    sp->string_used = 0;
   3337 	}
   3338 
   3339 	DumpParams();
   3340 	TRACE(("parse %04X -> %s %s (used=%lu)\n",
   3341 	       c, visibleVTparse(sp->nextstate),
   3342 	       which_table(sp->parsestate),
   3343 	       (unsigned long) sp->string_used));
   3344 
   3345 	/*
   3346 	 * If the parameter list has subparameters (tokens separated by ":")
   3347 	 * reject any controls that do not accept subparameters.
   3348 	 */
   3349 	if (parms.has_subparams) {
   3350 	    switch (sp->nextstate) {
   3351 	    case CASE_GROUND_STATE:
   3352 	    case CASE_CSI_IGNORE:
   3353 	    case CASE_SUB:
   3354 		/* FALLTHRU */
   3355 
   3356 	    case CASE_ESC_DIGIT:
   3357 	    case CASE_ESC_SEMI:
   3358 	    case CASE_ESC_COLON:
   3359 		/* these states are required to parse parameter lists */
   3360 		break;
   3361 
   3362 	    case CASE_SGR:
   3363 		TRACE(("...possible subparam usage\n"));
   3364 		break;
   3365 
   3366 	    case CASE_CSI_DEC_DOLLAR_STATE:
   3367 	    case CASE_CSI_DOLLAR_STATE:
   3368 	    case CASE_CSI_HASH_STATE:
   3369 	    case CASE_CSI_EX_STATE:
   3370 	    case CASE_CSI_QUOTE_STATE:
   3371 	    case CASE_CSI_SPACE_STATE:
   3372 	    case CASE_CSI_STAR_STATE:
   3373 	    case CASE_CSI_TICK_STATE:
   3374 	    case CASE_DEC2_STATE:
   3375 	    case CASE_DEC3_STATE:
   3376 	    case CASE_DEC_STATE:
   3377 		/* use this branch when we do not yet have the final character */
   3378 		TRACE(("...unexpected subparam usage\n"));
   3379 		InitParams();
   3380 		sp->nextstate = CASE_CSI_IGNORE;
   3381 		break;
   3382 
   3383 	    default:
   3384 		/* use this branch for cases where we have the final character
   3385 		 * in the table that processed the parameter list.
   3386 		 */
   3387 		TRACE(("...unexpected subparam usage\n"));
   3388 		ResetState(sp);
   3389 		break;
   3390 	    }
   3391 	}
   3392 
   3393 	if (xw->work.palette_changed) {
   3394 	    repaintWhenPaletteChanged(xw, sp);
   3395 	}
   3396 #if OPT_STATUS_LINE
   3397 	/*
   3398 	 * If we are currently writing to the status-line, ignore controls that
   3399 	 * apply only to the full screen, or which use features which we will
   3400 	 * not support in the status-line.
   3401 	 */
   3402 	if (IsStatusShown(screen) && (screen)->status_active) {
   3403 	    switch (sp->nextstate) {
   3404 	    case CASE_DECDHL:
   3405 	    case CASE_DECSWL:
   3406 	    case CASE_DECDWL:
   3407 	    case CASE_CUU:
   3408 	    case CASE_CUD:
   3409 	    case CASE_VPA:
   3410 	    case CASE_VPR:
   3411 	    case CASE_ED:
   3412 	    case CASE_TRACK_MOUSE:
   3413 	    case CASE_DECSTBM:
   3414 	    case CASE_DECALN:
   3415 	    case CASE_GRAPHICS_ATTRIBUTES:
   3416 	    case CASE_SUB:
   3417 	    case CASE_SPA:
   3418 	    case CASE_EPA:
   3419 	    case CASE_SU:
   3420 	    case CASE_IND:
   3421 	    case CASE_CPL:
   3422 	    case CASE_CNL:
   3423 	    case CASE_NEL:
   3424 	    case CASE_RI:
   3425 #if OPT_DEC_LOCATOR
   3426 	    case CASE_DECEFR:
   3427 	    case CASE_DECELR:
   3428 	    case CASE_DECSLE:
   3429 	    case CASE_DECRQLP:
   3430 #endif
   3431 #if OPT_DEC_RECTOPS
   3432 	    case CASE_DECRQCRA:
   3433 	    case CASE_DECCRA:
   3434 	    case CASE_DECERA:
   3435 	    case CASE_DECFRA:
   3436 	    case CASE_DECSERA:
   3437 	    case CASE_DECSACE:
   3438 	    case CASE_DECCARA:
   3439 	    case CASE_DECRARA:
   3440 #endif
   3441 		ResetState(sp);
   3442 		sp->nextstate = -1;	/* not a legal state */
   3443 		break;
   3444 	    }
   3445 	}
   3446 #endif
   3447 
   3448 	switch (sp->nextstate) {
   3449 	case CASE_PRINT:
   3450 	    TRACE(("CASE_PRINT - printable characters\n"));
   3451 	    break;
   3452 
   3453 	case CASE_GROUND_STATE:
   3454 	    TRACE(("CASE_GROUND_STATE - exit ignore mode\n"));
   3455 	    ResetState(sp);
   3456 	    break;
   3457 
   3458 	case CASE_IGNORE:
   3459 	    TRACE(("CASE_IGNORE - Ignore character %02X\n", c));
   3460 	    break;
   3461 
   3462 	case CASE_SUB:
   3463 	    TRACE(("CASE_SUB - substitute/show error\n"));
   3464 	    /*
   3465 	     * ECMA-48 5th edition (June 1991) documents SUB without describing
   3466 	     * its effect.  Earlier editions do not mention it.
   3467 	     *
   3468 	     * DEC's VT100 user guide documents SUB as having the same effect
   3469 	     * as CAN (cancel).  The VT220 reference adds a visible effect
   3470 	     * (display as a reverse "?"), as well as mentioning that device
   3471 	     * control sequences also are cancelled.  DEC 070 comments that a
   3472 	     * "half-tone blotch" is used with VT100, etc.
   3473 	     *
   3474 	     * None of that applies to VT52.
   3475 	     */
   3476 	    if (screen->terminal_id >= 100) {
   3477 		IChar effect = (
   3478 #if OPT_WIDE_CHARS
   3479 				   (screen->terminal_id > 200) ? 0x2426 : 0x2592
   3480 #else
   3481 				   2
   3482 #endif
   3483 		);
   3484 		dotext(xw,
   3485 		       screen->gsets[(int) (screen->curgl)],
   3486 		       &effect, 1);
   3487 	    }
   3488 	    ResetState(sp);
   3489 	    break;
   3490 
   3491 	case CASE_ENQ:
   3492 	    TRACE(("CASE_ENQ - answerback\n"));
   3493 	    if (((xw->keyboard.flags & MODE_SRM) == 0)
   3494 		? (sp->check_recur == 0)
   3495 		: (sp->check_recur <= 1)) {
   3496 		for (count = 0; screen->answer_back[count] != 0; count++)
   3497 		    unparseputc(xw, screen->answer_back[count]);
   3498 		unparse_end(xw);
   3499 	    }
   3500 	    break;
   3501 
   3502 	case CASE_BELL:
   3503 	    TRACE(("CASE_BELL - bell\n"));
   3504 	    if (sp->string_mode == ANSI_OSC) {
   3505 		if (sp->string_area) {
   3506 		    if (sp->string_used)
   3507 			sp->string_area[--(sp->string_used)] = '\0';
   3508 		    if (sp->check_recur <= 1)
   3509 			do_osc(xw, sp->string_area, sp->string_used, (int) c);
   3510 		}
   3511 		ResetState(sp);
   3512 	    } else {
   3513 		/* bell */
   3514 		Bell(xw, XkbBI_TerminalBell, 0);
   3515 	    }
   3516 	    break;
   3517 
   3518 	case CASE_BS:
   3519 	    TRACE(("CASE_BS - backspace\n"));
   3520 	    CursorBack(xw, 1);
   3521 	    break;
   3522 
   3523 	case CASE_CR:
   3524 	    TRACE(("CASE_CR\n"));
   3525 	    CarriageReturn(xw);
   3526 	    break;
   3527 
   3528 	case CASE_ESC:
   3529 	    if_OPT_VT52_MODE(screen, {
   3530 		sp->parsestate = vt52_esc_table;
   3531 		break;
   3532 	    });
   3533 	    sp->parsestate = esc_table;
   3534 	    break;
   3535 
   3536 #if OPT_VT52_MODE
   3537 	case CASE_VT52_CUP:
   3538 	    TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n"));
   3539 	    sp->vt52_cup = True;
   3540 	    ResetState(sp);
   3541 	    break;
   3542 
   3543 	case CASE_VT52_IGNORE:
   3544 	    TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n"));
   3545 	    sp->parsestate = vt52_ignore_table;
   3546 	    break;
   3547 #endif
   3548 
   3549 	case CASE_VMOT:
   3550 	    TRACE(("CASE_VMOT\n"));
   3551 	    /*
   3552 	     * form feed, line feed, vertical tab
   3553 	     */
   3554 	    xtermAutoPrint(xw, c);
   3555 	    xtermIndex(xw, 1);
   3556 	    if (xw->flags & LINEFEED)
   3557 		CarriageReturn(xw);
   3558 	    else if (screen->jumpscroll && !screen->fastscroll)
   3559 		do_xevents(xw);
   3560 	    break;
   3561 
   3562 	case CASE_CBT:
   3563 	    TRACE(("CASE_CBT\n"));
   3564 	    /* cursor backward tabulation */
   3565 	    count = one_if_default(0);
   3566 	    while ((count-- > 0)
   3567 		   && (TabToPrevStop(xw))) ;
   3568 	    ResetState(sp);
   3569 	    break;
   3570 
   3571 	case CASE_CHT:
   3572 	    TRACE(("CASE_CHT\n"));
   3573 	    /* cursor forward tabulation */
   3574 	    count = one_if_default(0);
   3575 	    while ((count-- > 0)
   3576 		   && (TabToNextStop(xw))) ;
   3577 	    ResetState(sp);
   3578 	    break;
   3579 
   3580 	case CASE_TAB:
   3581 	    /* tab */
   3582 	    TabToNextStop(xw);
   3583 	    break;
   3584 
   3585 	case CASE_SI:
   3586 	    screen->curgl = 0;
   3587 	    if_OPT_VT52_MODE(screen, {
   3588 		ResetState(sp);
   3589 	    });
   3590 	    break;
   3591 
   3592 	case CASE_SO:
   3593 	    screen->curgl = 1;
   3594 	    if_OPT_VT52_MODE(screen, {
   3595 		ResetState(sp);
   3596 	    });
   3597 	    break;
   3598 
   3599 	case CASE_DECDHL:
   3600 	    TRACE(("CASE_DECDHL - double-height line: %s\n",
   3601 		   (AsciiOf(c) == '3') ? "top" : "bottom"));
   3602 	    xterm_DECDHL(xw, AsciiOf(c) == '3');
   3603 	    ResetState(sp);
   3604 	    break;
   3605 
   3606 	case CASE_DECSWL:
   3607 	    TRACE(("CASE_DECSWL - single-width line\n"));
   3608 	    xterm_DECSWL(xw);
   3609 	    ResetState(sp);
   3610 	    break;
   3611 
   3612 	case CASE_DECDWL:
   3613 	    TRACE(("CASE_DECDWL - double-width line\n"));
   3614 	    xterm_DECDWL(xw);
   3615 	    ResetState(sp);
   3616 	    break;
   3617 
   3618 	case CASE_SCR_STATE:
   3619 	    /* enter scr state */
   3620 	    sp->parsestate = scrtable;
   3621 	    break;
   3622 
   3623 	case CASE_SCS0_STATE:
   3624 	    /* enter scs state 0 */
   3625 	    select_charset(sp, 0, 94);
   3626 	    break;
   3627 
   3628 	case CASE_SCS1_STATE:
   3629 	    /* enter scs state 1 */
   3630 	    select_charset(sp, 1, 94);
   3631 	    break;
   3632 
   3633 	case CASE_SCS2_STATE:
   3634 	    /* enter scs state 2 */
   3635 	    select_charset(sp, 2, 94);
   3636 	    break;
   3637 
   3638 	case CASE_SCS3_STATE:
   3639 	    /* enter scs state 3 */
   3640 	    select_charset(sp, 3, 94);
   3641 	    break;
   3642 
   3643 	case CASE_SCS1A_STATE:
   3644 	    /* enter scs state 1 */
   3645 	    select_charset(sp, 1, 96);
   3646 	    break;
   3647 
   3648 	case CASE_SCS2A_STATE:
   3649 	    /* enter scs state 2 */
   3650 	    select_charset(sp, 2, 96);
   3651 	    break;
   3652 
   3653 	case CASE_SCS3A_STATE:
   3654 	    /* enter scs state 3 */
   3655 	    select_charset(sp, 3, 96);
   3656 	    break;
   3657 
   3658 	case CASE_ESC_IGNORE:
   3659 	    /* unknown escape sequence */
   3660 	    sp->parsestate = eigtable;
   3661 	    break;
   3662 
   3663 	case CASE_ESC_DIGIT:
   3664 	    /* digit in csi or dec mode */
   3665 	    if (nparam > 0) {
   3666 		value = zero_if_default(nparam - 1);
   3667 		SetParam(nparam - 1, (10 * value) + (int) (AsciiOf(c) - '0'));
   3668 		if (GetParam(nparam - 1) > MAX_I_PARAM)
   3669 		    SetParam(nparam - 1, MAX_I_PARAM);
   3670 		if (sp->parsestate == csi_table)
   3671 		    sp->parsestate = csi2_table;
   3672 	    }
   3673 	    break;
   3674 
   3675 	case CASE_ESC_SEMI:
   3676 	    /* semicolon in csi or dec mode */
   3677 	    if (nparam < NPARAM) {
   3678 		parms.is_sub[nparam] = 0;
   3679 		SetParam(nparam++, DEFAULT);
   3680 	    }
   3681 	    if (sp->parsestate == csi_table)
   3682 		sp->parsestate = csi2_table;
   3683 	    break;
   3684 
   3685 	    /*
   3686 	     * A _few_ commands accept colon-separated subparameters.
   3687 	     * Mark the parameter list so that we can exclude (most) bogus
   3688 	     * commands with simple/fast checks.
   3689 	     */
   3690 	case CASE_ESC_COLON:
   3691 	    if (nparam < NPARAM) {
   3692 		parms.has_subparams = 1;
   3693 		if (nparam == 0) {
   3694 		    parms.is_sub[nparam] = 1;
   3695 		    SetParam(nparam++, DEFAULT);
   3696 		} else if (parms.is_sub[nparam - 1] == 0) {
   3697 		    parms.is_sub[nparam - 1] = 1;
   3698 		    parms.is_sub[nparam] = 2;
   3699 		    parms.params[nparam] = 0;
   3700 		    ++nparam;
   3701 		} else {
   3702 		    parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1];
   3703 		    parms.params[nparam] = 0;
   3704 		    ++nparam;
   3705 		}
   3706 	    }
   3707 	    break;
   3708 
   3709 	case CASE_DEC_STATE:
   3710 	    /* enter dec mode */
   3711 	    sp->parsestate = dec_table;
   3712 	    break;
   3713 
   3714 	case CASE_DEC2_STATE:
   3715 	    /* enter dec2 mode */
   3716 	    sp->parsestate = dec2_table;
   3717 	    break;
   3718 
   3719 	case CASE_DEC3_STATE:
   3720 	    /* enter dec3 mode */
   3721 	    sp->parsestate = dec3_table;
   3722 	    break;
   3723 
   3724 	case CASE_ICH:
   3725 	    TRACE(("CASE_ICH - insert char\n"));
   3726 	    InsertChar(xw, (unsigned) one_if_default(0));
   3727 	    ResetState(sp);
   3728 	    break;
   3729 
   3730 	case CASE_CUU:
   3731 	    TRACE(("CASE_CUU - cursor up\n"));
   3732 	    CursorUp(screen, one_if_default(0));
   3733 	    ResetState(sp);
   3734 	    break;
   3735 
   3736 	case CASE_CUD:
   3737 	    TRACE(("CASE_CUD - cursor down\n"));
   3738 	    CursorDown(screen, one_if_default(0));
   3739 	    ResetState(sp);
   3740 	    break;
   3741 
   3742 	case CASE_CUF:
   3743 	    TRACE(("CASE_CUF - cursor forward\n"));
   3744 	    CursorForward(xw, one_if_default(0));
   3745 	    ResetState(sp);
   3746 	    break;
   3747 
   3748 	case CASE_CUB:
   3749 	    TRACE(("CASE_CUB - cursor backward\n"));
   3750 	    CursorBack(xw, one_if_default(0));
   3751 	    ResetState(sp);
   3752 	    break;
   3753 
   3754 	case CASE_CUP:
   3755 	    TRACE(("CASE_CUP - cursor position\n"));
   3756 	    if_OPT_XMC_GLITCH(screen, {
   3757 		Jump_XMC(xw);
   3758 	    });
   3759 	    CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags);
   3760 	    ResetState(sp);
   3761 	    break;
   3762 
   3763 	case CASE_VPA:
   3764 	    TRACE(("CASE_VPA - vertical position absolute\n"));
   3765 	    CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags);
   3766 	    ResetState(sp);
   3767 	    break;
   3768 
   3769 	case CASE_HPA:
   3770 	    TRACE(("CASE_HPA - horizontal position absolute\n"));
   3771 	    CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags);
   3772 	    ResetState(sp);
   3773 	    break;
   3774 
   3775 	case CASE_VPR:
   3776 	    TRACE(("CASE_VPR - vertical position relative\n"));
   3777 	    CursorSet(screen,
   3778 		      CursorRow(xw) + one_if_default(0),
   3779 		      CursorCol(xw),
   3780 		      xw->flags);
   3781 	    ResetState(sp);
   3782 	    break;
   3783 
   3784 	case CASE_HPR:
   3785 	    TRACE(("CASE_HPR - horizontal position relative\n"));
   3786 	    CursorSet(screen,
   3787 		      CursorRow(xw),
   3788 		      CursorCol(xw) + one_if_default(0),
   3789 		      xw->flags);
   3790 	    ResetState(sp);
   3791 	    break;
   3792 
   3793 	case CASE_HP_BUGGY_LL:
   3794 	    TRACE(("CASE_HP_BUGGY_LL\n"));
   3795 	    /* Some HP-UX applications have the bug that they
   3796 	       assume ESC F goes to the lower left corner of
   3797 	       the screen, regardless of what terminfo says. */
   3798 	    if (screen->hp_ll_bc)
   3799 		CursorSet(screen, screen->max_row, 0, xw->flags);
   3800 	    ResetState(sp);
   3801 	    break;
   3802 
   3803 	case CASE_ED:
   3804 	    TRACE(("CASE_ED - erase display\n"));
   3805 	    do_cd_xtra_scroll(xw, zero_if_default(0));
   3806 	    do_erase_display(xw, zero_if_default(0), OFF_PROTECT);
   3807 	    ResetState(sp);
   3808 	    break;
   3809 
   3810 	case CASE_EL:
   3811 	    TRACE(("CASE_EL - erase line\n"));
   3812 	    do_erase_line(xw, zero_if_default(0), OFF_PROTECT);
   3813 	    ResetState(sp);
   3814 	    break;
   3815 
   3816 	case CASE_ECH:
   3817 	    TRACE(("CASE_ECH - erase char\n"));
   3818 	    /* ECH */
   3819 	    do_erase_char(xw, one_if_default(0), OFF_PROTECT);
   3820 	    ResetState(sp);
   3821 	    break;
   3822 
   3823 	case CASE_IL:
   3824 	    TRACE(("CASE_IL - insert line\n"));
   3825 	    InsertLine(xw, one_if_default(0));
   3826 	    ResetState(sp);
   3827 	    break;
   3828 
   3829 	case CASE_DL:
   3830 	    TRACE(("CASE_DL - delete line\n"));
   3831 	    DeleteLine(xw, one_if_default(0), True);
   3832 	    ResetState(sp);
   3833 	    break;
   3834 
   3835 	case CASE_DCH:
   3836 	    TRACE(("CASE_DCH - delete char\n"));
   3837 	    DeleteChar(xw, (unsigned) one_if_default(0));
   3838 	    ResetState(sp);
   3839 	    break;
   3840 
   3841 	case CASE_TRACK_MOUSE:
   3842 	    /*
   3843 	     * A single parameter other than zero is always scroll-down.
   3844 	     * A zero-parameter is used to reset the mouse mode, and is
   3845 	     * not useful for scrolling anyway.
   3846 	     */
   3847 	    if (nparam > 1 || GetParam(0) == 0) {
   3848 		CELL start;
   3849 
   3850 		TRACE(("CASE_TRACK_MOUSE\n"));
   3851 		/* Track mouse as long as in window and between
   3852 		 * specified rows
   3853 		 */
   3854 		start.row = one_if_default(2) - 1;
   3855 		start.col = GetParam(1) - 1;
   3856 		TrackMouse(xw,
   3857 			   GetParam(0),
   3858 			   &start,
   3859 			   GetParam(3) - 1, GetParam(4) - 2);
   3860 	    } else {
   3861 		TRACE(("CASE_SD - scroll down\n"));
   3862 		/* SD */
   3863 		RevScroll(xw, one_if_default(0));
   3864 		do_xevents(xw);
   3865 	    }
   3866 	    ResetState(sp);
   3867 	    break;
   3868 
   3869 	case CASE_SD:
   3870 	    /*
   3871 	     * Cater to ECMA-48's typographical error...
   3872 	     */
   3873 	    TRACE(("CASE_SD - scroll down\n"));
   3874 	    RevScroll(xw, one_if_default(0));
   3875 	    do_xevents(xw);
   3876 	    ResetState(sp);
   3877 	    break;
   3878 
   3879 	case CASE_DECID:
   3880 	    TRACE(("CASE_DECID\n"));
   3881 	    if_OPT_VT52_MODE(screen, {
   3882 		/*
   3883 		 * If xterm's started in VT52 mode, it's not emulating VT52
   3884 		 * within VT100, etc., so the terminal identifies differently.
   3885 		 */
   3886 		switch (screen->terminal_id) {
   3887 		case 50:
   3888 		    value = 'A';
   3889 		    break;
   3890 		case 52:
   3891 		    value = 'K';
   3892 		    break;
   3893 		case 55:
   3894 		    value = 'C';
   3895 		    break;
   3896 		default:
   3897 		    value = 'Z';
   3898 		    break;
   3899 		}
   3900 		unparseputc(xw, ANSI_ESC);
   3901 		unparseputc(xw, '/');
   3902 		unparseputc(xw, value);
   3903 		unparse_end(xw);
   3904 		ResetState(sp);
   3905 		break;
   3906 	    });
   3907 	    SetParam(0, DEFAULT);	/* Default ID parameter */
   3908 	    /* FALLTHRU */
   3909 	case CASE_DA1:
   3910 	    TRACE(("CASE_DA1\n"));
   3911 	    if (GetParam(0) <= 0) {	/* less than means DEFAULT */
   3912 		count = 0;
   3913 		init_reply(ANSI_CSI);
   3914 		reply.a_pintro = '?';
   3915 
   3916 		/*
   3917 		 * The first parameter corresponds to the highest operating
   3918 		 * level (i.e., service level) of the emulation.  A DEC
   3919 		 * terminal can be setup to respond with a different DA
   3920 		 * response, but there's no control sequence that modifies
   3921 		 * this.  We set it via a resource.
   3922 		 */
   3923 		if (screen->display_da1 < 200) {
   3924 		    switch (screen->display_da1) {
   3925 		    case 132:
   3926 			reply.a_param[count++] = 4;	/* VT132 */
   3927 #if OPT_REGIS_GRAPHICS
   3928 			reply.a_param[count++] = 6;	/* no STP, AVO, GPO (ReGIS) */
   3929 #else
   3930 			reply.a_param[count++] = 2;	/* no STP, AVO, no GPO (ReGIS) */
   3931 #endif
   3932 			break;
   3933 		    case 131:
   3934 			reply.a_param[count++] = 7;	/* VT131 */
   3935 			break;
   3936 		    case 125:
   3937 			reply.a_param[count++] = 12;	/* VT125 */
   3938 #if OPT_REGIS_GRAPHICS
   3939 			reply.a_param[count++] = 0 | 2 | 1;	/* no STP, AVO, GPO (ReGIS) */
   3940 #else
   3941 			reply.a_param[count++] = 0 | 2 | 0;	/* no STP, AVO, no GPO (ReGIS) */
   3942 #endif
   3943 			reply.a_param[count++] = 0;	/* no printer */
   3944 			reply.a_param[count++] = XTERM_PATCH;	/* ROM version */
   3945 			break;
   3946 		    case 102:
   3947 			reply.a_param[count++] = 6;	/* VT102 */
   3948 			break;
   3949 		    case 101:
   3950 			reply.a_param[count++] = 1;	/* VT101 */
   3951 			reply.a_param[count++] = 0;	/* no options */
   3952 			break;
   3953 		    default:	/* VT100 */
   3954 			reply.a_param[count++] = 1;	/* VT100 */
   3955 			reply.a_param[count++] = 2;	/* no STP, AVO, no GPO (ReGIS) */
   3956 			break;
   3957 		    }
   3958 		} else {
   3959 		    reply.a_param[count++] = (ParmType) (60
   3960 							 + screen->display_da1
   3961 							 / 100);
   3962 		    reply.a_param[count++] = 1;		/* 132-columns */
   3963 		    reply.a_param[count++] = 2;		/* printer */
   3964 #if OPT_REGIS_GRAPHICS
   3965 		    if (optRegisGraphics(screen)) {
   3966 			reply.a_param[count++] = 3;	/* ReGIS graphics */
   3967 		    }
   3968 #endif
   3969 #if OPT_SIXEL_GRAPHICS
   3970 		    if (optSixelGraphics(screen)) {
   3971 			reply.a_param[count++] = 4;	/* sixel graphics */
   3972 		    }
   3973 #endif
   3974 		    reply.a_param[count++] = 6;		/* selective-erase */
   3975 #if OPT_SUNPC_KBD
   3976 		    if (xw->keyboard.type == keyboardIsVT220)
   3977 #endif
   3978 			reply.a_param[count++] = 8;	/* user-defined-keys */
   3979 		    reply.a_param[count++] = 9;		/* national replacement charsets */
   3980 		    reply.a_param[count++] = 15;	/* technical characters */
   3981 		    reply.a_param[count++] = 16;	/* locator port */
   3982 		    if (screen->display_da1 >= 400) {
   3983 			reply.a_param[count++] = 17;	/* terminal state interrogation */
   3984 			reply.a_param[count++] = 18;	/* windowing extension */
   3985 			reply.a_param[count++] = 21;	/* horizontal scrolling */
   3986 		    }
   3987 		    if_OPT_ISO_COLORS(screen, {
   3988 			reply.a_param[count++] = 22;	/* ANSI color, VT525 */
   3989 		    });
   3990 		    reply.a_param[count++] = 28;	/* rectangular editing */
   3991 #if OPT_DEC_LOCATOR
   3992 		    reply.a_param[count++] = 29;	/* ANSI text locator */
   3993 #endif
   3994 		}
   3995 		reply.a_nparam = (ParmType) count;
   3996 		reply.a_final = 'c';
   3997 		unparseseq(xw, &reply);
   3998 	    }
   3999 	    ResetState(sp);
   4000 	    break;
   4001 
   4002 	case CASE_DA2:
   4003 	    TRACE(("CASE_DA2\n"));
   4004 	    if (GetParam(0) <= 0) {	/* less than means DEFAULT */
   4005 		count = 0;
   4006 		init_reply(ANSI_CSI);
   4007 		reply.a_pintro = '>';
   4008 
   4009 		if (screen->terminal_id >= 200) {
   4010 		    switch (screen->terminal_id) {
   4011 		    case 220:
   4012 		    default:
   4013 			reply.a_param[count++] = 1;	/* VT220 */
   4014 			break;
   4015 		    case 240:
   4016 		    case 241:
   4017 			/* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */
   4018 			reply.a_param[count++] = 2;	/* VT240 */
   4019 			break;
   4020 		    case 320:
   4021 			/* http://www.vt100.net/docs/vt320-uu/appendixe.html */
   4022 			reply.a_param[count++] = 24;	/* VT320 */
   4023 			break;
   4024 		    case 330:
   4025 			reply.a_param[count++] = 18;	/* VT330 */
   4026 			break;
   4027 		    case 340:
   4028 			reply.a_param[count++] = 19;	/* VT340 */
   4029 			break;
   4030 		    case 382:
   4031 			reply.a_param[count++] = 32;	/* VT382 */
   4032 			break;
   4033 		    case 420:
   4034 			reply.a_param[count++] = 41;	/* VT420 */
   4035 			break;
   4036 		    case 510:
   4037 			/* http://www.vt100.net/docs/vt510-rm/DA2 */
   4038 			reply.a_param[count++] = 61;	/* VT510 */
   4039 			break;
   4040 		    case 520:
   4041 			reply.a_param[count++] = 64;	/* VT520 */
   4042 			break;
   4043 		    case 525:
   4044 			reply.a_param[count++] = 65;	/* VT525 */
   4045 			break;
   4046 		    }
   4047 		} else {
   4048 		    reply.a_param[count++] = 0;		/* VT100 (nonstandard) */
   4049 		}
   4050 		reply.a_param[count++] = XTERM_PATCH;	/* Version */
   4051 		reply.a_param[count++] = 0;	/* options (none) */
   4052 		reply.a_nparam = (ParmType) count;
   4053 		reply.a_final = 'c';
   4054 		unparseseq(xw, &reply);
   4055 	    }
   4056 	    ResetState(sp);
   4057 	    break;
   4058 
   4059 	case CASE_DECRPTUI:
   4060 	    TRACE(("CASE_DECRPTUI\n"));
   4061 	    if ((screen->vtXX_level >= 4)
   4062 		&& (GetParam(0) <= 0)) {	/* less than means DEFAULT */
   4063 		unparseputc1(xw, ANSI_DCS);
   4064 		unparseputc(xw, '!');
   4065 		unparseputc(xw, '|');
   4066 		/* report the "terminal unit id" as 4 pairs of hexadecimal
   4067 		 * digits -- meaningless for a terminal emulator, but some
   4068 		 * host may care about the format.
   4069 		 */
   4070 		for (count = 0; count < 8; ++count) {
   4071 		    unparseputc(xw, '0');
   4072 		}
   4073 		unparseputc1(xw, ANSI_ST);
   4074 		unparse_end(xw);
   4075 	    }
   4076 	    ResetState(sp);
   4077 	    break;
   4078 
   4079 	case CASE_TBC:
   4080 	    TRACE(("CASE_TBC - tab clear\n"));
   4081 	    if ((value = GetParam(0)) <= 0)	/* less than means default */
   4082 		TabClear(xw->tabs, screen->cur_col);
   4083 	    else if (value == 3)
   4084 		TabZonk(xw->tabs);
   4085 	    ResetState(sp);
   4086 	    break;
   4087 
   4088 	case CASE_SET:
   4089 	    TRACE(("CASE_SET - set mode\n"));
   4090 	    ansi_modes(xw, bitset);
   4091 	    ResetState(sp);
   4092 	    break;
   4093 
   4094 	case CASE_RST:
   4095 	    TRACE(("CASE_RST - reset mode\n"));
   4096 	    ansi_modes(xw, bitclr);
   4097 	    ResetState(sp);
   4098 	    break;
   4099 
   4100 	case CASE_SGR:
   4101 	    for (item = 0; item < nparam; ++item) {
   4102 		int op = GetParam(item);
   4103 		int skip;
   4104 
   4105 		if_OPT_XMC_GLITCH(screen, {
   4106 		    Mark_XMC(xw, op);
   4107 		});
   4108 		TRACE(("CASE_SGR %d\n", op));
   4109 
   4110 		/*
   4111 		 * Only SGR 38/48 accept subparameters, and in those cases
   4112 		 * the values will not be seen at this point.
   4113 		 */
   4114 		if ((skip = param_has_subparams(item)) != 0) {
   4115 		    switch (op) {
   4116 		    case 38:
   4117 			/* FALLTHRU */
   4118 		    case 48:
   4119 			if_OPT_ISO_COLORS(screen, {
   4120 			    break;
   4121 			});
   4122 			/* FALLTHRU */
   4123 		    default:
   4124 			TRACE(("...unexpected subparameter in SGR\n"));
   4125 			item += skip;	/* ignore this */
   4126 			op = 9999;	/* will never use this, anyway */
   4127 			break;
   4128 		    }
   4129 		}
   4130 
   4131 		switch (op) {
   4132 		case DEFAULT:
   4133 		    /* FALLTHRU */
   4134 		case 0:
   4135 		    resetRendition(xw);
   4136 		    if_OPT_ISO_COLORS(screen, {
   4137 			reset_SGR_Colors(xw);
   4138 		    });
   4139 		    break;
   4140 		case 1:	/* Bold                 */
   4141 		    UIntSet(xw->flags, BOLD);
   4142 		    if_OPT_ISO_COLORS(screen, {
   4143 			setExtendedFG(xw);
   4144 		    });
   4145 		    break;
   4146 #if OPT_WIDE_ATTRS
   4147 		case 2:	/* faint, decreased intensity or second colour */
   4148 		    UIntSet(xw->flags, ATR_FAINT);
   4149 		    if_OPT_ISO_COLORS(screen, {
   4150 			setExtendedFG(xw);
   4151 		    });
   4152 		    break;
   4153 		case 3:	/* italicized */
   4154 		    setItalicFont(xw, UseItalicFont(screen));
   4155 		    UIntSet(xw->flags, ATR_ITALIC);
   4156 		    if_OPT_ISO_COLORS(screen, {
   4157 			setExtendedFG(xw);
   4158 		    });
   4159 		    break;
   4160 #endif
   4161 		case 4:	/* Underscore           */
   4162 		    UIntSet(xw->flags, UNDERLINE);
   4163 		    if_OPT_ISO_COLORS(screen, {
   4164 			setExtendedFG(xw);
   4165 		    });
   4166 		    break;
   4167 		case 5:	/* Blink (less than 150 per minute) */
   4168 		    /* FALLTHRU */
   4169 		case 6:	/* Blink (150 per minute, or more) */
   4170 		    UIntSet(xw->flags, BLINK);
   4171 		    StartBlinking(xw);
   4172 		    if_OPT_ISO_COLORS(screen, {
   4173 			setExtendedFG(xw);
   4174 		    });
   4175 		    break;
   4176 		case 7:
   4177 		    UIntSet(xw->flags, INVERSE);
   4178 		    if_OPT_ISO_COLORS(screen, {
   4179 			setExtendedBG(xw);
   4180 		    });
   4181 		    break;
   4182 		case 8:
   4183 		    UIntSet(xw->flags, INVISIBLE);
   4184 		    break;
   4185 #if OPT_WIDE_ATTRS
   4186 		case 9:	/* crossed-out characters */
   4187 		    UIntSet(xw->flags, ATR_STRIKEOUT);
   4188 		    break;
   4189 #endif
   4190 #if OPT_WIDE_ATTRS
   4191 		case 21:	/* doubly-underlined */
   4192 		    UIntSet(xw->flags, ATR_DBL_UNDER);
   4193 		    break;
   4194 #endif
   4195 		case 22:	/* reset 'bold' */
   4196 		    UIntClr(xw->flags, BOLD);
   4197 #if OPT_WIDE_ATTRS
   4198 		    UIntClr(xw->flags, ATR_FAINT);
   4199 #endif
   4200 		    if_OPT_ISO_COLORS(screen, {
   4201 			setExtendedFG(xw);
   4202 		    });
   4203 		    break;
   4204 #if OPT_WIDE_ATTRS
   4205 		case 23:	/* not italicized */
   4206 		    ResetItalics(xw);
   4207 		    if_OPT_ISO_COLORS(screen, {
   4208 			setExtendedFG(xw);
   4209 		    });
   4210 		    break;
   4211 #endif
   4212 		case 24:
   4213 		    UIntClr(xw->flags, UNDERLINE);
   4214 #if OPT_WIDE_ATTRS
   4215 		    UIntClr(xw->flags, ATR_DBL_UNDER);
   4216 #endif
   4217 		    if_OPT_ISO_COLORS(screen, {
   4218 			setExtendedFG(xw);
   4219 		    });
   4220 		    break;
   4221 		case 25:	/* reset 'blink' */
   4222 		    UIntClr(xw->flags, BLINK);
   4223 		    if_OPT_ISO_COLORS(screen, {
   4224 			setExtendedFG(xw);
   4225 		    });
   4226 		    break;
   4227 		case 27:
   4228 		    UIntClr(xw->flags, INVERSE);
   4229 		    if_OPT_ISO_COLORS(screen, {
   4230 			setExtendedBG(xw);
   4231 		    });
   4232 		    break;
   4233 		case 28:
   4234 		    UIntClr(xw->flags, INVISIBLE);
   4235 		    break;
   4236 #if OPT_WIDE_ATTRS
   4237 		case 29:	/* not crossed out */
   4238 		    UIntClr(xw->flags, ATR_STRIKEOUT);
   4239 		    break;
   4240 #endif
   4241 		case 30:
   4242 		    /* FALLTHRU */
   4243 		case 31:
   4244 		    /* FALLTHRU */
   4245 		case 32:
   4246 		    /* FALLTHRU */
   4247 		case 33:
   4248 		    /* FALLTHRU */
   4249 		case 34:
   4250 		    /* FALLTHRU */
   4251 		case 35:
   4252 		    /* FALLTHRU */
   4253 		case 36:
   4254 		    /* FALLTHRU */
   4255 		case 37:
   4256 		    if_OPT_ISO_COLORS(screen, {
   4257 			xw->sgr_foreground = (op - 30);
   4258 			xw->sgr_38_xcolors = False;
   4259 			clrDirectFG(xw->flags);
   4260 			setExtendedFG(xw);
   4261 		    });
   4262 		    break;
   4263 		case 38:
   4264 		    /* This is more complicated than I'd like, but it should
   4265 		     * properly eat all the parameters for unsupported modes.
   4266 		     */
   4267 		    if_OPT_ISO_COLORS(screen, {
   4268 			Boolean extended;
   4269 			if (parse_extended_colors(xw, &value, &item,
   4270 						  &extended)) {
   4271 			    xw->sgr_foreground = value;
   4272 			    xw->sgr_38_xcolors = True;
   4273 			    setDirectFG(xw->flags, extended);
   4274 			    setExtendedFG(xw);
   4275 			}
   4276 		    });
   4277 		    break;
   4278 		case 39:
   4279 		    if_OPT_ISO_COLORS(screen, {
   4280 			reset_SGR_Foreground(xw);
   4281 		    });
   4282 		    break;
   4283 		case 40:
   4284 		    /* FALLTHRU */
   4285 		case 41:
   4286 		    /* FALLTHRU */
   4287 		case 42:
   4288 		    /* FALLTHRU */
   4289 		case 43:
   4290 		    /* FALLTHRU */
   4291 		case 44:
   4292 		    /* FALLTHRU */
   4293 		case 45:
   4294 		    /* FALLTHRU */
   4295 		case 46:
   4296 		    /* FALLTHRU */
   4297 		case 47:
   4298 		    if_OPT_ISO_COLORS(screen, {
   4299 			xw->sgr_background = (op - 40);
   4300 			clrDirectBG(xw->flags);
   4301 			setExtendedBG(xw);
   4302 		    });
   4303 		    break;
   4304 		case 48:
   4305 		    if_OPT_ISO_COLORS(screen, {
   4306 			Boolean extended;
   4307 			if (parse_extended_colors(xw, &value, &item,
   4308 						  &extended)) {
   4309 			    xw->sgr_background = value;
   4310 			    setDirectBG(xw->flags, extended);
   4311 			    setExtendedBG(xw);
   4312 			}
   4313 		    });
   4314 		    break;
   4315 		case 49:
   4316 		    if_OPT_ISO_COLORS(screen, {
   4317 			reset_SGR_Background(xw);
   4318 		    });
   4319 		    break;
   4320 		case 90:
   4321 		    /* FALLTHRU */
   4322 		case 91:
   4323 		    /* FALLTHRU */
   4324 		case 92:
   4325 		    /* FALLTHRU */
   4326 		case 93:
   4327 		    /* FALLTHRU */
   4328 		case 94:
   4329 		    /* FALLTHRU */
   4330 		case 95:
   4331 		    /* FALLTHRU */
   4332 		case 96:
   4333 		    /* FALLTHRU */
   4334 		case 97:
   4335 		    if_OPT_AIX_COLORS(screen, {
   4336 			xw->sgr_foreground = (op - 90 + 8);
   4337 			clrDirectFG(xw->flags);
   4338 			setExtendedFG(xw);
   4339 		    });
   4340 		    break;
   4341 		case 100:
   4342 #if !OPT_AIX_COLORS
   4343 		    if_OPT_ISO_COLORS(screen, {
   4344 			reset_SGR_Foreground(xw);
   4345 			reset_SGR_Background(xw);
   4346 		    });
   4347 		    break;
   4348 #endif
   4349 		case 101:
   4350 		    /* FALLTHRU */
   4351 		case 102:
   4352 		    /* FALLTHRU */
   4353 		case 103:
   4354 		    /* FALLTHRU */
   4355 		case 104:
   4356 		    /* FALLTHRU */
   4357 		case 105:
   4358 		    /* FALLTHRU */
   4359 		case 106:
   4360 		    /* FALLTHRU */
   4361 		case 107:
   4362 		    if_OPT_AIX_COLORS(screen, {
   4363 			xw->sgr_background = (op - 100 + 8);
   4364 			clrDirectBG(xw->flags);
   4365 			setExtendedBG(xw);
   4366 		    });
   4367 		    break;
   4368 		default:
   4369 		    /* later: skip += NPARAM; */
   4370 		    break;
   4371 		}
   4372 	    }
   4373 	    ResetState(sp);
   4374 	    break;
   4375 
   4376 	    /* DSR (except for the '?') is a superset of CPR */
   4377 	case CASE_DSR:
   4378 	    sp->private_function = True;
   4379 
   4380 	    /* FALLTHRU */
   4381 	case CASE_CPR:
   4382 	    TRACE(("CASE_DSR - device status report\n"));
   4383 	    count = 0;
   4384 	    init_reply(ANSI_CSI);
   4385 	    reply.a_pintro = CharOf(sp->private_function ? '?' : 0);
   4386 	    reply.a_final = 'n';
   4387 
   4388 	    switch (GetParam(0)) {
   4389 	    case 5:
   4390 		TRACE(("...request operating status\n"));
   4391 		/* operating status */
   4392 		reply.a_param[count++] = 0;	/* (no malfunction ;-) */
   4393 		break;
   4394 	    case 6:
   4395 		TRACE(("...request %s\n",
   4396 		       (sp->private_function
   4397 			? "DECXCPR"
   4398 			: "CPR")));
   4399 		/* CPR */
   4400 		/* DECXCPR (with page=1) */
   4401 		value = screen->cur_row;
   4402 		if ((xw->flags & ORIGIN) != 0) {
   4403 		    value -= screen->top_marg;
   4404 		}
   4405 		if_STATUS_LINE(screen, {
   4406 		    if ((value -= LastRowNumber(screen)) < 0)
   4407 			value = 0;
   4408 		});
   4409 		reply.a_param[count++] = (ParmType) (value + 1);
   4410 
   4411 		value = (screen->cur_col + 1);
   4412 		if ((xw->flags & ORIGIN) != 0) {
   4413 		    value -= screen->lft_marg;
   4414 		}
   4415 		reply.a_param[count++] = (ParmType) value;
   4416 
   4417 		if (sp->private_function &&
   4418 		    (screen->vtXX_level >= 4 ||
   4419 		     (screen->terminal_id >= 330 &&
   4420 		      screen->vtXX_level >= 3))) {
   4421 		    /* VT330 (not VT320) and VT420 */
   4422 		    reply.a_param[count++] = 1;
   4423 		}
   4424 		reply.a_final = 'R';
   4425 		break;
   4426 	    case 15:
   4427 		TRACE(("...request printer status\n"));
   4428 		if (sp->private_function
   4429 		    && screen->vtXX_level >= 2) {	/* VT220 */
   4430 		    reply.a_param[count++] = 13;	/* no printer detected */
   4431 		}
   4432 		break;
   4433 	    case 25:
   4434 		TRACE(("...request UDK status\n"));
   4435 		if (sp->private_function
   4436 		    && screen->vtXX_level >= 2) {	/* VT220 */
   4437 		    reply.a_param[count++] = 20;	/* UDK always unlocked */
   4438 		}
   4439 		break;
   4440 	    case 26:
   4441 		TRACE(("...request keyboard status\n"));
   4442 		if (sp->private_function
   4443 		    && screen->vtXX_level >= 2) {	/* VT220 */
   4444 		    reply.a_param[count++] = 27;
   4445 		    reply.a_param[count++] = 1;		/* North American */
   4446 		    if (screen->vtXX_level >= 3) {	/* VT320 */
   4447 			reply.a_param[count++] = 0;	/* ready */
   4448 		    }
   4449 		    if (screen->vtXX_level >= 4) {	/* VT420 */
   4450 			reply.a_param[count++] = 0;	/* LK201 */
   4451 		    }
   4452 		}
   4453 		break;
   4454 	    case 55:		/* according to the VT330/VT340 Text Programming Manual */
   4455 		TRACE(("...request locator status\n"));
   4456 		if (sp->private_function
   4457 		    && screen->vtXX_level >= 3) {	/* VT330 */
   4458 #if OPT_DEC_LOCATOR
   4459 		    reply.a_param[count++] = 50;	/* locator ready */
   4460 #else
   4461 		    reply.a_param[count++] = 53;	/* no locator */
   4462 #endif
   4463 		}
   4464 		break;
   4465 	    case 56:
   4466 		TRACE(("...request locator type\n"));
   4467 		if (sp->private_function
   4468 		    && screen->vtXX_level >= 3) {	/* VT330 */
   4469 		    reply.a_param[count++] = 57;
   4470 #if OPT_DEC_LOCATOR
   4471 		    reply.a_param[count++] = 1;		/* mouse */
   4472 #else
   4473 		    reply.a_param[count++] = 0;		/* unknown */
   4474 #endif
   4475 		}
   4476 		break;
   4477 	    case 62:
   4478 		TRACE(("...request DECMSR - macro space\n"));
   4479 		if (sp->private_function
   4480 		    && screen->vtXX_level >= 4) {	/* VT420 */
   4481 		    reply.a_pintro = 0;
   4482 		    reply.a_radix[count] = 16;	/* no data */
   4483 		    reply.a_param[count++] = 0;		/* no space for macros */
   4484 		    reply.a_inters = '*';
   4485 		    reply.a_final = L_CURL;
   4486 		}
   4487 		break;
   4488 	    case 63:
   4489 		TRACE(("...request DECCKSR - memory checksum\n"));
   4490 		/* DECCKSR - Memory checksum */
   4491 		if (sp->private_function
   4492 		    && screen->vtXX_level >= 4) {	/* VT420 */
   4493 		    init_reply(ANSI_DCS);
   4494 		    reply.a_param[count++] = (ParmType) GetParam(1);	/* PID */
   4495 		    reply.a_delim = "!~";	/* delimiter */
   4496 		    reply.a_radix[count] = 16;	/* use hex */
   4497 		    reply.a_param[count++] = 0;		/* no data */
   4498 		}
   4499 		break;
   4500 	    case 75:
   4501 		TRACE(("...request data integrity\n"));
   4502 		if (sp->private_function
   4503 		    && screen->vtXX_level >= 4) {	/* VT420 */
   4504 		    reply.a_param[count++] = 70;	/* no errors */
   4505 		}
   4506 		break;
   4507 	    case 85:
   4508 		TRACE(("...request multi-session configuration\n"));
   4509 		if (sp->private_function
   4510 		    && screen->vtXX_level >= 4) {	/* VT420 */
   4511 		    reply.a_param[count++] = 83;	/* not configured */
   4512 		}
   4513 		break;
   4514 	    default:
   4515 		break;
   4516 	    }
   4517 
   4518 	    if ((reply.a_nparam = (ParmType) count) != 0)
   4519 		unparseseq(xw, &reply);
   4520 
   4521 	    ResetState(sp);
   4522 	    sp->private_function = False;
   4523 	    break;
   4524 
   4525 	case CASE_MC:
   4526 	    TRACE(("CASE_MC - media control\n"));
   4527 	    xtermMediaControl(xw, GetParam(0), False);
   4528 	    ResetState(sp);
   4529 	    break;
   4530 
   4531 	case CASE_DEC_MC:
   4532 	    TRACE(("CASE_DEC_MC - DEC media control\n"));
   4533 	    xtermMediaControl(xw, GetParam(0), True);
   4534 	    ResetState(sp);
   4535 	    break;
   4536 
   4537 	case CASE_HP_MEM_LOCK:
   4538 	    /* FALLTHRU */
   4539 	case CASE_HP_MEM_UNLOCK:
   4540 	    TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK)
   4541 			    ? "CASE_HP_MEM_LOCK"
   4542 			    : "CASE_HP_MEM_UNLOCK")));
   4543 	    if (screen->scroll_amt)
   4544 		FlushScroll(xw);
   4545 	    if (sp->parsestate[c] == CASE_HP_MEM_LOCK)
   4546 		set_tb_margins(screen, screen->cur_row, screen->bot_marg);
   4547 	    else
   4548 		set_tb_margins(screen, 0, screen->bot_marg);
   4549 	    ResetState(sp);
   4550 	    break;
   4551 
   4552 	case CASE_DECSTBM:
   4553 	    TRACE(("CASE_DECSTBM - set scrolling region\n"));
   4554 	    {
   4555 		int top;
   4556 		int bot;
   4557 		top = one_if_default(0);
   4558 		if (nparam < 2 || (bot = GetParam(1)) == DEFAULT
   4559 		    || bot > MaxRows(screen)
   4560 		    || bot == 0)
   4561 		    bot = MaxRows(screen);
   4562 		if (bot > top) {
   4563 		    if (screen->scroll_amt)
   4564 			FlushScroll(xw);
   4565 		    set_tb_margins(screen, top - 1, bot - 1);
   4566 		    CursorSet(screen, 0, 0, xw->flags);
   4567 		}
   4568 		ResetState(sp);
   4569 	    }
   4570 	    break;
   4571 
   4572 	case CASE_DECREQTPARM:
   4573 	    TRACE(("CASE_DECREQTPARM\n"));
   4574 	    if (screen->terminal_id < 200) {	/* VT102 */
   4575 		value = zero_if_default(0);
   4576 		if (value == 0 || value == 1) {
   4577 		    init_reply(ANSI_CSI);
   4578 		    reply.a_nparam = 7;
   4579 		    reply.a_param[0] = (ParmType) (value + 2);
   4580 		    reply.a_param[1] = 1;	/* no parity */
   4581 		    reply.a_param[2] = 1;	/* eight bits */
   4582 		    reply.a_param[3] = 128;	/* transmit 38.4k baud */
   4583 		    reply.a_param[4] = 128;	/* receive 38.4k baud */
   4584 		    reply.a_param[5] = 1;	/* clock multiplier ? */
   4585 		    reply.a_param[6] = 0;	/* STP flags ? */
   4586 		    reply.a_final = 'x';
   4587 		    unparseseq(xw, &reply);
   4588 		}
   4589 	    }
   4590 	    ResetState(sp);
   4591 	    break;
   4592 
   4593 	case CASE_DECSET:
   4594 	    /* DECSET */
   4595 #if OPT_VT52_MODE
   4596 	    if (screen->vtXX_level != 0)
   4597 #endif
   4598 		dpmodes(xw, bitset);
   4599 	    ResetState(sp);
   4600 #if OPT_TEK4014
   4601 	    if (TEK4014_ACTIVE(xw)) {
   4602 		TRACE(("Tek4014 is now active...\n"));
   4603 		if (sp->check_recur)
   4604 		    sp->check_recur--;
   4605 		return False;
   4606 	    }
   4607 #endif
   4608 	    break;
   4609 
   4610 	case CASE_DECRST:
   4611 	    /* DECRST */
   4612 	    dpmodes(xw, bitclr);
   4613 	    init_groundtable(screen, sp);
   4614 	    ResetState(sp);
   4615 	    break;
   4616 
   4617 	case CASE_DECALN:
   4618 	    TRACE(("CASE_DECALN - alignment test\n"));
   4619 	    if (screen->cursor_state)
   4620 		HideCursor(xw);
   4621 	    /*
   4622 	     * DEC STD 070 (see pages D-19 to D-20) does not mention left/right
   4623 	     * margins.  The section is dated March 1985, not updated for the
   4624 	     * VT420 (introduced in 1990).
   4625 	     */
   4626 	    UIntClr(xw->flags, ORIGIN);
   4627 	    screen->do_wrap = False;
   4628 	    resetRendition(xw);
   4629 	    resetMargins(xw);
   4630 	    xterm_ResetDouble(xw);
   4631 	    CursorSet(screen, 0, 0, xw->flags);
   4632 	    xtermParseRect(xw, 0, NULL, &myRect);
   4633 	    ScrnFillRectangle(xw, &myRect, 'E', 0, False);
   4634 	    ResetState(sp);
   4635 	    break;
   4636 
   4637 	case CASE_GSETS5:
   4638 	    if (screen->vtXX_level >= 5) {
   4639 		TRACE_GSETS("5");
   4640 		xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c);
   4641 	    }
   4642 	    ResetState(sp);
   4643 	    break;
   4644 
   4645 	case CASE_GSETS3:
   4646 	    if (screen->vtXX_level >= 3) {
   4647 		TRACE_GSETS("3");
   4648 		xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c);
   4649 	    }
   4650 	    ResetState(sp);
   4651 	    break;
   4652 
   4653 	case CASE_GSETS:
   4654 	    if (strchr("012AB", AsciiOf(c)) != NULL) {
   4655 		TRACE_GSETS("");
   4656 		xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c);
   4657 	    } else if (screen->vtXX_level >= 2) {
   4658 		TRACE_GSETS("");
   4659 		xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c);
   4660 	    }
   4661 	    ResetState(sp);
   4662 	    break;
   4663 
   4664 	case CASE_ANSI_SC:
   4665 	    if (IsLeftRightMode(xw)) {
   4666 		int left;
   4667 		int right;
   4668 
   4669 		TRACE(("CASE_DECSLRM - set left and right margin\n"));
   4670 		left = one_if_default(0);
   4671 		if (nparam < 2 || (right = GetParam(1)) == DEFAULT
   4672 		    || right > MaxCols(screen)
   4673 		    || right == 0)
   4674 		    right = MaxCols(screen);
   4675 		if (right > left) {
   4676 		    set_lr_margins(screen, left - 1, right - 1);
   4677 		    CursorSet(screen, 0, 0, xw->flags);
   4678 		}
   4679 	    } else if (only_default()) {
   4680 		TRACE(("CASE_ANSI_SC - save cursor\n"));
   4681 		CursorSave(xw);
   4682 	    }
   4683 	    ResetState(sp);
   4684 	    break;
   4685 
   4686 	case CASE_DECSC:
   4687 	    TRACE(("CASE_DECSC - save cursor\n"));
   4688 	    CursorSave(xw);
   4689 	    ResetState(sp);
   4690 	    break;
   4691 
   4692 	case CASE_ANSI_RC:
   4693 	    if (!only_default())
   4694 		break;
   4695 	    /* FALLTHRU */
   4696 	case CASE_DECRC:
   4697 	    TRACE(("CASE_%sRC - restore cursor\n",
   4698 		   (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_"));
   4699 	    CursorRestore(xw);
   4700 	    if_OPT_ISO_COLORS(screen, {
   4701 		setExtendedFG(xw);
   4702 	    });
   4703 	    ResetState(sp);
   4704 	    break;
   4705 
   4706 	case CASE_DECKPAM:
   4707 	    TRACE(("CASE_DECKPAM\n"));
   4708 	    xw->keyboard.flags |= MODE_DECKPAM;
   4709 	    update_appkeypad();
   4710 	    ResetState(sp);
   4711 	    break;
   4712 
   4713 	case CASE_DECKPNM:
   4714 	    TRACE(("CASE_DECKPNM\n"));
   4715 	    UIntClr(xw->keyboard.flags, MODE_DECKPAM);
   4716 	    update_appkeypad();
   4717 	    ResetState(sp);
   4718 	    break;
   4719 
   4720 	case CASE_CSI_QUOTE_STATE:
   4721 	    sp->parsestate = csi_quo_table;
   4722 	    break;
   4723 
   4724 #if OPT_BLINK_CURS
   4725 	case CASE_CSI_SPACE_STATE:
   4726 	    sp->parsestate = csi_sp_table;
   4727 	    break;
   4728 
   4729 	case CASE_DECSCUSR:
   4730 	    TRACE(("CASE_DECSCUSR\n"));
   4731 	    {
   4732 		Boolean change;
   4733 		int blinks = screen->cursor_blink_esc;
   4734 		XtCursorShape shapes = screen->cursor_shape;
   4735 
   4736 		HideCursor(xw);
   4737 
   4738 		switch (GetParam(0)) {
   4739 		case DEFAULT:
   4740 		    /* FALLTHRU */
   4741 		case DEFAULT_STYLE:
   4742 		    /* FALLTHRU */
   4743 		case BLINK_BLOCK:
   4744 		    blinks = True;
   4745 		    screen->cursor_shape = CURSOR_BLOCK;
   4746 		    break;
   4747 		case STEADY_BLOCK:
   4748 		    blinks = False;
   4749 		    screen->cursor_shape = CURSOR_BLOCK;
   4750 		    break;
   4751 		case BLINK_UNDERLINE:
   4752 		    blinks = True;
   4753 		    screen->cursor_shape = CURSOR_UNDERLINE;
   4754 		    break;
   4755 		case STEADY_UNDERLINE:
   4756 		    blinks = False;
   4757 		    screen->cursor_shape = CURSOR_UNDERLINE;
   4758 		    break;
   4759 		case BLINK_BAR:
   4760 		    blinks = True;
   4761 		    screen->cursor_shape = CURSOR_BAR;
   4762 		    break;
   4763 		case STEADY_BAR:
   4764 		    blinks = False;
   4765 		    screen->cursor_shape = CURSOR_BAR;
   4766 		    break;
   4767 		}
   4768 		change = (blinks != screen->cursor_blink_esc ||
   4769 			  shapes != screen->cursor_shape);
   4770 		TRACE(("cursor_shape:%d blinks:%d%s\n",
   4771 		       screen->cursor_shape, blinks,
   4772 		       change ? " (changed)" : ""));
   4773 		if (change) {
   4774 		    xtermSetCursorBox(screen);
   4775 		    if (SettableCursorBlink(screen)) {
   4776 			screen->cursor_blink_esc = blinks;
   4777 			UpdateCursorBlink(xw);
   4778 		    }
   4779 		}
   4780 	    }
   4781 	    ResetState(sp);
   4782 	    break;
   4783 #endif
   4784 
   4785 #if OPT_SCROLL_LOCK
   4786 	case CASE_DECLL:
   4787 	    TRACE(("CASE_DECLL\n"));
   4788 	    if (nparam > 0) {
   4789 		for (count = 0; count < nparam; ++count) {
   4790 		    int op = zero_if_default(count);
   4791 		    switch (op) {
   4792 		    case 0:
   4793 		    case DEFAULT:
   4794 			xtermClearLEDs(screen);
   4795 			break;
   4796 		    case 1:
   4797 			/* FALLTHRU */
   4798 		    case 2:
   4799 			/* FALLTHRU */
   4800 		    case 3:
   4801 			xtermShowLED(screen,
   4802 				     (Cardinal) op,
   4803 				     True);
   4804 			break;
   4805 		    case 21:
   4806 			/* FALLTHRU */
   4807 		    case 22:
   4808 			/* FALLTHRU */
   4809 		    case 23:
   4810 			xtermShowLED(screen,
   4811 				     (Cardinal) (op - 20),
   4812 				     True);
   4813 			break;
   4814 		    }
   4815 		}
   4816 	    } else {
   4817 		xtermClearLEDs(screen);
   4818 	    }
   4819 	    ResetState(sp);
   4820 	    break;
   4821 #endif
   4822 
   4823 #if OPT_VT52_MODE
   4824 	case CASE_VT52_FINISH:
   4825 	    TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n",
   4826 		   screen->terminal_id,
   4827 		   screen->vtXX_level));
   4828 	    if (screen->terminal_id >= 100
   4829 		&& screen->vtXX_level == 0) {
   4830 		sp->groundtable =
   4831 		    sp->parsestate = ansi_table;
   4832 		/*
   4833 		 * On restore, the terminal does not recognize DECRQSS for
   4834 		 * DECSCL (per vttest).
   4835 		 */
   4836 		set_vtXX_level(screen, 1);
   4837 		xw->flags = screen->vt52_save_flags;
   4838 		screen->curgl = screen->vt52_save_curgl;
   4839 		screen->curgr = screen->vt52_save_curgr;
   4840 		screen->curss = screen->vt52_save_curss;
   4841 		restoreCharsets(screen, screen->vt52_save_gsets);
   4842 		update_vt52_vt100_settings();
   4843 	    }
   4844 	    break;
   4845 #endif
   4846 
   4847 	case CASE_ANSI_LEVEL_1:
   4848 	    TRACE(("CASE_ANSI_LEVEL_1\n"));
   4849 	    set_ansi_conformance(screen, 1);
   4850 	    ResetState(sp);
   4851 	    break;
   4852 
   4853 	case CASE_ANSI_LEVEL_2:
   4854 	    TRACE(("CASE_ANSI_LEVEL_2\n"));
   4855 	    set_ansi_conformance(screen, 2);
   4856 	    ResetState(sp);
   4857 	    break;
   4858 
   4859 	case CASE_ANSI_LEVEL_3:
   4860 	    TRACE(("CASE_ANSI_LEVEL_3\n"));
   4861 	    set_ansi_conformance(screen, 3);
   4862 	    ResetState(sp);
   4863 	    break;
   4864 
   4865 	case CASE_DECSCL:
   4866 	    TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1)));
   4867 	    /*
   4868 	     * This changes the emulation level, and is not recognized by
   4869 	     * VT100s.  However, a VT220 or above can be set to conformance
   4870 	     * level 1 to act like a VT100.
   4871 	     */
   4872 	    if (screen->terminal_id >= 200) {
   4873 		/*
   4874 		 * Disallow unrecognized parameters, as well as attempts to set
   4875 		 * the operating level higher than the given terminal-id.
   4876 		 */
   4877 		if (GetParam(0) >= 61
   4878 		    && GetParam(0) <= 60 + (screen->terminal_id / 100)) {
   4879 		    int new_vtXX_level = GetParam(0) - 60;
   4880 		    int case_value = zero_if_default(1);
   4881 		    /*
   4882 		     * Note:
   4883 		     *
   4884 		     * The VT300, VT420, VT520 manuals claim that DECSCL does a
   4885 		     * hard reset (RIS).
   4886 		     *
   4887 		     * Both the VT220 manual and DEC STD 070 (which documents
   4888 		     * levels 1-4 in detail) state that it is a soft reset.
   4889 		     *
   4890 		     * Perhaps both sets of manuals are right (unlikely).
   4891 		     * Kermit says it's soft.
   4892 		     */
   4893 		    ReallyReset(xw, False, False);
   4894 		    init_parser(xw, sp);
   4895 		    set_vtXX_level(screen, new_vtXX_level);
   4896 		    if (new_vtXX_level > 1) {
   4897 			switch (case_value) {
   4898 			case 1:
   4899 			    show_8bit_control(False);
   4900 			    break;
   4901 			case 0:
   4902 			case 2:
   4903 			    show_8bit_control(True);
   4904 			    break;
   4905 			}
   4906 		    }
   4907 		}
   4908 	    }
   4909 	    ResetState(sp);
   4910 	    break;
   4911 
   4912 	case CASE_DECSCA:
   4913 	    TRACE(("CASE_DECSCA\n"));
   4914 	    screen->protected_mode = DEC_PROTECT;
   4915 	    if (GetParam(0) <= 0 || GetParam(0) == 2) {
   4916 		UIntClr(xw->flags, PROTECTED);
   4917 		TRACE(("...clear PROTECTED\n"));
   4918 	    } else if (GetParam(0) == 1) {
   4919 		xw->flags |= PROTECTED;
   4920 		TRACE(("...set PROTECTED\n"));
   4921 	    }
   4922 	    ResetState(sp);
   4923 	    break;
   4924 
   4925 	case CASE_DECSED:
   4926 	    TRACE(("CASE_DECSED\n"));
   4927 	    do_erase_display(xw, zero_if_default(0), DEC_PROTECT);
   4928 	    ResetState(sp);
   4929 	    break;
   4930 
   4931 	case CASE_DECSEL:
   4932 	    TRACE(("CASE_DECSEL\n"));
   4933 	    do_erase_line(xw, zero_if_default(0), DEC_PROTECT);
   4934 	    ResetState(sp);
   4935 	    break;
   4936 
   4937 	case CASE_GRAPHICS_ATTRIBUTES:
   4938 #if OPT_GRAPHICS
   4939 	    TRACE(("CASE_GRAPHICS_ATTRIBUTES\n"));
   4940 	    {
   4941 		/* request: item, action, value */
   4942 		/* reply: item, status, value */
   4943 		if (nparam != 3) {
   4944 		    TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam));
   4945 		} else {
   4946 		    int status = 3;	/* assume failure */
   4947 		    int result = 0;
   4948 		    int result2 = 0;
   4949 
   4950 		    TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n",
   4951 			   GetParam(0), GetParam(1), GetParam(2)));
   4952 		    switch (GetParam(0)) {
   4953 		    case 1:	/* color register count */
   4954 			switch (GetParam(1)) {
   4955 			case 1:	/* read */
   4956 			    status = 0;		/* success */
   4957 			    result = (int) get_color_register_count(screen);
   4958 			    break;
   4959 			case 2:	/* reset */
   4960 			    screen->numcolorregisters = 0;
   4961 			    status = 0;		/* success */
   4962 			    result = (int) get_color_register_count(screen);
   4963 			    break;
   4964 			case 3:	/* set */
   4965 			    if (GetParam(2) > 1 &&
   4966 				(unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) {
   4967 				screen->numcolorregisters = GetParam(2);
   4968 				status = 0;	/* success */
   4969 				result = (int) get_color_register_count(screen);
   4970 			    }
   4971 			    break;
   4972 			case 4:	/* read maximum */
   4973 			    status = 0;		/* success */
   4974 			    result = MAX_COLOR_REGISTERS;
   4975 			    break;
   4976 			default:
   4977 			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n",
   4978 				   GetParam(1)));
   4979 			    status = 2;		/* error in Pa */
   4980 			    break;
   4981 			}
   4982 			if (status == 0 && !(optSixelGraphics(screen)
   4983 					     || optRegisGraphics(screen)))
   4984 			    status = 3;
   4985 			break;
   4986 # if OPT_SIXEL_GRAPHICS
   4987 		    case 2:	/* graphics geometry */
   4988 			switch (GetParam(1)) {
   4989 			case 1:	/* read */
   4990 			    TRACE(("Get sixel graphics geometry\n"));
   4991 			    status = 0;		/* success */
   4992 			    result = Min(Width(screen), (int) screen->graphics_max_wide);
   4993 			    result2 = Min(Height(screen), (int) screen->graphics_max_high);
   4994 			    break;
   4995 			case 2:	/* reset */
   4996 			    /* FALLTHRU */
   4997 			case 3:	/* set */
   4998 			    break;
   4999 			case 4:	/* read maximum */
   5000 			    status = 0;		/* success */
   5001 			    result = screen->graphics_max_wide;
   5002 			    result2 = screen->graphics_max_high;
   5003 			    break;
   5004 			default:
   5005 			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n",
   5006 				   GetParam(1)));
   5007 			    status = 2;		/* error in Pa */
   5008 			    break;
   5009 			}
   5010 			if (status == 0 && !optSixelGraphics(screen))
   5011 			    status = 3;
   5012 			break;
   5013 #endif
   5014 # if OPT_REGIS_GRAPHICS
   5015 		    case 3:	/* ReGIS geometry */
   5016 			switch (GetParam(1)) {
   5017 			case 1:	/* read */
   5018 			    status = 0;		/* success */
   5019 			    result = screen->graphics_regis_def_wide;
   5020 			    result2 = screen->graphics_regis_def_high;
   5021 			    break;
   5022 			case 2:	/* reset */
   5023 			    /* FALLTHRU */
   5024 			case 3:	/* set */
   5025 			    /* FALLTHRU */
   5026 			case 4:	/* read maximum */
   5027 			    /* not implemented */
   5028 			    break;
   5029 			default:
   5030 			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n",
   5031 				   GetParam(1)));
   5032 			    status = 2;		/* error in Pa */
   5033 			    break;
   5034 			}
   5035 			if (status == 0 && !optRegisGraphics(screen))
   5036 			    status = 3;
   5037 			break;
   5038 #endif
   5039 		    default:
   5040 			TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n",
   5041 			       GetParam(0)));
   5042 			status = 1;
   5043 			break;
   5044 		    }
   5045 
   5046 		    init_reply(ANSI_CSI);
   5047 		    reply.a_pintro = '?';
   5048 		    count = 0;
   5049 		    reply.a_param[count++] = (ParmType) GetParam(0);
   5050 		    reply.a_param[count++] = (ParmType) status;
   5051 		    if (status == 0) {
   5052 			reply.a_param[count++] = (ParmType) result;
   5053 			if (GetParam(0) >= 2)
   5054 			    reply.a_param[count++] = (ParmType) result2;
   5055 		    }
   5056 		    reply.a_nparam = (ParmType) count;
   5057 		    reply.a_final = 'S';
   5058 		    unparseseq(xw, &reply);
   5059 		}
   5060 	    }
   5061 #endif
   5062 	    ResetState(sp);
   5063 	    break;
   5064 
   5065 	case CASE_ST:
   5066 	    TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n",
   5067 		   (unsigned long) sp->string_used,
   5068 		   sp->string_mode));
   5069 	    ResetState(sp);
   5070 	    if (!sp->string_used && !sp->string_args)
   5071 		break;
   5072 	    if (sp->string_skip) {
   5073 		xtermWarning("Ignoring too-long string (%lu) for mode %#02x\n",
   5074 			     (unsigned long) sp->string_used,
   5075 			     sp->string_mode);
   5076 		sp->string_skip = False;
   5077 		sp->string_used = 0;
   5078 	    } else {
   5079 		if (sp->string_used)
   5080 		    sp->string_area[--(sp->string_used)] = '\0';
   5081 		if (sp->check_recur <= 1) {
   5082 		    switch (sp->string_mode) {
   5083 		    case ANSI_APC:
   5084 			/* ignored */
   5085 			break;
   5086 		    case ANSI_DCS:
   5087 #if OPT_SIXEL_GRAPHICS
   5088 			if (sp->string_args == sa_SIXEL) {
   5089 			    parse_sixel_finished();
   5090 			    TRACE(("DONE parsed sixel data\n"));
   5091 			} else
   5092 #endif
   5093 			    do_dcs(xw, sp->string_area, sp->string_used);
   5094 			break;
   5095 		    case ANSI_OSC:
   5096 			do_osc(xw, sp->string_area, sp->string_used, ANSI_ST);
   5097 			break;
   5098 		    case ANSI_PM:
   5099 			/* ignored */
   5100 			break;
   5101 		    case ANSI_SOS:
   5102 			/* ignored */
   5103 			break;
   5104 		    default:
   5105 			TRACE(("unknown mode\n"));
   5106 			break;
   5107 		    }
   5108 		}
   5109 	    }
   5110 	    break;
   5111 
   5112 	case CASE_SOS:
   5113 	    TRACE(("CASE_SOS: Start of String\n"));
   5114 	    if (ParseSOS(screen)) {
   5115 		BeginString(ANSI_SOS);
   5116 	    } else {
   5117 		illegal_parse(xw, c, sp);
   5118 	    }
   5119 	    break;
   5120 
   5121 	case CASE_PM:
   5122 	    TRACE(("CASE_PM: Privacy Message\n"));
   5123 	    if (ParseSOS(screen)) {
   5124 		BeginString(ANSI_PM);
   5125 	    } else {
   5126 		illegal_parse(xw, c, sp);
   5127 	    }
   5128 	    break;
   5129 
   5130 	case CASE_DCS:
   5131 	    TRACE(("CASE_DCS: Device Control String\n"));
   5132 	    BeginString2(ANSI_DCS);
   5133 	    break;
   5134 
   5135 	case CASE_APC:
   5136 	    TRACE(("CASE_APC: Application Program Command\n"));
   5137 	    if (ParseSOS(screen)) {
   5138 		BeginString(ANSI_APC);
   5139 	    } else {
   5140 		illegal_parse(xw, c, sp);
   5141 	    }
   5142 	    break;
   5143 
   5144 	case CASE_SPA:
   5145 	    TRACE(("CASE_SPA - start protected area\n"));
   5146 	    screen->protected_mode = ISO_PROTECT;
   5147 	    xw->flags |= PROTECTED;
   5148 	    ResetState(sp);
   5149 	    break;
   5150 
   5151 	case CASE_EPA:
   5152 	    TRACE(("CASE_EPA - end protected area\n"));
   5153 	    UIntClr(xw->flags, PROTECTED);
   5154 	    ResetState(sp);
   5155 	    break;
   5156 
   5157 	case CASE_SU:
   5158 	    TRACE(("CASE_SU - scroll up\n"));
   5159 	    xtermScroll(xw, one_if_default(0));
   5160 	    ResetState(sp);
   5161 	    break;
   5162 
   5163 	case CASE_SL:		/* ISO 6429, non-DEC */
   5164 	    TRACE(("CASE_SL - scroll left\n"));
   5165 	    xtermScrollLR(xw, one_if_default(0), True);
   5166 	    ResetState(sp);
   5167 	    break;
   5168 
   5169 	case CASE_SR:		/* ISO 6429, non-DEC */
   5170 	    TRACE(("CASE_SR - scroll right\n"));
   5171 	    xtermScrollLR(xw, one_if_default(0), False);
   5172 	    ResetState(sp);
   5173 	    break;
   5174 
   5175 	case CASE_DECDC:
   5176 	    TRACE(("CASE_DC - delete column\n"));
   5177 	    if (screen->vtXX_level >= 4) {
   5178 		xtermColScroll(xw, one_if_default(0), True, screen->cur_col);
   5179 	    }
   5180 	    ResetState(sp);
   5181 	    break;
   5182 
   5183 	case CASE_DECIC:
   5184 	    TRACE(("CASE_IC - insert column\n"));
   5185 	    if (screen->vtXX_level >= 4) {
   5186 		xtermColScroll(xw, one_if_default(0), False, screen->cur_col);
   5187 	    }
   5188 	    ResetState(sp);
   5189 	    break;
   5190 
   5191 	case CASE_DECBI:
   5192 	    TRACE(("CASE_BI - back index\n"));
   5193 	    if (screen->vtXX_level >= 4) {
   5194 		xtermColIndex(xw, True);
   5195 	    }
   5196 	    ResetState(sp);
   5197 	    break;
   5198 
   5199 	case CASE_DECFI:
   5200 	    TRACE(("CASE_FI - forward index\n"));
   5201 	    if (screen->vtXX_level >= 4) {
   5202 		xtermColIndex(xw, False);
   5203 	    }
   5204 	    ResetState(sp);
   5205 	    break;
   5206 
   5207 	case CASE_IND:
   5208 	    TRACE(("CASE_IND - index\n"));
   5209 	    xtermIndex(xw, 1);
   5210 	    do_xevents(xw);
   5211 	    ResetState(sp);
   5212 	    break;
   5213 
   5214 	case CASE_CPL:
   5215 	    TRACE(("CASE_CPL - cursor prev line\n"));
   5216 	    CursorPrevLine(xw, one_if_default(0));
   5217 	    ResetState(sp);
   5218 	    break;
   5219 
   5220 	case CASE_CNL:
   5221 	    TRACE(("CASE_CNL - cursor next line\n"));
   5222 	    CursorNextLine(xw, one_if_default(0));
   5223 	    ResetState(sp);
   5224 	    break;
   5225 
   5226 	case CASE_NEL:
   5227 	    TRACE(("CASE_NEL\n"));
   5228 	    xtermIndex(xw, 1);
   5229 	    CarriageReturn(xw);
   5230 	    ResetState(sp);
   5231 	    break;
   5232 
   5233 	case CASE_HTS:
   5234 	    TRACE(("CASE_HTS - horizontal tab set\n"));
   5235 	    TabSet(xw->tabs, screen->cur_col);
   5236 	    ResetState(sp);
   5237 	    break;
   5238 
   5239 	case CASE_REPORT_VERSION:
   5240 	    TRACE(("CASE_REPORT_VERSION - report terminal version\n"));
   5241 	    if (GetParam(0) <= 0) {
   5242 		unparseputc1(xw, ANSI_DCS);
   5243 		unparseputc(xw, '>');
   5244 		unparseputc(xw, '|');
   5245 		unparseputs(xw, xtermVersion());
   5246 		unparseputc1(xw, ANSI_ST);
   5247 		unparse_end(xw);
   5248 	    }
   5249 	    ResetState(sp);
   5250 	    break;
   5251 
   5252 	case CASE_RI:
   5253 	    TRACE(("CASE_RI - reverse index\n"));
   5254 	    RevIndex(xw, 1);
   5255 	    ResetState(sp);
   5256 	    break;
   5257 
   5258 	case CASE_SS2:
   5259 	    TRACE(("CASE_SS2\n"));
   5260 	    if (screen->vtXX_level > 1)
   5261 		screen->curss = 2;
   5262 	    ResetState(sp);
   5263 	    break;
   5264 
   5265 	case CASE_SS3:
   5266 	    TRACE(("CASE_SS3\n"));
   5267 	    if (screen->vtXX_level > 1)
   5268 		screen->curss = 3;
   5269 	    ResetState(sp);
   5270 	    break;
   5271 
   5272 	case CASE_CSI_STATE:
   5273 	    /* enter csi state */
   5274 	    InitParams();
   5275 	    SetParam(nparam++, DEFAULT);
   5276 	    sp->parsestate = csi_table;
   5277 	    break;
   5278 
   5279 	case CASE_ESC_SP_STATE:
   5280 	    /* esc space */
   5281 	    sp->parsestate = esc_sp_table;
   5282 	    break;
   5283 
   5284 	case CASE_CSI_EX_STATE:
   5285 	    /* csi exclamation */
   5286 	    sp->parsestate = csi_ex_table;
   5287 	    break;
   5288 
   5289 	case CASE_CSI_TICK_STATE:
   5290 	    /* csi tick (') */
   5291 	    sp->parsestate = csi_tick_table;
   5292 	    break;
   5293 
   5294 #if OPT_DEC_LOCATOR
   5295 	case CASE_DECEFR:
   5296 	    TRACE(("CASE_DECEFR - Enable Filter Rectangle\n"));
   5297 	    if (okSendMousePos(xw) == DEC_LOCATOR) {
   5298 		MotionOff(screen, xw);
   5299 		if ((screen->loc_filter_top = GetParam(0)) < 1)
   5300 		    screen->loc_filter_top = LOC_FILTER_POS;
   5301 		if (nparam < 2
   5302 		    || (screen->loc_filter_left = GetParam(1)) < 1)
   5303 		    screen->loc_filter_left = LOC_FILTER_POS;
   5304 		if (nparam < 3
   5305 		    || (screen->loc_filter_bottom = GetParam(2)) < 1)
   5306 		    screen->loc_filter_bottom = LOC_FILTER_POS;
   5307 		if (nparam < 4
   5308 		    || (screen->loc_filter_right = GetParam(3)) < 1)
   5309 		    screen->loc_filter_right = LOC_FILTER_POS;
   5310 		InitLocatorFilter(xw);
   5311 	    }
   5312 	    ResetState(sp);
   5313 	    break;
   5314 
   5315 	case CASE_DECELR:
   5316 	    MotionOff(screen, xw);
   5317 	    if (GetParam(0) <= 0 || GetParam(0) > 2) {
   5318 		screen->send_mouse_pos = MOUSE_OFF;
   5319 		TRACE(("DECELR - Disable Locator Reports\n"));
   5320 	    } else {
   5321 		TRACE(("DECELR - Enable Locator Reports\n"));
   5322 		screen->send_mouse_pos = DEC_LOCATOR;
   5323 		xtermShowPointer(xw, True);
   5324 		if (GetParam(0) == 2) {
   5325 		    screen->locator_reset = True;
   5326 		} else {
   5327 		    screen->locator_reset = False;
   5328 		}
   5329 		if (nparam < 2 || GetParam(1) != 1) {
   5330 		    screen->locator_pixels = False;
   5331 		} else {
   5332 		    screen->locator_pixels = True;
   5333 		}
   5334 		screen->loc_filter = False;
   5335 	    }
   5336 	    ResetState(sp);
   5337 	    break;
   5338 
   5339 	case CASE_DECSLE:
   5340 	    TRACE(("DECSLE - Select Locator Events\n"));
   5341 	    for (count = 0; count < nparam; ++count) {
   5342 		switch (zero_if_default(count)) {
   5343 		case 0:
   5344 		    MotionOff(screen, xw);
   5345 		    screen->loc_filter = False;
   5346 		    screen->locator_events = 0;
   5347 		    break;
   5348 		case 1:
   5349 		    screen->locator_events |= LOC_BTNS_DN;
   5350 		    break;
   5351 		case 2:
   5352 		    UIntClr(screen->locator_events, LOC_BTNS_DN);
   5353 		    break;
   5354 		case 3:
   5355 		    screen->locator_events |= LOC_BTNS_UP;
   5356 		    break;
   5357 		case 4:
   5358 		    UIntClr(screen->locator_events, LOC_BTNS_UP);
   5359 		    break;
   5360 		}
   5361 	    }
   5362 	    ResetState(sp);
   5363 	    break;
   5364 
   5365 	case CASE_DECRQLP:
   5366 	    TRACE(("DECRQLP - Request Locator Position\n"));
   5367 	    if (GetParam(0) < 2) {
   5368 		/* Issue DECLRP Locator Position Report */
   5369 		GetLocatorPosition(xw);
   5370 	    }
   5371 	    ResetState(sp);
   5372 	    break;
   5373 #endif /* OPT_DEC_LOCATOR */
   5374 
   5375 	case CASE_CSI_AMP_STATE:
   5376 	    TRACE(("CASE_CSI_AMP_STATE\n"));
   5377 	    /* csi ampersand (&) */
   5378 	    if (screen->vtXX_level >= 3)
   5379 		sp->parsestate = csi_amp_table;
   5380 	    else
   5381 		sp->parsestate = eigtable;
   5382 	    break;
   5383 
   5384 #if OPT_DEC_RECTOPS
   5385 	case CASE_CSI_DOLLAR_STATE:
   5386 	    TRACE(("CASE_CSI_DOLLAR_STATE\n"));
   5387 	    /* csi dollar ($) */
   5388 	    if (screen->vtXX_level >= 3)
   5389 		sp->parsestate = csi_dollar_table;
   5390 	    else
   5391 		sp->parsestate = eigtable;
   5392 	    break;
   5393 
   5394 	case CASE_CSI_STAR_STATE:
   5395 	    TRACE(("CASE_CSI_STAR_STATE\n"));
   5396 	    /* csi star (*) */
   5397 	    if (screen->vtXX_level >= 4)
   5398 		sp->parsestate = csi_star_table;
   5399 	    else
   5400 		sp->parsestate = eigtable;
   5401 	    break;
   5402 
   5403 	case CASE_DECRQCRA:
   5404 	    if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) {
   5405 		int checksum;
   5406 		int pid;
   5407 
   5408 		TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n"));
   5409 		xtermCheckRect(xw, ParamPair(0), &checksum);
   5410 		init_reply(ANSI_DCS);
   5411 		count = 0;
   5412 		checksum &= 0xffff;
   5413 		pid = GetParam(0);
   5414 		reply.a_param[count++] = (ParmType) pid;
   5415 		reply.a_delim = "!~";	/* delimiter */
   5416 		reply.a_radix[count] = 16;
   5417 		reply.a_param[count++] = (ParmType) checksum;
   5418 		reply.a_nparam = (ParmType) count;
   5419 		TRACE(("...checksum(%d) = %04X\n", pid, checksum));
   5420 		unparseseq(xw, &reply);
   5421 	    }
   5422 	    ResetState(sp);
   5423 	    break;
   5424 
   5425 	case CASE_DECCRA:
   5426 	    if (screen->vtXX_level >= 4) {
   5427 		TRACE(("CASE_DECCRA - Copy rectangular area\n"));
   5428 		xtermParseRect(xw, ParamPair(0), &myRect);
   5429 		ScrnCopyRectangle(xw, &myRect, ParamPair(5));
   5430 	    }
   5431 	    ResetState(sp);
   5432 	    break;
   5433 
   5434 	case CASE_DECERA:
   5435 	    if (screen->vtXX_level >= 4) {
   5436 		TRACE(("CASE_DECERA - Erase rectangular area\n"));
   5437 		xtermParseRect(xw, ParamPair(0), &myRect);
   5438 		ScrnFillRectangle(xw, &myRect, ' ', xw->flags, True);
   5439 	    }
   5440 	    ResetState(sp);
   5441 	    break;
   5442 
   5443 	case CASE_DECFRA:
   5444 	    if (screen->vtXX_level >= 4) {
   5445 		value = use_default_value(0, ' ');
   5446 
   5447 		TRACE(("CASE_DECFRA - Fill rectangular area\n"));
   5448 		/* DEC 070, page 5-170 says the fill-character is either
   5449 		 * ASCII or Latin1; xterm allows printable Unicode values.
   5450 		 */
   5451 		if (nparam > 0
   5452 		    && ((value >= 256 && CharWidth(screen, value) > 0)
   5453 			|| IsLatin1(value))) {
   5454 		    xtermParseRect(xw, ParamPair(1), &myRect);
   5455 		    ScrnFillRectangle(xw, &myRect, value, xw->flags, True);
   5456 		}
   5457 	    }
   5458 	    ResetState(sp);
   5459 	    break;
   5460 
   5461 	case CASE_DECSERA:
   5462 	    if (screen->vtXX_level >= 4) {
   5463 		TRACE(("CASE_DECSERA - Selective erase rectangular area\n"));
   5464 		xtermParseRect(xw, ParamPair(0), &myRect);
   5465 		ScrnWipeRectangle(xw, &myRect);
   5466 	    }
   5467 	    ResetState(sp);
   5468 	    break;
   5469 
   5470 	case CASE_DECSACE:
   5471 	    TRACE(("CASE_DECSACE - Select attribute change extent\n"));
   5472 	    screen->cur_decsace = zero_if_default(0);
   5473 	    ResetState(sp);
   5474 	    break;
   5475 
   5476 	case CASE_DECCARA:
   5477 	    if (screen->vtXX_level >= 4) {
   5478 		TRACE(("CASE_DECCARA - Change attributes in rectangular area\n"));
   5479 		xtermParseRect(xw, ParamPair(0), &myRect);
   5480 		ScrnMarkRectangle(xw, &myRect, False, ParamPair(4));
   5481 	    }
   5482 	    ResetState(sp);
   5483 	    break;
   5484 
   5485 	case CASE_DECRARA:
   5486 	    if (screen->vtXX_level >= 4) {
   5487 		TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n"));
   5488 		xtermParseRect(xw, ParamPair(0), &myRect);
   5489 		ScrnMarkRectangle(xw, &myRect, True, ParamPair(4));
   5490 	    }
   5491 	    ResetState(sp);
   5492 	    break;
   5493 
   5494 	case CASE_DECSCPP:
   5495 	    if (screen->vtXX_level >= 3) {
   5496 		TRACE(("CASE_DECSCPP\n"));
   5497 		/* default and 0 are "80", with "132" as the other legal choice */
   5498 		switch (zero_if_default(0)) {
   5499 		case 0:
   5500 		case 80:
   5501 		    value = 80;
   5502 		    break;
   5503 		case 132:
   5504 		    value = 132;
   5505 		    break;
   5506 		default:
   5507 		    value = -1;
   5508 		    break;
   5509 		}
   5510 		if (value > 0) {
   5511 		    if (screen->cur_col + 1 > value)
   5512 			CursorSet(screen, screen->cur_row, value - 1, xw->flags);
   5513 		    UIntClr(xw->flags, IN132COLUMNS);
   5514 		    if (value == 132)
   5515 			UIntSet(xw->flags, IN132COLUMNS);
   5516 		    RequestResize(xw, -1, value, True);
   5517 		}
   5518 	    }
   5519 	    ResetState(sp);
   5520 	    break;
   5521 
   5522 	case CASE_DECSNLS:
   5523 	    if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetWinLines)) {
   5524 		TRACE(("CASE_DECSNLS\n"));
   5525 		value = zero_if_default(0);
   5526 		if (value >= 1 && value <= 255) {
   5527 		    RequestResize(xw, value, -1, True);
   5528 		}
   5529 	    }
   5530 	    ResetState(sp);
   5531 	    break;
   5532 
   5533 	case CASE_DECRQDE:
   5534 	    if (screen->vtXX_level >= 3) {
   5535 		init_reply(ANSI_CSI);
   5536 		count = 0;
   5537 		reply.a_param[count++] = (ParmType) MaxRows(screen);	/* number of lines */
   5538 		reply.a_param[count++] = (ParmType) MaxCols(screen);	/* number of columns */
   5539 		reply.a_param[count++] = 1;	/* current page column */
   5540 		reply.a_param[count++] = 1;	/* current page line */
   5541 		reply.a_param[count++] = 1;	/* current page */
   5542 		reply.a_inters = '"';
   5543 		reply.a_final = 'w';
   5544 		reply.a_nparam = (ParmType) count;
   5545 		unparseseq(xw, &reply);
   5546 	    }
   5547 	    ResetState(sp);
   5548 	    break;
   5549 
   5550 	case CASE_DECRQPSR:
   5551 #define reply_char(n,c) do { reply.a_radix[(n)] = 1; reply.a_param[(n)++] = (ParmType)(c); } while (0)
   5552 #define reply_bit(n,c) ((n) ? (c) : 0)
   5553 	    if (screen->vtXX_level >= 3) {
   5554 		TRACE(("CASE_DECRQPSR\n"));
   5555 		switch (GetParam(0)) {
   5556 		case 1:
   5557 		    TRACE(("...DECCIR\n"));
   5558 		    init_reply(ANSI_DCS);
   5559 		    count = 0;
   5560 		    reply_char(count, '1');
   5561 		    reply_char(count, '$');
   5562 		    reply_char(count, 'u');
   5563 		    reply.a_param[count++] = (ParmType) (screen->cur_row + 1);
   5564 		    reply.a_param[count++] = (ParmType) (screen->cur_col + 1);
   5565 		    reply.a_param[count++] = (ParmType) thispage;
   5566 		    reply_char(count, ';');
   5567 		    reply_char(count, (0x40
   5568 				       | reply_bit(xw->flags & INVERSE, 8)
   5569 				       | reply_bit(xw->flags & BLINK, 4)
   5570 				       | reply_bit(xw->flags & UNDERLINE, 2)
   5571 				       | reply_bit(xw->flags & BOLD, 1)
   5572 			       ));
   5573 		    reply_char(count, ';');
   5574 		    reply_char(count, 0x40 |
   5575 			       reply_bit(screen->protected_mode &
   5576 					 DEC_PROTECT, 1)
   5577 			);
   5578 		    reply_char(count, ';');
   5579 		    reply_char(count, (0x40
   5580 				       | reply_bit(screen->do_wrap, 8)
   5581 				       | reply_bit((screen->curss == 3), 4)
   5582 				       | reply_bit((screen->curss == 2), 2)
   5583 				       | reply_bit(xw->flags & ORIGIN, 1)
   5584 			       ));
   5585 		    reply_char(count, ';');
   5586 		    reply.a_param[count++] = screen->curgl;
   5587 		    reply.a_param[count++] = screen->curgr;
   5588 		    reply_char(count, ';');
   5589 		    value = 0x40;
   5590 		    for (item = 0; item < NUM_GSETS; ++item) {
   5591 			value |= (is_96charset(screen->gsets[item]) << item);
   5592 		    }
   5593 		    reply_char(count, value);	/* encoded charset sizes */
   5594 		    reply_char(count, ';');
   5595 		    for (item = 0; item < NUM_GSETS; ++item) {
   5596 			int ps;
   5597 			char *temp = encode_scs(screen->gsets[item], &ps);
   5598 			while (*temp != '\0') {
   5599 			    reply_char(count, *temp++);
   5600 			}
   5601 		    }
   5602 		    reply.a_nparam = (ParmType) count;
   5603 		    unparseseq(xw, &reply);
   5604 		    break;
   5605 		case 2:
   5606 		    TRACE(("...DECTABSR\n"));
   5607 		    init_reply(ANSI_DCS);
   5608 		    reply.a_delim = "/";
   5609 		    count = 0;
   5610 		    reply_char(count, '2');
   5611 		    reply_char(count, '$');
   5612 		    reply_char(count, 'u');
   5613 		    for (item = 0; item < MAX_TABS; ++item) {
   5614 			if (count + 1 >= NPARAM)
   5615 			    break;
   5616 			if (item > screen->max_col)
   5617 			    break;
   5618 			if (TabIsSet(xw->tabs, item))
   5619 			    reply.a_param[count++] = (ParmType) (item + 1);
   5620 		    }
   5621 		    reply.a_nparam = (ParmType) count;
   5622 		    unparseseq(xw, &reply);
   5623 		    break;
   5624 		}
   5625 	    }
   5626 	    ResetState(sp);
   5627 	    break;
   5628 
   5629 	case CASE_DECRQUPSS:
   5630 	    TRACE(("CASE_DECRQUPSS\n"));
   5631 	    if (screen->vtXX_level >= 3) {
   5632 		int psize = 0;
   5633 		char *encoded = encode_scs(screen->gsets_upss, &psize);
   5634 		init_reply(ANSI_DCS);
   5635 		count = 0;
   5636 		reply_char(count, psize ? '1' : '0');
   5637 		reply_char(count, '!');
   5638 		reply_char(count, 'u');
   5639 		reply_char(count, *encoded++);
   5640 		if (*encoded)
   5641 		    reply_char(count, *encoded);
   5642 		reply.a_nparam = (ParmType) count;
   5643 		unparseseq(xw, &reply);
   5644 	    }
   5645 	    break;
   5646 
   5647 	case CASE_RQM:
   5648 	    TRACE(("CASE_RQM\n"));
   5649 	    do_ansi_rqm(xw, ParamPair(0));
   5650 	    ResetState(sp);
   5651 	    break;
   5652 
   5653 	case CASE_DECRQM:
   5654 	    TRACE(("CASE_DECRQM\n"));
   5655 	    do_dec_rqm(xw, ParamPair(0));
   5656 	    ResetState(sp);
   5657 	    break;
   5658 
   5659 	case CASE_CSI_DEC_DOLLAR_STATE:
   5660 	    TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n"));
   5661 	    /* csi ? dollar ($) */
   5662 	    sp->parsestate = csi_dec_dollar_table;
   5663 	    break;
   5664 
   5665 	case CASE_DECST8C:
   5666 	    TRACE(("CASE_DECST8C\n"));
   5667 	    if (screen->vtXX_level >= 5
   5668 		&& (GetParam(0) == 5 || GetParam(0) <= 0)) {
   5669 		TabZonk(xw->tabs);
   5670 		for (count = 0; count < MAX_TABS; ++count) {
   5671 		    item = (count + 1) * 8;
   5672 		    if (item > screen->max_col)
   5673 			break;
   5674 		    TabSet(xw->tabs, item);
   5675 		}
   5676 	    }
   5677 	    ResetState(sp);
   5678 	    break;
   5679 #else
   5680 	case CASE_CSI_DOLLAR_STATE:
   5681 	    /* csi dollar ($) */
   5682 	    sp->parsestate = eigtable;
   5683 	    break;
   5684 
   5685 	case CASE_CSI_STAR_STATE:
   5686 	    /* csi dollar (*) */
   5687 	    sp->parsestate = eigtable;
   5688 	    break;
   5689 
   5690 	case CASE_CSI_DEC_DOLLAR_STATE:
   5691 	    /* csi ? dollar ($) */
   5692 	    sp->parsestate = eigtable;
   5693 	    break;
   5694 
   5695 	case CASE_DECST8C:
   5696 	    /* csi ? 5 W */
   5697 	    ResetState(sp);
   5698 	    break;
   5699 #endif /* OPT_DEC_RECTOPS */
   5700 
   5701 #if OPT_VT525_COLORS
   5702 	case CASE_CSI_COMMA_STATE:
   5703 	    TRACE(("CASE_CSI_COMMA_STATE\n"));
   5704 	    /* csi comma (,) */
   5705 	    if (screen->vtXX_level >= 5)
   5706 		sp->parsestate = csi_comma_table;
   5707 	    else
   5708 		sp->parsestate = eigtable;
   5709 	    break;
   5710 
   5711 	case CASE_DECAC:
   5712 	    TRACE(("CASE_DECAC\n"));
   5713 #if OPT_ISO_COLORS
   5714 	    if (screen->terminal_id >= 525) {
   5715 		int fg, bg;
   5716 
   5717 		switch (GetParam(0)) {
   5718 		case 1:
   5719 		    fg = GetParam(1);
   5720 		    bg = GetParam(2);
   5721 		    if (fg >= 0 && fg < 16 && bg >= 0 && bg < 16) {
   5722 			Boolean repaint = False;
   5723 
   5724 			if (AssignFgColor(xw,
   5725 					  GET_COLOR_RES(xw, screen->Acolors[fg])))
   5726 			    repaint = True;
   5727 			if (AssignBgColor(xw,
   5728 					  GET_COLOR_RES(xw, screen->Acolors[bg])))
   5729 			    repaint = True;
   5730 			if (repaint)
   5731 			    xtermRepaint(xw);
   5732 			screen->assigned_fg = fg;
   5733 			screen->assigned_bg = bg;
   5734 		    }
   5735 		    break;
   5736 		case 2:
   5737 		    /* window frames: not implemented */
   5738 		    break;
   5739 		}
   5740 	    }
   5741 #endif
   5742 	    ResetState(sp);
   5743 	    break;
   5744 
   5745 	case CASE_DECATC:
   5746 #if OPT_ISO_COLORS
   5747 	    TRACE(("CASE_DECATC\n"));
   5748 	    if (screen->terminal_id >= 525) {
   5749 		int ps = GetParam(0);
   5750 		int fg = GetParam(1);
   5751 		int bg = GetParam(2);
   5752 		if (ps >= 0 && ps < 16
   5753 		    && fg >= 0 && fg < 16
   5754 		    && bg >= 0 && bg < 16) {
   5755 		    screen->alt_colors[ps].fg = fg;
   5756 		    screen->alt_colors[ps].bg = bg;
   5757 		}
   5758 	    }
   5759 #endif
   5760 	    ResetState(sp);
   5761 	    break;
   5762 
   5763 	case CASE_DECTID:
   5764 	    TRACE(("CASE_DECTID\n"));
   5765 	    switch (GetParam(0)) {
   5766 	    case 0:
   5767 		screen->display_da1 = 100;
   5768 		break;
   5769 	    case 1:
   5770 		screen->display_da1 = 101;
   5771 		break;
   5772 	    case 2:
   5773 		screen->display_da1 = 102;
   5774 		break;
   5775 	    case 5:
   5776 		screen->display_da1 = 220;
   5777 		break;
   5778 	    case 7:
   5779 		screen->display_da1 = 320;
   5780 		break;
   5781 	    case 9:
   5782 		screen->display_da1 = 420;
   5783 		break;
   5784 	    case 10:
   5785 		screen->display_da1 = 520;
   5786 		break;
   5787 	    }
   5788 	    ResetState(sp);
   5789 	    break;
   5790 #else
   5791 	case CASE_CSI_COMMA_STATE:
   5792 	    sp->parsestate = eigtable;
   5793 	    break;
   5794 #endif
   5795 
   5796 	case CASE_DECSASD:
   5797 #if OPT_STATUS_LINE
   5798 	    if (screen->vtXX_level >= 2) {
   5799 		handle_DECSASD(xw, zero_if_default(0));
   5800 	    }
   5801 #endif
   5802 	    ResetState(sp);
   5803 	    break;
   5804 
   5805 	case CASE_DECSSDT:
   5806 #if OPT_STATUS_LINE
   5807 	    if (screen->vtXX_level >= 2) {
   5808 		handle_DECSSDT(xw, zero_if_default(0));
   5809 	    }
   5810 #endif
   5811 	    ResetState(sp);
   5812 	    break;
   5813 
   5814 #if OPT_XTERM_SGR		/* most are related, all use csi_hash_table[] */
   5815 	case CASE_CSI_HASH_STATE:
   5816 	    TRACE(("CASE_CSI_HASH_STATE\n"));
   5817 	    /* csi hash (#) */
   5818 	    sp->parsestate = csi_hash_table;
   5819 	    break;
   5820 
   5821 	case CASE_XTERM_CHECKSUM:
   5822 #if OPT_DEC_RECTOPS
   5823 	    if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) {
   5824 		TRACE(("CASE_XTERM_CHECKSUM\n"));
   5825 		screen->checksum_ext = zero_if_default(0);
   5826 	    }
   5827 #endif
   5828 	    ResetState(sp);
   5829 	    break;
   5830 
   5831 	case CASE_XTERM_PUSH_SGR:
   5832 	    TRACE(("CASE_XTERM_PUSH_SGR\n"));
   5833 	    value = 0;
   5834 	    if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) {
   5835 		value = DEFAULT;
   5836 	    } else if (nparam > 0) {
   5837 		for (count = 0; count < nparam; ++count) {
   5838 		    item = zero_if_default(count);
   5839 		    /* deprecated - for compatibility */
   5840 #if OPT_ISO_COLORS
   5841 		    if (item == psFG_COLOR_obs) {
   5842 			item = psFG_COLOR;
   5843 		    } else if (item == psBG_COLOR_obs) {
   5844 			item = psBG_COLOR;
   5845 		    }
   5846 #endif
   5847 		    if (item > 0 && item < MAX_PUSH_SGR) {
   5848 			value |= (1 << (item - 1));
   5849 		    }
   5850 		}
   5851 	    }
   5852 	    xtermPushSGR(xw, value);
   5853 	    ResetState(sp);
   5854 	    break;
   5855 
   5856 	case CASE_XTERM_REPORT_SGR:
   5857 	    TRACE(("CASE_XTERM_REPORT_SGR\n"));
   5858 	    xtermParseRect(xw, ParamPair(0), &myRect);
   5859 	    xtermReportSGR(xw, &myRect);
   5860 	    ResetState(sp);
   5861 	    break;
   5862 
   5863 	case CASE_XTERM_POP_SGR:
   5864 	    TRACE(("CASE_XTERM_POP_SGR\n"));
   5865 	    xtermPopSGR(xw);
   5866 	    ResetState(sp);
   5867 	    break;
   5868 
   5869 	case CASE_XTERM_PUSH_COLORS:
   5870 	    TRACE(("CASE_XTERM_PUSH_COLORS\n"));
   5871 	    if (nparam == 0) {
   5872 		xtermPushColors(xw, DEFAULT);
   5873 	    } else {
   5874 		for (count = 0; count < nparam; ++count) {
   5875 		    xtermPushColors(xw, GetParam(count));
   5876 		}
   5877 	    }
   5878 	    ResetState(sp);
   5879 	    break;
   5880 
   5881 	case CASE_XTERM_POP_COLORS:
   5882 	    TRACE(("CASE_XTERM_POP_COLORS\n"));
   5883 	    if (nparam == 0) {
   5884 		xtermPopColors(xw, DEFAULT);
   5885 	    } else {
   5886 		for (count = 0; count < nparam; ++count) {
   5887 		    xtermPopColors(xw, GetParam(count));
   5888 		}
   5889 	    }
   5890 	    ResetState(sp);
   5891 	    break;
   5892 
   5893 	case CASE_XTERM_REPORT_COLORS:
   5894 	    TRACE(("CASE_XTERM_REPORT_COLORS\n"));
   5895 	    xtermReportColors(xw);
   5896 	    ResetState(sp);
   5897 	    break;
   5898 
   5899 	case CASE_XTERM_TITLE_STACK:
   5900 	    xtermReportTitleStack(xw);
   5901 	    ResetState(sp);
   5902 	    break;
   5903 #endif
   5904 
   5905 	case CASE_S7C1T:
   5906 	    TRACE(("CASE_S7C1T\n"));
   5907 	    if (screen->vtXX_level >= 2) {
   5908 		show_8bit_control(False);
   5909 		ResetState(sp);
   5910 	    }
   5911 	    break;
   5912 
   5913 	case CASE_S8C1T:
   5914 	    TRACE(("CASE_S8C1T\n"));
   5915 	    if (screen->vtXX_level >= 2) {
   5916 		show_8bit_control(True);
   5917 		ResetState(sp);
   5918 	    }
   5919 	    break;
   5920 
   5921 	case CASE_OSC:
   5922 	    TRACE(("CASE_OSC: Operating System Command\n"));
   5923 	    BeginString(ANSI_OSC);
   5924 	    break;
   5925 
   5926 	case CASE_RIS:
   5927 	    TRACE(("CASE_RIS\n"));
   5928 	    VTReset(xw, True, True);
   5929 	    /* NOTREACHED */
   5930 
   5931 	case CASE_DECSTR:
   5932 	    TRACE(("CASE_DECSTR\n"));
   5933 	    VTReset(xw, False, False);
   5934 	    /* NOTREACHED */
   5935 
   5936 	case CASE_REP:
   5937 	    TRACE(("CASE_REP\n"));
   5938 	    if (CharWidth(screen, sp->lastchar) > 0) {
   5939 		IChar repeated[2];
   5940 		count = one_if_default(0);
   5941 		repeated[0] = (IChar) sp->lastchar;
   5942 		while (count-- > 0) {
   5943 		    dotext(xw,
   5944 			   screen->gsets[(int) (screen->curgl)],
   5945 			   repeated, 1);
   5946 		}
   5947 	    }
   5948 	    ResetState(sp);
   5949 	    break;
   5950 
   5951 	case CASE_LS2:
   5952 	    TRACE(("CASE_LS2\n"));
   5953 	    if (screen->ansi_level > 2)
   5954 		screen->curgl = 2;
   5955 	    ResetState(sp);
   5956 	    break;
   5957 
   5958 	case CASE_LS3:
   5959 	    TRACE(("CASE_LS3\n"));
   5960 	    if (screen->ansi_level > 2)
   5961 		screen->curgl = 3;
   5962 	    ResetState(sp);
   5963 	    break;
   5964 
   5965 	case CASE_LS3R:
   5966 	    TRACE(("CASE_LS3R\n"));
   5967 	    if (screen->ansi_level > 2)
   5968 		screen->curgr = 3;
   5969 	    ResetState(sp);
   5970 	    break;
   5971 
   5972 	case CASE_LS2R:
   5973 	    TRACE(("CASE_LS2R\n"));
   5974 	    if (screen->ansi_level > 2)
   5975 		screen->curgr = 2;
   5976 	    ResetState(sp);
   5977 	    break;
   5978 
   5979 	case CASE_LS1R:
   5980 	    TRACE(("CASE_LS1R\n"));
   5981 	    if (screen->ansi_level > 2)
   5982 		screen->curgr = 1;
   5983 	    ResetState(sp);
   5984 	    break;
   5985 
   5986 	case CASE_XTERM_SAVE:
   5987 	    savemodes(xw);
   5988 	    ResetState(sp);
   5989 	    break;
   5990 
   5991 	case CASE_XTERM_RESTORE:
   5992 	    restoremodes(xw);
   5993 	    ResetState(sp);
   5994 	    break;
   5995 
   5996 	case CASE_XTERM_WINOPS:
   5997 	    TRACE(("CASE_XTERM_WINOPS\n"));
   5998 	    window_ops(xw);
   5999 	    ResetState(sp);
   6000 	    break;
   6001 #if OPT_WIDE_CHARS
   6002 	case CASE_ESC_PERCENT:
   6003 	    TRACE(("CASE_ESC_PERCENT\n"));
   6004 	    sp->parsestate = esc_pct_table;
   6005 	    break;
   6006 
   6007 	case CASE_UTF8:
   6008 	    /* If we did not set UTF-8 mode from resource or the
   6009 	     * command-line, allow it to be enabled/disabled by
   6010 	     * control sequence.
   6011 	     */
   6012 	    TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n",
   6013 		   screen->wide_chars,
   6014 		   screen->utf8_mode,
   6015 		   BtoS(AsciiOf(c) == 'G')));
   6016 	    if ((!screen->wide_chars) && (AsciiOf(c) == 'G')) {
   6017 		WriteNow();
   6018 		ChangeToWide(xw);
   6019 	    }
   6020 	    if (screen->wide_chars
   6021 		&& !screen->utf8_always) {
   6022 		switchPtyData(screen, AsciiOf(c) == 'G');
   6023 		TRACE(("UTF8 mode %s\n",
   6024 		       BtoS(screen->utf8_mode)));
   6025 	    } else {
   6026 		TRACE(("UTF8 mode NOT turned %s (%s)\n",
   6027 		       BtoS(AsciiOf(c) == 'G'),
   6028 		       (screen->utf8_mode == uAlways)
   6029 		       ? "UTF-8 mode set from command-line"
   6030 		       : "wideChars resource was not set"));
   6031 	    }
   6032 	    ResetState(sp);
   6033 	    break;
   6034 
   6035 	case CASE_SCS_DQUOTE:
   6036 	    TRACE(("CASE_SCS_DQUOTE\n"));
   6037 	    sp->parsestate = scs_2qt_table;
   6038 	    break;
   6039 
   6040 	case CASE_GSETS_DQUOTE:
   6041 	    if (screen->vtXX_level >= 5) {
   6042 		TRACE_GSETS("_DQUOTE");
   6043 		xtermDecodeSCS(xw, sp->scstype, 5, '"', (int) c);
   6044 	    }
   6045 	    ResetState(sp);
   6046 	    break;
   6047 
   6048 	case CASE_SCS_AMPRSND:
   6049 	    TRACE(("CASE_SCS_AMPRSND\n"));
   6050 	    sp->parsestate = scs_amp_table;
   6051 	    break;
   6052 
   6053 	case CASE_GSETS_AMPRSND:
   6054 	    if (screen->vtXX_level >= 5) {
   6055 		TRACE_GSETS("_AMPRSND");
   6056 		xtermDecodeSCS(xw, sp->scstype, 5, '&', (int) c);
   6057 	    }
   6058 	    ResetState(sp);
   6059 	    break;
   6060 
   6061 	case CASE_SCS_PERCENT:
   6062 	    TRACE(("CASE_SCS_PERCENT\n"));
   6063 	    sp->parsestate = scs_pct_table;
   6064 	    break;
   6065 
   6066 	case CASE_GSETS_PERCENT:
   6067 	    if (screen->vtXX_level >= 3) {
   6068 		TRACE_GSETS("_PERCENT");
   6069 		switch (AsciiOf(c)) {
   6070 		case '0':	/* DEC Turkish */
   6071 		case '2':	/* Turkish */
   6072 		case '=':	/* Hebrew */
   6073 		    value = 5;
   6074 		    break;
   6075 		case '5':	/* DEC Supplemental Graphics */
   6076 		case '6':	/* Portuguese */
   6077 		default:
   6078 		    value = 3;
   6079 		    break;
   6080 		}
   6081 		xtermDecodeSCS(xw, sp->scstype, value, '%', (int) c);
   6082 	    }
   6083 	    ResetState(sp);
   6084 	    break;
   6085 #endif
   6086 	case CASE_XTERM_SHIFT_ESCAPE:
   6087 	    TRACE(("CASE_XTERM_SHIFT_ESCAPE\n"));
   6088 	    value = ((nparam == 0)
   6089 		     ? 0
   6090 		     : one_if_default(0));
   6091 	    if (value >= 0 && value <= 1)
   6092 		xw->keyboard.shift_escape = value;
   6093 	    ResetState(sp);
   6094 	    break;
   6095 
   6096 #if OPT_MOD_FKEYS
   6097 	case CASE_SET_MOD_FKEYS:
   6098 	    TRACE(("CASE_SET_MOD_FKEYS\n"));
   6099 	    if (nparam >= 1) {
   6100 		set_mod_fkeys(xw,
   6101 			      GetParam(0),
   6102 			      ((nparam > 1)
   6103 			       ? GetParam(1)
   6104 			       : DEFAULT),
   6105 			      True);
   6106 	    } else {
   6107 		for (value = 1; value <= 5; ++value)
   6108 		    set_mod_fkeys(xw, value, DEFAULT, True);
   6109 	    }
   6110 	    ResetState(sp);
   6111 	    break;
   6112 
   6113 	case CASE_SET_MOD_FKEYS0:
   6114 	    TRACE(("CASE_SET_MOD_FKEYS0\n"));
   6115 	    if (nparam >= 1 && GetParam(0) != DEFAULT) {
   6116 		set_mod_fkeys(xw, GetParam(0), -1, False);
   6117 	    } else {
   6118 		xw->keyboard.modify_now.function_keys = -1;
   6119 	    }
   6120 	    ResetState(sp);
   6121 	    break;
   6122 
   6123 	case CASE_XTERM_REPORT_MOD_FKEYS:
   6124 	    TRACE(("CASE_XTERM_REPORT_MOD_FKEYS\n"));
   6125 	    for (value = 0; value < nparam; ++value) {
   6126 		report_mod_fkeys(xw, GetParam(value));
   6127 	    }
   6128 	    ResetState(sp);
   6129 	    break;
   6130 #endif
   6131 	case CASE_HIDE_POINTER:
   6132 	    TRACE(("CASE_HIDE_POINTER\n"));
   6133 	    if (nparam >= 1 && GetParam(0) != DEFAULT) {
   6134 		screen->pointer_mode = GetParam(0);
   6135 	    } else {
   6136 		screen->pointer_mode = DEF_POINTER_MODE;
   6137 	    }
   6138 	    ResetState(sp);
   6139 	    break;
   6140 
   6141 	case CASE_XTERM_SM_TITLE:
   6142 	    TRACE(("CASE_XTERM_SM_TITLE\n"));
   6143 	    if (nparam >= 1) {
   6144 		for (count = 0; count < nparam; ++count) {
   6145 		    value = GetParam(count);
   6146 		    if (ValidTitleMode(value))
   6147 			screen->title_modes |= xBIT(value);
   6148 		}
   6149 	    } else {
   6150 		screen->title_modes = DEF_TITLE_MODES;
   6151 	    }
   6152 	    TRACE(("...title_modes %#x\n", screen->title_modes));
   6153 	    ResetState(sp);
   6154 	    break;
   6155 
   6156 	case CASE_XTERM_RM_TITLE:
   6157 	    TRACE(("CASE_XTERM_RM_TITLE\n"));
   6158 	    if (nparam >= 1) {
   6159 		for (count = 0; count < nparam; ++count) {
   6160 		    value = GetParam(count);
   6161 		    if (ValidTitleMode(value))
   6162 			screen->title_modes &= ~xBIT(value);
   6163 		}
   6164 	    } else {
   6165 		screen->title_modes = DEF_TITLE_MODES;
   6166 	    }
   6167 	    TRACE(("...title_modes %#x\n", screen->title_modes));
   6168 	    ResetState(sp);
   6169 	    break;
   6170 
   6171 	case CASE_CSI_IGNORE:
   6172 	    sp->parsestate = cigtable;
   6173 	    break;
   6174 
   6175 	case CASE_DECSWBV:
   6176 	    TRACE(("CASE_DECSWBV\n"));
   6177 	    switch (zero_if_default(0)) {
   6178 	    case 2:
   6179 		/* FALLTHRU */
   6180 	    case 3:
   6181 		/* FALLTHRU */
   6182 	    case 4:
   6183 		screen->warningVolume = bvLow;
   6184 		break;
   6185 	    case 5:
   6186 		/* FALLTHRU */
   6187 	    case 6:
   6188 		/* FALLTHRU */
   6189 	    case 7:
   6190 		/* FALLTHRU */
   6191 	    case 8:
   6192 		screen->warningVolume = bvHigh;
   6193 		break;
   6194 	    default:
   6195 		screen->warningVolume = bvOff;
   6196 		break;
   6197 	    }
   6198 	    TRACE(("...warningVolume %d\n", screen->warningVolume));
   6199 	    ResetState(sp);
   6200 	    break;
   6201 
   6202 	case CASE_DECSMBV:
   6203 	    TRACE(("CASE_DECSMBV\n"));
   6204 	    switch (zero_if_default(0)) {
   6205 	    case 2:
   6206 		/* FALLTHRU */
   6207 	    case 3:
   6208 		/* FALLTHRU */
   6209 	    case 4:
   6210 		screen->marginVolume = bvLow;
   6211 		break;
   6212 	    case 0:
   6213 		/* FALLTHRU */
   6214 	    case 5:
   6215 		/* FALLTHRU */
   6216 	    case 6:
   6217 		/* FALLTHRU */
   6218 	    case 7:
   6219 		/* FALLTHRU */
   6220 	    case 8:
   6221 		screen->marginVolume = bvHigh;
   6222 		break;
   6223 	    default:
   6224 		screen->marginVolume = bvOff;
   6225 		break;
   6226 	    }
   6227 	    TRACE(("...marginVolume %d\n", screen->marginVolume));
   6228 	    ResetState(sp);
   6229 	    break;
   6230 	}
   6231 	if (sp->parsestate == sp->groundtable)
   6232 	    sp->lastchar = thischar;
   6233     } while (0);
   6234 
   6235 #if OPT_WIDE_CHARS
   6236     screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse)
   6237 				      && (sp->parsestate != sos_table));
   6238 #endif
   6239 
   6240     if (sp->check_recur)
   6241 	sp->check_recur--;
   6242     return True;
   6243 }
   6244 
   6245 static void
   6246 VTparse(XtermWidget xw)
   6247 {
   6248     Boolean keep_running;
   6249 
   6250     /* We longjmp back to this point in VTReset() */
   6251     (void) setjmp(vtjmpbuf);
   6252     init_parser(xw, &myState);
   6253 
   6254     do {
   6255 	keep_running = doparsing(xw, doinput(xw), &myState);
   6256 	if (myState.check_recur == 0 && myState.defer_used != 0) {
   6257 	    while (myState.defer_used) {
   6258 		Char *deferred = myState.defer_area;
   6259 		size_t len = myState.defer_used;
   6260 		size_t i;
   6261 		myState.defer_area = NULL;
   6262 		myState.defer_size = 0;
   6263 		myState.defer_used = 0;
   6264 		for (i = 0; i < len; i++) {
   6265 		    (void) doparsing(xw, deferred[i], &myState);
   6266 		}
   6267 		free(deferred);
   6268 	    }
   6269 	} else {
   6270 	    free(myState.defer_area);
   6271 	}
   6272 	myState.defer_area = NULL;
   6273 	myState.defer_size = 0;
   6274 	myState.defer_used = 0;
   6275     } while (keep_running);
   6276 }
   6277 
   6278 static Char *v_buffer;		/* pointer to physical buffer */
   6279 static Char *v_bufstr = NULL;	/* beginning of area to write */
   6280 static Char *v_bufptr;		/* end of area to write */
   6281 static Char *v_bufend;		/* end of physical buffer */
   6282 
   6283 /* Write data to the pty as typed by the user, pasted with the mouse,
   6284    or generated by us in response to a query ESC sequence. */
   6285 
   6286 void
   6287 v_write(int f, const Char *data, size_t len)
   6288 {
   6289     TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len)));
   6290     if (v_bufstr == NULL) {
   6291 	if (len > 0) {
   6292 	    v_buffer = (Char *) XtMalloc((Cardinal) len);
   6293 	    v_bufstr = v_buffer;
   6294 	    v_bufptr = v_buffer;
   6295 	    v_bufend = v_buffer + len;
   6296 	}
   6297 	if (v_bufstr == NULL) {
   6298 	    return;
   6299 	}
   6300     }
   6301     if_DEBUG({
   6302 	fprintf(stderr, "v_write called with %lu bytes (%lu left over)",
   6303 		(unsigned long) len,
   6304 		(unsigned long) (v_bufptr - v_bufstr));
   6305 	if (len > 1 && len < 10)
   6306 	    fprintf(stderr, " \"%.*s\"", (int) len, (const char *) data);
   6307 	fprintf(stderr, "\n");
   6308     });
   6309 
   6310     if (!FD_ISSET(f, &pty_mask)) {
   6311 	IGNORE_RC(write(f, (const char *) data, (size_t) len));
   6312 	return;
   6313     }
   6314 
   6315     /*
   6316      * Append to the block we already have.
   6317      * Always doing this simplifies the code, and
   6318      * isn't too bad, either.  If this is a short
   6319      * block, it isn't too expensive, and if this is
   6320      * a long block, we won't be able to write it all
   6321      * anyway.
   6322      */
   6323 
   6324     if (len > 0) {
   6325 #if OPT_DABBREV
   6326 	TScreenOf(term)->dabbrev_working = False;	/* break dabbrev sequence */
   6327 #endif
   6328 	if (v_bufend < v_bufptr + len) {	/* we've run out of room */
   6329 	    if (v_bufstr != v_buffer) {
   6330 		/* there is unused space, move everything down */
   6331 		/* possibly overlapping memmove here */
   6332 		if_DEBUG({
   6333 		    fprintf(stderr, "moving data down %ld\n",
   6334 			    (long) (v_bufstr - v_buffer));
   6335 		});
   6336 		memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr));
   6337 		v_bufptr -= v_bufstr - v_buffer;
   6338 		v_bufstr = v_buffer;
   6339 	    }
   6340 	    if (v_bufend < v_bufptr + len) {
   6341 		/* still won't fit: get more space */
   6342 		/* Don't use XtRealloc because an error is not fatal. */
   6343 		size_t size = (size_t) (v_bufptr - v_buffer);
   6344 		v_buffer = TypeRealloc(Char, size + len, v_buffer);
   6345 		if (v_buffer) {
   6346 		    if_DEBUG({
   6347 			fprintf(stderr, "expanded buffer to %lu\n",
   6348 				(unsigned long) (size + len));
   6349 		    });
   6350 		    v_bufstr = v_buffer;
   6351 		    v_bufptr = v_buffer + size;
   6352 		    v_bufend = v_bufptr + len;
   6353 		} else {
   6354 		    /* no memory: ignore entire write request */
   6355 		    xtermWarning("cannot allocate buffer space\n");
   6356 		    v_buffer = v_bufstr;	/* restore clobbered pointer */
   6357 		}
   6358 	    }
   6359 	}
   6360 	if (v_bufend >= v_bufptr + len) {
   6361 	    /* new stuff will fit */
   6362 	    memmove(v_bufptr, data, (size_t) len);
   6363 	    v_bufptr += len;
   6364 	}
   6365     }
   6366 
   6367     /*
   6368      * Write out as much of the buffer as we can.
   6369      * Be careful not to overflow the pty's input silo.
   6370      * We are conservative here and only write
   6371      * a small amount at a time.
   6372      *
   6373      * If we can't push all the data into the pty yet, we expect write
   6374      * to return a non-negative number less than the length requested
   6375      * (if some data written) or -1 and set errno to EAGAIN,
   6376      * EWOULDBLOCK, or EINTR (if no data written).
   6377      *
   6378      * (Not all systems do this, sigh, so the code is actually
   6379      * a little more forgiving.)
   6380      */
   6381 
   6382 #define MAX_PTY_WRITE 128	/* 1/2 POSIX minimum MAX_INPUT */
   6383 
   6384     if (v_bufptr > v_bufstr) {
   6385 	int riten;
   6386 
   6387 	riten = (int) write(f, v_bufstr,
   6388 			    (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE)
   6389 				      ? v_bufptr - v_bufstr
   6390 				      : MAX_PTY_WRITE));
   6391 	if (riten < 0) {
   6392 	    if_DEBUG({
   6393 		perror("write");
   6394 	    });
   6395 	    riten = 0;
   6396 	}
   6397 	if_DEBUG({
   6398 	    fprintf(stderr, "write called with %ld, wrote %d\n",
   6399 		    ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE)
   6400 		     ? (long) (v_bufptr - v_bufstr)
   6401 		     : MAX_PTY_WRITE),
   6402 		    riten);
   6403 	});
   6404 	v_bufstr += riten;
   6405 	if (v_bufstr >= v_bufptr)	/* we wrote it all */
   6406 	    v_bufstr = v_bufptr = v_buffer;
   6407     }
   6408 
   6409     /*
   6410      * If we have lots of unused memory allocated, return it
   6411      */
   6412     if (v_bufend - v_bufptr > 1024) {	/* arbitrary hysteresis */
   6413 	/* save pointers across realloc */
   6414 	size_t start = (size_t) (v_bufstr - v_buffer);
   6415 	size_t size = (size_t) (v_bufptr - v_buffer);
   6416 	size_t allocsize = (size ? size : 1);
   6417 
   6418 	v_buffer = TypeRealloc(Char, allocsize, v_buffer);
   6419 	if (v_buffer) {
   6420 	    v_bufstr = v_buffer + start;
   6421 	    v_bufptr = v_buffer + size;
   6422 	    v_bufend = v_buffer + allocsize;
   6423 	    if_DEBUG({
   6424 		fprintf(stderr, "shrunk buffer to %lu\n", (unsigned long) allocsize);
   6425 	    });
   6426 	} else {
   6427 	    /* should we print a warning if couldn't return memory? */
   6428 	    v_buffer = v_bufstr - start;	/* restore clobbered pointer */
   6429 	}
   6430     }
   6431 }
   6432 
   6433 static void
   6434 updateCursor(XtermWidget xw)
   6435 {
   6436     TScreen *screen = TScreenOf(xw);
   6437 
   6438     if (screen->cursor_set != screen->cursor_state) {
   6439 	if (screen->cursor_set)
   6440 	    ShowCursor(xw);
   6441 	else
   6442 	    HideCursor(xw);
   6443     }
   6444 }
   6445 
   6446 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
   6447 static void
   6448 reallyStopBlinking(XtermWidget xw)
   6449 {
   6450     TScreen *screen = TScreenOf(xw);
   6451 
   6452     if (screen->cursor_state == BLINKED_OFF) {
   6453 	/* force cursor to display if it is enabled */
   6454 	screen->cursor_state = !screen->cursor_set;
   6455 	updateCursor(xw);
   6456 	xevents(xw);
   6457     }
   6458 }
   6459 #endif
   6460 
   6461 static void
   6462 update_the_screen(XtermWidget xw)
   6463 {
   6464     TScreen *screen = TScreenOf(xw);
   6465     Boolean moved;
   6466 
   6467     if (screen->scroll_amt)
   6468 	FlushScroll(xw);
   6469     moved = CursorMoved(screen);
   6470     if (screen->cursor_set && moved) {
   6471 	if (screen->cursor_state)
   6472 	    HideCursor(xw);
   6473 	ShowCursor(xw);
   6474 #if OPT_INPUT_METHOD
   6475 	PreeditPosition(xw);
   6476 #endif
   6477     } else {
   6478 #if OPT_INPUT_METHOD
   6479 	if (moved)
   6480 	    PreeditPosition(xw);
   6481 #endif
   6482 	updateCursor(xw);
   6483     }
   6484 }
   6485 
   6486 static void
   6487 init_timeval(struct timeval *target, long usecs)
   6488 {
   6489     target->tv_sec = 0;
   6490     target->tv_usec = usecs;
   6491     while (target->tv_usec > 1000000) {
   6492 	target->tv_usec -= 1000000;
   6493 	target->tv_sec++;
   6494     }
   6495 }
   6496 
   6497 static Boolean
   6498 better_timeout(struct timeval *check, struct timeval *against)
   6499 {
   6500     Boolean result = False;
   6501     if (against->tv_sec == 0 && against->tv_usec == 0) {
   6502 	result = True;
   6503     } else if (check->tv_sec == against->tv_sec) {
   6504 	if (check->tv_usec < against->tv_usec) {
   6505 	    result = True;
   6506 	}
   6507     } else if (check->tv_sec < against->tv_sec) {
   6508 	result = True;
   6509     }
   6510     return result;
   6511 }
   6512 
   6513 #if OPT_BLINK_CURS
   6514 static long
   6515 smaller_timeout(long value)
   6516 {
   6517     /* 1000 for msec/usec, 8 for "much" smaller */
   6518     value *= (1000 / 8);
   6519     if (value < 1)
   6520 	value = 1;
   6521     return value;
   6522 }
   6523 #endif
   6524 
   6525 static void
   6526 in_put(XtermWidget xw)
   6527 {
   6528     static PtySelect select_mask;
   6529     static PtySelect write_mask;
   6530 
   6531     TScreen *screen = TScreenOf(xw);
   6532     int i;
   6533     int update = VTbuffer->update;
   6534 #if USE_DOUBLE_BUFFER
   6535     int should_wait = 1;
   6536 #endif
   6537     struct timeval my_timeout;
   6538 
   6539     for (;;) {
   6540 	int size;
   6541 	int time_select;
   6542 
   6543 	if (screen->eventMode == NORMAL
   6544 	    && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) {
   6545 	    if (screen->scrollWidget
   6546 		&& screen->scrollttyoutput
   6547 		&& screen->topline < 0)
   6548 		WindowScroll(xw, 0, False);	/* Scroll to bottom */
   6549 	    /* stop speed reading at some point to look for X stuff */
   6550 	    TRACE(("VTbuffer uses %ld/%d\n",
   6551 		   (long) (VTbuffer->last - VTbuffer->buffer),
   6552 		   BUF_SIZE));
   6553 	    if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) {
   6554 		FD_CLR(screen->respond, &select_mask);
   6555 		break;
   6556 	    }
   6557 #if USE_DOUBLE_BUFFER
   6558 	    if (resource.buffered && should_wait) {
   6559 		/* wait for potential extra data (avoids some flickering) */
   6560 		usleep((unsigned) DbeMsecs(xw));
   6561 		should_wait = 0;
   6562 	    }
   6563 #endif
   6564 #if defined(HAVE_SCHED_YIELD)
   6565 	    /*
   6566 	     * If we've read a full (small/fragment) buffer, let the operating
   6567 	     * system have a turn, and we'll resume reading until we've either
   6568 	     * read only a fragment of the buffer, or we've filled the large
   6569 	     * buffer (see above).  Doing this helps keep up with large bursts
   6570 	     * of output.
   6571 	     */
   6572 	    if (size == FRG_SIZE) {
   6573 		init_timeval(&my_timeout, 0L);
   6574 		i = Select(max_plus1, &select_mask, &write_mask, 0, &my_timeout);
   6575 		if (i > 0 && FD_ISSET(screen->respond, &select_mask)) {
   6576 		    sched_yield();
   6577 		} else
   6578 		    break;
   6579 	    } else {
   6580 		break;
   6581 	    }
   6582 #else
   6583 	    (void) size;	/* unused in this branch */
   6584 	    break;
   6585 #endif
   6586 	}
   6587 	update_the_screen(xw);
   6588 
   6589 	XFlush(screen->display);	/* always flush writes before waiting */
   6590 
   6591 	/* Update the masks and, unless X events are already in the queue,
   6592 	   wait for I/O to be possible. */
   6593 	XFD_COPYSET(&Select_mask, &select_mask);
   6594 	/* in selection mode xterm does not read pty */
   6595 	if (screen->eventMode != NORMAL)
   6596 	    FD_CLR(screen->respond, &select_mask);
   6597 
   6598 	if (v_bufptr > v_bufstr) {
   6599 	    XFD_COPYSET(&pty_mask, &write_mask);
   6600 	} else
   6601 	    FD_ZERO(&write_mask);
   6602 	init_timeval(&my_timeout, 0L);
   6603 	time_select = 0;
   6604 
   6605 	/*
   6606 	 * if there's either an XEvent or an XtTimeout pending, just take
   6607 	 * a quick peek, i.e. timeout from the select() immediately.  If
   6608 	 * there's nothing pending, let select() block a little while, but
   6609 	 * for a shorter interval than the arrow-style scrollbar timeout.
   6610 	 * The blocking is optional, because it tends to increase the load
   6611 	 * on the host.
   6612 	 */
   6613 	if (xtermAppPending()) {
   6614 	    time_select = 1;
   6615 	} else {
   6616 #define ImproveTimeout(usecs) \
   6617 		struct timeval try_timeout; \
   6618 		init_timeval(&try_timeout, usecs); \
   6619 		if (better_timeout(&try_timeout, &my_timeout)) { \
   6620 		    my_timeout = try_timeout; \
   6621 		}
   6622 #if OPT_STATUS_LINE
   6623 	    if ((screen->status_type == 1) && screen->status_timeout) {
   6624 		ImproveTimeout(find_SL_Timeout(xw) * 1000L);
   6625 		time_select = 1;
   6626 	    }
   6627 #endif
   6628 	    if (screen->awaitInput) {
   6629 		ImproveTimeout(50000L);
   6630 		time_select = 1;
   6631 	    }
   6632 #if OPT_BLINK_CURS
   6633 	    if ((screen->blink_timer != 0 &&
   6634 		 ((screen->select & FOCUS) || screen->always_highlight)) ||
   6635 		(screen->cursor_state == BLINKED_OFF)) {
   6636 		/*
   6637 		 * Compute the timeout for the blinking cursor to be much
   6638 		 * smaller than the "on" or "off" interval.
   6639 		 */
   6640 		long tick = smaller_timeout((long) ((screen->blink_on < screen->blink_off)
   6641 						    ? screen->blink_on
   6642 						    : screen->blink_off));
   6643 		ImproveTimeout(tick);
   6644 		time_select = 1;
   6645 	    }
   6646 #endif
   6647 	}
   6648 #if OPT_SESSION_MGT
   6649 	if (resource.sessionMgt && (ice_fd >= 0)) {
   6650 	    FD_SET(ice_fd, &select_mask);
   6651 	}
   6652 #endif
   6653 	if (need_cleanup)
   6654 	    NormalExit();
   6655 	xtermFlushDbe(xw);
   6656 	i = Select(max_plus1, &select_mask, &write_mask, 0,
   6657 		   (time_select ? &my_timeout : NULL));
   6658 	if (i < 0) {
   6659 	    if (errno != EINTR)
   6660 		SysError(ERROR_SELECT);
   6661 	    continue;
   6662 	}
   6663 
   6664 	/* if there is room to write more data to the pty, go write more */
   6665 	if (FD_ISSET(screen->respond, &write_mask)) {
   6666 	    v_write(screen->respond, (Char *) 0, (size_t) 0);	/* flush buffer */
   6667 	}
   6668 
   6669 	/* if there are X events already in our queue, it
   6670 	   counts as being readable */
   6671 	if (xtermAppPending() ||
   6672 	    FD_ISSET(ConnectionNumber(screen->display), &select_mask)) {
   6673 	    xevents(xw);
   6674 	    if (VTbuffer->update != update)	/* HandleInterpret */
   6675 		break;
   6676 	}
   6677 
   6678     }
   6679 }
   6680 
   6681 static IChar
   6682 doinput(XtermWidget xw)
   6683 {
   6684     TScreen *screen = TScreenOf(xw);
   6685 
   6686     while (!morePtyData(screen, VTbuffer))
   6687 	in_put(xw);
   6688     return nextPtyData(screen, VTbuffer);
   6689 }
   6690 
   6691 #if OPT_INPUT_METHOD
   6692 /*
   6693  *  For OverTheSpot, client has to inform the position for XIM preedit.
   6694  */
   6695 static void
   6696 PreeditPosition(XtermWidget xw)
   6697 {
   6698     TInput *input = lookupTInput(xw, (Widget) xw);
   6699     TScreen *screen = TScreenOf(xw);
   6700     CLineData *ld;
   6701     XPoint spot;
   6702     XVaNestedList list;
   6703 
   6704     if (input && input->xic
   6705 	&& (ld = getLineData(screen, screen->cur_row)) != NULL) {
   6706 	spot.x = (short) LineCursorX(screen, ld, screen->cur_col);
   6707 	spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent);
   6708 	list = XVaCreateNestedList(0,
   6709 				   XNSpotLocation, &spot,
   6710 				   XNForeground, T_COLOR(screen, TEXT_FG),
   6711 				   XNBackground, T_COLOR(screen, TEXT_BG),
   6712 				   (void *) 0);
   6713 	XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0);
   6714 	XFree(list);
   6715     }
   6716 }
   6717 #endif
   6718 
   6719 static void
   6720 WrapLine(XtermWidget xw)
   6721 {
   6722     TScreen *screen = TScreenOf(xw);
   6723     LineData *ld = getLineData(screen, screen->cur_row);
   6724 
   6725     if (ld != NULL) {
   6726 	/* mark that we had to wrap this line */
   6727 	LineSetFlag(ld, LINEWRAPPED);
   6728 	ShowWrapMarks(xw, screen->cur_row, ld);
   6729 	xtermAutoPrint(xw, '\n');
   6730 	xtermIndex(xw, 1);
   6731 	set_cur_col(screen, ScrnLeftMargin(xw));
   6732     }
   6733 }
   6734 
   6735 /*
   6736  * Process a string of characters according to the character set indicated by
   6737  * charset.  Worry about end of line conditions (wraparound if selected).
   6738  *
   6739  * It is possible to use CUP, etc., to move outside margins.  In that case, the
   6740  * right-margin is ineffective until the text (may) wrap and get within the
   6741  * margins.
   6742  */
   6743 void
   6744 dotext(XtermWidget xw,
   6745        DECNRCM_codes charset,
   6746        IChar *buf,		/* start of characters to process */
   6747        Cardinal len)		/* end */
   6748 {
   6749     TScreen *screen = TScreenOf(xw);
   6750 #if OPT_WIDE_CHARS
   6751     Cardinal chars_chomped = 1;
   6752     int next_col = screen->cur_col;
   6753 #else
   6754     int next_col, this_col;	/* must be signed */
   6755 #endif
   6756     Cardinal offset;
   6757     int rmargin = ScrnRightMargin(xw);
   6758 
   6759     xw->work.write_text = buf;
   6760 #if OPT_DEC_RECTOPS
   6761     xw->work.write_sums = NULL;
   6762 #endif
   6763 #if OPT_WIDE_CHARS
   6764     if (screen->vt100_graphics)
   6765 #endif
   6766     {
   6767 	DECNRCM_codes rightset = screen->gsets[(int) (screen->curgr)];
   6768 	if (charset != nrc_ASCII || rightset != nrc_ASCII) {
   6769 	    len = xtermCharSetOut(xw, len, charset);
   6770 	    if (len == 0)
   6771 		return;
   6772 	}
   6773     }
   6774 
   6775     if_OPT_XMC_GLITCH(screen, {
   6776 	Cardinal n;
   6777 	if (charset != '?') {
   6778 	    for (n = 0; n < len; n++) {
   6779 		if (buf[n] == XMC_GLITCH)
   6780 		    buf[n] = XMC_GLITCH + 1;
   6781 	    }
   6782 	}
   6783     });
   6784 
   6785 #if OPT_WIDE_CHARS
   6786     for (offset = 0;
   6787 	 offset < len && (chars_chomped > 0 || screen->do_wrap);
   6788 	 offset += chars_chomped) {
   6789 #if OPT_DEC_CHRSET
   6790 	CLineData *ld = getLineData(screen, screen->cur_row);
   6791 	int real_rmargin = (CSET_DOUBLE(GetLineDblCS(ld))
   6792 			    ? (rmargin / 2)
   6793 			    : rmargin);
   6794 #else
   6795 	int real_rmargin = rmargin;
   6796 #endif
   6797 	int last_col = LineMaxCol(screen, ld);
   6798 	int width_here = 0;
   6799 	int last_chomp = 0;
   6800 	Boolean force_wrap;
   6801 
   6802 	chars_chomped = 0;
   6803 	do {
   6804 	    int right = ((screen->cur_col > real_rmargin)
   6805 			 ? last_col
   6806 			 : real_rmargin);
   6807 	    int width_available = right + 1 - screen->cur_col;
   6808 	    Boolean need_wrap = False;
   6809 	    Boolean did_wrap = False;
   6810 
   6811 	    force_wrap = False;
   6812 
   6813 	    if (screen->do_wrap) {
   6814 		screen->do_wrap = False;
   6815 		if ((xw->flags & WRAPAROUND)) {
   6816 		    WrapLine(xw);
   6817 		    right = ((screen->cur_col > real_rmargin)
   6818 			     ? last_col
   6819 			     : real_rmargin);
   6820 		    width_available = right + 1 - screen->cur_col;
   6821 		    next_col = screen->cur_col;
   6822 		    did_wrap = True;
   6823 		}
   6824 	    }
   6825 
   6826 	    /*
   6827 	     * This can happen with left/right margins...
   6828 	     */
   6829 	    if (width_available <= 0) {
   6830 		break;
   6831 	    }
   6832 
   6833 	    /*
   6834 	     * Regarding the soft-hyphen aberration, see
   6835 	     * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html
   6836 	     */
   6837 	    while (width_here <= width_available
   6838 		   && chars_chomped < (len - offset)) {
   6839 		Cardinal n = chars_chomped + offset;
   6840 		if (!screen->utf8_mode
   6841 		    || (screen->vt100_graphics && charset == '0')) {
   6842 		    last_chomp = 1;
   6843 		} else if (screen->c1_printable &&
   6844 			   buf[n] >= 0x80 &&
   6845 			   buf[n] <= 0xa0) {
   6846 		    last_chomp = 1;
   6847 		} else {
   6848 		    last_chomp = CharWidth(screen, buf[n]);
   6849 		    if (last_chomp <= 0) {
   6850 			IChar ch = buf[n];
   6851 			Bool eat_it = !screen->utf8_mode && (ch > 127);
   6852 			if (ch == 0xad) {
   6853 			    /*
   6854 			     * Only display soft-hyphen if it happens to be at
   6855 			     * the right-margin.  While that means that only
   6856 			     * the displayed character could be selected for
   6857 			     * pasting, a well-behaved application would never
   6858 			     * send this, anyway...
   6859 			     */
   6860 			    if (width_here < width_available - 1) {
   6861 				eat_it = True;
   6862 			    } else {
   6863 				last_chomp = 1;
   6864 				eat_it = False;
   6865 			    }
   6866 			    TRACE(("...will%s display soft-hyphen\n",
   6867 				   eat_it ? " not" : ""));
   6868 			}
   6869 			/*
   6870 			 * Supposedly we dealt with combining characters and
   6871 			 * control characters in doparse().  Anything left over
   6872 			 * is junk that we will not attempt to display.
   6873 			 */
   6874 			if (eat_it) {
   6875 			    TRACE(("...will not display U+%04X\n", ch));
   6876 			    --len;
   6877 			    while (n < len) {
   6878 				buf[n] = buf[n + 1];
   6879 				++n;
   6880 			    }
   6881 			    last_chomp = 0;
   6882 			    chars_chomped--;
   6883 			}
   6884 		    }
   6885 		}
   6886 		width_here += last_chomp;
   6887 		chars_chomped++;
   6888 	    }
   6889 
   6890 	    if (width_here > width_available) {
   6891 		if (last_chomp > right + 1) {
   6892 		    break;	/* give up - it is too big */
   6893 		} else if (chars_chomped-- == 0) {
   6894 		    /* This can happen with left/right margins... */
   6895 		    break;
   6896 		}
   6897 		width_here -= last_chomp;
   6898 		if (chars_chomped > 0) {
   6899 		    if (!(xw->flags & WRAPAROUND)) {
   6900 			buf[chars_chomped + offset - 1] = buf[len - 1];
   6901 		    } else {
   6902 			need_wrap = True;
   6903 		    }
   6904 		}
   6905 	    } else if (width_here == width_available) {
   6906 		need_wrap = True;
   6907 	    } else if (chars_chomped != (len - offset)) {
   6908 		need_wrap = True;
   6909 	    }
   6910 
   6911 	    if (chars_chomped != 0 && next_col <= last_col) {
   6912 		WriteText(xw, offset, chars_chomped);
   6913 	    } else if (!did_wrap
   6914 		       && len > 0
   6915 		       && (xw->flags & WRAPAROUND)
   6916 		       && screen->cur_col > ScrnLeftMargin(xw)) {
   6917 		force_wrap = True;
   6918 		need_wrap = True;
   6919 	    }
   6920 	    next_col += width_here;
   6921 	    screen->do_wrap = need_wrap;
   6922 	} while (force_wrap);
   6923     }
   6924 
   6925     /*
   6926      * Remember that we wrote something to the screen, for use as a base of
   6927      * combining characters.  The logic above may have called cursor-forward
   6928      * or carriage-return operations which resets this flag, so we set it at
   6929      * the very end.
   6930      */
   6931     screen->char_was_written = True;
   6932 #else /* ! OPT_WIDE_CHARS */
   6933 
   6934     for (offset = 0; offset < len; offset += (Cardinal) this_col) {
   6935 #if OPT_DEC_CHRSET
   6936 	CLineData *ld = getLineData(screen, screen->cur_row);
   6937 #endif
   6938 	int right = ((screen->cur_col > rmargin)
   6939 		     ? screen->max_col
   6940 		     : rmargin);
   6941 
   6942 	int last_col = LineMaxCol(screen, ld);
   6943 	if (last_col > right)
   6944 	    last_col = right;
   6945 	this_col = last_col - screen->cur_col + 1;
   6946 	if (screen->do_wrap) {
   6947 	    screen->do_wrap = False;
   6948 	    if ((xw->flags & WRAPAROUND)) {
   6949 		WrapLine(xw);
   6950 	    }
   6951 	    this_col = 1;
   6952 	}
   6953 	if (offset + (Cardinal) this_col > len) {
   6954 	    this_col = (int) (len - offset);
   6955 	}
   6956 	next_col = screen->cur_col + this_col;
   6957 
   6958 	WriteText(xw, offset, (unsigned) this_col);
   6959 
   6960 	/*
   6961 	 * The call to WriteText updates screen->cur_col.
   6962 	 * If screen->cur_col is less than next_col, we must have
   6963 	 * hit the right margin - so set the do_wrap flag.
   6964 	 */
   6965 	screen->do_wrap = (Boolean) (screen->cur_col < next_col);
   6966     }
   6967 
   6968 #endif /* OPT_WIDE_CHARS */
   6969 }
   6970 
   6971 #if OPT_WIDE_CHARS
   6972 unsigned
   6973 visual_width(const IChar *str, Cardinal len)
   6974 {
   6975     /* returns the visual width of a string (doublewide characters count
   6976        as 2, normalwide characters count as 1) */
   6977     unsigned my_len = 0;
   6978     while (len) {
   6979 	int ch = (int) *str++;
   6980 	if (isWide(ch))
   6981 	    my_len += 2;
   6982 	else
   6983 	    my_len++;
   6984 	len--;
   6985     }
   6986     return my_len;
   6987 }
   6988 #endif
   6989 
   6990 #if HANDLE_STRUCT_NOTIFY
   6991 /* Flag icon name with "***" on window output when iconified.
   6992  */
   6993 static void
   6994 HandleStructNotify(Widget w GCC_UNUSED,
   6995 		   XtPointer closure GCC_UNUSED,
   6996 		   XEvent *event,
   6997 		   Boolean *cont GCC_UNUSED)
   6998 {
   6999     XtermWidget xw = term;
   7000     TScreen *screen = TScreenOf(xw);
   7001 
   7002     (void) screen;
   7003     TRACE_EVENT("HandleStructNotify", event, NULL, NULL);
   7004     switch (event->type) {
   7005     case MapNotify:
   7006 	resetZIconBeep(xw);
   7007 	mapstate = !IsUnmapped;
   7008 	break;
   7009     case UnmapNotify:
   7010 	mapstate = IsUnmapped;
   7011 	break;
   7012     case MappingNotify:
   7013 	XRefreshKeyboardMapping(&(event->xmapping));
   7014 	VTInitModifiers(xw);
   7015 	break;
   7016     case ConfigureNotify:
   7017 	if (event->xconfigure.window == XtWindow(toplevel)) {
   7018 #if !OPT_TOOLBAR
   7019 	    int height = event->xconfigure.height;
   7020 	    int width = event->xconfigure.width;
   7021 #endif
   7022 
   7023 #if USE_DOUBLE_BUFFER
   7024 	    discardRenderDraw(screen);
   7025 #endif /* USE_DOUBLE_BUFFER */
   7026 #if OPT_TOOLBAR
   7027 	    /*
   7028 	     * The notification is for the top-level widget, but we care about
   7029 	     * vt100 (ignore the tek4014 window).
   7030 	     */
   7031 	    if (screen->Vshow) {
   7032 		VTwin *Vwin = WhichVWin(screen);
   7033 		TbInfo *info = &(Vwin->tb_info);
   7034 		TbInfo save = *info;
   7035 
   7036 		if (info->menu_bar) {
   7037 		    XtVaGetValues(info->menu_bar,
   7038 				  XtNheight, &info->menu_height,
   7039 				  XtNborderWidth, &info->menu_border,
   7040 				  (XtPointer) 0);
   7041 
   7042 		    if (save.menu_height != info->menu_height
   7043 			|| save.menu_border != info->menu_border) {
   7044 
   7045 			TRACE(("...menu_height %d\n", info->menu_height));
   7046 			TRACE(("...menu_border %d\n", info->menu_border));
   7047 			TRACE(("...had height  %d, border %d\n",
   7048 			       save.menu_height,
   7049 			       save.menu_border));
   7050 
   7051 			/*
   7052 			 * Window manager still may be using the old values.
   7053 			 * Try to fool it.
   7054 			 */
   7055 			REQ_RESIZE((Widget) xw,
   7056 				   screen->fullVwin.fullwidth,
   7057 				   (Dimension) (info->menu_height
   7058 						- save.menu_height
   7059 						+ screen->fullVwin.fullheight),
   7060 				   NULL, NULL);
   7061 			repairSizeHints();
   7062 		    }
   7063 		}
   7064 	    }
   7065 #else
   7066 	    if (!xw->work.doing_resize
   7067 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
   7068 		&& !(resource.buffered && UsingRenderFont(xw))	/* buggyXft */
   7069 #endif
   7070 		&& (height != xw->hints.height
   7071 		    || width != xw->hints.width)) {
   7072 		/*
   7073 		 * This is a special case: other calls to RequestResize that
   7074 		 * could set the screensize arbitrarily are via escape
   7075 		 * sequences, and we've limited resizing.  But a configure
   7076 		 * notify is from the window manager, presumably under control
   7077 		 * of the interactive user (ignoring abuse of wmctrl).  Ignore
   7078 		 * the limit for this case.
   7079 		 */
   7080 		int saved_limit = xw->misc.limit_resize;
   7081 		xw->misc.limit_resize = 0;
   7082 		RequestResize(xw, height, width, False);
   7083 		xw->misc.limit_resize = saved_limit;
   7084 	    }
   7085 #endif /* OPT_TOOLBAR */
   7086 	}
   7087 	break;
   7088     }
   7089 }
   7090 #endif /* HANDLE_STRUCT_NOTIFY */
   7091 
   7092 #if OPT_BLINK_CURS
   7093 static int
   7094 DoStartBlinking(TScreen *screen)
   7095 {
   7096     int actual = ((screen->cursor_blink == cbTrue ||
   7097 		   screen->cursor_blink == cbAlways)
   7098 		  ? 1
   7099 		  : 0);
   7100     int wanted = screen->cursor_blink_esc ? 1 : 0;
   7101     int result;
   7102     if (screen->cursor_blink_xor) {
   7103 	result = actual ^ wanted;
   7104     } else {
   7105 	result = actual | wanted;
   7106     }
   7107     return result;
   7108 }
   7109 
   7110 static void
   7111 SetCursorBlink(XtermWidget xw, BlinkOps enable)
   7112 {
   7113     TScreen *screen = TScreenOf(xw);
   7114 
   7115     if (SettableCursorBlink(screen)) {
   7116 	screen->cursor_blink = enable;
   7117     }
   7118     if (DoStartBlinking(screen)) {
   7119 	StartBlinking(xw);
   7120     } else {
   7121 	/* EMPTY */
   7122 #if OPT_BLINK_TEXT
   7123 	reallyStopBlinking(xw);
   7124 #else
   7125 	StopBlinking(xw);
   7126 #endif
   7127     }
   7128     update_cursorblink();
   7129 }
   7130 
   7131 void
   7132 ToggleCursorBlink(XtermWidget xw)
   7133 {
   7134     TScreen *screen = TScreenOf(xw);
   7135 
   7136     if (screen->cursor_blink == cbTrue) {
   7137 	SetCursorBlink(xw, cbFalse);
   7138     } else if (screen->cursor_blink == cbFalse) {
   7139 	SetCursorBlink(xw, cbTrue);
   7140     }
   7141 }
   7142 #endif
   7143 
   7144 /*
   7145  * process ANSI modes set, reset
   7146  */
   7147 static void
   7148 ansi_modes(XtermWidget xw, BitFunc func)
   7149 {
   7150     int i;
   7151 
   7152     for (i = 0; i < nparam; ++i) {
   7153 	switch (GetParam(i)) {
   7154 	case 2:		/* KAM (if set, keyboard locked */
   7155 	    (*func) (&xw->keyboard.flags, MODE_KAM);
   7156 	    break;
   7157 
   7158 	case 4:		/* IRM                          */
   7159 	    (*func) (&xw->flags, INSERT);
   7160 	    break;
   7161 
   7162 	case 12:		/* SRM (if set, local echo      */
   7163 	    (*func) (&xw->keyboard.flags, MODE_SRM);
   7164 	    break;
   7165 
   7166 	case 20:		/* LNM                          */
   7167 	    (*func) (&xw->flags, LINEFEED);
   7168 	    update_autolinefeed();
   7169 	    break;
   7170 	}
   7171     }
   7172 }
   7173 
   7174 #define IsSM() (func == bitset)
   7175 
   7176 #define set_bool_mode(flag) \
   7177 	flag = (Boolean) IsSM()
   7178 
   7179 static void
   7180 really_set_mousemode(XtermWidget xw,
   7181 		     Bool enabled,
   7182 		     XtermMouseModes mode)
   7183 {
   7184     TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF;
   7185     if (okSendMousePos(xw) != MOUSE_OFF)
   7186 	xtermShowPointer(xw, True);
   7187 }
   7188 
   7189 #define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode)
   7190 
   7191 #if OPT_PASTE64 || OPT_READLINE
   7192 #define set_mouseflag(f)		\
   7193 	(IsSM()				\
   7194 	 ? SCREEN_FLAG_set(screen, f)	\
   7195 	 : SCREEN_FLAG_unset(screen, f))
   7196 #endif
   7197 
   7198 /*
   7199  * DEC 070, pp 5-29 to 5-30 (DECLRMM).
   7200  * DEC 070, pp 5-71 to 5-72 (DECCOLM).
   7201  *
   7202  * The descriptions for DECLRMM and DECCOLM agree that setting DECLRMM resets
   7203  * double-sized mode to single-size, and that if DECLRMM is being set, then
   7204  * double-sized mode is disabled.  Resetting DECLRMM has no effect on the
   7205  * double-sized mode.  The description of DECCOLM has an apparent error in its
   7206  * pseudo-code (because it is inconsistent with the description of DECLRMM),
   7207  * indicating that left_right_margins_mode is changed to SETABLE no matter
   7208  * which way DECCOLM is set.
   7209  */
   7210 static void
   7211 set_column_mode(XtermWidget xw)
   7212 {
   7213     TScreen *screen = TScreenOf(xw);
   7214 
   7215     /* switch 80/132 columns clears the screen and sets to single-width */
   7216     xterm_ResetDouble(xw);
   7217     resetMargins(xw);
   7218     CursorSet(screen, 0, 0, xw->flags);
   7219 }
   7220 
   7221 /*
   7222  * DEC 070, pp 5-29 to 5-30.
   7223  */
   7224 static void
   7225 set_left_right_margin_mode(XtermWidget xw)
   7226 {
   7227     TScreen *screen = TScreenOf(xw);
   7228 
   7229     if (screen->vtXX_level >= 4) {
   7230 	if (IsLeftRightMode(xw)) {
   7231 	    xterm_ResetDouble(xw);
   7232 	} else {
   7233 	    reset_lr_margins(screen);
   7234 	}
   7235     }
   7236 }
   7237 
   7238 /*
   7239  * process DEC private modes set, reset
   7240  */
   7241 static void
   7242 dpmodes(XtermWidget xw, BitFunc func)
   7243 {
   7244     TScreen *screen = TScreenOf(xw);
   7245     int i, j;
   7246     unsigned myflags;
   7247 
   7248     TRACE(("changing %d DEC private modes\n", nparam));
   7249     if_STATUS_LINE(screen, {
   7250 	return;
   7251     });
   7252     for (i = 0; i < nparam; ++i) {
   7253 	int code = GetParam(i);
   7254 
   7255 	TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code));
   7256 	switch ((DECSET_codes) code) {
   7257 	case srm_DECCKM:
   7258 	    (*func) (&xw->keyboard.flags, MODE_DECCKM);
   7259 	    update_appcursor();
   7260 	    break;
   7261 	case srm_DECANM:	/* ANSI/VT52 mode      */
   7262 #if OPT_STATUS_LINE
   7263 	    if (screen->status_type == 2 && screen->status_active) {
   7264 		/* DEC 070, section 14.2.3 item 4 */
   7265 		/* EMPTY */ ;
   7266 	    } else
   7267 #endif
   7268 	    if (IsSM()) {	/* ANSI (VT100) */
   7269 		/*
   7270 		 * Setting DECANM should have no effect, since this function
   7271 		 * cannot be reached from vt52 mode.
   7272 		 */
   7273 		/* EMPTY */ ;
   7274 	    }
   7275 #if OPT_VT52_MODE
   7276 	    else if (screen->terminal_id >= 100) {	/* VT52 */
   7277 		TRACE(("DECANM terminal_id %d, vtXX_level %d\n",
   7278 		       screen->terminal_id,
   7279 		       screen->vtXX_level));
   7280 		/*
   7281 		 * According to DEC STD 070 section A.5.5, the various VT100
   7282 		 * modes have undefined behavior when entering/exiting VT52
   7283 		 * mode.  xterm saves/restores/initializes the most commonly
   7284 		 * used settings, but a real VT100 or VT520 may differ.
   7285 		 *
   7286 		 * For instance, DEC's documentation goes on to comment that
   7287 		 * while the VT52 uses hardware tabs (8 columns), the emulation
   7288 		 * (e.g., a VT420) does not alter those tab settings when
   7289 		 * switching modes.
   7290 		 */
   7291 		set_vtXX_level(screen, 0);
   7292 		screen->vt52_save_flags = xw->flags;
   7293 		xw->flags = 0;
   7294 		screen->vt52_save_curgl = screen->curgl;
   7295 		screen->vt52_save_curgr = screen->curgr;
   7296 		screen->vt52_save_curss = screen->curss;
   7297 		saveCharsets(screen, screen->vt52_save_gsets);
   7298 		resetCharsets(screen);
   7299 		InitParams();	/* ignore the remaining params, if any */
   7300 		update_vt52_vt100_settings();
   7301 		RequestResize(xw, -1, 80, True);
   7302 	    }
   7303 #endif
   7304 	    break;
   7305 	case srm_DECCOLM:
   7306 	    if (screen->c132) {
   7307 		Boolean willResize = ((j = IsSM()
   7308 				       ? 132
   7309 				       : 80)
   7310 				      != ((xw->flags & IN132COLUMNS)
   7311 					  ? 132
   7312 					  : 80)
   7313 				      || j != MaxCols(screen));
   7314 		if (!(xw->flags & NOCLEAR_COLM)) {
   7315 #if OPT_STATUS_LINE
   7316 		    if (IsStatusShown(screen))
   7317 			clear_status_line(xw);
   7318 #endif
   7319 		    ClearScreen(xw);
   7320 		}
   7321 		if (willResize)
   7322 		    RequestResize(xw, -1, j, True);
   7323 		(*func) (&xw->flags, IN132COLUMNS);
   7324 		set_column_mode(xw);
   7325 	    }
   7326 	    break;
   7327 	case srm_DECSCLM:	/* (slow scroll)        */
   7328 	    if (IsSM()) {
   7329 		screen->jumpscroll = 0;
   7330 		if (screen->scroll_amt)
   7331 		    FlushScroll(xw);
   7332 	    } else
   7333 		screen->jumpscroll = 1;
   7334 	    (*func) (&xw->flags, SMOOTHSCROLL);
   7335 	    update_jumpscroll();
   7336 	    break;
   7337 	case srm_DECSCNM:
   7338 	    myflags = xw->flags;
   7339 	    (*func) (&xw->flags, REVERSE_VIDEO);
   7340 	    if ((xw->flags ^ myflags) & REVERSE_VIDEO)
   7341 		ReverseVideo(xw);
   7342 	    /* update_reversevideo done in RevVid */
   7343 	    break;
   7344 
   7345 	case srm_DECOM:
   7346 	    (*func) (&xw->flags, ORIGIN);
   7347 	    CursorSet(screen, 0, 0, xw->flags);
   7348 	    break;
   7349 
   7350 	case srm_DECAWM:
   7351 	    (*func) (&xw->flags, WRAPAROUND);
   7352 	    update_autowrap();
   7353 	    break;
   7354 	case srm_DECARM:
   7355 	    /* ignore autorepeat
   7356 	     * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only
   7357 	     * for the whole display - not limited to a given window.
   7358 	     */
   7359 	    break;
   7360 	case srm_X10_MOUSE:	/* MIT bogus sequence           */
   7361 	    MotionOff(screen, xw);
   7362 	    set_mousemode(X10_MOUSE);
   7363 	    break;
   7364 #if OPT_TOOLBAR
   7365 	case srm_RXVT_TOOLBAR:
   7366 	    ShowToolbar(IsSM());
   7367 	    break;
   7368 #else
   7369 	case srm_DECEDM:	/* vt330:edit */
   7370 	    break;
   7371 #endif
   7372 #if OPT_BLINK_CURS
   7373 	case srm_ATT610_BLINK:	/* AT&T 610: Start/stop blinking cursor */
   7374 	    if (SettableCursorBlink(screen)) {
   7375 		set_bool_mode(screen->cursor_blink_esc);
   7376 		UpdateCursorBlink(xw);
   7377 	    }
   7378 	    break;
   7379 	case srm_CURSOR_BLINK_OPS:
   7380 	    /* intentionally ignored (this is user-preference) */
   7381 	    break;
   7382 	case srm_XOR_CURSOR_BLINKS:
   7383 	    /* intentionally ignored (this is user-preference) */
   7384 	    break;
   7385 #else
   7386 	case srm_DECKANAM:	/* vt382:Katakana shift */
   7387 	case srm_DECSCFDM:	/* vt330:space compression field delimiter */
   7388 	case srm_DECTEM:	/* vt330:transmission execution */
   7389 	    break;
   7390 #endif
   7391 	case srm_DECPFF:	/* print form feed */
   7392 	    set_bool_mode(PrinterOf(screen).printer_formfeed);
   7393 	    break;
   7394 	case srm_DECPEX:	/* print extent */
   7395 	    set_bool_mode(PrinterOf(screen).printer_extent);
   7396 	    break;
   7397 	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
   7398 	    set_bool_mode(screen->cursor_set);
   7399 	    break;
   7400 	case srm_RXVT_SCROLLBAR:
   7401 	    if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF))
   7402 		ToggleScrollBar(xw);
   7403 	    break;
   7404 #if OPT_SHIFT_FONTS
   7405 	case srm_RXVT_FONTSIZE:
   7406 	    set_bool_mode(xw->misc.shift_fonts);
   7407 	    break;
   7408 #endif
   7409 #if OPT_TEK4014
   7410 	case srm_DECTEK:
   7411 	    if (IsSM() && !(screen->inhibit & I_TEK)) {
   7412 		FlushLog(xw);
   7413 		TEK4014_ACTIVE(xw) = True;
   7414 		TRACE(("Tek4014 is now active...\n"));
   7415 		update_vttekmode();
   7416 	    }
   7417 	    break;
   7418 #endif
   7419 	case srm_132COLS:	/* 132 column mode              */
   7420 	    set_bool_mode(screen->c132);
   7421 	    update_allow132();
   7422 	    break;
   7423 	case srm_CURSES_HACK:
   7424 	    set_bool_mode(screen->curses);
   7425 	    update_cursesemul();
   7426 	    break;
   7427 	case srm_DECNRCM:	/* national charset (VT220) */
   7428 	    if (screen->vtXX_level >= 2) {
   7429 		if ((*func) (&xw->flags, NATIONAL)) {
   7430 		    modified_DECNRCM(xw);
   7431 		}
   7432 	    }
   7433 	    break;
   7434 #if OPT_PRINT_GRAPHICS
   7435 	case srm_DECGEPM:	/* Graphics Expanded Print Mode */
   7436 	    set_bool_mode(screen->graphics_expanded_print_mode);
   7437 	    break;
   7438 #endif
   7439 	case srm_MARGIN_BELL:	/* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
   7440 	    if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_mode)) {
   7441 		set_bool_mode(screen->marginbell);
   7442 		if (!screen->marginbell)
   7443 		    screen->bellArmed = -1;
   7444 		update_marginbell();
   7445 	    }
   7446 	    break;
   7447 	case srm_REVERSEWRAP:	/* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
   7448 	    if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_syntax)) {
   7449 		(*func) (&xw->flags, REVERSEWRAP);
   7450 		update_reversewrap();
   7451 	    }
   7452 	    break;
   7453 	case srm_REVERSEWRAP2:	/* extended reverse wraparound (xterm) */
   7454 	    (*func) (&xw->flags, REVERSEWRAP2);
   7455 	    break;
   7456 #ifdef ALLOWLOGGING
   7457 	case srm_ALLOWLOGGING:	/* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
   7458 	    if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_background_mode)) {
   7459 #ifdef ALLOWLOGFILEONOFF
   7460 		/*
   7461 		 * if this feature is enabled, logging may be
   7462 		 * enabled and disabled via escape sequences.
   7463 		 */
   7464 		if (IsSM())
   7465 		    StartLog(xw);
   7466 		else
   7467 		    CloseLog(xw);
   7468 #else
   7469 		Bell(xw, XkbBI_Info, 0);
   7470 		Bell(xw, XkbBI_Info, 0);
   7471 #endif /* ALLOWLOGFILEONOFF */
   7472 	    }
   7473 	    break;
   7474 #elif OPT_PRINT_GRAPHICS
   7475 	case srm_DECGPBM:	/* Graphics Print Background Mode */
   7476 	    set_bool_mode(screen->graphics_print_background_mode);
   7477 	    break;
   7478 #endif /* ALLOWLOGGING */
   7479 	case srm_OPT_ALTBUF_CURSOR:	/* optional alternate buffer and clear (xterm) */
   7480 	    if (!xw->misc.titeInhibit) {
   7481 		if (IsSM()) {
   7482 		    CursorSave(xw);
   7483 		    ToAlternate(xw, True);
   7484 		    ClearScreen(xw);
   7485 		} else {
   7486 		    FromAlternate(xw, False);
   7487 		    CursorRestore(xw);
   7488 		}
   7489 	    } else if (IsSM()) {
   7490 		do_ti_xtra_scroll(xw);
   7491 	    }
   7492 	    break;
   7493 	case srm_OPT_ALTBUF:	/* optional alternate buffer and clear (xterm) */
   7494 	    if (!xw->misc.titeInhibit) {
   7495 		if (IsSM()) {
   7496 		    ToAlternate(xw, False);
   7497 		} else {
   7498 		    if (screen->whichBuf)
   7499 			ClearScreen(xw);
   7500 		    FromAlternate(xw, False);
   7501 		}
   7502 	    } else if (IsSM()) {
   7503 		do_ti_xtra_scroll(xw);
   7504 	    }
   7505 	    break;
   7506 	case srm_ALTBUF:	/* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
   7507 	    if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_rotated_print_mode)) {
   7508 		if (!xw->misc.titeInhibit) {
   7509 		    if (IsSM()) {
   7510 			ToAlternate(xw, False);
   7511 		    } else {
   7512 			FromAlternate(xw, False);
   7513 		    }
   7514 		} else if (IsSM()) {
   7515 		    do_ti_xtra_scroll(xw);
   7516 		}
   7517 	    }
   7518 	    break;
   7519 	case srm_DECNKM:
   7520 	    (*func) (&xw->keyboard.flags, MODE_DECKPAM);
   7521 	    update_appkeypad();
   7522 	    break;
   7523 	case srm_DECBKM:
   7524 	    /* back-arrow mapped to backspace or delete(D) */
   7525 	    (*func) (&xw->keyboard.flags, MODE_DECBKM);
   7526 	    TRACE(("DECSET DECBKM %s\n",
   7527 		   BtoS(xw->keyboard.flags & MODE_DECBKM)));
   7528 	    update_decbkm();
   7529 	    break;
   7530 	case srm_DECLRMM:
   7531 	    if (screen->vtXX_level >= 4) {	/* VT420 */
   7532 		(*func) (&xw->flags, LEFT_RIGHT);
   7533 		set_left_right_margin_mode(xw);
   7534 	    }
   7535 	    break;
   7536 #if OPT_SIXEL_GRAPHICS
   7537 	case srm_DECSDM:	/* sixel display mode (no scrolling) */
   7538 	    if (optSixelGraphics(screen)) {	/* FIXME: VT24x did not scroll sixel graphics */
   7539 		(*func) (&xw->keyboard.flags, MODE_DECSDM);
   7540 		TRACE(("DECSET/DECRST DECSDM %s (resource default is %s)\n",
   7541 		       BtoS(xw->keyboard.flags & MODE_DECSDM),
   7542 		       BtoS(!screen->sixel_scrolling)));
   7543 		update_decsdm();
   7544 	    }
   7545 	    break;
   7546 #endif
   7547 	case srm_DECNCSM:
   7548 	    if (screen->vtXX_level >= 5) {	/* VT510 */
   7549 		(*func) (&xw->flags, NOCLEAR_COLM);
   7550 	    }
   7551 	    break;
   7552 	case srm_VT200_MOUSE:	/* xterm bogus sequence         */
   7553 	    MotionOff(screen, xw);
   7554 	    set_mousemode(VT200_MOUSE);
   7555 	    break;
   7556 	case srm_VT200_HIGHLIGHT_MOUSE:	/* xterm sequence w/hilite tracking */
   7557 	    MotionOff(screen, xw);
   7558 	    set_mousemode(VT200_HIGHLIGHT_MOUSE);
   7559 	    break;
   7560 	case srm_BTN_EVENT_MOUSE:
   7561 	    MotionOff(screen, xw);
   7562 	    set_mousemode(BTN_EVENT_MOUSE);
   7563 	    break;
   7564 	case srm_ANY_EVENT_MOUSE:
   7565 	    set_mousemode(ANY_EVENT_MOUSE);
   7566 	    if (screen->send_mouse_pos == MOUSE_OFF) {
   7567 		MotionOff(screen, xw);
   7568 	    } else {
   7569 		MotionOn(screen, xw);
   7570 	    }
   7571 	    break;
   7572 #if OPT_FOCUS_EVENT
   7573 	case srm_FOCUS_EVENT_MOUSE:
   7574 	    set_bool_mode(screen->send_focus_pos);
   7575 	    break;
   7576 #endif
   7577 	case srm_EXT_MODE_MOUSE:
   7578 	    /* FALLTHRU */
   7579 	case srm_SGR_EXT_MODE_MOUSE:
   7580 	    /* FALLTHRU */
   7581 	case srm_URXVT_EXT_MODE_MOUSE:
   7582 	    /* FALLTHRU */
   7583 	case srm_PIXEL_POSITION_MOUSE:
   7584 	    /*
   7585 	     * Rather than choose an arbitrary precedence among the coordinate
   7586 	     * modes, they are mutually exclusive.  For consistency, a reset is
   7587 	     * only effective against the matching mode.
   7588 	     */
   7589 	    if (IsSM()) {
   7590 		screen->extend_coords = code;
   7591 	    } else if (screen->extend_coords == code) {
   7592 		screen->extend_coords = 0;
   7593 	    }
   7594 	    break;
   7595 	case srm_ALTERNATE_SCROLL:
   7596 	    set_bool_mode(screen->alternateScroll);
   7597 	    break;
   7598 	case srm_RXVT_SCROLL_TTY_OUTPUT:
   7599 	    set_bool_mode(screen->scrollttyoutput);
   7600 	    update_scrollttyoutput();
   7601 	    break;
   7602 	case srm_RXVT_SCROLL_TTY_KEYPRESS:
   7603 	    set_bool_mode(screen->scrollkey);
   7604 	    update_scrollkey();
   7605 	    break;
   7606 	case srm_EIGHT_BIT_META:
   7607 	    if (screen->eight_bit_meta != ebNever) {
   7608 		set_bool_mode(screen->eight_bit_meta);
   7609 	    }
   7610 	    break;
   7611 #if OPT_NUM_LOCK
   7612 	case srm_REAL_NUMLOCK:
   7613 	    set_bool_mode(xw->misc.real_NumLock);
   7614 	    update_num_lock();
   7615 	    break;
   7616 	case srm_META_SENDS_ESC:
   7617 	    set_bool_mode(screen->meta_sends_esc);
   7618 	    update_meta_esc();
   7619 	    break;
   7620 #endif
   7621 	case srm_DELETE_IS_DEL:
   7622 	    set_bool_mode(screen->delete_is_del);
   7623 	    update_delete_del();
   7624 	    break;
   7625 #if OPT_NUM_LOCK
   7626 	case srm_ALT_SENDS_ESC:
   7627 	    set_bool_mode(screen->alt_sends_esc);
   7628 	    update_alt_esc();
   7629 	    break;
   7630 #endif
   7631 	case srm_KEEP_SELECTION:
   7632 	    set_bool_mode(screen->keepSelection);
   7633 	    update_keepSelection();
   7634 	    break;
   7635 	case srm_SELECT_TO_CLIPBOARD:
   7636 	    set_bool_mode(screen->selectToClipboard);
   7637 	    update_selectToClipboard();
   7638 	    break;
   7639 	case srm_BELL_IS_URGENT:
   7640 	    set_bool_mode(screen->bellIsUrgent);
   7641 	    update_bellIsUrgent();
   7642 	    break;
   7643 	case srm_POP_ON_BELL:
   7644 	    set_bool_mode(screen->poponbell);
   7645 	    update_poponbell();
   7646 	    break;
   7647 	case srm_KEEP_CLIPBOARD:
   7648 	    set_bool_mode(screen->keepClipboard);
   7649 	    update_keepClipboard();
   7650 	    break;
   7651 	case srm_ALLOW_ALTBUF:
   7652 	    if (IsSM()) {
   7653 		xw->misc.titeInhibit = False;
   7654 	    } else if (!xw->misc.titeInhibit) {
   7655 		xw->misc.titeInhibit = True;
   7656 		FromAlternate(xw, False);
   7657 	    }
   7658 	    update_titeInhibit();
   7659 	    break;
   7660 	case srm_SAVE_CURSOR:
   7661 	    if (!xw->misc.titeInhibit) {
   7662 		if (IsSM())
   7663 		    CursorSave(xw);
   7664 		else
   7665 		    CursorRestore(xw);
   7666 	    }
   7667 	    break;
   7668 	case srm_FAST_SCROLL:
   7669 	    set_bool_mode(screen->fastscroll);
   7670 	    break;
   7671 #if OPT_TCAP_FKEYS
   7672 	case srm_TCAP_FKEYS:
   7673 	    set_keyboard_type(xw, keyboardIsTermcap, IsSM());
   7674 	    break;
   7675 #endif
   7676 #if OPT_SUN_FUNC_KEYS
   7677 	case srm_SUN_FKEYS:
   7678 	    set_keyboard_type(xw, keyboardIsSun, IsSM());
   7679 	    break;
   7680 #endif
   7681 #if OPT_HP_FUNC_KEYS
   7682 	case srm_HP_FKEYS:
   7683 	    set_keyboard_type(xw, keyboardIsHP, IsSM());
   7684 	    break;
   7685 #endif
   7686 #if OPT_SCO_FUNC_KEYS
   7687 	case srm_SCO_FKEYS:
   7688 	    set_keyboard_type(xw, keyboardIsSCO, IsSM());
   7689 	    break;
   7690 #endif
   7691 	case srm_LEGACY_FKEYS:
   7692 	    set_keyboard_type(xw, keyboardIsLegacy, IsSM());
   7693 	    break;
   7694 #if OPT_SUNPC_KBD
   7695 	case srm_VT220_FKEYS:
   7696 	    set_keyboard_type(xw, keyboardIsVT220, IsSM());
   7697 	    break;
   7698 #endif
   7699 #if OPT_PASTE64 || OPT_READLINE
   7700 	case srm_PASTE_IN_BRACKET:
   7701 	    set_mouseflag(paste_brackets);
   7702 	    break;
   7703 #endif
   7704 #if OPT_READLINE
   7705 	case srm_BUTTON1_MOVE_POINT:
   7706 	    set_mouseflag(click1_moves);
   7707 	    break;
   7708 	case srm_BUTTON2_MOVE_POINT:
   7709 	    set_mouseflag(paste_moves);
   7710 	    break;
   7711 	case srm_DBUTTON3_DELETE:
   7712 	    set_mouseflag(dclick3_deletes);
   7713 	    break;
   7714 	case srm_PASTE_QUOTE:
   7715 	    set_mouseflag(paste_quotes);
   7716 	    break;
   7717 	case srm_PASTE_LITERAL_NL:
   7718 	    set_mouseflag(paste_literal_nl);
   7719 	    break;
   7720 #endif /* OPT_READLINE */
   7721 #if OPT_GRAPHICS
   7722 	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
   7723 	    TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n",
   7724 		   BtoS(screen->privatecolorregisters),
   7725 		   BtoS(screen->privatecolorregisters0)));
   7726 	    set_bool_mode(screen->privatecolorregisters);
   7727 	    update_privatecolorregisters();
   7728 	    break;
   7729 #endif
   7730 #if OPT_SIXEL_GRAPHICS
   7731 	case srm_SIXEL_SCROLLS_RIGHT:	/* sixel scrolling moves cursor to right */
   7732 	    if (optSixelGraphics(screen)) {	/* FIXME: VT24x did not scroll sixel graphics */
   7733 		set_bool_mode(screen->sixel_scrolls_right);
   7734 		TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n",
   7735 		       BtoS(screen->sixel_scrolls_right),
   7736 		       BtoS(TScreenOf(xw)->sixel_scrolls_right)));
   7737 	    }
   7738 	    break;
   7739 #endif
   7740 	case srm_DEC131TM:	/* ignore */
   7741 	case srm_DECAAM:	/* ignore */
   7742 	case srm_DECARSM:	/* ignore */
   7743 	case srm_DECATCBM:	/* ignore */
   7744 	case srm_DECATCUM:	/* ignore */
   7745 	case srm_DECBBSM:	/* ignore */
   7746 	case srm_DECCANSM:	/* ignore */
   7747 	case srm_DECCAPSLK:	/* ignore */
   7748 	case srm_DECCRTSM:	/* ignore */
   7749 	case srm_DECECM:	/* ignore */
   7750 	case srm_DECEKEM:	/* ignore */
   7751 	case srm_DECESKM:	/* ignore */
   7752 	case srm_DECFWM:	/* ignore */
   7753 	case srm_DECHCCM:	/* ignore */
   7754 	case srm_DECHDPXM:	/* ignore */
   7755 	case srm_DECHEM:	/* ignore */
   7756 	case srm_DECHWUM:	/* ignore */
   7757 	case srm_DECIPEM:	/* ignore */
   7758 	case srm_DECKBUM:	/* ignore */
   7759 	case srm_DECKLHIM:	/* ignore */
   7760 	case srm_DECKKDM:	/* ignore */
   7761 	case srm_DECKPM:	/* ignore */
   7762 	case srm_DECLTM:	/* ignore */
   7763 	case srm_DECMCM:	/* ignore */
   7764 	case srm_DECNAKB:	/* ignore */
   7765 	case srm_DECNULM:	/* ignore */
   7766 	case srm_DECNUMLK:	/* ignore */
   7767 	case srm_DECOSCNM:	/* ignore */
   7768 	case srm_DECPCCM:	/* ignore */
   7769 	case srm_DECRLCM:	/* ignore */
   7770 	case srm_DECRLM:	/* ignore */
   7771 	case srm_DECRPL:	/* ignore */
   7772 	case srm_DECVCCM:	/* ignore */
   7773 	case srm_DECXRLM:	/* ignore */
   7774 	default:
   7775 	    TRACE(("DATA_ERROR: unknown private code %d\n", code));
   7776 	    break;
   7777 	}
   7778     }
   7779 }
   7780 
   7781 /*
   7782  * process xterm private modes save
   7783  */
   7784 static void
   7785 savemodes(XtermWidget xw)
   7786 {
   7787     TScreen *screen = TScreenOf(xw);
   7788     int i;
   7789 
   7790     if_STATUS_LINE(screen, {
   7791 	return;
   7792     });
   7793     for (i = 0; i < nparam; i++) {
   7794 	int code = GetParam(i);
   7795 
   7796 	TRACE(("savemodes %d\n", code));
   7797 	switch ((DECSET_codes) code) {
   7798 	case srm_DECCKM:
   7799 	    DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM);
   7800 	    break;
   7801 	case srm_DECANM:	/* ANSI/VT52 mode      */
   7802 	    /* no effect */
   7803 	    break;
   7804 	case srm_DECCOLM:
   7805 	    if (screen->c132)
   7806 		DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS);
   7807 	    break;
   7808 	case srm_DECSCLM:	/* (slow scroll)        */
   7809 	    DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL);
   7810 	    break;
   7811 	case srm_DECSCNM:
   7812 	    DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO);
   7813 	    break;
   7814 	case srm_DECOM:
   7815 	    DoSM(DP_DECOM, xw->flags & ORIGIN);
   7816 	    break;
   7817 	case srm_DECAWM:
   7818 	    DoSM(DP_DECAWM, xw->flags & WRAPAROUND);
   7819 	    break;
   7820 	case srm_DECARM:
   7821 	    /* ignore autorepeat */
   7822 	    break;
   7823 	case srm_X10_MOUSE:	/* mouse bogus sequence */
   7824 	    DoSM(DP_X_X10MSE, screen->send_mouse_pos);
   7825 	    break;
   7826 #if OPT_TOOLBAR
   7827 	case srm_RXVT_TOOLBAR:
   7828 	    DoSM(DP_TOOLBAR, resource.toolBar);
   7829 	    break;
   7830 #else
   7831 	case srm_DECEDM:	/* vt330:edit */
   7832 	    break;
   7833 #endif
   7834 #if OPT_BLINK_CURS
   7835 	case srm_ATT610_BLINK:	/* AT&T 610: Start/stop blinking cursor */
   7836 	    if (SettableCursorBlink(screen)) {
   7837 		DoSM(DP_CRS_BLINK, screen->cursor_blink_esc);
   7838 	    }
   7839 	    break;
   7840 	case srm_CURSOR_BLINK_OPS:
   7841 	    /* intentionally ignored (this is user-preference) */
   7842 	    break;
   7843 	case srm_XOR_CURSOR_BLINKS:
   7844 	    /* intentionally ignored (this is user-preference) */
   7845 	    break;
   7846 #else
   7847 	case srm_DECKANAM:	/* vt382:Katakana shift */
   7848 	case srm_DECSCFDM:	/* vt330:space compression field delimiter */
   7849 	case srm_DECTEM:	/* vt330:transmission execution */
   7850 	    break;
   7851 #endif
   7852 	case srm_DECPFF:	/* print form feed */
   7853 	    DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
   7854 	    break;
   7855 	case srm_DECPEX:	/* print extent */
   7856 	    DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
   7857 	    break;
   7858 	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
   7859 	    DoSM(DP_CRS_VISIBLE, screen->cursor_set);
   7860 	    break;
   7861 	case srm_RXVT_SCROLLBAR:
   7862 	    DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0));
   7863 	    break;
   7864 #if OPT_SHIFT_FONTS
   7865 	case srm_RXVT_FONTSIZE:
   7866 	    DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
   7867 	    break;
   7868 #endif
   7869 #if OPT_TEK4014
   7870 	case srm_DECTEK:
   7871 	    DoSM(DP_DECTEK, TEK4014_ACTIVE(xw));
   7872 	    break;
   7873 #endif
   7874 	case srm_132COLS:	/* 132 column mode              */
   7875 	    DoSM(DP_X_DECCOLM, screen->c132);
   7876 	    break;
   7877 	case srm_CURSES_HACK:	/* curses hack                  */
   7878 	    DoSM(DP_X_MORE, screen->curses);
   7879 	    break;
   7880 	case srm_DECNRCM:	/* national charset (VT220) */
   7881 	    if (screen->vtXX_level >= 2) {
   7882 		DoSM(DP_DECNRCM, xw->flags & NATIONAL);
   7883 	    }
   7884 	    break;
   7885 #if OPT_PRINT_GRAPHICS
   7886 	case srm_DECGEPM:	/* Graphics Expanded Print Mode */
   7887 	    DoSM(DP_DECGEPM, screen->graphics_expanded_print_mode);
   7888 	    break;
   7889 #endif
   7890 	case srm_MARGIN_BELL:	/* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
   7891 	    if_PRINT_GRAPHICS2(DoSM(DP_DECGPCM, screen->graphics_print_color_mode)) {
   7892 		DoSM(DP_X_MARGIN, screen->marginbell);
   7893 	    }
   7894 	    break;
   7895 	case srm_REVERSEWRAP:	/* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
   7896 	    if_PRINT_GRAPHICS2(DoSM(DP_DECGPCS, screen->graphics_print_color_syntax)) {
   7897 		DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP);
   7898 	    }
   7899 	    break;
   7900 	case srm_REVERSEWRAP2:	/* extended reverse wraparound (xterm) */
   7901 	    DoSM(DP_X_REVWRAP2, xw->flags & REVERSEWRAP2);
   7902 	    break;
   7903 #ifdef ALLOWLOGGING
   7904 	case srm_ALLOWLOGGING:	/* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
   7905 	    if_PRINT_GRAPHICS2(DoSM(DP_DECGPBM, screen->graphics_print_background_mode)) {
   7906 #ifdef ALLOWLOGFILEONOFF
   7907 		DoSM(DP_X_LOGGING, screen->logging);
   7908 #endif /* ALLOWLOGFILEONOFF */
   7909 	    }
   7910 	    break;
   7911 #elif OPT_PRINT_GRAPHICS
   7912 	case srm_DECGPBM:	/* Graphics Print Background Mode */
   7913 	    DoSM(DP_DECGPBM, screen->graphics_print_background_mode);
   7914 	    break;
   7915 #endif /* ALLOWLOGGING */
   7916 	case srm_OPT_ALTBUF_CURSOR:	/* optional alternate buffer and clear (xterm) */
   7917 	    /* FALLTHRU */
   7918 	case srm_OPT_ALTBUF:	/* optional alternate buffer and clear (xterm) */
   7919 	    DoSM(DP_X_ALTBUF, screen->whichBuf);
   7920 	    break;
   7921 	case srm_ALTBUF:	/* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
   7922 	    if_PRINT_GRAPHICS2(DoSM(DP_DECGRPM, screen->graphics_rotated_print_mode)) {
   7923 		DoSM(DP_X_ALTBUF, screen->whichBuf);
   7924 	    }
   7925 	    break;
   7926 	case srm_DECNKM:
   7927 	    DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM);
   7928 	    break;
   7929 	case srm_DECBKM:	/* backarrow mapping */
   7930 	    DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM);
   7931 	    break;
   7932 	case srm_DECLRMM:	/* left-right */
   7933 	    DoSM(DP_X_LRMM, LEFT_RIGHT);
   7934 	    break;
   7935 #if OPT_SIXEL_GRAPHICS
   7936 	case srm_DECSDM:	/* sixel display mode (no scroll) */
   7937 	    DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM);
   7938 	    update_decsdm();
   7939 	    break;
   7940 #endif
   7941 	case srm_DECNCSM:	/* noclear */
   7942 	    DoSM(DP_X_NCSM, NOCLEAR_COLM);
   7943 	    break;
   7944 	case srm_VT200_MOUSE:	/* mouse bogus sequence         */
   7945 	    /* FALLTHRU */
   7946 	case srm_VT200_HIGHLIGHT_MOUSE:
   7947 	    /* FALLTHRU */
   7948 	case srm_BTN_EVENT_MOUSE:
   7949 	    /* FALLTHRU */
   7950 	case srm_ANY_EVENT_MOUSE:
   7951 	    DoSM(DP_X_MOUSE, screen->send_mouse_pos);
   7952 	    break;
   7953 #if OPT_FOCUS_EVENT
   7954 	case srm_FOCUS_EVENT_MOUSE:
   7955 	    DoSM(DP_X_FOCUS, screen->send_focus_pos);
   7956 	    break;
   7957 #endif
   7958 	case srm_EXT_MODE_MOUSE:
   7959 	    /* FALLTHRU */
   7960 	case srm_SGR_EXT_MODE_MOUSE:
   7961 	    /* FALLTHRU */
   7962 	case srm_URXVT_EXT_MODE_MOUSE:
   7963 	    /* FALLTHRU */
   7964 	case srm_PIXEL_POSITION_MOUSE:
   7965 	    DoSM(DP_X_EXT_MOUSE, screen->extend_coords);
   7966 	    break;
   7967 	case srm_ALTERNATE_SCROLL:
   7968 	    DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
   7969 	    break;
   7970 	case srm_RXVT_SCROLL_TTY_OUTPUT:
   7971 	    DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
   7972 	    break;
   7973 	case srm_RXVT_SCROLL_TTY_KEYPRESS:
   7974 	    DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
   7975 	    break;
   7976 	case srm_EIGHT_BIT_META:
   7977 	    DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
   7978 	    break;
   7979 #if OPT_NUM_LOCK
   7980 	case srm_REAL_NUMLOCK:
   7981 	    DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
   7982 	    break;
   7983 	case srm_META_SENDS_ESC:
   7984 	    DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc);
   7985 	    break;
   7986 #endif
   7987 	case srm_DELETE_IS_DEL:
   7988 	    DoSM(DP_DELETE_IS_DEL, screen->delete_is_del);
   7989 	    break;
   7990 #if OPT_NUM_LOCK
   7991 	case srm_ALT_SENDS_ESC:
   7992 	    DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
   7993 	    break;
   7994 #endif
   7995 	case srm_KEEP_SELECTION:
   7996 	    DoSM(DP_KEEP_SELECTION, screen->keepSelection);
   7997 	    break;
   7998 	case srm_SELECT_TO_CLIPBOARD:
   7999 	    DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
   8000 	    break;
   8001 	case srm_BELL_IS_URGENT:
   8002 	    DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
   8003 	    break;
   8004 	case srm_POP_ON_BELL:
   8005 	    DoSM(DP_POP_ON_BELL, screen->poponbell);
   8006 	    break;
   8007 	case srm_KEEP_CLIPBOARD:
   8008 	    DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
   8009 	    break;
   8010 #if OPT_TCAP_FKEYS
   8011 	case srm_TCAP_FKEYS:
   8012 	    /* FALLTHRU */
   8013 #endif
   8014 #if OPT_SUN_FUNC_KEYS
   8015 	case srm_SUN_FKEYS:
   8016 	    /* FALLTHRU */
   8017 #endif
   8018 #if OPT_HP_FUNC_KEYS
   8019 	case srm_HP_FKEYS:
   8020 	    /* FALLTHRU */
   8021 #endif
   8022 #if OPT_SCO_FUNC_KEYS
   8023 	case srm_SCO_FKEYS:
   8024 	    /* FALLTHRU */
   8025 #endif
   8026 #if OPT_SUNPC_KBD
   8027 	case srm_VT220_FKEYS:
   8028 	    /* FALLTHRU */
   8029 #endif
   8030 	case srm_LEGACY_FKEYS:
   8031 	    DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type);
   8032 	    break;
   8033 	case srm_ALLOW_ALTBUF:
   8034 	    DoSM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit);
   8035 	    break;
   8036 	case srm_SAVE_CURSOR:
   8037 	    if (!xw->misc.titeInhibit) {
   8038 		CursorSave(xw);
   8039 	    }
   8040 	    break;
   8041 	case srm_FAST_SCROLL:
   8042 	    DoSM(DP_FAST_SCROLL, screen->fastscroll);
   8043 	    break;
   8044 #if OPT_PASTE64 || OPT_READLINE
   8045 	case srm_PASTE_IN_BRACKET:
   8046 	    SCREEN_FLAG_save(screen, paste_brackets);
   8047 	    break;
   8048 #endif
   8049 #if OPT_READLINE
   8050 	case srm_BUTTON1_MOVE_POINT:
   8051 	    SCREEN_FLAG_save(screen, click1_moves);
   8052 	    break;
   8053 	case srm_BUTTON2_MOVE_POINT:
   8054 	    SCREEN_FLAG_save(screen, paste_moves);
   8055 	    break;
   8056 	case srm_DBUTTON3_DELETE:
   8057 	    SCREEN_FLAG_save(screen, dclick3_deletes);
   8058 	    break;
   8059 	case srm_PASTE_QUOTE:
   8060 	    SCREEN_FLAG_save(screen, paste_quotes);
   8061 	    break;
   8062 	case srm_PASTE_LITERAL_NL:
   8063 	    SCREEN_FLAG_save(screen, paste_literal_nl);
   8064 	    break;
   8065 #endif /* OPT_READLINE */
   8066 #if OPT_GRAPHICS
   8067 	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
   8068 	    TRACE(("save PRIVATE_COLOR_REGISTERS %s\n",
   8069 		   BtoS(screen->privatecolorregisters)));
   8070 	    DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
   8071 	    update_privatecolorregisters();
   8072 	    break;
   8073 #endif
   8074 #if OPT_SIXEL_GRAPHICS
   8075 	case srm_SIXEL_SCROLLS_RIGHT:
   8076 	    TRACE(("save SIXEL_SCROLLS_RIGHT %s\n",
   8077 		   BtoS(screen->sixel_scrolls_right)));
   8078 	    DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
   8079 	    break;
   8080 #endif
   8081 	case srm_DEC131TM:	/* ignore */
   8082 	case srm_DECAAM:	/* ignore */
   8083 	case srm_DECARSM:	/* ignore */
   8084 	case srm_DECATCBM:	/* ignore */
   8085 	case srm_DECATCUM:	/* ignore */
   8086 	case srm_DECBBSM:	/* ignore */
   8087 	case srm_DECCANSM:	/* ignore */
   8088 	case srm_DECCAPSLK:	/* ignore */
   8089 	case srm_DECCRTSM:	/* ignore */
   8090 	case srm_DECECM:	/* ignore */
   8091 	case srm_DECEKEM:	/* ignore */
   8092 	case srm_DECESKM:	/* ignore */
   8093 	case srm_DECFWM:	/* ignore */
   8094 	case srm_DECHCCM:	/* ignore */
   8095 	case srm_DECHDPXM:	/* ignore */
   8096 	case srm_DECHEM:	/* ignore */
   8097 	case srm_DECHWUM:	/* ignore */
   8098 	case srm_DECIPEM:	/* ignore */
   8099 	case srm_DECKBUM:	/* ignore */
   8100 	case srm_DECKKDM:	/* ignore */
   8101 	case srm_DECKLHIM:	/* ignore */
   8102 	case srm_DECKPM:	/* ignore */
   8103 	case srm_DECLTM:	/* ignore */
   8104 	case srm_DECMCM:	/* ignore */
   8105 	case srm_DECNAKB:	/* ignore */
   8106 	case srm_DECNULM:	/* ignore */
   8107 	case srm_DECNUMLK:	/* ignore */
   8108 	case srm_DECOSCNM:	/* ignore */
   8109 	case srm_DECPCCM:	/* ignore */
   8110 	case srm_DECRLCM:	/* ignore */
   8111 	case srm_DECRLM:	/* ignore */
   8112 	case srm_DECRPL:	/* ignore */
   8113 	case srm_DECVCCM:	/* ignore */
   8114 	case srm_DECXRLM:	/* ignore */
   8115 	default:
   8116 	    break;
   8117 	}
   8118     }
   8119 }
   8120 
   8121 /*
   8122  * process xterm private modes restore
   8123  */
   8124 static void
   8125 restoremodes(XtermWidget xw)
   8126 {
   8127     TScreen *screen = TScreenOf(xw);
   8128     int i, j;
   8129 
   8130     if_STATUS_LINE(screen, {
   8131 	return;
   8132     });
   8133     for (i = 0; i < nparam; i++) {
   8134 	int code = GetParam(i);
   8135 
   8136 	TRACE(("restoremodes %d\n", code));
   8137 	switch ((DECSET_codes) code) {
   8138 	case srm_DECCKM:
   8139 	    bitcpy(&xw->keyboard.flags,
   8140 		   screen->save_modes[DP_DECCKM], MODE_DECCKM);
   8141 	    update_appcursor();
   8142 	    break;
   8143 	case srm_DECANM:	/* ANSI/VT52 mode      */
   8144 	    /* no effect */
   8145 	    break;
   8146 	case srm_DECCOLM:
   8147 	    if (screen->c132) {
   8148 		if (!(xw->flags & NOCLEAR_COLM))
   8149 		    ClearScreen(xw);
   8150 		CursorSet(screen, 0, 0, xw->flags);
   8151 		if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS)
   8152 		     ? 132 : 80) != ((xw->flags & IN132COLUMNS)
   8153 				     ? 132 : 80) || j != MaxCols(screen))
   8154 		    RequestResize(xw, -1, j, True);
   8155 		bitcpy(&xw->flags,
   8156 		       screen->save_modes[DP_DECCOLM],
   8157 		       IN132COLUMNS);
   8158 	    }
   8159 	    break;
   8160 	case srm_DECSCLM:	/* (slow scroll)        */
   8161 	    if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) {
   8162 		screen->jumpscroll = 0;
   8163 		if (screen->scroll_amt)
   8164 		    FlushScroll(xw);
   8165 	    } else
   8166 		screen->jumpscroll = 1;
   8167 	    bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL);
   8168 	    update_jumpscroll();
   8169 	    break;
   8170 	case srm_DECSCNM:
   8171 	    if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) {
   8172 		bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO);
   8173 		ReverseVideo(xw);
   8174 		/* update_reversevideo done in RevVid */
   8175 	    }
   8176 	    break;
   8177 	case srm_DECOM:
   8178 	    bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN);
   8179 	    CursorSet(screen, 0, 0, xw->flags);
   8180 	    break;
   8181 
   8182 	case srm_DECAWM:
   8183 	    bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND);
   8184 	    update_autowrap();
   8185 	    break;
   8186 	case srm_DECARM:
   8187 	    /* ignore autorepeat */
   8188 	    break;
   8189 	case srm_X10_MOUSE:	/* MIT bogus sequence           */
   8190 	    DoRM0(DP_X_X10MSE, screen->send_mouse_pos);
   8191 	    really_set_mousemode(xw,
   8192 				 screen->send_mouse_pos != MOUSE_OFF,
   8193 				 (XtermMouseModes) screen->send_mouse_pos);
   8194 	    break;
   8195 #if OPT_TOOLBAR
   8196 	case srm_RXVT_TOOLBAR:
   8197 	    DoRM(DP_TOOLBAR, resource.toolBar);
   8198 	    ShowToolbar(resource.toolBar);
   8199 	    break;
   8200 #else
   8201 	case srm_DECEDM:	/* vt330:edit */
   8202 	    break;
   8203 #endif
   8204 #if OPT_BLINK_CURS
   8205 	case srm_ATT610_BLINK:	/* Start/stop blinking cursor */
   8206 	    if (SettableCursorBlink(screen)) {
   8207 		DoRM(DP_CRS_BLINK, screen->cursor_blink_esc);
   8208 		UpdateCursorBlink(xw);
   8209 	    }
   8210 	    break;
   8211 	case srm_CURSOR_BLINK_OPS:
   8212 	    /* intentionally ignored (this is user-preference) */
   8213 	    break;
   8214 	case srm_XOR_CURSOR_BLINKS:
   8215 	    /* intentionally ignored (this is user-preference) */
   8216 	    break;
   8217 #else
   8218 	case srm_DECKANAM:	/* vt382:Katakana shift */
   8219 	case srm_DECSCFDM:	/* vt330:space compression field delimiter */
   8220 	case srm_DECTEM:	/* vt330:transmission execution */
   8221 	    break;
   8222 #endif
   8223 	case srm_DECPFF:	/* print form feed */
   8224 	    DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
   8225 	    break;
   8226 	case srm_DECPEX:	/* print extent */
   8227 	    DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
   8228 	    break;
   8229 	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
   8230 	    DoRM(DP_CRS_VISIBLE, screen->cursor_set);
   8231 	    updateCursor(xw);
   8232 	    break;
   8233 	case srm_RXVT_SCROLLBAR:
   8234 	    if ((screen->fullVwin.sb_info.width != 0) !=
   8235 		screen->save_modes[DP_RXVT_SCROLLBAR]) {
   8236 		ToggleScrollBar(xw);
   8237 	    }
   8238 	    break;
   8239 #if OPT_SHIFT_FONTS
   8240 	case srm_RXVT_FONTSIZE:
   8241 	    DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
   8242 	    break;
   8243 #endif
   8244 #if OPT_TEK4014
   8245 	case srm_DECTEK:
   8246 	    if (!(screen->inhibit & I_TEK) &&
   8247 		(TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) {
   8248 		FlushLog(xw);
   8249 		TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK];
   8250 		update_vttekmode();
   8251 	    }
   8252 	    break;
   8253 #endif
   8254 	case srm_132COLS:	/* 132 column mode              */
   8255 	    DoRM(DP_X_DECCOLM, screen->c132);
   8256 	    update_allow132();
   8257 	    break;
   8258 	case srm_CURSES_HACK:	/* curses hack                  */
   8259 	    DoRM(DP_X_MORE, screen->curses);
   8260 	    update_cursesemul();
   8261 	    break;
   8262 	case srm_DECNRCM:	/* national charset (VT220) */
   8263 	    if (screen->vtXX_level >= 2) {
   8264 		if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL))
   8265 		    modified_DECNRCM(xw);
   8266 	    }
   8267 	    break;
   8268 #if OPT_PRINT_GRAPHICS
   8269 	case srm_DECGEPM:	/* Graphics Expanded Print Mode */
   8270 	    DoRM(DP_DECGEPM, screen->graphics_expanded_print_mode);
   8271 	    break;
   8272 #endif
   8273 	case srm_MARGIN_BELL:	/* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
   8274 	    if_PRINT_GRAPHICS2(DoRM(DP_DECGPCM, screen->graphics_print_color_mode)) {
   8275 		if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0)
   8276 		    screen->bellArmed = -1;
   8277 		update_marginbell();
   8278 	    }
   8279 	    break;
   8280 	case srm_REVERSEWRAP:	/* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
   8281 	    if_PRINT_GRAPHICS2(DoRM(DP_DECGPCS, screen->graphics_print_color_syntax)) {
   8282 		bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP);
   8283 		update_reversewrap();
   8284 	    }
   8285 	    break;
   8286 	case srm_REVERSEWRAP2:	/* extended reverse wraparound (xterm) */
   8287 	    bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP2], REVERSEWRAP2);
   8288 	    break;
   8289 #ifdef ALLOWLOGGING
   8290 	case srm_ALLOWLOGGING:	/* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
   8291 	    if_PRINT_GRAPHICS2(DoRM(DP_DECGPBM, screen->graphics_print_background_mode)) {
   8292 #ifdef ALLOWLOGFILEONOFF
   8293 		if (screen->save_modes[DP_X_LOGGING])
   8294 		    StartLog(xw);
   8295 		else
   8296 		    CloseLog(xw);
   8297 #endif /* ALLOWLOGFILEONOFF */
   8298 		/* update_logging done by StartLog and CloseLog */
   8299 	    }
   8300 	    break;
   8301 #elif OPT_PRINT_GRAPHICS
   8302 	case srm_DECGPBM:	/* Graphics Print Background Mode */
   8303 	    DoRM(DP_DECGPBM, screen->graphics_print_background_mode);
   8304 	    break;
   8305 #endif /* ALLOWLOGGING */
   8306 	case srm_OPT_ALTBUF_CURSOR:	/* optional alternate buffer and clear (xterm) */
   8307 	    /* FALLTHRU */
   8308 	case srm_OPT_ALTBUF:	/* optional alternate buffer and clear (xterm) */
   8309 	    if (!xw->misc.titeInhibit) {
   8310 		if (screen->save_modes[DP_X_ALTBUF])
   8311 		    ToAlternate(xw, False);
   8312 		else
   8313 		    FromAlternate(xw, False);
   8314 		/* update_altscreen done by ToAlt and FromAlt */
   8315 	    } else if (screen->save_modes[DP_X_ALTBUF]) {
   8316 		do_ti_xtra_scroll(xw);
   8317 	    }
   8318 	    break;
   8319 	case srm_ALTBUF:	/* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
   8320 	    if_PRINT_GRAPHICS2(DoRM(DP_DECGRPM, screen->graphics_rotated_print_mode)) {
   8321 		if (!xw->misc.titeInhibit) {
   8322 		    if (screen->save_modes[DP_X_ALTBUF])
   8323 			ToAlternate(xw, False);
   8324 		    else
   8325 			FromAlternate(xw, False);
   8326 		    /* update_altscreen done by ToAlt and FromAlt */
   8327 		} else if (screen->save_modes[DP_X_ALTBUF]) {
   8328 		    do_ti_xtra_scroll(xw);
   8329 		}
   8330 	    }
   8331 	    break;
   8332 	case srm_DECNKM:
   8333 	    bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM);
   8334 	    update_appkeypad();
   8335 	    break;
   8336 	case srm_DECBKM:	/* backarrow mapping */
   8337 	    bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM);
   8338 	    update_decbkm();
   8339 	    break;
   8340 	case srm_DECLRMM:	/* left-right */
   8341 	    bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT);
   8342 	    if (IsLeftRightMode(xw)) {
   8343 		xterm_ResetDouble(xw);
   8344 	    } else {
   8345 		reset_lr_margins(screen);
   8346 	    }
   8347 	    break;
   8348 #if OPT_SIXEL_GRAPHICS
   8349 	case srm_DECSDM:	/* sixel display mode (no scroll) */
   8350 	    bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM);
   8351 	    update_decsdm();
   8352 	    break;
   8353 #endif
   8354 	case srm_DECNCSM:	/* noclear */
   8355 	    bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM);
   8356 	    break;
   8357 	case srm_VT200_MOUSE:	/* mouse bogus sequence         */
   8358 	    /* FALLTHRU */
   8359 	case srm_VT200_HIGHLIGHT_MOUSE:
   8360 	    /* FALLTHRU */
   8361 	case srm_BTN_EVENT_MOUSE:
   8362 	    /* FALLTHRU */
   8363 	case srm_ANY_EVENT_MOUSE:
   8364 	    DoRM0(DP_X_MOUSE, screen->send_mouse_pos);
   8365 	    really_set_mousemode(xw,
   8366 				 screen->send_mouse_pos != MOUSE_OFF,
   8367 				 (XtermMouseModes) screen->send_mouse_pos);
   8368 	    break;
   8369 #if OPT_FOCUS_EVENT
   8370 	case srm_FOCUS_EVENT_MOUSE:
   8371 	    DoRM(DP_X_FOCUS, screen->send_focus_pos);
   8372 	    break;
   8373 #endif
   8374 	case srm_EXT_MODE_MOUSE:
   8375 	    /* FALLTHRU */
   8376 	case srm_SGR_EXT_MODE_MOUSE:
   8377 	    /* FALLTHRU */
   8378 	case srm_URXVT_EXT_MODE_MOUSE:
   8379 	    /* FALLTHRU */
   8380 	case srm_PIXEL_POSITION_MOUSE:
   8381 	    DoRM(DP_X_EXT_MOUSE, screen->extend_coords);
   8382 	    break;
   8383 	case srm_ALLOW_ALTBUF:
   8384 	    DoRM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit);
   8385 	    if (xw->misc.titeInhibit)
   8386 		FromAlternate(xw, False);
   8387 	    update_titeInhibit();
   8388 	    break;
   8389 	case srm_SAVE_CURSOR:
   8390 	    if (!xw->misc.titeInhibit) {
   8391 		CursorRestore(xw);
   8392 	    }
   8393 	    break;
   8394 	case srm_FAST_SCROLL:
   8395 	    DoRM(DP_FAST_SCROLL, screen->fastscroll);
   8396 	    break;
   8397 	case srm_ALTERNATE_SCROLL:
   8398 	    DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
   8399 	    break;
   8400 	case srm_RXVT_SCROLL_TTY_OUTPUT:
   8401 	    DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
   8402 	    update_scrollttyoutput();
   8403 	    break;
   8404 	case srm_RXVT_SCROLL_TTY_KEYPRESS:
   8405 	    DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
   8406 	    update_scrollkey();
   8407 	    break;
   8408 	case srm_EIGHT_BIT_META:
   8409 	    DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
   8410 	    break;
   8411 #if OPT_NUM_LOCK
   8412 	case srm_REAL_NUMLOCK:
   8413 	    DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
   8414 	    update_num_lock();
   8415 	    break;
   8416 	case srm_META_SENDS_ESC:
   8417 	    DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc);
   8418 	    update_meta_esc();
   8419 	    break;
   8420 #endif
   8421 	case srm_DELETE_IS_DEL:
   8422 	    DoRM(DP_DELETE_IS_DEL, screen->delete_is_del);
   8423 	    update_delete_del();
   8424 	    break;
   8425 #if OPT_NUM_LOCK
   8426 	case srm_ALT_SENDS_ESC:
   8427 	    DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
   8428 	    update_alt_esc();
   8429 	    break;
   8430 #endif
   8431 	case srm_KEEP_SELECTION:
   8432 	    DoRM(DP_KEEP_SELECTION, screen->keepSelection);
   8433 	    update_keepSelection();
   8434 	    break;
   8435 	case srm_SELECT_TO_CLIPBOARD:
   8436 	    DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
   8437 	    update_selectToClipboard();
   8438 	    break;
   8439 	case srm_BELL_IS_URGENT:
   8440 	    DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
   8441 	    update_bellIsUrgent();
   8442 	    break;
   8443 	case srm_POP_ON_BELL:
   8444 	    DoRM(DP_POP_ON_BELL, screen->poponbell);
   8445 	    update_poponbell();
   8446 	    break;
   8447 	case srm_KEEP_CLIPBOARD:
   8448 	    DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
   8449 	    update_keepClipboard();
   8450 	    break;
   8451 #if OPT_TCAP_FKEYS
   8452 	case srm_TCAP_FKEYS:
   8453 	    /* FALLTHRU */
   8454 #endif
   8455 #if OPT_SUN_FUNC_KEYS
   8456 	case srm_SUN_FKEYS:
   8457 	    /* FALLTHRU */
   8458 #endif
   8459 #if OPT_HP_FUNC_KEYS
   8460 	case srm_HP_FKEYS:
   8461 	    /* FALLTHRU */
   8462 #endif
   8463 #if OPT_SCO_FUNC_KEYS
   8464 	case srm_SCO_FKEYS:
   8465 	    /* FALLTHRU */
   8466 #endif
   8467 #if OPT_SUNPC_KBD
   8468 	case srm_VT220_FKEYS:
   8469 	    /* FALLTHRU */
   8470 #endif
   8471 	case srm_LEGACY_FKEYS:
   8472 	    xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE];
   8473 	    break;
   8474 #if OPT_PASTE64 || OPT_READLINE
   8475 	case srm_PASTE_IN_BRACKET:
   8476 	    SCREEN_FLAG_restore(screen, paste_brackets);
   8477 	    break;
   8478 #endif
   8479 #if OPT_READLINE
   8480 	case srm_BUTTON1_MOVE_POINT:
   8481 	    SCREEN_FLAG_restore(screen, click1_moves);
   8482 	    break;
   8483 	case srm_BUTTON2_MOVE_POINT:
   8484 	    SCREEN_FLAG_restore(screen, paste_moves);
   8485 	    break;
   8486 	case srm_DBUTTON3_DELETE:
   8487 	    SCREEN_FLAG_restore(screen, dclick3_deletes);
   8488 	    break;
   8489 	case srm_PASTE_QUOTE:
   8490 	    SCREEN_FLAG_restore(screen, paste_quotes);
   8491 	    break;
   8492 	case srm_PASTE_LITERAL_NL:
   8493 	    SCREEN_FLAG_restore(screen, paste_literal_nl);
   8494 	    break;
   8495 #endif /* OPT_READLINE */
   8496 #if OPT_GRAPHICS
   8497 	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
   8498 	    TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n",
   8499 		   BtoS(screen->privatecolorregisters)));
   8500 	    DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
   8501 	    TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n",
   8502 		   BtoS(screen->privatecolorregisters)));
   8503 	    update_privatecolorregisters();
   8504 	    break;
   8505 #endif
   8506 #if OPT_SIXEL_GRAPHICS
   8507 	case srm_SIXEL_SCROLLS_RIGHT:
   8508 	    TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n",
   8509 		   BtoS(screen->sixel_scrolls_right)));
   8510 	    DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
   8511 	    TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n",
   8512 		   BtoS(screen->sixel_scrolls_right)));
   8513 	    break;
   8514 #endif
   8515 	case srm_DEC131TM:	/* ignore */
   8516 	case srm_DECAAM:	/* ignore */
   8517 	case srm_DECARSM:	/* ignore */
   8518 	case srm_DECATCBM:	/* ignore */
   8519 	case srm_DECATCUM:	/* ignore */
   8520 	case srm_DECBBSM:	/* ignore */
   8521 	case srm_DECCANSM:	/* ignore */
   8522 	case srm_DECCAPSLK:	/* ignore */
   8523 	case srm_DECCRTSM:	/* ignore */
   8524 	case srm_DECECM:	/* ignore */
   8525 	case srm_DECEKEM:	/* ignore */
   8526 	case srm_DECESKM:	/* ignore */
   8527 	case srm_DECFWM:	/* ignore */
   8528 	case srm_DECHCCM:	/* ignore */
   8529 	case srm_DECHDPXM:	/* ignore */
   8530 	case srm_DECHEM:	/* ignore */
   8531 	case srm_DECHWUM:	/* ignore */
   8532 	case srm_DECIPEM:	/* ignore */
   8533 	case srm_DECKBUM:	/* ignore */
   8534 	case srm_DECKKDM:	/* ignore */
   8535 	case srm_DECKLHIM:	/* ignore */
   8536 	case srm_DECKPM:	/* ignore */
   8537 	case srm_DECLTM:	/* ignore */
   8538 	case srm_DECMCM:	/* ignore */
   8539 	case srm_DECNAKB:	/* ignore */
   8540 	case srm_DECNULM:	/* ignore */
   8541 	case srm_DECNUMLK:	/* ignore */
   8542 	case srm_DECOSCNM:	/* ignore */
   8543 	case srm_DECPCCM:	/* ignore */
   8544 	case srm_DECRLCM:	/* ignore */
   8545 	case srm_DECRLM:	/* ignore */
   8546 	case srm_DECRPL:	/* ignore */
   8547 	case srm_DECVCCM:	/* ignore */
   8548 	case srm_DECXRLM:	/* ignore */
   8549 	default:
   8550 	    break;
   8551 	}
   8552     }
   8553 }
   8554 
   8555 /*
   8556  * Convert an XTextProperty to a string.
   8557  *
   8558  * This frees the data owned by the XTextProperty, and returns in its place the
   8559  * string, which must be freed by the caller.
   8560  */
   8561 static char *
   8562 property_to_string(XtermWidget xw, XTextProperty * text)
   8563 {
   8564     TScreen *screen = TScreenOf(xw);
   8565     Display *dpy = screen->display;
   8566     char *result = NULL;
   8567     char **list = NULL;
   8568     int length = 0;
   8569     int rc;
   8570 
   8571     TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n",
   8572 	   text->value,
   8573 	   TraceAtomName(dpy, text->encoding),
   8574 	   text->format,
   8575 	   text->nitems));
   8576 
   8577 #if OPT_WIDE_CHARS
   8578     /*
   8579      * We will use the XmbTextPropertyToTextList call to extract UTF-8 data.
   8580      * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to
   8581      * ISO-8859-1.
   8582      */
   8583     rc = -1;
   8584     if ((text->format != 8)
   8585 	|| IsTitleMode(xw, tmGetUtf8)
   8586 	|| (text->encoding == XA_UTF8_STRING(dpy) &&
   8587 	    !(screen->wide_chars || screen->c1_printable) &&
   8588 	    (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0)
   8589 	|| (rc < 0))
   8590 #endif
   8591 	if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0)
   8592 	    rc = XTextPropertyToStringList(text, &list, &length);
   8593 
   8594     if (rc >= 0) {
   8595 	int n, c, pass;
   8596 	size_t need;
   8597 
   8598 	for (pass = 0; pass < 2; ++pass) {
   8599 	    for (n = 0, need = 0; n < length; n++) {
   8600 		char *s = list[n];
   8601 		while ((c = *s++) != '\0') {
   8602 		    if (pass)
   8603 			result[need] = (char) c;
   8604 		    ++need;
   8605 		}
   8606 	    }
   8607 	    if (pass)
   8608 		result[need] = '\0';
   8609 	    else
   8610 		result = malloc(need + 1);
   8611 	    if (result == NULL)
   8612 		break;
   8613 	}
   8614 	XFreeStringList(list);
   8615     }
   8616     if (text->value != NULL)
   8617 	XFree(text->value);
   8618 
   8619     return result;
   8620 }
   8621 
   8622 static char *
   8623 get_icon_label(XtermWidget xw)
   8624 {
   8625     XTextProperty text;
   8626     char *result = NULL;
   8627 
   8628     if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
   8629 	result = property_to_string(xw, &text);
   8630     }
   8631     return result;
   8632 }
   8633 
   8634 static char *
   8635 get_window_label(XtermWidget xw)
   8636 {
   8637     XTextProperty text;
   8638     char *result = NULL;
   8639 
   8640     if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
   8641 	result = property_to_string(xw, &text);
   8642     }
   8643     return result;
   8644 }
   8645 
   8646 /*
   8647  * Report window label (icon or title) in dtterm protocol
   8648  * ESC ] code label ESC backslash
   8649  */
   8650 static void
   8651 report_win_label(XtermWidget xw,
   8652 		 int code,
   8653 		 char *text)
   8654 {
   8655     unparseputc(xw, ANSI_ESC);
   8656     unparseputc(xw, ']');
   8657     unparseputc(xw, code);
   8658 
   8659     if (text != NULL) {
   8660 	int copy = IsTitleMode(xw, tmGetBase16);
   8661 	if (copy) {
   8662 	    TRACE(("Encoding hex:%s\n", text));
   8663 	    text = x_encode_hex(text);
   8664 	}
   8665 	unparseputs(xw, text);
   8666 	if (copy)
   8667 	    free(text);
   8668     }
   8669 
   8670     unparseputc(xw, ANSI_ESC);
   8671     unparseputc(xw, '\\');	/* should be ST */
   8672     unparse_end(xw);
   8673 }
   8674 
   8675 /*
   8676  * Window operations (from CDE dtterm description, as well as extensions).
   8677  * See also "allowWindowOps" resource.
   8678  */
   8679 static void
   8680 window_ops(XtermWidget xw)
   8681 {
   8682     TScreen *screen = TScreenOf(xw);
   8683     XWindowChanges values;
   8684     XWindowAttributes win_attrs;
   8685 #if OPT_MAXIMIZE
   8686     unsigned root_width;
   8687     unsigned root_height;
   8688 #endif
   8689     int code = zero_if_default(0);
   8690     char *label;
   8691 
   8692     TRACE(("window_ops %d\n", code));
   8693     switch (code) {
   8694     case ewRestoreWin:		/* Restore (de-iconify) window */
   8695 	if (AllowWindowOps(xw, ewRestoreWin)) {
   8696 	    xtermDeiconify(xw);
   8697 	}
   8698 	break;
   8699 
   8700     case ewMinimizeWin:	/* Minimize (iconify) window */
   8701 	if (AllowWindowOps(xw, ewMinimizeWin)) {
   8702 	    xtermIconify(xw);
   8703 	}
   8704 	break;
   8705 
   8706     case ewSetWinPosition:	/* Move the window to the given position */
   8707 	if (AllowWindowOps(xw, ewSetWinPosition)) {
   8708 	    unsigned value_mask;
   8709 
   8710 	    values.x = (Position) zero_if_default(1);
   8711 	    values.y = (Position) zero_if_default(2);
   8712 	    TRACE(("...move window to %d,%d\n", values.x, values.y));
   8713 	    value_mask = (CWX | CWY);
   8714 	    XReconfigureWMWindow(screen->display,
   8715 				 VShellWindow(xw),
   8716 				 DefaultScreen(screen->display),
   8717 				 value_mask,
   8718 				 &values);
   8719 	}
   8720 	break;
   8721 
   8722     case ewSetWinSizePixels:	/* Resize the window to given size in pixels */
   8723 	if (AllowWindowOps(xw, ewSetWinSizePixels)) {
   8724 	    RequestResize(xw, optional_param(1), optional_param(2), False);
   8725 	}
   8726 	break;
   8727 
   8728     case ewRaiseWin:		/* Raise the window to the front of the stack */
   8729 	if (AllowWindowOps(xw, ewRaiseWin)) {
   8730 	    TRACE(("...raise window\n"));
   8731 	    XRaiseWindow(screen->display, VShellWindow(xw));
   8732 	}
   8733 	break;
   8734 
   8735     case ewLowerWin:		/* Lower the window to the bottom of the stack */
   8736 	if (AllowWindowOps(xw, ewLowerWin)) {
   8737 	    TRACE(("...lower window\n"));
   8738 	    XLowerWindow(screen->display, VShellWindow(xw));
   8739 	}
   8740 	break;
   8741 
   8742     case ewRefreshWin:		/* Refresh the window */
   8743 	if (AllowWindowOps(xw, ewRefreshWin)) {
   8744 	    TRACE(("...redraw window\n"));
   8745 	    Redraw();
   8746 	}
   8747 	break;
   8748 
   8749     case ewSetWinSizeChars:	/* Resize the text-area, in characters */
   8750 	if (AllowWindowOps(xw, ewSetWinSizeChars)) {
   8751 	    RequestResize(xw, optional_param(1), optional_param(2), True);
   8752 	}
   8753 	break;
   8754 
   8755 #if OPT_MAXIMIZE
   8756     case ewMaximizeWin:	/* Maximize or restore */
   8757 	if (AllowWindowOps(xw, ewMaximizeWin)) {
   8758 	    RequestMaximize(xw, zero_if_default(1));
   8759 	}
   8760 	break;
   8761     case ewFullscreenWin:	/* Fullscreen or restore */
   8762 	if (AllowWindowOps(xw, ewFullscreenWin)) {
   8763 	    switch (zero_if_default(1)) {
   8764 	    default:
   8765 		RequestMaximize(xw, 0);
   8766 		break;
   8767 	    case 1:
   8768 		RequestMaximize(xw, 1);
   8769 		break;
   8770 	    case 2:
   8771 		RequestMaximize(xw, !(screen->restore_data));
   8772 		break;
   8773 	    }
   8774 	}
   8775 	break;
   8776 #endif
   8777 
   8778     case ewGetWinState:	/* Report the window's state */
   8779 	if (AllowWindowOps(xw, ewGetWinState)) {
   8780 	    TRACE(("...get window attributes\n"));
   8781 	    init_reply(ANSI_CSI);
   8782 	    reply.a_nparam = 1;
   8783 	    reply.a_param[0] = (ParmType) (xtermIsIconified(xw) ? 2 : 1);
   8784 	    reply.a_final = 't';
   8785 	    unparseseq(xw, &reply);
   8786 	}
   8787 	break;
   8788 
   8789     case ewGetWinPosition:	/* Report the window's position */
   8790 	if (AllowWindowOps(xw, ewGetWinPosition)) {
   8791 	    Window win;
   8792 	    Window result_win;
   8793 	    int result_y, result_x;
   8794 
   8795 	    TRACE(("...get window position\n"));
   8796 	    init_reply(ANSI_CSI);
   8797 	    reply.a_nparam = 3;
   8798 	    reply.a_param[0] = 3;
   8799 	    switch (zero_if_default(1)) {
   8800 	    case 2:		/* report the text-window's position */
   8801 		result_y = 0;
   8802 		result_x = 0;
   8803 		{
   8804 		    Widget mw;
   8805 		    for (mw = (Widget) xw; mw != NULL; mw = XtParent(mw)) {
   8806 			result_x += mw->core.x;
   8807 			result_y += mw->core.y;
   8808 			if (mw == SHELL_OF(xw))
   8809 			    break;
   8810 		    }
   8811 		}
   8812 		result_x += OriginX(screen);
   8813 		result_y += OriginY(screen);
   8814 		break;
   8815 	    default:
   8816 		win = WMFrameWindow(xw);
   8817 		xtermGetWinAttrs(screen->display,
   8818 				 win,
   8819 				 &win_attrs);
   8820 		XTranslateCoordinates(screen->display,
   8821 				      VShellWindow(xw),
   8822 				      win_attrs.root,
   8823 				      -win_attrs.border_width,
   8824 				      -win_attrs.border_width,
   8825 				      &result_x, &result_y, &result_win);
   8826 		TRACE(("translated position %d,%d vs %d,%d\n",
   8827 		       result_y, result_x,
   8828 		       win_attrs.y, win_attrs.x));
   8829 		if (!discount_frame_extents(xw, &result_y, &result_x)) {
   8830 		    TRACE(("...cancelled translation\n"));
   8831 		    result_y = win_attrs.y;
   8832 		    result_x = win_attrs.x;
   8833 		}
   8834 		break;
   8835 	    }
   8836 	    reply.a_param[1] = (ParmType) result_x;
   8837 	    reply.a_param[2] = (ParmType) result_y;
   8838 	    reply.a_final = 't';
   8839 	    unparseseq(xw, &reply);
   8840 	}
   8841 	break;
   8842 
   8843     case ewGetWinSizePixels:	/* Report the window's size in pixels */
   8844 	if (AllowWindowOps(xw, ewGetWinSizePixels)) {
   8845 	    ParmType high = (ParmType) Height(screen);
   8846 	    ParmType wide = (ParmType) Width(screen);
   8847 
   8848 	    TRACE(("...get window size in pixels\n"));
   8849 	    init_reply(ANSI_CSI);
   8850 	    reply.a_nparam = 3;
   8851 	    reply.a_param[0] = 4;
   8852 	    switch (zero_if_default(1)) {
   8853 	    case 2:		/* report the shell-window's size */
   8854 		xtermGetWinAttrs(screen->display,
   8855 				 WMFrameWindow(xw),
   8856 				 &win_attrs);
   8857 		high = (ParmType) win_attrs.height;
   8858 		wide = (ParmType) win_attrs.width;
   8859 		/* FALLTHRU */
   8860 	    default:
   8861 		reply.a_param[1] = high;
   8862 		reply.a_param[2] = wide;
   8863 		break;
   8864 	    }
   8865 	    reply.a_final = 't';
   8866 	    unparseseq(xw, &reply);
   8867 	}
   8868 	break;
   8869 
   8870 #if OPT_MAXIMIZE
   8871     case ewGetScreenSizePixels:	/* Report the screen's size, in Pixels */
   8872 	if (AllowWindowOps(xw, ewGetScreenSizePixels)) {
   8873 	    TRACE(("...get screen size in pixels\n"));
   8874 	    (void) QueryMaximize(xw, &root_width, &root_height);
   8875 	    init_reply(ANSI_CSI);
   8876 	    reply.a_nparam = 3;
   8877 	    reply.a_param[0] = 5;
   8878 	    reply.a_param[1] = (ParmType) root_height;
   8879 	    reply.a_param[2] = (ParmType) root_width;
   8880 	    reply.a_final = 't';
   8881 	    unparseseq(xw, &reply);
   8882 	}
   8883 	break;
   8884     case ewGetCharSizePixels:	/* Report the font's size, in pixel */
   8885 	if (AllowWindowOps(xw, ewGetScreenSizeChars)) {
   8886 	    TRACE(("...get font size in pixels\n"));
   8887 	    TRACE(("...using font size %dx%d\n",
   8888 		   FontHeight(screen),
   8889 		   FontWidth(screen)));
   8890 	    init_reply(ANSI_CSI);
   8891 	    reply.a_nparam = 3;
   8892 	    reply.a_param[0] = 6;
   8893 	    reply.a_param[1] = (ParmType) FontHeight(screen);
   8894 	    reply.a_param[2] = (ParmType) FontWidth(screen);
   8895 	    reply.a_final = 't';
   8896 	    unparseseq(xw, &reply);
   8897 	}
   8898 	break;
   8899 #endif
   8900 
   8901     case ewGetWinSizeChars:	/* Report the text's size in characters */
   8902 	if (AllowWindowOps(xw, ewGetWinSizeChars)) {
   8903 	    TRACE(("...get window size in characters\n"));
   8904 	    init_reply(ANSI_CSI);
   8905 	    reply.a_nparam = 3;
   8906 	    reply.a_param[0] = 8;
   8907 	    reply.a_param[1] = (ParmType) MaxRows(screen);
   8908 	    reply.a_param[2] = (ParmType) MaxCols(screen);
   8909 	    reply.a_final = 't';
   8910 	    unparseseq(xw, &reply);
   8911 	}
   8912 	break;
   8913 
   8914 #if OPT_MAXIMIZE
   8915     case ewGetScreenSizeChars:	/* Report the screen's size, in characters */
   8916 	if (AllowWindowOps(xw, ewGetScreenSizeChars)) {
   8917 	    TRACE(("...get screen size in characters\n"));
   8918 	    TRACE(("...using font size %dx%d\n",
   8919 		   FontHeight(screen),
   8920 		   FontWidth(screen)));
   8921 	    (void) QueryMaximize(xw, &root_width, &root_height);
   8922 	    init_reply(ANSI_CSI);
   8923 	    reply.a_nparam = 3;
   8924 	    reply.a_param[0] = 9;
   8925 	    reply.a_param[1] = (ParmType) (root_height
   8926 					   / (unsigned) FontHeight(screen));
   8927 	    reply.a_param[2] = (ParmType) (root_width
   8928 					   / (unsigned) FontWidth(screen));
   8929 	    reply.a_final = 't';
   8930 	    unparseseq(xw, &reply);
   8931 	}
   8932 	break;
   8933 #endif
   8934 
   8935     case ewGetIconTitle:	/* Report the icon's label */
   8936 	if (AllowWindowOps(xw, ewGetIconTitle)) {
   8937 	    TRACE(("...get icon's label\n"));
   8938 	    report_win_label(xw, 'L', label = get_icon_label(xw));
   8939 	    free(label);
   8940 	}
   8941 	break;
   8942 
   8943     case ewGetWinTitle:	/* Report the window's title */
   8944 	if (AllowWindowOps(xw, ewGetWinTitle)) {
   8945 	    TRACE(("...get window's label\n"));
   8946 	    report_win_label(xw, 'l', label = get_window_label(xw));
   8947 	    free(label);
   8948 	}
   8949 	break;
   8950 
   8951 #define WhichTitle(n) \
   8952 	((n) == 0 \
   8953 	 ? "window/icon titles" \
   8954 	 : ((n) == 1 \
   8955 	    ? "icon title" \
   8956 	    : ((n) == 2 \
   8957 	       ? "window title" \
   8958 	       : "no titles")))
   8959 
   8960     case ewPushTitle:		/* save the window's title(s) on stack */
   8961 	if (AllowWindowOps(xw, ewPushTitle)) {
   8962 	    SaveTitle item;
   8963 
   8964 	    TRACE(("...push %s onto stack\n", WhichTitle(zero_if_default(1))));
   8965 	    memset(&item, 0, sizeof(item));
   8966 	    switch (zero_if_default(1)) {
   8967 	    case 0:
   8968 		item.iconName = get_icon_label(xw);
   8969 		item.windowName = get_window_label(xw);
   8970 		break;
   8971 	    case 1:
   8972 		item.iconName = get_icon_label(xw);
   8973 		break;
   8974 	    case 2:
   8975 		item.windowName = get_window_label(xw);
   8976 		break;
   8977 	    }
   8978 	    xtermPushTitle(screen, zero_if_default(2), &item);
   8979 	}
   8980 	break;
   8981 
   8982     case ewPopTitle:		/* restore the window's title(s) from stack */
   8983 	if (AllowWindowOps(xw, ewPopTitle)) {
   8984 	    SaveTitle item;
   8985 
   8986 	    TRACE(("...%s %s off stack\n",
   8987 		   (zero_if_default(2)
   8988 		    ? "get"
   8989 		    : "pop"),
   8990 		   WhichTitle(zero_if_default(1))));
   8991 
   8992 	    if (xtermPopTitle(screen, zero_if_default(2), &item)) {
   8993 		switch (zero_if_default(1)) {
   8994 		case 0:
   8995 		    ChangeIconName(xw, item.iconName);
   8996 		    ChangeTitle(xw, item.windowName);
   8997 		    break;
   8998 		case 1:
   8999 		    ChangeIconName(xw, item.iconName);
   9000 		    break;
   9001 		case 2:
   9002 		    ChangeTitle(xw, item.windowName);
   9003 		    break;
   9004 		}
   9005 		if (!zero_if_default(2))
   9006 		    xtermFreeTitle(&item);
   9007 	    }
   9008 	}
   9009 	break;
   9010 
   9011     default:			/* DECSLPP (24, 25, 36, 48, 72, 144) */
   9012 	if (AllowWindowOps(xw, ewSetWinLines)) {
   9013 	    if (code >= 24)
   9014 		RequestResize(xw, code, -1, True);
   9015 	}
   9016 	break;
   9017     }
   9018 }
   9019 
   9020 /*
   9021  * set a bit in a word given a pointer to the word and a mask.
   9022  */
   9023 static int
   9024 bitset(unsigned *p, unsigned mask)
   9025 {
   9026     unsigned before = *p;
   9027     *p |= mask;
   9028     return (before != *p);
   9029 }
   9030 
   9031 /*
   9032  * clear a bit in a word given a pointer to the word and a mask.
   9033  */
   9034 static int
   9035 bitclr(unsigned *p, unsigned mask)
   9036 {
   9037     unsigned before = *p;
   9038     *p &= ~mask;
   9039     return (before != *p);
   9040 }
   9041 
   9042 /*
   9043  * Copy bits from one word to another, given a mask
   9044  */
   9045 static int
   9046 bitcpy(unsigned *p, unsigned q, unsigned mask)
   9047 {
   9048     unsigned before = *p;
   9049     bitclr(p, mask);
   9050     bitset(p, q & mask);
   9051     return (before != *p);
   9052 }
   9053 
   9054 void
   9055 unparseputc1(XtermWidget xw, int c)
   9056 {
   9057     if (c >= 0x80 && c <= 0x9F) {
   9058 	if (!TScreenOf(xw)->control_eight_bits) {
   9059 	    unparseputc(xw, ANSI_ESC);
   9060 	    c = c - 0x40;
   9061 	}
   9062     }
   9063     unparseputc(xw, c);
   9064 }
   9065 
   9066 void
   9067 unparseseq(XtermWidget xw, ANSI *ap)
   9068 {
   9069     int c;
   9070 
   9071     assert(ap->a_nparam < NPARAM);
   9072     unparseputc1(xw, c = ap->a_type);
   9073     if (c == ANSI_ESC
   9074 	|| c == ANSI_DCS
   9075 	|| c == ANSI_CSI
   9076 	|| c == ANSI_OSC
   9077 	|| c == ANSI_PM
   9078 	|| c == ANSI_APC
   9079 	|| c == ANSI_SS3) {
   9080 	int i;
   9081 	int inters;
   9082 	char temp[8];
   9083 
   9084 	if (ap->a_pintro != 0)
   9085 	    unparseputc(xw, ap->a_pintro);
   9086 	for (i = 0; i < ap->a_nparam; ++i) {
   9087 	    if (i != 0) {
   9088 		if (ap->a_radix[i] == 1 || ap->a_radix[i - 1] == 1) {
   9089 		    ;
   9090 		} else if (ap->a_delim) {
   9091 		    unparseputs(xw, ap->a_delim);
   9092 		} else {
   9093 		    unparseputc(xw, ';');
   9094 		}
   9095 	    }
   9096 	    switch (ap->a_radix[i]) {
   9097 	    case 16:
   9098 		sprintf(temp, "%04X", UParmOf(ap->a_param[i]));
   9099 		unparseputs(xw, temp);
   9100 		break;
   9101 	    case 1:
   9102 		unparseputc(xw, ap->a_param[i]);
   9103 		break;
   9104 	    default:
   9105 		unparseputn(xw, UParmOf(ap->a_param[i]));
   9106 		break;
   9107 	    }
   9108 	}
   9109 	if ((inters = ap->a_inters) != 0) {
   9110 	    for (i = 3; i >= 0; --i) {
   9111 		c = CharOf(inters >> (8 * i));
   9112 		if (c != 0)
   9113 		    unparseputc(xw, c);
   9114 	    }
   9115 	}
   9116 	switch (ap->a_type) {
   9117 	case ANSI_DCS:
   9118 	    /* FALLTHRU */
   9119 	case ANSI_OSC:
   9120 	    /* FALLTHRU */
   9121 	case ANSI_PM:
   9122 	    /* FALLTHRU */
   9123 	case ANSI_APC:
   9124 	    unparseputc1(xw, ANSI_ST);
   9125 	    break;
   9126 	default:
   9127 	    unparseputc(xw, (char) ap->a_final);
   9128 	    break;
   9129 	}
   9130     }
   9131     unparse_end(xw);
   9132 }
   9133 
   9134 void
   9135 unparseputn(XtermWidget xw, unsigned n)
   9136 {
   9137     unsigned q;
   9138 
   9139     q = n / 10;
   9140     if (q != 0)
   9141 	unparseputn(xw, q);
   9142     unparseputc(xw, (char) ('0' + (n % 10)));
   9143 }
   9144 
   9145 void
   9146 unparseputs(XtermWidget xw, const char *s)
   9147 {
   9148     if (s != NULL) {
   9149 	while (*s)
   9150 	    unparseputc(xw, *s++);
   9151     }
   9152 }
   9153 
   9154 void
   9155 unparseputc(XtermWidget xw, int c)
   9156 {
   9157     TScreen *screen = TScreenOf(xw);
   9158     IChar *buf = screen->unparse_bfr;
   9159     unsigned len;
   9160 
   9161     if ((screen->unparse_len + 2) >= screen->unparse_max)
   9162 	unparse_end(xw);
   9163 
   9164     len = screen->unparse_len;
   9165 
   9166 #if OPT_TCAP_QUERY
   9167     /*
   9168      * If we're returning a termcap string, it has to be translated since
   9169      * a DCS must not contain any characters except for the normal 7-bit
   9170      * printable ASCII (counting tab, carriage return, etc).  For now,
   9171      * just use hexadecimal for the whole thing.
   9172      */
   9173     if (screen->tc_query_code >= 0) {
   9174 	char tmp[3];
   9175 	sprintf(tmp, "%02X", (unsigned) (c & 0xFF));
   9176 	buf[len++] = CharOf(tmp[0]);
   9177 	buf[len++] = CharOf(tmp[1]);
   9178     } else
   9179 #endif
   9180     if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) {
   9181 	buf[len++] = '\n';
   9182     }
   9183 
   9184     screen->unparse_len = len;
   9185 
   9186     /* If send/receive mode is reset, we echo characters locally */
   9187     if ((xw->keyboard.flags & MODE_SRM) == 0) {
   9188 	doparsing(xw, (unsigned) c, &myState);
   9189     }
   9190 }
   9191 
   9192 void
   9193 unparse_end(XtermWidget xw)
   9194 {
   9195     TScreen *screen = TScreenOf(xw);
   9196 
   9197 #if OPT_TCAP_QUERY
   9198     /*
   9199      * tcap-query works by simulating key-presses, which ordinarily would be
   9200      * flushed out at the end of each key.  For better efficiency, do not do
   9201      * the flush unless we are about to fill the buffer used to capture the
   9202      * response.
   9203      */
   9204     if ((screen->tc_query_code >= 0)
   9205 	&& (screen->unparse_len + 2 < screen->unparse_max)) {
   9206 	return;
   9207     }
   9208 #endif
   9209     if (screen->unparse_len) {
   9210 	TRACE(("unparse_end %u:%s\n",
   9211 	       screen->unparse_len,
   9212 	       visibleIChars(screen->unparse_bfr, (size_t) screen->unparse_len)));
   9213 	writePtyData(screen->respond, screen->unparse_bfr, (size_t) screen->unparse_len);
   9214 	screen->unparse_len = 0;
   9215     }
   9216 }
   9217 
   9218 void
   9219 ToggleAlternate(XtermWidget xw)
   9220 {
   9221     if (TScreenOf(xw)->whichBuf)
   9222 	FromAlternate(xw, False);
   9223     else
   9224 	ToAlternate(xw, False);
   9225 }
   9226 
   9227 static void
   9228 ToAlternate(XtermWidget xw, Bool clearFirst)
   9229 {
   9230     TScreen *screen = TScreenOf(xw);
   9231 
   9232     if (screen->whichBuf == 0) {
   9233 	TRACE(("ToAlternate\n"));
   9234 	if (!screen->editBuf_index[1]) {
   9235 	    screen->editBuf_index[1] = allocScrnBuf(xw,
   9236 						    (unsigned) MaxRows(screen),
   9237 						    (unsigned) MaxCols(screen),
   9238 						    &screen->editBuf_data[1]);
   9239 	}
   9240 	SwitchBufs(xw, 1, clearFirst);
   9241 	screen->visbuf = screen->editBuf_index[screen->whichBuf];
   9242 	update_altscreen();
   9243     }
   9244 }
   9245 
   9246 static void
   9247 FromAlternate(XtermWidget xw, Bool clearFirst)
   9248 {
   9249     TScreen *screen = TScreenOf(xw);
   9250 
   9251     if (screen->whichBuf != 0) {
   9252 	TRACE(("FromAlternate\n"));
   9253 	if (screen->scroll_amt) {
   9254 	    FlushScroll(xw);
   9255 	}
   9256 	if (clearFirst)
   9257 	    ClearScreen(xw);
   9258 	SwitchBufs(xw, 0, False);
   9259 	screen->visbuf = screen->editBuf_index[screen->whichBuf];
   9260 	update_altscreen();
   9261     }
   9262 }
   9263 
   9264 static void
   9265 SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst)
   9266 {
   9267     TScreen *screen = TScreenOf(xw);
   9268     int rows, top;
   9269 
   9270     screen->whichBuf = toBuf;
   9271     if (screen->cursor_state)
   9272 	HideCursor(xw);
   9273 
   9274     rows = MaxRows(screen);
   9275 #if OPT_STATUS_LINE
   9276     if (IsStatusShown(screen) && (rows > 0)) {
   9277 	/* avoid clearing the status-line in this function */
   9278 	--rows;
   9279     }
   9280 #endif
   9281     SwitchBufPtrs(xw, toBuf);
   9282 
   9283     if ((top = INX2ROW(screen, 0)) < rows) {
   9284 	if (screen->scroll_amt) {
   9285 	    FlushScroll(xw);
   9286 	}
   9287 	xtermClear2(xw,
   9288 		    (int) OriginX(screen),
   9289 		    (int) top * FontHeight(screen) + screen->border,
   9290 		    (unsigned) Width(screen),
   9291 		    (unsigned) ((rows - top) * FontHeight(screen)));
   9292 	if (clearFirst) {
   9293 	    ClearBufRows(xw, top, rows);
   9294 	}
   9295     }
   9296     ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False);
   9297 }
   9298 
   9299 Bool
   9300 CheckBufPtrs(TScreen *screen)
   9301 {
   9302     return (screen->visbuf != NULL
   9303 	    && screen->editBuf_index[0] != NULL
   9304 	    && screen->editBuf_index[1] != NULL);
   9305 }
   9306 
   9307 /*
   9308  * Swap buffer line pointers between alternate and regular screens.
   9309  */
   9310 void
   9311 SwitchBufPtrs(XtermWidget xw, int toBuf)
   9312 {
   9313     TScreen *screen = TScreenOf(xw);
   9314 
   9315     if (CheckBufPtrs(screen)) {
   9316 #if OPT_STATUS_LINE
   9317 	if (IsStatusShown(screen)
   9318 	    && (screen->visbuf != screen->editBuf_index[toBuf])) {
   9319 	    LineData *oldLD;
   9320 	    LineData *newLD;
   9321 	    int row = MaxRows(screen);
   9322 
   9323 	    oldLD = getLineData(screen, row);
   9324 	    screen->visbuf = screen->editBuf_index[toBuf];
   9325 	    newLD = getLineData(screen, row);
   9326 
   9327 	    copyLineData(newLD, oldLD);
   9328 	} else
   9329 #endif
   9330 	    screen->visbuf = screen->editBuf_index[toBuf];
   9331     }
   9332 }
   9333 
   9334 void
   9335 VTRun(XtermWidget xw)
   9336 {
   9337     TScreen *screen = TScreenOf(xw);
   9338 
   9339     TRACE(("VTRun ...\n"));
   9340 
   9341     if (!screen->Vshow && !resource.notMapped) {
   9342 	set_vt_visibility(True);
   9343     }
   9344     update_vttekmode();
   9345     update_vtshow();
   9346     update_tekshow();
   9347     set_vthide_sensitivity();
   9348 
   9349     ScrnAllocBuf(xw);
   9350 
   9351     screen->cursor_state = OFF;
   9352     screen->cursor_set = ON;
   9353 #if OPT_BLINK_CURS
   9354     if (DoStartBlinking(screen))
   9355 	StartBlinking(xw);
   9356 #endif
   9357 
   9358 #if OPT_TEK4014
   9359     if (Tpushb > Tpushback) {
   9360 	fillPtyData(xw, VTbuffer, (char *) Tpushback, (size_t) (Tpushb - Tpushback));
   9361 	Tpushb = Tpushback;
   9362     }
   9363 #endif
   9364     screen->is_running = True;
   9365     if (screen->embed_high && screen->embed_wide) {
   9366 	ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags));
   9367     }
   9368 #if OPT_MAXIMIZE
   9369     else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways)
   9370 	FullScreen(xw, True);
   9371 #endif
   9372     if (!setjmp(VTend))
   9373 	VTparse(xw);
   9374     StopBlinking(xw);
   9375     HideCursor(xw);
   9376     screen->cursor_set = OFF;
   9377     TRACE(("... VTRun\n"));
   9378 }
   9379 
   9380 /*ARGSUSED*/
   9381 static void
   9382 VTExpose(Widget w GCC_UNUSED,
   9383 	 XEvent *event,
   9384 	 Region region GCC_UNUSED)
   9385 {
   9386     DEBUG_MSG("Expose\n");
   9387     if (event->type == Expose)
   9388 	HandleExposure(term, event);
   9389 }
   9390 
   9391 static void
   9392 VTGraphicsOrNoExpose(XEvent *event)
   9393 {
   9394     XtermWidget xw = term;
   9395     TScreen *screen = TScreenOf(xw);
   9396     if (screen->incopy <= 0) {
   9397 	screen->incopy = 1;
   9398 	if (screen->scrolls > 0)
   9399 	    screen->scrolls--;
   9400     }
   9401     if (event->type == GraphicsExpose)
   9402 	if (HandleExposure(xw, event))
   9403 	    screen->cursor_state = OFF;
   9404     if ((event->type == NoExpose)
   9405 	|| ((XGraphicsExposeEvent *) event)->count == 0) {
   9406 	if (screen->incopy <= 0 && screen->scrolls > 0)
   9407 	    screen->scrolls--;
   9408 	if (screen->scrolls)
   9409 	    screen->incopy = -1;
   9410 	else
   9411 	    screen->incopy = 0;
   9412     }
   9413 }
   9414 
   9415 /*ARGSUSED*/
   9416 static void
   9417 VTNonMaskableEvent(Widget w GCC_UNUSED,
   9418 		   XtPointer closure GCC_UNUSED,
   9419 		   XEvent *event,
   9420 		   Boolean *cont GCC_UNUSED)
   9421 {
   9422     switch (event->type) {
   9423     case GraphicsExpose:
   9424 	/* FALLTHRU */
   9425     case NoExpose:
   9426 	VTGraphicsOrNoExpose(event);
   9427 	break;
   9428     }
   9429 }
   9430 
   9431 static void
   9432 VTResize(Widget w)
   9433 {
   9434     if (XtIsRealized(w)) {
   9435 	XtermWidget xw = (XtermWidget) w;
   9436 	ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags);
   9437     }
   9438 }
   9439 
   9440 #define okDimension(src,dst) ((src <= MAX_U_COORD) \
   9441 			  && ((dst = (Dimension) src) == src))
   9442 
   9443 static void
   9444 RequestResize(XtermWidget xw, int rows, int cols, Bool text)
   9445 {
   9446     TScreen *screen = TScreenOf(xw);
   9447     Dimension replyWidth, replyHeight;
   9448     Dimension askedWidth, askedHeight;
   9449     XtGeometryResult status;
   9450     XWindowAttributes attrs;
   9451 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
   9452     Boolean buggyXft = False;
   9453     Cardinal ignore = 0;
   9454 #endif
   9455 
   9456     TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text));
   9457 #if OPT_STATUS_LINE
   9458     if (IsStatusShown(screen)) {
   9459 	if (rows == -1) {
   9460 	    /* prevent shrinking on DECCOLM, XTRESTORE, DECSCPP, DECANM */
   9461 	    rows = MaxRows(screen);
   9462 	}
   9463 	if (rows > 0) {
   9464 	    TRACE(("...reserve a row for status-line\n"));
   9465 	    ++rows;
   9466 	}
   9467     }
   9468 #endif
   9469 
   9470     /* check first if the row/column values fit into a Dimension */
   9471     if (cols > 0) {
   9472 	if ((int) (askedWidth = (Dimension) cols) < cols) {
   9473 	    TRACE(("... cols too large for Dimension\n"));
   9474 	    return;
   9475 	}
   9476     } else {
   9477 	askedWidth = 0;
   9478     }
   9479     if (rows > 0) {
   9480 	if ((int) (askedHeight = (Dimension) rows) < rows) {
   9481 	    TRACE(("... rows too large for Dimension\n"));
   9482 	    return;
   9483 	}
   9484     } else {
   9485 	askedHeight = 0;
   9486     }
   9487 
   9488     xw->work.doing_resize = True;
   9489 
   9490 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
   9491     /*
   9492      * Work around a bug seen when vttest switches from 132 columns back to 80
   9493      * columns, while double-buffering is active.  If Xft is active during the
   9494      * resize, the screen will be blank thereafter.  This workaround causes
   9495      * some extra flickering, but that is preferable to a blank screen.
   9496      *
   9497      * Since the bitmap- and TrueType-fonts do not always have identical sizes,
   9498      * do this switching early, to use the updated font-sizes in the request
   9499      * for resizing the window.
   9500      */
   9501 #define ToggleXft() HandleRenderFont((Widget)xw, (XEvent *)0, (String *)0, &ignore)
   9502     if (resource.buffered
   9503 	&& UsingRenderFont(xw)) {
   9504 	ToggleXft();
   9505 	buggyXft = True;
   9506     }
   9507 #endif
   9508 
   9509     /*
   9510      * If the requested values will fit into a Dimension, and one or both are
   9511      * zero, get the current corresponding screen dimension to use as a limit.
   9512      */
   9513     if (askedHeight == 0
   9514 	|| askedWidth == 0
   9515 	|| xw->misc.limit_resize > 0) {
   9516 	xtermGetWinAttrs(XtDisplay(xw),
   9517 			 RootWindowOfScreen(XtScreen(xw)), &attrs);
   9518     }
   9519 
   9520     /*
   9521      * Using the current font metrics, translate the requested character
   9522      * rows/columns into pixels.
   9523      */
   9524     if (text) {
   9525 	unsigned long value;
   9526 
   9527 	if ((value = (unsigned long) rows) != 0) {
   9528 	    if (rows < 0)
   9529 		value = (unsigned long) MaxRows(screen);
   9530 	    value *= (unsigned long) FontHeight(screen);
   9531 	    value += (unsigned long) (2 * screen->border);
   9532 	    if (!okDimension(value, askedHeight))
   9533 		goto give_up;
   9534 	}
   9535 
   9536 	if ((value = (unsigned long) cols) != 0) {
   9537 	    if (cols < 0)
   9538 		value = (unsigned long) MaxCols(screen);
   9539 	    value *= (unsigned long) FontWidth(screen);
   9540 	    value += (unsigned long) ((2 * screen->border)
   9541 				      + ScrollbarWidth(screen));
   9542 	    if (!okDimension(value, askedWidth))
   9543 		goto give_up;
   9544 	}
   9545 
   9546     } else {
   9547 	if (rows < 0)
   9548 	    askedHeight = FullHeight(screen);
   9549 	if (cols < 0)
   9550 	    askedWidth = FullWidth(screen);
   9551     }
   9552 
   9553     if (rows == 0) {
   9554 	askedHeight = (Dimension) attrs.height;
   9555     }
   9556     if (cols == 0) {
   9557 	askedWidth = (Dimension) attrs.width;
   9558     }
   9559 
   9560     if (xw->misc.limit_resize > 0) {
   9561 	Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height);
   9562 	Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width);
   9563 	if ((int) high < attrs.height)
   9564 	    high = (Dimension) attrs.height;
   9565 	if (askedHeight > high)
   9566 	    askedHeight = high;
   9567 	if ((int) wide < attrs.width)
   9568 	    wide = (Dimension) attrs.width;
   9569 	if (askedWidth > wide)
   9570 	    askedWidth = wide;
   9571     }
   9572 #ifndef nothack
   9573     getXtermSizeHints(xw);
   9574 #endif
   9575 
   9576     TRACE(("...requesting resize %dx%d (%dx%d)\n",
   9577 	   askedHeight, askedWidth,
   9578 	   askedHeight / FontHeight(screen),
   9579 	   askedWidth / FontWidth(screen)));
   9580     status = REQ_RESIZE((Widget) xw,
   9581 			askedWidth, askedHeight,
   9582 			&replyWidth, &replyHeight);
   9583 
   9584     if (status == XtGeometryYes ||
   9585 	status == XtGeometryDone) {
   9586 	ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
   9587     }
   9588 #ifndef nothack
   9589     /*
   9590      * XtMakeResizeRequest() has the undesirable side-effect of clearing
   9591      * the window manager's hints, even on a failed request.  This would
   9592      * presumably be fixed if the shell did its own work.
   9593      */
   9594     if (xw->hints.flags
   9595 	&& replyHeight
   9596 	&& replyWidth) {
   9597 	xw->hints.height = replyHeight;
   9598 	xw->hints.width = replyWidth;
   9599 
   9600 	TRACE(("%s@%d -- ", __FILE__, __LINE__));
   9601 	TRACE_HINTS(&xw->hints);
   9602 	XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints);
   9603 	TRACE(("%s@%d -- ", __FILE__, __LINE__));
   9604 	TRACE_WM_HINTS(xw);
   9605     }
   9606 #endif
   9607 
   9608     XSync(screen->display, False);	/* synchronize */
   9609     if (xtermAppPending()) {
   9610 	xevents(xw);
   9611     }
   9612 
   9613   give_up:
   9614 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
   9615     if (buggyXft) {
   9616 	ToggleXft();
   9617 	if (xtermAppPending()) {
   9618 	    xevents(xw);
   9619 	}
   9620     }
   9621 #endif
   9622 
   9623     xw->work.doing_resize = False;
   9624 
   9625     TRACE(("...RequestResize done\n"));
   9626     return;
   9627 }
   9628 
   9629 static String xterm_trans =
   9630 "<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
   9631      <MappingNotify>: KeyboardMapping()\n";
   9632 
   9633 int
   9634 VTInit(XtermWidget xw)
   9635 {
   9636     Widget vtparent = SHELL_OF(xw);
   9637 
   9638     TRACE(("VTInit " TRACE_L "\n"));
   9639 
   9640     XtRealizeWidget(vtparent);
   9641     XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
   9642     (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent),
   9643 			   &wm_delete_window, 1);
   9644 
   9645     if (IsEmpty(xw->keyboard.print_translations)) {
   9646 	TRACE_TRANS("shell", vtparent);
   9647 	TRACE_TRANS("vt100", (Widget) (xw));
   9648 	xtermButtonInit(xw);
   9649     }
   9650 
   9651     ScrnAllocBuf(xw);
   9652 
   9653     TRACE(("..." TRACE_R " VTInit\n"));
   9654     return (1);
   9655 }
   9656 
   9657 static void
   9658 VTClassInit(void)
   9659 {
   9660     XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
   9661 		   (XtConvertArgList) NULL, (Cardinal) 0);
   9662 }
   9663 
   9664 /*
   9665  * Override the use of XtDefaultForeground/XtDefaultBackground to make some
   9666  * colors, such as cursor color, use the actual foreground/background value
   9667  * if there is no explicit resource value used.
   9668  */
   9669 static Pixel
   9670 fill_Tres(XtermWidget target, XtermWidget source, int offset)
   9671 {
   9672     char *name;
   9673     ScrnColors temp;
   9674     TScreen *src = TScreenOf(source);
   9675     TScreen *dst = TScreenOf(target);
   9676 
   9677     dst->Tcolors[offset] = src->Tcolors[offset];
   9678     dst->Tcolors[offset].mode = False;
   9679 
   9680     if ((name = x_strtrim(dst->Tcolors[offset].resource)) != NULL)
   9681 	dst->Tcolors[offset].resource = name;
   9682 
   9683     if (name == NULL) {
   9684 	dst->Tcolors[offset].value = target->dft_foreground;
   9685     } else if (isDefaultForeground(name)) {
   9686 	dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
   9687 				      ? target->dft_foreground
   9688 				      : dst->Tcolors[TEXT_FG].value);
   9689     } else if (isDefaultBackground(name)) {
   9690 	dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
   9691 				      ? target->dft_background
   9692 				      : dst->Tcolors[TEXT_BG].value);
   9693     } else {
   9694 	memset(&temp, 0, sizeof(temp));
   9695 	if (AllocateTermColor(target, &temp, offset, name, True)) {
   9696 	    if (COLOR_DEFINED(&(temp), offset))
   9697 		free(temp.names[offset]);
   9698 	    dst->Tcolors[offset].value = temp.colors[offset];
   9699 	} else if (offset == TEXT_FG || offset == TEXT_BG) {
   9700 	    free(name);
   9701 	    dst->Tcolors[offset].resource = NULL;
   9702 	}
   9703     }
   9704     return dst->Tcolors[offset].value;
   9705 }
   9706 
   9707 /*
   9708  * If one or both of the foreground/background colors cannot be allocated,
   9709  * e.g., due to gross misconfiguration, recover by setting both to the
   9710  * display's default values.
   9711  */
   9712 static void
   9713 repairColors(XtermWidget target)
   9714 {
   9715     TScreen *screen = TScreenOf(target);
   9716 
   9717     if (screen->Tcolors[TEXT_FG].resource == NULL ||
   9718 	screen->Tcolors[TEXT_BG].resource == NULL) {
   9719 	xtermWarning("unable to allocate fg/bg colors\n");
   9720 	screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground);
   9721 	screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground);
   9722 	if (screen->Tcolors[TEXT_FG].resource == NULL ||
   9723 	    screen->Tcolors[TEXT_BG].resource == NULL) {
   9724 	    Exit(ERROR_MISC);
   9725 	}
   9726 	screen->Tcolors[TEXT_FG].value = target->dft_foreground;
   9727 	screen->Tcolors[TEXT_BG].value = target->dft_background;
   9728     }
   9729 }
   9730 
   9731 #if OPT_WIDE_CHARS
   9732 static void
   9733 set_utf8_feature(TScreen *screen, int *feature)
   9734 {
   9735     if (*feature == uDefault) {
   9736 	switch (screen->utf8_mode) {
   9737 	case uFalse:
   9738 	    /* FALLTHRU */
   9739 	case uTrue:
   9740 	    *feature = screen->utf8_mode;
   9741 	    break;
   9742 	case uDefault:
   9743 	    /* should not happen */
   9744 	    *feature = uTrue;
   9745 	    break;
   9746 	case uAlways:
   9747 	    /* use this to disable menu entry */
   9748 	    break;
   9749 	}
   9750     }
   9751 }
   9752 
   9753 static void
   9754 VTInitialize_locale(XtermWidget xw)
   9755 {
   9756     TScreen *screen = TScreenOf(xw);
   9757     Bool is_utf8 = xtermEnvUTF8();
   9758 
   9759     TRACE(("VTInitialize_locale\n"));
   9760     TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode));
   9761     TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts));
   9762     TRACE(("... request screen.utf8_title = %d\n", screen->utf8_title));
   9763 
   9764     screen->utf8_always = (screen->utf8_mode == uAlways);
   9765     if (screen->utf8_mode < 0)
   9766 	screen->utf8_mode = uFalse;
   9767 
   9768     if (screen->utf8_mode > 3)
   9769 	screen->utf8_mode = uDefault;
   9770 
   9771     screen->latin9_mode = 0;
   9772     screen->unicode_font = 0;
   9773 #if OPT_LUIT_PROG
   9774     xw->misc.callfilter = 0;
   9775     xw->misc.use_encoding = 0;
   9776 
   9777     TRACE(("... setup for luit:\n"));
   9778     TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str));
   9779 
   9780     if (screen->utf8_mode == uFalse) {
   9781 	TRACE(("... command-line +u8 overrides\n"));
   9782     } else
   9783 #if OPT_MINI_LUIT
   9784     if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) {
   9785 	int fl = (int) strlen(DefaultFontN(xw));
   9786 	if (fl > 11
   9787 	    && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) {
   9788 	    screen->unicode_font = 1;
   9789 	    /* unicode font, use True */
   9790 #ifdef HAVE_LANGINFO_CODESET
   9791 	    if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968")
   9792 		|| !strcmp(xtermEnvEncoding(), "ISO-8859-1")) {
   9793 		if (screen->utf8_mode == uDefault)
   9794 		    screen->utf8_mode = uFalse;
   9795 	    } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) {
   9796 		if (screen->utf8_mode == uDefault)
   9797 		    screen->utf8_mode = uFalse;
   9798 		screen->latin9_mode = 1;
   9799 	    } else {
   9800 		xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
   9801 		screen->utf8_mode = uAlways;
   9802 	    }
   9803 #else
   9804 	    xw->misc.callfilter = is_utf8 ? 0 : 1;
   9805 	    screen->utf8_mode = uAlways;
   9806 #endif
   9807 	} else {
   9808 	    /* other encoding, use False */
   9809 	    if (screen->utf8_mode == uDefault) {
   9810 		screen->utf8_mode = is_utf8 ? uAlways : uFalse;
   9811 	    }
   9812 	}
   9813     } else
   9814 #endif /* OPT_MINI_LUIT */
   9815 	if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 ||
   9816 	    x_strcasecmp(xw->misc.locale_str, "ON") == 0 ||
   9817 	    x_strcasecmp(xw->misc.locale_str, "YES") == 0 ||
   9818 	    x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 ||
   9819 	    strcmp(xw->misc.locale_str, "1") == 0) {
   9820 	/* when true ... fully obeying LC_CTYPE locale */
   9821 	xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
   9822 	screen->utf8_mode = uAlways;
   9823     } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 ||
   9824 	       x_strcasecmp(xw->misc.locale_str, "OFF") == 0 ||
   9825 	       x_strcasecmp(xw->misc.locale_str, "NO") == 0 ||
   9826 	       strcmp(xw->misc.locale_str, "0") == 0) {
   9827 	/* when false ... original value of utf8_mode is effective */
   9828 	if (screen->utf8_mode == uDefault) {
   9829 	    screen->utf8_mode = is_utf8 ? uAlways : uFalse;
   9830 	}
   9831     } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 ||
   9832 	       x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) {
   9833 	/* when medium ... obeying locale only for UTF-8 and Asian */
   9834 	if (is_utf8) {
   9835 	    screen->utf8_mode = uAlways;
   9836 	} else if (
   9837 #ifdef MB_CUR_MAX
   9838 		      MB_CUR_MAX > 1 ||
   9839 #else
   9840 		      !strncmp(xtermEnvLocale(), "ja", (size_t) 2) ||
   9841 		      !strncmp(xtermEnvLocale(), "ko", (size_t) 2) ||
   9842 		      !strncmp(xtermEnvLocale(), "zh", (size_t) 2) ||
   9843 #endif
   9844 		      !strncmp(xtermEnvLocale(), "th", (size_t) 2) ||
   9845 		      !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) {
   9846 	    xw->misc.callfilter = 1;
   9847 	    screen->utf8_mode = uAlways;
   9848 	} else {
   9849 	    screen->utf8_mode = uFalse;
   9850 	}
   9851     } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 ||
   9852 	       x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) {
   9853 	/* when UTF-8 ... UTF-8 mode */
   9854 	screen->utf8_mode = uAlways;
   9855     } else {
   9856 	/* other words are regarded as encoding name passed to luit */
   9857 	xw->misc.callfilter = 1;
   9858 	screen->utf8_mode = uAlways;
   9859 	xw->misc.use_encoding = 1;
   9860     }
   9861     TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter)));
   9862     TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding)));
   9863 #else
   9864     if (screen->utf8_mode == uDefault) {
   9865 	screen->utf8_mode = is_utf8 ? uAlways : uFalse;
   9866     }
   9867 #endif /* OPT_LUIT_PROG */
   9868 
   9869     set_utf8_feature(screen, &screen->utf8_fonts);
   9870     set_utf8_feature(screen, &screen->utf8_title);
   9871 
   9872     screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse);
   9873 
   9874     TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode));
   9875     TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts));
   9876     TRACE(("... updated screen.utf8_title = %d\n", screen->utf8_title));
   9877     TRACE(("...VTInitialize_locale done\n"));
   9878 }
   9879 #endif
   9880 
   9881 void
   9882 lookupSelectUnit(XtermWidget xw, Cardinal item, String value)
   9883 {
   9884     /* *INDENT-OFF* */
   9885     static const struct {
   9886 	const char *	name;
   9887 	SelectUnit	code;
   9888     } table[] = {
   9889     	{ "char",	Select_CHAR },
   9890     	{ "word",	Select_WORD },
   9891     	{ "line",	Select_LINE },
   9892     	{ "group",	Select_GROUP },
   9893     	{ "page",	Select_PAGE },
   9894     	{ "all",	Select_ALL },
   9895 #if OPT_SELECT_REGEX
   9896     	{ "regex",	Select_REGEX },
   9897 #endif
   9898     };
   9899     /* *INDENT-ON* */
   9900 
   9901     TScreen *screen = TScreenOf(xw);
   9902     String next = x_skip_nonblanks(value);
   9903     Cardinal n;
   9904 
   9905     screen->selectMap[item] = NSELECTUNITS;
   9906     for (n = 0; n < XtNumber(table); ++n) {
   9907 	if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) {
   9908 	    screen->selectMap[item] = table[n].code;
   9909 #if OPT_SELECT_REGEX
   9910 	    if (table[n].code == Select_REGEX) {
   9911 		screen->selectExpr[item] = x_strtrim(next);
   9912 		TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item]));
   9913 	    }
   9914 #endif
   9915 	    break;
   9916 	}
   9917     }
   9918 }
   9919 
   9920 static void
   9921 ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item)
   9922 {
   9923     lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]);
   9924 }
   9925 
   9926 /*
   9927  * Parse a comma-separated list, returning a string which the caller must
   9928  * free, and updating the source pointer.
   9929  */
   9930 static char *
   9931 ParseList(const char **source)
   9932 {
   9933     const char *base = *source;
   9934     const char *next;
   9935     char *value = NULL;
   9936     char *result;
   9937 
   9938     /* ignore empty values */
   9939     while (*base == ',')
   9940 	++base;
   9941 
   9942     if (*base != '\0') {
   9943 	size_t size;
   9944 
   9945 	next = base;
   9946 	while (*next != '\0' && *next != ',')
   9947 	    ++next;
   9948 	size = (size_t) (1 + next - base);
   9949 	value = malloc(size);
   9950 	if (value != NULL) {
   9951 	    memcpy(value, base, size);
   9952 	    value[size - 1] = '\0';
   9953 	}
   9954 	*source = next;
   9955     } else {
   9956 	*source = base;
   9957     }
   9958     result = x_strtrim(value);
   9959     free(value);
   9960     return result;
   9961 }
   9962 
   9963 static void
   9964 set_flags_from_list(char *target,
   9965 		    const char *source,
   9966 		    const FlagList * list)
   9967 {
   9968     Cardinal n;
   9969 
   9970     while (!IsEmpty(source)) {
   9971 	char *next = ParseList(&source);
   9972 	Boolean found = False;
   9973 	char flag = 1;
   9974 
   9975 	if (next == NULL)
   9976 	    break;
   9977 	if (*next == '~') {
   9978 	    flag = 0;
   9979 	    next++;
   9980 	}
   9981 	if (isdigit(CharOf(*next))) {
   9982 	    char *temp;
   9983 	    int value = (int) strtol(next, &temp, 0);
   9984 	    if (!FullS2L(next, temp)) {
   9985 		xtermWarning("Expected a number: %s\n", next);
   9986 	    } else {
   9987 		for (n = 0; list[n].name != NULL; ++n) {
   9988 		    if (list[n].code == value) {
   9989 			target[value] = flag;
   9990 			found = True;
   9991 			TRACE(("...found %s (%d)\n", list[n].name, value));
   9992 			break;
   9993 		    }
   9994 		}
   9995 	    }
   9996 	} else {
   9997 	    for (n = 0; list[n].name != NULL; ++n) {
   9998 		if (!x_wildstrcmp(next, list[n].name)) {
   9999 		    int value = list[n].code;
   10000 		    target[value] = flag;
   10001 		    found = True;
   10002 		    TRACE(("...found %s (%d)\n", list[n].name, value));
   10003 		}
   10004 	    }
   10005 	}
   10006 	if (!found) {
   10007 	    xtermWarning("Unrecognized keyword: %s\n", next);
   10008 	}
   10009 	free(next);
   10010     }
   10011 }
   10012 
   10013 #define InitCursorShape(target, source) \
   10014     target->cursor_shape = source->cursor_underline ? CURSOR_UNDERLINE : \
   10015                            source->cursor_bar ? CURSOR_BAR : CURSOR_BLOCK
   10016 
   10017 #if OPT_XRES_QUERY
   10018 static XtResource *
   10019 findVT100Resource(const char *name)
   10020 {
   10021     Cardinal n;
   10022     XtResource *result = NULL;
   10023 
   10024     if (!IsEmpty(name)) {
   10025 	XrmQuark quarkName = XrmPermStringToQuark(name);
   10026 	for (n = 0; n < XtNumber(xterm_resources); ++n) {
   10027 	    if ((int) xterm_resources[n].resource_offset >= 0
   10028 		&& !strcmp(xterm_resources[n].resource_name, name)) {
   10029 		result = &xterm_resources[n];
   10030 		break;
   10031 	    } else if (xterm_resources[n].resource_name
   10032 		       == (String) (intptr_t) quarkName) {
   10033 		result = &xterm_resources[n];
   10034 		break;
   10035 	    }
   10036 	}
   10037     }
   10038     return result;
   10039 }
   10040 
   10041 static int
   10042 cmp_resources(const void *a, const void *b)
   10043 {
   10044     return strcmp((*(const String *) a),
   10045 		  (*(const String *) b));
   10046 }
   10047 
   10048 static void
   10049 reportResources(XtermWidget xw)
   10050 {
   10051     String *list = TypeMallocN(String, XtNumber(xterm_resources));
   10052     Cardinal n;
   10053     int widest = 0;
   10054 
   10055     if (list == NULL)
   10056 	return;
   10057 
   10058     for (n = 0; n < XtNumber(xterm_resources); ++n) {
   10059 	int width;
   10060 	list[n] = (((int) xterm_resources[n].resource_offset < 0)
   10061 		   ? XrmQuarkToString((XrmQuark) (intptr_t)
   10062 				      xterm_resources[n].resource_name)
   10063 		   : xterm_resources[n].resource_name);
   10064 	width = (int) strlen(list[n]);
   10065 	if (widest < width)
   10066 	    widest = width;
   10067     }
   10068     qsort(list, (size_t) XtNumber(xterm_resources), sizeof(String), cmp_resources);
   10069     for (n = 0; n < XtNumber(xterm_resources); ++n) {
   10070 	char *value = vt100ResourceToString(xw, list[n]);
   10071 	printf("%-*s : %s\n", widest, list[n], value ? value : "(skip)");
   10072 	free(value);
   10073     }
   10074     free(list);
   10075 }
   10076 
   10077 char *
   10078 vt100ResourceToString(XtermWidget xw, const char *name)
   10079 {
   10080     XtResource *data;
   10081     char *result = NULL;
   10082 
   10083     if ((data = findVT100Resource(name)) != NULL) {
   10084 	int fake_offset = (int) data->resource_offset;
   10085 	void *res_addr;
   10086 	int real_offset;
   10087 	String res_type;
   10088 
   10089 	/*
   10090 	 * X Toolkit "compiles" the resource-list into quarks and changes the
   10091 	 * resource-offset at the same time to a negative value.
   10092 	 */
   10093 	if (fake_offset < 0) {
   10094 	    real_offset = -(fake_offset + 1);
   10095 	    res_type = XrmQuarkToString((XrmQuark) (intptr_t) data->resource_type);
   10096 	} else {
   10097 	    real_offset = fake_offset;
   10098 	    res_type = data->resource_type;
   10099 	}
   10100 	res_addr = (void *) ((char *) xw + real_offset);
   10101 
   10102 	if (!strcmp(res_type, XtRString)) {
   10103 	    char *value = *(char **) res_addr;
   10104 	    if (value != NULL) {
   10105 		size_t need = strlen(value);
   10106 		if ((result = malloc(1 + need)) != NULL)
   10107 		    strcpy(result, value);
   10108 	    }
   10109 	} else if (!strcmp(res_type, XtRInt)) {
   10110 	    if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != NULL)
   10111 		sprintf(result, "%d", *(int *) res_addr);
   10112 	} else if (!strcmp(res_type, XtRFloat)) {
   10113 	    if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != NULL)
   10114 		sprintf(result, "%f", (double) (*(float *) res_addr));
   10115 	} else if (!strcmp(res_type, XtRBoolean)) {
   10116 	    if ((result = malloc((size_t) 6)) != NULL)
   10117 		strcpy(result, *(Boolean *) res_addr ? "true" : "false");
   10118 	}
   10119     }
   10120     TRACE(("vt100ResourceToString(%s) %s\n", name, NonNull(result)));
   10121     return result;
   10122 }
   10123 #endif /* OPT_XRES_QUERY */
   10124 
   10125 /*
   10126  * Decode a terminal-ID or graphics-terminal-ID, using the default terminal-ID
   10127  * if the value is outside a (looser) range than limitedTerminalID.  This uses
   10128  * a wider range, to avoid being a nuisance when using X resources with
   10129  * different configurations of xterm.
   10130  */
   10131 static int
   10132 decodeTerminalID(const char *value)
   10133 {
   10134     const char *s;
   10135     char *t;
   10136     long result;
   10137 
   10138     for (s = value; *s; s++) {
   10139 	if (!isalpha(CharOf(*s)))
   10140 	    break;
   10141     }
   10142     result = strtol(s, &t, 10);
   10143     if (t == s || *t != '\0' || result <= 0L || result > 1000L) {
   10144 	xtermWarning("unexpected value for terminalID: \"%s\"\n", value);
   10145 	result = atoi(DFT_DECID);
   10146     }
   10147     TRACE(("decodeTerminalID \"%s\" ->%d\n", value, (int) result));
   10148     return (int) result;
   10149 }
   10150 
   10151 /*
   10152  * Ensures that the value returned by decodeTerminalID is either in the range
   10153  * of IDs matching a known terminal, or (failing that), set to the built-in
   10154  * default.  The DA response relies on having the ID being set to a known
   10155  * value.
   10156  */
   10157 static int
   10158 limitedTerminalID(int terminal_id)
   10159 {
   10160     if (terminal_id < MIN_DECID)
   10161 	terminal_id = MIN_DECID;
   10162     else if (terminal_id > MAX_DECID)
   10163 	terminal_id = MAX_DECID;
   10164     else
   10165 	terminal_id = atoi(DFT_DECID);
   10166     return terminal_id;
   10167 }
   10168 
   10169 #define DATA_END   { NULL,  -1       }
   10170 
   10171 #define DATA(name) { #name, ec##name }
   10172 static const FlagList tblColorOps[] =
   10173 {
   10174     DATA(SetColor)
   10175     ,DATA(GetColor)
   10176     ,DATA(GetAnsiColor)
   10177     ,DATA_END
   10178 };
   10179 #undef DATA
   10180 
   10181 #define DATA(name) { #name, ef##name }
   10182 static const FlagList tblFontOps[] =
   10183 {
   10184     DATA(SetFont)
   10185     ,DATA(GetFont)
   10186     ,DATA_END
   10187 };
   10188 #undef DATA
   10189 
   10190 #define DATA(name) { #name, em##name }
   10191 static const FlagList tblMouseOps[] =
   10192 {
   10193     DATA(X10)
   10194     ,DATA(Locator)
   10195     ,DATA(VT200Click)
   10196     ,DATA(VT200Hilite)
   10197     ,DATA(AnyButton)
   10198     ,DATA(AnyEvent)
   10199     ,DATA(FocusEvent)
   10200     ,DATA(Extended)
   10201     ,DATA(SGR)
   10202     ,DATA(URXVT)
   10203     ,DATA(AlternateScroll)
   10204     ,DATA_END
   10205 };
   10206 #undef DATA
   10207 
   10208 #define DATA(name) { #name, ep##name }
   10209 #define DATA2(alias,name) { #alias, ep##name }
   10210 static const FlagList tblPasteOps[] =
   10211 {
   10212     DATA(NUL)
   10213     ,DATA(SOH)
   10214     ,DATA(STX)
   10215     ,DATA(ETX)
   10216     ,DATA(EOT)
   10217     ,DATA(ENQ)
   10218     ,DATA(ACK)
   10219     ,DATA(BEL)
   10220     ,DATA(BS)
   10221     ,DATA(HT)
   10222     ,DATA(LF)
   10223     ,DATA(VT)
   10224     ,DATA(FF)
   10225     ,DATA(CR)
   10226     ,DATA(SO)
   10227     ,DATA(SI)
   10228     ,DATA(DLE)
   10229     ,DATA(DC1)
   10230     ,DATA(DC2)
   10231     ,DATA(DC3)
   10232     ,DATA(DC4)
   10233     ,DATA(NAK)
   10234     ,DATA(SYN)
   10235     ,DATA(ETB)
   10236     ,DATA(CAN)
   10237     ,DATA(EM)
   10238     ,DATA(SUB)
   10239     ,DATA(ESC)
   10240     ,DATA(FS)
   10241     ,DATA(GS)
   10242     ,DATA(RS)
   10243     ,DATA(US)
   10244 /* aliases */
   10245     ,DATA2(NL, LF)
   10246     ,DATA(C0)
   10247     ,DATA(DEL)
   10248     ,DATA(STTY)
   10249     ,DATA_END
   10250 };
   10251 #undef DATA
   10252 #undef DATA2
   10253 
   10254 #define DATA(name) { #name, et##name }
   10255 static const FlagList tblTcapOps[] =
   10256 {
   10257     DATA(SetTcap)
   10258     ,DATA(GetTcap)
   10259     ,DATA_END
   10260 };
   10261 #undef DATA
   10262 
   10263 #define DATA(name) { #name, ew##name }
   10264 static const FlagList tblWindowOps[] =
   10265 {
   10266     DATA(RestoreWin)
   10267     ,DATA(MinimizeWin)
   10268     ,DATA(SetWinPosition)
   10269     ,DATA(SetWinSizePixels)
   10270     ,DATA(RaiseWin)
   10271     ,DATA(LowerWin)
   10272     ,DATA(RefreshWin)
   10273     ,DATA(SetWinSizeChars)
   10274 #if OPT_MAXIMIZE
   10275     ,DATA(MaximizeWin)
   10276     ,DATA(FullscreenWin)
   10277 #endif
   10278     ,DATA(GetWinState)
   10279     ,DATA(GetWinPosition)
   10280     ,DATA(GetWinSizePixels)
   10281     ,DATA(GetWinSizeChars)
   10282 #if OPT_MAXIMIZE
   10283     ,DATA(GetScreenSizeChars)
   10284 #endif
   10285     ,DATA(GetIconTitle)
   10286     ,DATA(GetWinTitle)
   10287     ,DATA(PushTitle)
   10288     ,DATA(PopTitle)
   10289 /* this item uses all remaining numbers in the sequence */
   10290     ,DATA(SetWinLines)
   10291 /* starting at this point, numbers do not apply */
   10292     ,DATA(SetXprop)
   10293     ,DATA(GetSelection)
   10294     ,DATA(SetSelection)
   10295     ,DATA(GetChecksum)
   10296     ,DATA(SetChecksum)
   10297     ,DATA_END
   10298 };
   10299 #undef DATA
   10300 
   10301 void
   10302 unparse_disallowed_ops(XtermWidget xw, char *value)
   10303 {
   10304     TScreen *screen = TScreenOf(xw);
   10305 #define DATA(mixed, plain, flags) { #mixed, offsetof(TScreen, plain), sizeof(screen->plain), flags }
   10306     /* *INDENT-OFF* */
   10307     static const struct {
   10308 	const char *	name;
   10309 	size_t		offset;
   10310 	size_t		length;
   10311 	const FlagList *codes;
   10312     } table[] = {
   10313 	DATA(allowColorOps,	 disallow_color_ops, tblColorOps),
   10314 	DATA(allowFontOps,	 disallow_font_ops,  tblFontOps),
   10315 	DATA(allowMouseOps,	 disallow_mouse_ops, tblMouseOps),
   10316 	DATA(allowPasteControls, disallow_paste_ops, tblPasteOps),
   10317 	DATA(allowTcapOps,	 disallow_tcap_ops,  tblTcapOps),
   10318 	DATA(allowWinOps,	 disallow_win_ops,   tblWindowOps),
   10319     };
   10320     /* *INDENT-ON* */
   10321 #undef DATA
   10322     Cardinal j, k, jk;
   10323     char delim = ';';
   10324 
   10325     for (j = 0; j < XtNumber(table); ++j) {
   10326 	if (!x_strcasecmp(value, table[j].name)) {
   10327 	    const char *flags = (char *) screen + table[j].offset;
   10328 
   10329 	    for (k = 0; k < table[j].length; ++k) {
   10330 		if (flags[k]) {
   10331 		    const FlagList *codes = table[j].codes;
   10332 		    Boolean found = False;
   10333 
   10334 		    unparseputc(xw, delim);
   10335 		    for (jk = 0; codes[jk].name; ++jk) {
   10336 			if (codes[jk].code == (int) k) {
   10337 			    unparseputs(xw, codes[jk].name);
   10338 			    found = True;
   10339 			    break;
   10340 			}
   10341 		    }
   10342 		    if (!found)
   10343 			unparseputn(xw, k);
   10344 		    delim = ',';
   10345 		}
   10346 	    }
   10347 	    break;
   10348 	}
   10349     }
   10350 }
   10351 
   10352 /* ARGSUSED */
   10353 static void
   10354 VTInitialize(Widget wrequest,
   10355 	     Widget new_arg,
   10356 	     ArgList args GCC_UNUSED,
   10357 	     Cardinal *num_args GCC_UNUSED)
   10358 {
   10359 #define Kolor(name) TScreenOf(wnew)->name.resource
   10360 #define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name))
   10361 #define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name))
   10362 #define DftFg(name) isDefaultForeground(Kolor(name))
   10363 #define DftBg(name) isDefaultBackground(Kolor(name))
   10364 
   10365 #if OPT_BLINK_CURS
   10366 #define DATA(name) { #name, cb##name }
   10367     static const FlagList tblBlinkOps[] =
   10368     {
   10369 	DATA(Always)
   10370 	,DATA(Never)
   10371 	,DATA_END
   10372     };
   10373 #undef DATA
   10374 #endif
   10375 
   10376 #if OPT_RENDERFONT
   10377 #define DATA(name) { #name, er##name }
   10378     static const FlagList tblRenderFont[] =
   10379     {
   10380 	DATA(Default)
   10381 	,DATA(DefaultOff)
   10382 	,DATA_END
   10383     };
   10384 #undef DATA
   10385 #endif
   10386 
   10387 #define DATA(name) { #name, ss##name }
   10388     static const FlagList tblShift2S[] =
   10389     {
   10390 	DATA(Always)
   10391 	,DATA(Never)
   10392 	,DATA_END
   10393     };
   10394 #undef DATA
   10395 
   10396 #if OPT_WIDE_CHARS
   10397 #define DATA(name) { #name, u##name }
   10398     static const FlagList tblUtf8Mode[] =
   10399     {
   10400 	DATA(Always)
   10401 	,DATA(Default)
   10402 	,DATA_END
   10403     };
   10404 #undef DATA
   10405 #endif
   10406 
   10407 #ifndef NO_ACTIVE_ICON
   10408 #define DATA(name) { #name, ei##name }
   10409     static const FlagList tblAIconOps[] =
   10410     {
   10411 	DATA(Default)
   10412 	,DATA_END
   10413     };
   10414 #undef DATA
   10415 #endif
   10416 
   10417 #define DATA(name) { #name, eb##name }
   10418     static const FlagList tbl8BitMeta[] =
   10419     {
   10420 	DATA(Never)
   10421 	,DATA(Locale)
   10422 	,DATA_END
   10423     };
   10424 #undef DATA
   10425 
   10426 #define DATA(name) { #name, ed##name }
   10427     static const FlagList tblCdXtraScroll[] =
   10428     {
   10429 	DATA(Trim)
   10430 	,DATA_END
   10431     };
   10432 #undef DATA
   10433 
   10434     XtermWidget request = (XtermWidget) wrequest;
   10435     XtermWidget wnew = (XtermWidget) new_arg;
   10436     Widget my_parent = SHELL_OF(wnew);
   10437     int i;
   10438 
   10439 #if OPT_ISO_COLORS
   10440     Bool color_ok;
   10441 #endif
   10442 
   10443 #if OPT_ISO_COLORS
   10444     static XtResource fake_resources[] =
   10445     {
   10446 #if OPT_256_COLORS
   10447 # include <256colres.h>
   10448 #elif OPT_88_COLORS
   10449 # include <88colres.h>
   10450 #endif
   10451     };
   10452 #endif
   10453 
   10454     TScreen *screen = TScreenOf(wnew);
   10455     char *saveLocale = xtermSetLocale(LC_NUMERIC, "C");
   10456 #if OPT_BLINK_CURS
   10457     int ebValue;
   10458 #endif
   10459 
   10460 #if OPT_TRACE
   10461     check_bitmasks();
   10462     check_tables();
   10463 #endif
   10464 
   10465     TRACE(("VTInitialize wnew %p, %d / %d resources " TRACE_L "\n",
   10466 	   (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES));
   10467     assert(XtNumber(xterm_resources) < MAXRESOURCES);
   10468 
   10469     /* Zero out the entire "screen" component of "wnew" widget, then do
   10470      * field-by-field assignment of "screen" fields that are named in the
   10471      * resource list.
   10472      */
   10473     memset(screen, 0, sizeof(wnew->screen));
   10474 
   10475     /* DESCO Sys#67660
   10476      * Zero out the entire "keyboard" component of "wnew" widget.
   10477      */
   10478     memset(&wnew->keyboard, 0, sizeof(wnew->keyboard));
   10479 
   10480     /*
   10481      * The workspace has no resources - clear it.
   10482      */
   10483     memset(&wnew->work, 0, sizeof(wnew->work));
   10484 
   10485     /* dummy values so that we don't try to Realize the parent shell with height
   10486      * or width of 0, which is illegal in X.  The real size is computed in the
   10487      * xtermWidget's Realize proc, but the shell's Realize proc is called first,
   10488      * and must see a valid size.
   10489      */
   10490     wnew->core.height = wnew->core.width = 1;
   10491 
   10492     /*
   10493      * The definition of -rv now is that it changes the definition of
   10494      * XtDefaultForeground and XtDefaultBackground.  So, we no longer
   10495      * need to do anything special.
   10496      */
   10497     screen->display = wnew->core.screen->display;
   10498 
   10499     /* prep getVisualInfo() */
   10500     wnew->visInfo = NULL;
   10501     wnew->numVisuals = 0;
   10502     (void) getVisualInfo(wnew);
   10503 
   10504 #if OPT_STATUS_LINE
   10505     StatusInit(&screen->status_data[0]);
   10506     StatusInit(&screen->status_data[1]);
   10507 #endif
   10508 
   10509     /*
   10510      * We use the default foreground/background colors to compare/check if a
   10511      * color-resource has been set.
   10512      */
   10513 #define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy))
   10514 #define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy))
   10515 
   10516     if (request->misc.re_verse) {
   10517 	wnew->dft_foreground = MyWhitePixel(screen->display);
   10518 	wnew->dft_background = MyBlackPixel(screen->display);
   10519     } else {
   10520 	wnew->dft_foreground = MyBlackPixel(screen->display);
   10521 	wnew->dft_background = MyWhitePixel(screen->display);
   10522     }
   10523 
   10524     init_Tres(TEXT_FG);
   10525     init_Tres(TEXT_BG);
   10526     repairColors(wnew);
   10527 
   10528     wnew->old_foreground = T_COLOR(screen, TEXT_FG);
   10529     wnew->old_background = T_COLOR(screen, TEXT_BG);
   10530 
   10531     TRACE(("Color resource initialization:\n"));
   10532     TRACE(("   Default foreground 0x%06lx\n", wnew->dft_foreground));
   10533     TRACE(("   Default background 0x%06lx\n", wnew->dft_background));
   10534     TRACE(("   Screen foreground  0x%06lx\n", T_COLOR(screen, TEXT_FG)));
   10535     TRACE(("   Screen background  0x%06lx\n", T_COLOR(screen, TEXT_BG)));
   10536     TRACE(("   Actual  foreground 0x%06lx\n", wnew->old_foreground));
   10537     TRACE(("   Actual  background 0x%06lx\n", wnew->old_background));
   10538 
   10539     screen->mouse_button = 0;
   10540     screen->mouse_row = -1;
   10541     screen->mouse_col = -1;
   10542 
   10543 #if OPT_BOX_CHARS
   10544     init_Bres(screen.force_box_chars);
   10545     init_Bres(screen.force_packed);
   10546     init_Bres(screen.assume_all_chars);
   10547 #endif
   10548 #if OPT_BOX_CHARS || OPT_WIDE_CHARS
   10549     init_Bres(screen.force_all_chars);
   10550 #endif
   10551     init_Bres(screen.free_bold_box);
   10552     init_Bres(screen.allowBoldFonts);
   10553 
   10554     init_Bres(screen.c132);
   10555     init_Bres(screen.curses);
   10556     init_Bres(screen.hp_ll_bc);
   10557 #if OPT_XMC_GLITCH
   10558     init_Ires(screen.xmc_glitch);
   10559     init_Ires(screen.xmc_attributes);
   10560     init_Bres(screen.xmc_inline);
   10561     init_Bres(screen.move_sgr_ok);
   10562 #endif
   10563 #if OPT_BLINK_CURS
   10564     init_Sres(screen.cursor_blink_s);
   10565     ebValue = extendedBoolean(wnew->screen.cursor_blink_s, tblBlinkOps, cbLAST);
   10566     wnew->screen.cursor_blink = (BlinkOps) ebValue;
   10567     init_Bres(screen.cursor_blink_xor);
   10568     init_Ires(screen.blink_on);
   10569     init_Ires(screen.blink_off);
   10570     screen->cursor_blink_i = screen->cursor_blink;
   10571 #endif
   10572     init_Bres(screen.cursor_underline);
   10573     init_Bres(screen.cursor_bar);
   10574     /* resources allow for underline or block, not (yet) bar */
   10575     InitCursorShape(screen, TScreenOf(request));
   10576 #if OPT_BLINK_CURS
   10577     TRACE(("cursor_shape:%d blinks:%d\n",
   10578 	   screen->cursor_shape,
   10579 	   screen->cursor_blink));
   10580 #endif
   10581 #if OPT_BLINK_TEXT
   10582     init_Ires(screen.blink_as_bold);
   10583 #endif
   10584     init_Ires(screen.border);
   10585     init_Bres(screen.jumpscroll);
   10586     init_Bres(screen.fastscroll);
   10587 
   10588     init_Bres(screen.old_fkeys);
   10589     wnew->screen.old_fkeys0 = wnew->screen.old_fkeys;
   10590     wnew->keyboard.type = screen->old_fkeys
   10591 	? keyboardIsLegacy
   10592 	: keyboardIsDefault;
   10593 
   10594     init_Mres(screen.delete_is_del);
   10595 #ifdef ALLOWLOGGING
   10596     init_Bres(misc.logInhibit);
   10597     init_Bres(misc.log_on);
   10598     init_Sres(screen.logfile);
   10599 #endif
   10600     init_Bres(screen.bellIsUrgent);
   10601     init_Bres(screen.bellOnReset);
   10602     init_Bres(screen.marginbell);
   10603     init_Bres(screen.multiscroll);
   10604     init_Ires(screen.nmarginbell);
   10605     init_Ires(screen.savelines);
   10606     init_Ires(screen.scrollBarBorder);
   10607     init_Ires(screen.scrolllines);
   10608     init_Bres(screen.alternateScroll);
   10609     init_Bres(screen.scrollttyoutput);
   10610     init_Bres(screen.scrollkey);
   10611 
   10612     init_Dres(screen.scale_height);
   10613     if (screen->scale_height < MIN_SCALE_HEIGHT)
   10614 	screen->scale_height = MIN_SCALE_HEIGHT;
   10615     if (screen->scale_height > MAX_SCALE_HEIGHT)
   10616 	screen->scale_height = MAX_SCALE_HEIGHT;
   10617 
   10618     init_Bres(misc.autoWrap);
   10619     init_Bres(misc.login_shell);
   10620     init_Bres(misc.reverseWrap);
   10621     init_Bres(misc.scrollbar);
   10622     init_Sres(misc.geo_metry);
   10623     init_Sres(misc.T_geometry);
   10624 
   10625     init_Sres(screen.term_id);
   10626     screen->terminal_id = decodeTerminalID(TScreenOf(request)->term_id);
   10627     screen->display_da1 = screen->terminal_id;
   10628     /*
   10629      * (1) If a known terminal model, and not a graphical terminal, preserve
   10630      *     the terminal id.
   10631      * (2) Otherwise, if ReGIS or sixel graphics are enabled, preserve the ID,
   10632      *     even if it is not a known terminal.
   10633      * (3) Otherwise force the terminal ID to the min, max, or VT420 depending
   10634      *     on the input.
   10635      */
   10636     switch (screen->terminal_id) {
   10637     case 52:			/* MIN_DECID */
   10638     case 100:
   10639     case 101:
   10640     case 102:
   10641     case 131:
   10642     case 132:
   10643     case 220:
   10644     case 320:
   10645     case 420:			/* DFT_DECID, unless overridden in configure */
   10646     case 510:
   10647     case 520:
   10648     case 525:			/* MAX_DECID */
   10649 	break;
   10650     default:
   10651 #if OPT_REGIS_GRAPHICS
   10652 	if (optRegisGraphics(screen))
   10653 	    break;
   10654 #endif
   10655 #if OPT_SIXEL_GRAPHICS
   10656 	if (optSixelGraphics(screen))
   10657 	    break;
   10658 #endif
   10659 	screen->terminal_id = limitedTerminalID(screen->terminal_id);
   10660 	screen->display_da1 = screen->terminal_id;
   10661 	break;
   10662     }
   10663     TRACE(("term_id '%s' -> terminal_id %d\n",
   10664 	   screen->term_id,
   10665 	   screen->terminal_id));
   10666 
   10667     set_vtXX_level(screen, (screen->terminal_id / 100));
   10668 
   10669     init_Ires(screen.title_modes);
   10670     screen->title_modes0 = screen->title_modes;
   10671 
   10672     init_Ires(screen.nextEventDelay);
   10673     if (screen->nextEventDelay <= 0)
   10674 	screen->nextEventDelay = 1;
   10675 
   10676     init_Bres(screen.visualbell);
   10677     init_Bres(screen.flash_line);
   10678     init_Ires(screen.visualBellDelay);
   10679     init_Bres(screen.poponbell);
   10680 
   10681     init_Bres(screen.eraseSavedLines0);
   10682     screen->eraseSavedLines = screen->eraseSavedLines0;
   10683 
   10684     init_Ires(misc.limit_resize);
   10685 
   10686 #if OPT_NUM_LOCK
   10687     init_Bres(misc.real_NumLock);
   10688     init_Bres(misc.alwaysUseMods);
   10689 #endif
   10690 
   10691 #if OPT_INPUT_METHOD
   10692     init_Bres(misc.open_im);
   10693     init_Ires(misc.retry_im);
   10694     init_Sres(misc.f_x);
   10695     init_Sres(misc.input_method);
   10696     init_Sres(misc.preedit_type);
   10697 #endif
   10698 
   10699 #if OPT_SHIFT_FONTS
   10700     init_Bres(misc.shift_fonts);
   10701 #endif
   10702 #if OPT_SUNPC_KBD
   10703     init_Ires(misc.ctrl_fkeys);
   10704 #endif
   10705 #if OPT_TEK4014
   10706     TEK4014_SHOWN(wnew) = False;	/* not a resource... */
   10707     init_Bres(misc.tekInhibit);
   10708     init_Bres(misc.tekSmall);
   10709     init_Bres(misc.TekEmu);
   10710 #endif
   10711 #if OPT_TCAP_QUERY
   10712     screen->tc_query_code = -1;
   10713 #endif
   10714     wnew->misc.re_verse0 = request->misc.re_verse;
   10715     init_Bres(misc.re_verse);
   10716     init_Ires(screen.multiClickTime);
   10717     init_Ires(screen.bellSuppressTime);
   10718     init_Sres(screen.charClass);
   10719 
   10720     init_Bres(screen.always_highlight);
   10721     init_Bres(screen.brokenSelections);
   10722     init_Bres(screen.cutNewline);
   10723     init_Bres(screen.cutToBeginningOfLine);
   10724     init_Bres(screen.highlight_selection);
   10725     init_Bres(screen.show_wrap_marks);
   10726     init_Bres(screen.i18nSelections);
   10727     init_Bres(screen.keepClipboard);
   10728     init_Bres(screen.keepSelection);
   10729     init_Bres(screen.selectToClipboard);
   10730     init_Bres(screen.trim_selection);
   10731 
   10732     screen->pointer_cursor = TScreenOf(request)->pointer_cursor;
   10733     init_Ires(screen.pointer_mode);
   10734     wnew->screen.pointer_mode0 = wnew->screen.pointer_mode;
   10735 
   10736     init_Sres(screen.answer_back);
   10737     init_Bres(screen.prefer_latin1);
   10738 
   10739     wnew->SPS.printer_checked = False;
   10740     init_Sres(SPS.printer_command);
   10741     init_Bres(SPS.printer_autoclose);
   10742     init_Bres(SPS.printer_extent);
   10743     init_Bres(SPS.printer_formfeed);
   10744     init_Bres(SPS.printer_newline);
   10745     init_Ires(SPS.printer_controlmode);
   10746 #if OPT_PRINT_COLORS
   10747     init_Ires(SPS.print_attributes);
   10748 #endif
   10749     init_Bres(screen.print_rawchars);
   10750 
   10751     init_Sres(screen.keyboard_dialect);
   10752 
   10753     init_Sres(screen.cursor_font_name);
   10754     init_Sres(screen.pointer_shape);
   10755 
   10756     init_Bres(screen.input_eight_bits);
   10757     init_Bres(screen.output_eight_bits);
   10758     init_Bres(screen.control_eight_bits);
   10759     init_Bres(screen.backarrow_key);
   10760     init_Bres(screen.alt_is_not_meta);
   10761     init_Bres(screen.alt_sends_esc);
   10762     init_Bres(screen.meta_sends_esc);
   10763 
   10764     init_Bres(screen.allowPasteControl0);
   10765     init_Bres(screen.allowSendEvent0);
   10766     init_Bres(screen.allowColorOp0);
   10767     init_Bres(screen.allowFontOp0);
   10768     init_Bres(screen.allowMouseOp0);
   10769     init_Bres(screen.allowTcapOp0);
   10770     init_Bres(screen.allowTitleOp0);
   10771     init_Bres(screen.allowWindowOp0);
   10772 
   10773 #if OPT_SCROLL_LOCK
   10774     init_Bres(screen.allowScrollLock0);
   10775     init_Bres(screen.autoScrollLock);
   10776 #endif
   10777 
   10778     init_Sres(screen.disallowedColorOps);
   10779 
   10780     set_flags_from_list(screen->disallow_color_ops,
   10781 			screen->disallowedColorOps,
   10782 			tblColorOps);
   10783 
   10784     init_Sres(screen.disallowedFontOps);
   10785 
   10786     set_flags_from_list(screen->disallow_font_ops,
   10787 			screen->disallowedFontOps,
   10788 			tblFontOps);
   10789 
   10790     init_Sres(screen.disallowedMouseOps);
   10791 
   10792     set_flags_from_list(screen->disallow_mouse_ops,
   10793 			screen->disallowedMouseOps,
   10794 			tblMouseOps);
   10795 
   10796     init_Sres(screen.disallowedPasteOps);
   10797 
   10798     set_flags_from_list(screen->disallow_paste_ops,
   10799 			screen->disallowedPasteOps,
   10800 			tblPasteOps);
   10801 
   10802     init_Sres(screen.disallowedTcapOps);
   10803 
   10804     set_flags_from_list(screen->disallow_tcap_ops,
   10805 			screen->disallowedTcapOps,
   10806 			tblTcapOps);
   10807 
   10808     init_Sres(screen.disallowedWinOps);
   10809 
   10810     set_flags_from_list(screen->disallow_win_ops,
   10811 			screen->disallowedWinOps,
   10812 			tblWindowOps);
   10813 
   10814     init_Sres(screen.default_string);
   10815     init_Sres(screen.eightbit_select_types);
   10816 #if OPT_WIDE_CHARS
   10817     init_Sres(screen.utf8_select_types);
   10818 #endif
   10819 
   10820     /* make a copy so that editres cannot change the resource after startup */
   10821     screen->allowPasteControls = screen->allowPasteControl0;
   10822     screen->allowSendEvents = screen->allowSendEvent0;
   10823     screen->allowColorOps = screen->allowColorOp0;
   10824     screen->allowFontOps = screen->allowFontOp0;
   10825     screen->allowMouseOps = screen->allowMouseOp0;
   10826     screen->allowTcapOps = screen->allowTcapOp0;
   10827     screen->allowTitleOps = screen->allowTitleOp0;
   10828     screen->allowWindowOps = screen->allowWindowOp0;
   10829 
   10830 #if OPT_SCROLL_LOCK
   10831     screen->allowScrollLock = screen->allowScrollLock0;
   10832 #endif
   10833 
   10834     init_Bres(screen.quiet_grab);
   10835 
   10836 #ifndef NO_ACTIVE_ICON
   10837     init_Sres(screen.icon_fontname);
   10838     getIconicFont(screen)->fs = xtermLoadQueryFont(wnew,
   10839 						   screen->icon_fontname);
   10840     TRACE(("iconFont '%s' %sloaded successfully\n",
   10841 	   screen->icon_fontname,
   10842 	   getIconicFont(screen)->fs ? "" : "NOT "));
   10843     init_Sres(misc.active_icon_s);
   10844     wnew->work.active_icon =
   10845 	(Boolean) extendedBoolean(wnew->misc.active_icon_s,
   10846 				  tblAIconOps, eiLAST);
   10847     init_Ires(misc.icon_border_width);
   10848     wnew->misc.icon_border_pixel = request->misc.icon_border_pixel;
   10849 #endif /* NO_ACTIVE_ICON */
   10850 
   10851     init_Bres(misc.signalInhibit);
   10852     init_Bres(misc.titeInhibit);
   10853     init_Bres(misc.color_inner_border);
   10854     init_Bres(misc.dynamicColors);
   10855     init_Bres(misc.resizeByPixel);
   10856 
   10857     init_Sres(misc.cdXtraScroll_s);
   10858     wnew->misc.cdXtraScroll =
   10859 	extendedBoolean(request->misc.cdXtraScroll_s, tblCdXtraScroll, edLast);
   10860 
   10861     init_Sres(misc.tiXtraScroll_s);
   10862     wnew->misc.tiXtraScroll =
   10863 	extendedBoolean(request->misc.tiXtraScroll_s, tblCdXtraScroll, edLast);
   10864 
   10865 #if OPT_DEC_CHRSET
   10866     for (i = 0; i < NUM_CHRSET; i++) {
   10867 	screen->double_fonts[i].warn = fwResource;
   10868     }
   10869 #endif
   10870     for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) {
   10871 	init_Sres2(screen.MenuFontName, i);
   10872     }
   10873     for (i = 0; i < fMAX; i++) {
   10874 	screen->fnts[i].warn = fwResource;
   10875 #if OPT_WIDE_ATTRS
   10876 	screen->ifnts[i].warn = fwResource;
   10877 #endif
   10878     }
   10879 #ifndef NO_ACTIVE_ICON
   10880     screen->fnt_icon.warn = fwResource;
   10881 #endif
   10882 
   10883     init_Ires(misc.fontWarnings);
   10884 
   10885     initFontLists(wnew);
   10886 
   10887 #define DefaultFontNames screen->menu_font_names[fontMenu_default]
   10888 
   10889     /*
   10890      * Process Xft font resources first, since faceName may contain X11 fonts
   10891      * that should override the "font" resource.
   10892      */
   10893 #if OPT_RENDERFONT
   10894     init_Bres(screen.force_xft_height);
   10895     for (i = 0; i <= fontMenu_lastBuiltin; ++i) {
   10896 	init_Dres2(misc.face_size, i);
   10897     }
   10898     init_Ires(screen.xft_max_glyph_memory);
   10899     init_Ires(screen.xft_max_unref_fonts);
   10900     init_Bres(screen.xft_track_mem_usage);
   10901 
   10902 #define ALLOC_FONTLIST(name,which,field) \
   10903     init_Sres(misc.default_xft.field);\
   10904     allocFontList(wnew,\
   10905 		  name,\
   10906 		  &(wnew->work.fonts),\
   10907 		  which,\
   10908 		  wnew->misc.default_xft.field,\
   10909 		  True)
   10910 
   10911     ALLOC_FONTLIST(XtNfaceName, fNorm, f_n);
   10912 
   10913 #if OPT_WIDE_CHARS
   10914     ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w);
   10915 #endif
   10916 
   10917 #undef ALLOC_FONTLIST
   10918 
   10919 #endif
   10920 
   10921     /*
   10922      * Process X11 (XLFD) font specifications.
   10923      */
   10924 #define ALLOC_FONTLIST(name,which,field) \
   10925     init_Sres(misc.default_font.field);\
   10926     allocFontList(wnew,\
   10927 		  name,\
   10928 		  &(wnew->work.fonts),\
   10929 		  which,\
   10930 		  wnew->misc.default_font.field,\
   10931 		  False)
   10932 
   10933     ALLOC_FONTLIST(XtNfont, fNorm, f_n);
   10934     ALLOC_FONTLIST(XtNboldFont, fBold, f_b);
   10935 
   10936     DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew));
   10937     DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew));
   10938 
   10939 #if OPT_WIDE_CHARS
   10940     ALLOC_FONTLIST(XtNwideFont, fWide, f_w);
   10941     ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb);
   10942 
   10943     DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew));
   10944     DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew));
   10945 #endif
   10946 
   10947 #undef ALLOC_FONTLIST
   10948 
   10949     screen->EscapeFontName() = NULL;
   10950     screen->SelectFontName() = NULL;
   10951 
   10952     screen->menu_font_number = fontMenu_default;
   10953     init_Sres(screen.initial_font);
   10954     if (screen->initial_font != NULL) {
   10955 	int result = xtermGetFont(screen->initial_font);
   10956 	if (result >= 0)
   10957 	    screen->menu_font_number = result;
   10958     }
   10959 #if OPT_BROKEN_OSC
   10960     init_Bres(screen.brokenLinuxOSC);
   10961 #endif
   10962 
   10963 #if OPT_BROKEN_ST
   10964     init_Bres(screen.brokenStringTerm);
   10965 #endif
   10966 
   10967 #if OPT_C1_PRINT
   10968     init_Bres(screen.c1_printable);
   10969 #endif
   10970 
   10971 #if OPT_CLIP_BOLD
   10972     init_Bres(screen.use_border_clipping);
   10973     init_Bres(screen.use_clipping);
   10974 #endif
   10975 
   10976 #if OPT_DEC_CHRSET
   10977     init_Bres(screen.font_doublesize);
   10978     init_Ires(screen.cache_doublesize);
   10979     if (screen->cache_doublesize > NUM_CHRSET)
   10980 	screen->cache_doublesize = NUM_CHRSET;
   10981     if (screen->cache_doublesize == 0)
   10982 	screen->font_doublesize = False;
   10983     TRACE(("Doublesize%s enabled, up to %d fonts\n",
   10984 	   screen->font_doublesize ? "" : " not",
   10985 	   screen->cache_doublesize));
   10986 #endif
   10987 #if OPT_DEC_RECTOPS
   10988     init_Ires(screen.checksum_ext0);
   10989     screen->checksum_ext = screen->checksum_ext0;
   10990 #endif
   10991 
   10992 #if OPT_ISO_COLORS
   10993     init_Ires(screen.veryBoldColors);
   10994     init_Bres(screen.boldColors);
   10995     init_Bres(screen.colorAttrMode);
   10996     init_Bres(screen.colorBDMode);
   10997     init_Bres(screen.colorBLMode);
   10998     init_Bres(screen.colorMode);
   10999     init_Bres(screen.colorULMode);
   11000     init_Bres(screen.italicULMode);
   11001     init_Bres(screen.colorRVMode);
   11002 
   11003 #if OPT_WIDE_ATTRS
   11004     init_Bres(screen.colorITMode);
   11005 #endif
   11006 #if OPT_DIRECT_COLOR
   11007     init_Bres(screen.direct_color);
   11008 #endif
   11009 #if OPT_WIDE_ATTRS && OPT_SGR2_HASH
   11010     init_Bres(screen.faint_relative);
   11011 #endif
   11012 
   11013 #if OPT_VT525_COLORS
   11014     screen->assigned_fg = 7;
   11015     screen->assigned_bg = 0;
   11016 #if MIN_ANSI_COLORS >= 16
   11017     /*
   11018      * VT520-RM does not define the initial palette, but this is preferable
   11019      * to black-on-black.
   11020      */
   11021     for (i = 0; i < 16; i++) {
   11022 	screen->alt_colors[i].fg = screen->assigned_fg;
   11023 	screen->alt_colors[i].bg = screen->assigned_bg;
   11024     }
   11025 #endif
   11026 #endif
   11027 
   11028     TRACE(("...will fake resources for color%d to color%d\n",
   11029 	   MIN_ANSI_COLORS,
   11030 	   NUM_ANSI_COLORS - 1));
   11031 
   11032     for (i = 0, color_ok = False; i < MAXCOLORS; i++) {
   11033 	/*
   11034 	 * Xt has a hardcoded limit on the maximum number of resources that can
   11035 	 * be used in a widget.  If we configured both luit (which implies
   11036 	 * wide-characters) and 256-colors, it goes over that limit.  Most
   11037 	 * people would not need a resource-file with 256-colors; the default
   11038 	 * values in our table are sufficient.  Fake the resource setting by
   11039 	 * copying the default value from the table.  The #define's can be
   11040 	 * overridden to make these true resources.
   11041 	 */
   11042 	if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) {
   11043 	    screen->Acolors[i].resource =
   11044 		x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr);
   11045 	    if (screen->Acolors[i].resource == NULL)
   11046 		screen->Acolors[i].resource = XtDefaultForeground;
   11047 	} else {
   11048 	    screen->Acolors[i] = TScreenOf(request)->Acolors[i];
   11049 	    screen->Acolors[i].resource =
   11050 		x_strtrim(screen->Acolors[i].resource);
   11051 	}
   11052 
   11053 	TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource));
   11054 	screen->Acolors[i].mode = False;
   11055 	if (DftFg(Acolors[i])) {
   11056 	    screen->Acolors[i].value = T_COLOR(screen, TEXT_FG);
   11057 	    screen->Acolors[i].mode = True;
   11058 	} else if (DftBg(Acolors[i])) {
   11059 	    screen->Acolors[i].value = T_COLOR(screen, TEXT_BG);
   11060 	    screen->Acolors[i].mode = True;
   11061 	} else {
   11062 	    color_ok = True;
   11063 	}
   11064     }
   11065 
   11066     /*
   11067      * Check if we're trying to use color in a monochrome screen.  Disable
   11068      * color in that case, since that would make ANSI colors unusable.  A 4-bit
   11069      * or 8-bit display is usable, so we do not have to check for anything more
   11070      * specific.
   11071      */
   11072     if (color_ok) {
   11073 	if (getVisualDepth(wnew) <= 1) {
   11074 	    TRACE(("disabling color since screen is monochrome\n"));
   11075 	    color_ok = False;
   11076 	}
   11077     }
   11078 
   11079     /* If none of the colors are anything other than the foreground or
   11080      * background, we'll assume this isn't color, no matter what the colorMode
   11081      * resource says.  (There doesn't seem to be any good way to determine if
   11082      * the resource lookup failed versus the user having misconfigured this).
   11083      */
   11084     if (!color_ok) {
   11085 	screen->colorMode = False;
   11086 	TRACE(("All colors are foreground or background: disable colorMode\n"));
   11087     }
   11088     wnew->sgr_foreground = -1;
   11089     wnew->sgr_background = -1;
   11090     wnew->sgr_38_xcolors = False;
   11091     clrDirectFG(wnew->flags);
   11092     clrDirectFG(wnew->flags);
   11093 #endif /* OPT_ISO_COLORS */
   11094 
   11095     /*
   11096      * Decode the resources that control the behavior on multiple mouse clicks.
   11097      * A single click is always bound to normal character selection, but the
   11098      * other flavors can be changed.
   11099      */
   11100     for (i = 0; i < NSELECTUNITS; ++i) {
   11101 	int ck = (i + 1);
   11102 	screen->maxClicks = ck;
   11103 	if (i == Select_CHAR)
   11104 	    screen->selectMap[i] = Select_CHAR;
   11105 	else if (TScreenOf(request)->onClick[i] != NULL)
   11106 	    ParseOnClicks(wnew, request, (unsigned) i);
   11107 	else if (i <= Select_LINE)
   11108 	    screen->selectMap[i] = (SelectUnit) i;
   11109 	else
   11110 	    break;
   11111 #if OPT_XRES_QUERY
   11112 	init_Sres(screen.onClick[i]);
   11113 #endif
   11114 	TRACE(("on%dClicks %s=%d\n", ck,
   11115 	       NonNull(TScreenOf(request)->onClick[i]),
   11116 	       screen->selectMap[i]));
   11117 	if (screen->selectMap[i] == NSELECTUNITS)
   11118 	    break;
   11119     }
   11120     TRACE(("maxClicks %d\n", screen->maxClicks));
   11121 
   11122     init_Tres(MOUSE_FG);
   11123     init_Tres(MOUSE_BG);
   11124     init_Tres(TEXT_CURSOR);
   11125 #if OPT_HIGHLIGHT_COLOR
   11126     init_Tres(HIGHLIGHT_BG);
   11127     init_Tres(HIGHLIGHT_FG);
   11128     init_Bres(screen.hilite_reverse);
   11129     init_Mres(screen.hilite_color);
   11130     if (screen->hilite_color == Maybe) {
   11131 	screen->hilite_color = False;
   11132 	/*
   11133 	 * If the highlight text/background are both set, and if they are
   11134 	 * not equal to either the text/background or background/text, then
   11135 	 * set the highlightColorMode automatically.
   11136 	 */
   11137 	if (!DftFg(Tcolors[HIGHLIGHT_BG])
   11138 	    && !DftBg(Tcolors[HIGHLIGHT_FG])
   11139 	    && !TxtFg(Tcolors[HIGHLIGHT_BG])
   11140 	    && !TxtBg(Tcolors[HIGHLIGHT_FG])
   11141 	    && !TxtBg(Tcolors[HIGHLIGHT_BG])
   11142 	    && !TxtFg(Tcolors[HIGHLIGHT_FG])) {
   11143 	    TRACE(("...setting hilite_color automatically\n"));
   11144 	    screen->hilite_color = True;
   11145 	}
   11146     }
   11147 #endif
   11148 
   11149 #if OPT_TEK4014
   11150     /*
   11151      * The Tek4014 window has no separate resources for foreground, background
   11152      * and cursor color.  Since xterm always creates the vt100 widget first, we
   11153      * can set the Tektronix colors here.  That lets us use escape sequences to
   11154      * set its dynamic colors and get consistent behavior whether or not the
   11155      * window is displayed.
   11156      */
   11157     screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG];
   11158     screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG];
   11159     screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR];
   11160 #endif
   11161 
   11162 #ifdef SCROLLBAR_RIGHT
   11163     init_Bres(misc.useRight);
   11164 #endif
   11165 
   11166 #if OPT_RENDERFONT
   11167     init_Ires(misc.limit_fontsets);
   11168     init_Ires(misc.limit_fontheight);
   11169     if (wnew->misc.limit_fontheight > 50) {
   11170 	xtermWarning("limiting extra fontheight percent to 50 (was %d)\n",
   11171 		     wnew->misc.limit_fontheight);
   11172 	wnew->misc.limit_fontheight = 50;
   11173     }
   11174     init_Ires(misc.limit_fontwidth);
   11175     if (wnew->misc.limit_fontwidth > 50) {
   11176 	xtermWarning("limiting extra fontwidth percent to 50 (was %d)\n",
   11177 		     wnew->misc.limit_fontwidth);
   11178 	wnew->misc.limit_fontwidth = 50;
   11179     }
   11180     wnew->work.max_fontsets = (unsigned) wnew->misc.limit_fontsets;
   11181     if (wnew->work.max_fontsets > 255) {
   11182 	xtermWarning("limiting number of fontsets to 255 (was %u)\n",
   11183 		     wnew->work.max_fontsets);
   11184 	wnew->work.max_fontsets = 255;
   11185     }
   11186 
   11187     init_Sres(misc.render_font_s);
   11188     wnew->work.render_font =
   11189 	(Boolean) extendedBoolean(wnew->misc.render_font_s,
   11190 				  tblRenderFont, erLast);
   11191     if (wnew->work.render_font == erDefault) {
   11192 	if (IsEmpty(CurrentXftFont(wnew))) {
   11193 	    free((void *) CurrentXftFont(wnew));
   11194 	    CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO);
   11195 	    TRACE(("will allow runtime switch to render_font using \"%s\"\n",
   11196 		   CurrentXftFont(wnew)));
   11197 	} else {
   11198 	    wnew->work.render_font = erTrue;
   11199 	    TRACE(("initially using TrueType font\n"));
   11200 	}
   11201     } else if (wnew->work.render_font == erDefaultOff) {
   11202 	wnew->work.render_font = erFalse;
   11203     }
   11204     /* minor tweak to make debug traces consistent: */
   11205     if (wnew->work.render_font) {
   11206 	if (IsEmpty(CurrentXftFont(wnew))) {
   11207 	    wnew->work.render_font = False;
   11208 	    TRACE(("reset render_font since there is no face_name\n"));
   11209 	}
   11210     }
   11211 #endif
   11212 
   11213 #if OPT_WIDE_CHARS
   11214     /* setup data for next call */
   11215     init_Sres(screen.utf8_mode_s);
   11216     request->screen.utf8_mode =
   11217 	extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast);
   11218 
   11219     init_Sres(screen.utf8_fonts_s);
   11220     request->screen.utf8_fonts =
   11221 	extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast);
   11222 
   11223     init_Sres(screen.utf8_title_s);
   11224     request->screen.utf8_title =
   11225 	extendedBoolean(request->screen.utf8_title_s, tblUtf8Mode, uLast);
   11226 
   11227     /*
   11228      * Make a copy in the input/request so that DefaultFontN() works for
   11229      * the "CHECKFONT" option.
   11230      */
   11231     copyFontList(&(request->work.fonts.x11.list_n),
   11232 		 wnew->work.fonts.x11.list_n);
   11233 
   11234     VTInitialize_locale(request);
   11235     init_Bres(screen.normalized_c);
   11236     init_Bres(screen.utf8_latin1);
   11237     init_Bres(screen.utf8_weblike);
   11238 
   11239 #if OPT_LUIT_PROG
   11240     init_Bres(misc.callfilter);
   11241     init_Bres(misc.use_encoding);
   11242     init_Sres(misc.locale_str);
   11243     init_Sres(misc.localefilter);
   11244 #endif
   11245 
   11246     init_Ires(screen.utf8_inparse);
   11247     init_Ires(screen.utf8_mode);
   11248     init_Ires(screen.utf8_fonts);
   11249     init_Ires(screen.utf8_title);
   11250     init_Ires(screen.max_combining);
   11251 
   11252     init_Ires(screen.utf8_always);	/* from utf8_mode, used in doparse */
   11253 
   11254     if (screen->max_combining < 0) {
   11255 	screen->max_combining = 0;
   11256     }
   11257     if (screen->max_combining > 5) {
   11258 	screen->max_combining = 5;
   11259     }
   11260 
   11261     init_Bres(screen.vt100_graphics);
   11262     init_Bres(screen.wide_chars);
   11263     init_Bres(misc.mk_width);
   11264     init_Bres(misc.cjk_width);
   11265 
   11266     init_Ires(misc.mk_samplesize);
   11267     init_Ires(misc.mk_samplepass);
   11268 
   11269     if (wnew->misc.mk_samplesize > 0xffff)
   11270 	wnew->misc.mk_samplesize = 0xffff;
   11271     if (wnew->misc.mk_samplesize < 0)
   11272 	wnew->misc.mk_samplesize = 0;
   11273 
   11274     if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize)
   11275 	wnew->misc.mk_samplepass = wnew->misc.mk_samplesize;
   11276     if (wnew->misc.mk_samplepass < 0)
   11277 	wnew->misc.mk_samplepass = 0;
   11278 
   11279     if (TScreenOf(request)->utf8_mode) {
   11280 	TRACE(("setting wide_chars on\n"));
   11281 	screen->wide_chars = True;
   11282     } else {
   11283 	TRACE(("setting utf8_mode to 0\n"));
   11284 	screen->utf8_mode = uFalse;
   11285     }
   11286     mk_wcwidth_init(screen->utf8_mode);
   11287     TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode));
   11288 
   11289 #if OPT_MINI_LUIT
   11290     if (TScreenOf(request)->latin9_mode) {
   11291 	screen->latin9_mode = True;
   11292     }
   11293     if (TScreenOf(request)->unicode_font) {
   11294 	screen->unicode_font = True;
   11295     }
   11296     TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode));
   11297     TRACE(("initialized unicode_font to %d\n", screen->unicode_font));
   11298 #endif
   11299 
   11300     decode_wcwidth(wnew);
   11301     xtermSaveVTFonts(wnew);
   11302 #endif /* OPT_WIDE_CHARS */
   11303 
   11304     init_Sres(screen.eight_bit_meta_s);
   11305     wnew->screen.eight_bit_meta =
   11306 	extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, ebLast);
   11307     if (wnew->screen.eight_bit_meta == ebLocale) {
   11308 #if OPT_WIDE_CHARS
   11309 	if (xtermEnvUTF8()) {
   11310 	    wnew->screen.eight_bit_meta = ebFalse;
   11311 	    TRACE(("...eightBitMeta is false due to locale\n"));
   11312 	} else
   11313 #endif /* OPT_WIDE_CHARS */
   11314 	{
   11315 	    wnew->screen.eight_bit_meta = ebTrue;
   11316 	    TRACE(("...eightBitMeta is true due to locale\n"));
   11317 	}
   11318     }
   11319 
   11320     init_Bres(screen.always_bold_mode);
   11321     init_Bres(screen.bold_mode);
   11322     init_Bres(screen.underline);
   11323 
   11324     wnew->cur_foreground = 0;
   11325     wnew->cur_background = 0;
   11326 
   11327     wnew->keyboard.flags = MODE_SRM;
   11328 
   11329     if (screen->backarrow_key)
   11330 	wnew->keyboard.flags |= MODE_DECBKM;
   11331     TRACE(("initialized DECBKM %s\n",
   11332 	   BtoS(wnew->keyboard.flags & MODE_DECBKM)));
   11333 
   11334 #if OPT_SIXEL_GRAPHICS
   11335     /* Sixel scrolling is opposite of Sixel Display Mode */
   11336     init_Bres(screen.sixel_scrolling);
   11337     if (screen->sixel_scrolling)
   11338 	UIntClr(wnew->keyboard.flags, MODE_DECSDM);
   11339     else
   11340 	UIntSet(wnew->keyboard.flags, MODE_DECSDM);
   11341     TRACE(("initialized DECSDM %s\n",
   11342 	   BtoS(wnew->keyboard.flags & MODE_DECSDM)));
   11343 #endif
   11344 
   11345 #if OPT_GRAPHICS
   11346     init_Sres(screen.graph_termid);
   11347     screen->graphics_termid = decodeTerminalID(TScreenOf(request)->graph_termid);
   11348     switch (screen->graphics_termid) {
   11349     case 125:
   11350     case 240:
   11351     case 241:
   11352     case 330:
   11353     case 340:
   11354     case 382:
   11355 	break;
   11356     default:
   11357 	screen->graphics_termid = 0;
   11358 	break;
   11359     }
   11360     TRACE(("graph_termid '%s' -> graphics_termid %d\n",
   11361 	   screen->graph_termid,
   11362 	   screen->graphics_termid));
   11363 
   11364     init_Ires(screen.numcolorregisters);
   11365     TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n",
   11366 	   screen->numcolorregisters));
   11367 
   11368     init_Bres(screen.privatecolorregisters);	/* FIXME: should this be off unconditionally here? */
   11369     TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n",
   11370 	   BtoS(screen->privatecolorregisters)));
   11371     screen->privatecolorregisters0 = screen->privatecolorregisters;
   11372 
   11373     init_Bres(screen.incremental_graphics);
   11374     TRACE(("initialized INCREMENTAL_GRAPHICS to resource default: %s\n",
   11375 	   BtoS(screen->incremental_graphics)));
   11376 #endif
   11377 
   11378 #if OPT_GRAPHICS
   11379     {
   11380 	int native_w, native_h;
   11381 
   11382 	switch (GraphicsTermId(screen)) {
   11383 	case 125:
   11384 	    native_w = 768;
   11385 	    native_h = 460;
   11386 	    break;
   11387 	case 240:
   11388 	    /* FALLTHRU */
   11389 	case 241:
   11390 	    native_w = 800;
   11391 	    native_h = 460;
   11392 	    break;
   11393 	case 330:
   11394 	    /* FALLTHRU */
   11395 	case 340:
   11396 	    native_w = 800;
   11397 	    native_h = 480;
   11398 	    break;
   11399 	default:
   11400 	    native_w = 800;
   11401 	    native_h = 480;
   11402 	    break;
   11403 	case 382:
   11404 	    native_w = 960;
   11405 	    native_h = 720;
   11406 	    break;
   11407 	}
   11408 
   11409 # if OPT_REGIS_GRAPHICS
   11410 	init_Sres(screen.graphics_regis_default_font);
   11411 	TRACE(("default ReGIS font: %s\n",
   11412 	       screen->graphics_regis_default_font));
   11413 
   11414 	init_Sres(screen.graphics_regis_screensize);
   11415 	screen->graphics_regis_def_high = 1000;
   11416 	screen->graphics_regis_def_wide = 1000;
   11417 	if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) {
   11418 	    TRACE(("setting default ReGIS screensize based on graphics_id %d\n",
   11419 		   GraphicsTermId(screen)));
   11420 	    screen->graphics_regis_def_high = (Dimension) native_h;
   11421 	    screen->graphics_regis_def_wide = (Dimension) native_w;
   11422 	} else {
   11423 	    int conf_high;
   11424 	    int conf_wide;
   11425 	    char ignore;
   11426 
   11427 	    if (sscanf(screen->graphics_regis_screensize,
   11428 		       "%dx%d%c",
   11429 		       &conf_wide,
   11430 		       &conf_high,
   11431 		       &ignore) == 2) {
   11432 		if (conf_high > 0 && conf_wide > 0) {
   11433 		    screen->graphics_regis_def_high =
   11434 			(Dimension) conf_high;
   11435 		    screen->graphics_regis_def_wide =
   11436 			(Dimension) conf_wide;
   11437 		} else {
   11438 		    TRACE(("ignoring invalid regisScreenSize %s\n",
   11439 			   screen->graphics_regis_screensize));
   11440 		}
   11441 	    } else {
   11442 		TRACE(("ignoring invalid regisScreenSize %s\n",
   11443 		       screen->graphics_regis_screensize));
   11444 	    }
   11445 	}
   11446 	TRACE(("default ReGIS graphics screensize %dx%d\n",
   11447 	       (int) screen->graphics_regis_def_wide,
   11448 	       (int) screen->graphics_regis_def_high));
   11449 # endif
   11450 
   11451 	init_Sres(screen.graphics_max_size);
   11452 	screen->graphics_max_high = 1000;
   11453 	screen->graphics_max_wide = 1000;
   11454 	if (!x_strcasecmp(screen->graphics_max_size, "auto")) {
   11455 	    TRACE(("setting max graphics screensize based on graphics_id %d\n",
   11456 		   GraphicsTermId(screen)));
   11457 	    screen->graphics_max_high = (Dimension) native_h;
   11458 	    screen->graphics_max_wide = (Dimension) native_w;
   11459 	} else {
   11460 	    int conf_high;
   11461 	    int conf_wide;
   11462 	    char ignore;
   11463 
   11464 	    if (sscanf(screen->graphics_max_size,
   11465 		       "%dx%d%c",
   11466 		       &conf_wide,
   11467 		       &conf_high,
   11468 		       &ignore) == 2) {
   11469 		if (conf_high > 0 && conf_wide > 0) {
   11470 		    screen->graphics_max_high = (Dimension) conf_high;
   11471 		    screen->graphics_max_wide = (Dimension) conf_wide;
   11472 		} else {
   11473 		    TRACE(("ignoring invalid maxGraphicSize %s\n",
   11474 			   screen->graphics_max_size));
   11475 		}
   11476 	    } else {
   11477 		TRACE(("ignoring invalid maxGraphicSize %s\n",
   11478 		       screen->graphics_max_size));
   11479 	    }
   11480 	}
   11481 # if OPT_REGIS_GRAPHICS
   11482 	/* Make sure the max is large enough for the default ReGIS size. */
   11483 	if (screen->graphics_regis_def_high >
   11484 	    screen->graphics_max_high) {
   11485 	    screen->graphics_max_high =
   11486 		screen->graphics_regis_def_high;
   11487 	}
   11488 	if (screen->graphics_regis_def_wide >
   11489 	    screen->graphics_max_wide) {
   11490 	    screen->graphics_max_wide =
   11491 		screen->graphics_regis_def_wide;
   11492 	}
   11493 # endif
   11494 	TRACE(("max graphics screensize %dx%d\n",
   11495 	       (int) screen->graphics_max_wide,
   11496 	       (int) screen->graphics_max_high));
   11497     }
   11498 #endif
   11499 
   11500 #if OPT_SIXEL_GRAPHICS
   11501     init_Bres(screen.sixel_scrolls_right);
   11502     screen->sixel_scrolls_right0 = screen->sixel_scrolls_right;
   11503 #endif
   11504 #if OPT_PRINT_GRAPHICS
   11505     init_Bres(screen.graphics_print_to_host);
   11506     init_Bres(screen.graphics_expanded_print_mode);
   11507     init_Bres(screen.graphics_print_color_mode);
   11508     init_Bres(screen.graphics_print_color_syntax);
   11509     init_Bres(screen.graphics_print_background_mode);
   11510     init_Bres(screen.graphics_rotated_print_mode);
   11511 #endif
   11512 
   11513 #if OPT_STATUS_LINE
   11514     init_Sres(screen.status_fmt);
   11515 #endif
   11516 
   11517     /* look for focus related events on the shell, because we need
   11518      * to care about the shell's border being part of our focus.
   11519      */
   11520     TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent));
   11521     XtAddEventHandler(my_parent, EnterWindowMask, False,
   11522 		      HandleEnterWindow, (Opaque) NULL);
   11523     XtAddEventHandler(my_parent, LeaveWindowMask, False,
   11524 		      HandleLeaveWindow, (Opaque) NULL);
   11525     XtAddEventHandler(my_parent, FocusChangeMask, False,
   11526 		      HandleFocusChange, (Opaque) NULL);
   11527     XtAddEventHandler((Widget) wnew, 0L, True,
   11528 		      VTNonMaskableEvent, (Opaque) NULL);
   11529     XtAddEventHandler((Widget) wnew, PropertyChangeMask, False,
   11530 		      HandleBellPropertyChange, (Opaque) NULL);
   11531 
   11532 #if HANDLE_STRUCT_NOTIFY
   11533 #if OPT_TOOLBAR
   11534     wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar);
   11535     init_Ires(VT100_TB_INFO(menu_height));
   11536 #endif
   11537     XtAddEventHandler(my_parent, MappingNotify | StructureNotifyMask, False,
   11538 		      HandleStructNotify, (Opaque) 0);
   11539 #endif /* HANDLE_STRUCT_NOTIFY */
   11540 
   11541     screen->bellInProgress = False;
   11542 
   11543     set_character_class(screen->charClass);
   11544 #if OPT_REPORT_CCLASS
   11545     if (resource.reportCClass)
   11546 	report_char_class(wnew);
   11547 #endif
   11548 
   11549     /* create it, but don't realize it */
   11550     ScrollBarOn(wnew, True);
   11551 
   11552     /* make sure that the resize gravity acceptable */
   11553     if (!GravityIsNorthWest(wnew) &&
   11554 	!GravityIsSouthWest(wnew)) {
   11555 	char value[80];
   11556 	String temp[2];
   11557 	Cardinal nparams = 1;
   11558 
   11559 	sprintf(value, "%d", wnew->misc.resizeGravity);
   11560 	temp[0] = value;
   11561 	temp[1] = NULL;
   11562 	XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
   11563 			"unsupported resizeGravity resource value (%s)",
   11564 			temp, &nparams);
   11565 	wnew->misc.resizeGravity = SouthWestGravity;
   11566     }
   11567 #ifndef NO_ACTIVE_ICON
   11568     screen->whichVwin = &screen->fullVwin;
   11569 #endif /* NO_ACTIVE_ICON */
   11570 
   11571     init_Ires(screen.unparse_max);
   11572     if ((int) screen->unparse_max < 256)
   11573 	screen->unparse_max = 256;
   11574     screen->unparse_bfr = (IChar *) (void *) XtCalloc(screen->unparse_max,
   11575 						      (Cardinal) sizeof(IChar));
   11576 
   11577     init_Ires(screen.strings_max);
   11578 
   11579     if (screen->savelines < 0)
   11580 	screen->savelines = 0;
   11581 
   11582     init_Bres(screen.awaitInput);
   11583 
   11584     wnew->flags = 0;
   11585     if (!screen->jumpscroll)
   11586 	wnew->flags |= SMOOTHSCROLL;
   11587     if (wnew->misc.reverseWrap)
   11588 	wnew->flags |= REVERSEWRAP;
   11589     if (wnew->misc.autoWrap)
   11590 	wnew->flags |= WRAPAROUND;
   11591     if (wnew->misc.re_verse != wnew->misc.re_verse0)
   11592 	wnew->flags |= REVERSE_VIDEO;
   11593     if (screen->c132)
   11594 	wnew->flags |= IN132COLUMNS;
   11595 
   11596     wnew->initflags = wnew->flags;
   11597 
   11598     init_Sres(keyboard.shift_escape_s);
   11599     wnew->keyboard.shift_escape =
   11600 	extendedBoolean(wnew->keyboard.shift_escape_s, tblShift2S, ssLAST);
   11601 
   11602 #if OPT_MOD_FKEYS
   11603     init_Ires(keyboard.modify_1st.allow_keys);
   11604     init_Ires(keyboard.modify_1st.cursor_keys);
   11605     init_Ires(keyboard.modify_1st.function_keys);
   11606     init_Ires(keyboard.modify_1st.keypad_keys);
   11607     init_Ires(keyboard.modify_1st.other_keys);
   11608     init_Ires(keyboard.modify_1st.string_keys);
   11609     init_Ires(keyboard.format_keys);
   11610     wnew->keyboard.modify_now = wnew->keyboard.modify_1st;
   11611 #endif
   11612 
   11613     init_Ires(misc.appcursorDefault);
   11614     if (wnew->misc.appcursorDefault)
   11615 	wnew->keyboard.flags |= MODE_DECCKM;
   11616 
   11617     init_Ires(misc.appkeypadDefault);
   11618     if (wnew->misc.appkeypadDefault)
   11619 	wnew->keyboard.flags |= MODE_DECKPAM;
   11620 
   11621     initLineData(wnew);
   11622 #if OPT_WIDE_CHARS
   11623     freeFontList(&(request->work.fonts.x11.list_n));
   11624 #endif
   11625 #if OPT_XRES_QUERY
   11626     if (resource.reportXRes)
   11627 	reportResources(wnew);
   11628 #endif
   11629     xtermResetLocale(LC_NUMERIC, saveLocale);
   11630     TRACE(("" TRACE_R " VTInitialize\n"));
   11631     return;
   11632 }
   11633 
   11634 void
   11635 releaseCursorGCs(XtermWidget xw)
   11636 {
   11637     TScreen *screen = TScreenOf(xw);
   11638     VTwin *win = WhichVWin(screen);
   11639     int n;
   11640 
   11641     for_each_curs_gc(n) {
   11642 	freeCgs(xw, win, (CgsEnum) n);
   11643     }
   11644 }
   11645 
   11646 void
   11647 releaseWindowGCs(XtermWidget xw, VTwin *win)
   11648 {
   11649     int n;
   11650 
   11651     for_each_text_gc(n) {
   11652 	switch (n) {
   11653 	case gcBorder:
   11654 	case gcFiller:
   11655 	    break;
   11656 	default:
   11657 	    freeCgs(xw, win, (CgsEnum) n);
   11658 	    break;
   11659 	}
   11660     }
   11661 }
   11662 
   11663 #define TRACE_FREE_LEAK(name) \
   11664 	if (name) { \
   11665 	    TRACE(("freed " #name ": %p\n", (const void *) name)); \
   11666 	    FreeAndNull(name); \
   11667 	}
   11668 
   11669 #define TRACE_FREE_GC(name,part) \
   11670 	if (part) { \
   11671 	    TRACE(("freed %s " #part ": %p\n", name, (const void *) part)); \
   11672 	    XFreeGC(dpy, part); \
   11673 	    part = NULL; \
   11674 	}
   11675 
   11676 #if OPT_INPUT_METHOD
   11677 static void
   11678 cleanupInputMethod(XtermWidget xw)
   11679 {
   11680     TInput *input = lookupTInput(xw, (Widget) xw);
   11681 
   11682     if (input && input->xim) {
   11683 	XCloseIM(input->xim);
   11684 	input->xim = NULL;
   11685 	TRACE(("freed screen->xim\n"));
   11686     }
   11687 }
   11688 #else
   11689 #define cleanupInputMethod(xw)	/* nothing */
   11690 #endif
   11691 
   11692 #ifdef NO_LEAKS
   11693 #define FREE_VT_WIN(name) freeVTwin(dpy, #name, &(screen->name))
   11694 static void
   11695 freeVTwin(Display *dpy, const char *whichWin, VTwin *win)
   11696 {
   11697     (void) whichWin;
   11698     TRACE_FREE_GC(whichWin, win->filler_gc);
   11699     TRACE_FREE_GC(whichWin, win->border_gc);
   11700     TRACE_FREE_GC(whichWin, win->marker_gc[0]);
   11701     TRACE_FREE_GC(whichWin, win->marker_gc[1]);
   11702 }
   11703 #endif
   11704 
   11705 static void
   11706 VTDestroy(Widget w GCC_UNUSED)
   11707 {
   11708 #ifdef NO_LEAKS
   11709     XtermWidget xw = (XtermWidget) w;
   11710     TScreen *screen = TScreenOf(xw);
   11711     Display *dpy = screen->display;
   11712     Cardinal n, k;
   11713 
   11714     StopBlinking(xw);
   11715 
   11716     if (screen->scrollWidget) {
   11717 	XtUninstallTranslations(screen->scrollWidget);
   11718 	XtDestroyWidget(screen->scrollWidget);
   11719     }
   11720 
   11721     while (screen->saved_fifo > 0) {
   11722 	deleteScrollback(screen);
   11723     }
   11724 
   11725     for (n = 0; n < MAX_SAVED_TITLES; ++n)
   11726 	xtermFreeTitle(&screen->saved_titles.data[n]);
   11727 
   11728 #if OPT_STATUS_LINE
   11729     free(screen->status_fmt);
   11730 #endif
   11731 #ifndef NO_ACTIVE_ICON
   11732     TRACE_FREE_LEAK(xw->misc.active_icon_s);
   11733 #endif
   11734 #if OPT_ISO_COLORS
   11735     TRACE_FREE_LEAK(screen->cmap_data);
   11736     for (n = 0; n < MAXCOLORS; n++) {
   11737 	TRACE_FREE_LEAK(screen->Acolors[n].resource);
   11738     }
   11739     for (n = 0; n < MAX_SAVED_SGR; n++) {
   11740 	TRACE_FREE_LEAK(xw->saved_colors.palettes[n]);
   11741     }
   11742 #endif
   11743     for (n = 0; n < NCOLORS; n++) {
   11744 	switch (n) {
   11745 #if OPT_TEK4014
   11746 	case TEK_BG:
   11747 	    /* FALLTHRU */
   11748 	case TEK_FG:
   11749 	    /* FALLTHRU */
   11750 	case TEK_CURSOR:
   11751 	    break;
   11752 #endif
   11753 	default:
   11754 	    TRACE_FREE_LEAK(screen->Tcolors[n].resource);
   11755 	    break;
   11756 	}
   11757     }
   11758     FreeMarkGCs(xw);
   11759     TRACE_FREE_LEAK(screen->unparse_bfr);
   11760     TRACE_FREE_LEAK(screen->save_ptr);
   11761     TRACE_FREE_LEAK(screen->saveBuf_data);
   11762     TRACE_FREE_LEAK(screen->saveBuf_index);
   11763     for (n = 0; n < 2; ++n) {
   11764 	TRACE_FREE_LEAK(screen->editBuf_data[n]);
   11765 	TRACE_FREE_LEAK(screen->editBuf_index[n]);
   11766     }
   11767     TRACE_FREE_LEAK(screen->keyboard_dialect);
   11768     TRACE_FREE_LEAK(screen->cursor_font_name);
   11769     TRACE_FREE_LEAK(screen->pointer_shape);
   11770     TRACE_FREE_LEAK(screen->term_id);
   11771 #if OPT_WIDE_CHARS
   11772     TRACE_FREE_LEAK(screen->utf8_mode_s);
   11773     TRACE_FREE_LEAK(screen->utf8_fonts_s);
   11774     TRACE_FREE_LEAK(screen->utf8_title_s);
   11775 #if OPT_LUIT_PROG
   11776     TRACE_FREE_LEAK(xw->misc.locale_str);
   11777     TRACE_FREE_LEAK(xw->misc.localefilter);
   11778 #endif
   11779 #endif
   11780     TRACE_FREE_LEAK(xw->misc.T_geometry);
   11781     TRACE_FREE_LEAK(xw->misc.geo_metry);
   11782 #if OPT_INPUT_METHOD
   11783     cleanupInputMethod(xw);
   11784     TRACE_FREE_LEAK(xw->misc.f_x);
   11785     TRACE_FREE_LEAK(xw->misc.input_method);
   11786     TRACE_FREE_LEAK(xw->misc.preedit_type);
   11787 #endif
   11788     releaseCursorGCs(xw);
   11789     releaseWindowGCs(xw, &(screen->fullVwin));
   11790 #ifndef NO_ACTIVE_ICON
   11791     XFreeFont(screen->display, getIconicFont(screen)->fs);
   11792     releaseWindowGCs(xw, &(screen->iconVwin));
   11793 #endif
   11794     XtUninstallTranslations((Widget) xw);
   11795 #if OPT_TOOLBAR
   11796     XtUninstallTranslations((Widget) XtParent(xw));
   11797 #endif
   11798     XtUninstallTranslations((Widget) SHELL_OF(xw));
   11799 
   11800     if (screen->hidden_cursor)
   11801 	XFreeCursor(screen->display, screen->hidden_cursor);
   11802 
   11803     xtermCloseFonts(xw, screen->fnts);
   11804 #if OPT_WIDE_ATTRS
   11805     xtermCloseFonts(xw, screen->ifnts);
   11806 #endif
   11807     noleaks_cachedCgs(xw);
   11808     free_termcap(xw);
   11809 
   11810     FREE_VT_WIN(fullVwin);
   11811 #ifndef NO_ACTIVE_ICON
   11812     FREE_VT_WIN(iconVwin);
   11813 #endif /* NO_ACTIVE_ICON */
   11814 
   11815     TRACE_FREE_LEAK(screen->selection_targets_8bit);
   11816 #if OPT_SELECT_REGEX
   11817     for (n = 0; n < NSELECTUNITS; ++n) {
   11818 	if (screen->selectMap[n] == Select_REGEX) {
   11819 	    TRACE_FREE_LEAK(screen->selectExpr[n]);
   11820 	}
   11821     }
   11822 #endif
   11823 
   11824 #if OPT_RENDERFONT
   11825     for (n = 0; n < NMENUFONTS; ++n) {
   11826 	int e;
   11827 	for (e = 0; e < fMAX; ++e) {
   11828 	    xtermCloseXft(screen, getMyXftFont(xw, e, (int) n));
   11829 	}
   11830     }
   11831     discardRenderDraw(screen);
   11832     {
   11833 	ListXftFonts *p;
   11834 	while ((p = screen->list_xft_fonts) != NULL) {
   11835 	    screen->list_xft_fonts = p->next;
   11836 	    free(p);
   11837 	}
   11838     }
   11839 #endif
   11840 
   11841     /* free things allocated via init_Sres or Init_Sres2 */
   11842 #ifndef NO_ACTIVE_ICON
   11843     TRACE_FREE_LEAK(screen->icon_fontname);
   11844 #endif
   11845 #ifdef ALLOWLOGGING
   11846     TRACE_FREE_LEAK(screen->logfile);
   11847 #endif
   11848     TRACE_FREE_LEAK(screen->eight_bit_meta_s);
   11849     TRACE_FREE_LEAK(screen->charClass);
   11850     TRACE_FREE_LEAK(screen->answer_back);
   11851     TRACE_FREE_LEAK(screen->printer_state.printer_command);
   11852     TRACE_FREE_LEAK(screen->disallowedColorOps);
   11853     TRACE_FREE_LEAK(screen->disallowedFontOps);
   11854     TRACE_FREE_LEAK(screen->disallowedMouseOps);
   11855     TRACE_FREE_LEAK(screen->disallowedPasteOps);
   11856     TRACE_FREE_LEAK(screen->disallowedTcapOps);
   11857     TRACE_FREE_LEAK(screen->disallowedWinOps);
   11858     TRACE_FREE_LEAK(screen->default_string);
   11859     TRACE_FREE_LEAK(screen->eightbit_select_types);
   11860 
   11861 #if OPT_WIDE_CHARS
   11862     TRACE_FREE_LEAK(screen->utf8_select_types);
   11863 #endif
   11864 
   11865 #if 0
   11866     for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) {
   11867 	TRACE_FREE_LEAK(screen->MenuFontName(n));
   11868     }
   11869 #endif
   11870 
   11871     TRACE_FREE_LEAK(screen->initial_font);
   11872 
   11873 #if OPT_LUIT_PROG
   11874     TRACE_FREE_LEAK(xw->misc.locale_str);
   11875     TRACE_FREE_LEAK(xw->misc.localefilter);
   11876 #endif
   11877 
   11878     TRACE_FREE_LEAK(xw->misc.cdXtraScroll_s);
   11879     TRACE_FREE_LEAK(xw->misc.tiXtraScroll_s);
   11880 
   11881 #if OPT_RENDERFONT
   11882     TRACE_FREE_LEAK(xw->misc.default_xft.f_n);
   11883 #if OPT_WIDE_CHARS
   11884     TRACE_FREE_LEAK(xw->misc.default_xft.f_w);
   11885 #endif
   11886     TRACE_FREE_LEAK(xw->misc.render_font_s);
   11887 #endif
   11888 
   11889     TRACE_FREE_LEAK(xw->misc.default_font.f_n);
   11890     TRACE_FREE_LEAK(xw->misc.default_font.f_b);
   11891 
   11892 #if OPT_WIDE_CHARS
   11893     TRACE_FREE_LEAK(xw->misc.default_font.f_w);
   11894     TRACE_FREE_LEAK(xw->misc.default_font.f_wb);
   11895 #endif
   11896 
   11897     TRACE_FREE_LEAK(xw->work.wm_name);
   11898     freeFontLists(&(xw->work.fonts.x11));
   11899 #if OPT_RENDERFONT
   11900     freeFontLists(&(xw->work.fonts.xft));
   11901 #endif
   11902 
   11903     xtermFontName(NULL);
   11904 #if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS
   11905     TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n);
   11906     TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b);
   11907 #if OPT_WIDE_CHARS
   11908     TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w);
   11909     TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb);
   11910 #endif
   11911     freeFontLists(&(screen->cacheVTFonts.fonts.x11));
   11912     for (n = 0; n < NMENUFONTS; ++n) {
   11913 	for (k = 0; k < fMAX; ++k) {
   11914 	    if (screen->menu_font_names[n][k] !=
   11915 		screen->cacheVTFonts.menu_font_names[n][k]) {
   11916 		if (screen->menu_font_names[n][k] != _Font_Selected_) {
   11917 		    TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
   11918 		}
   11919 		TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]);
   11920 	    } else {
   11921 		TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
   11922 	    }
   11923 	}
   11924     }
   11925 #endif
   11926 
   11927 #if OPT_BLINK_CURS
   11928     TRACE_FREE_LEAK(screen->cursor_blink_s);
   11929 #endif
   11930 
   11931 #if OPT_REGIS_GRAPHICS
   11932     TRACE_FREE_LEAK(screen->graphics_regis_default_font);
   11933     TRACE_FREE_LEAK(screen->graphics_regis_screensize);
   11934 #endif
   11935 #if OPT_GRAPHICS
   11936     TRACE_FREE_LEAK(screen->graph_termid);
   11937     TRACE_FREE_LEAK(screen->graphics_max_size);
   11938 #endif
   11939 
   11940     for (n = 0; n < NSELECTUNITS; ++n) {
   11941 #if OPT_SELECT_REGEX
   11942 	TRACE_FREE_LEAK(screen->selectExpr[n]);
   11943 #endif
   11944 #if OPT_XRES_QUERY
   11945 	TRACE_FREE_LEAK(screen->onClick[n]);
   11946 #endif
   11947     }
   11948 
   11949     XtFree((void *) (screen->selection_atoms));
   11950 
   11951     for (n = 0; n < MAX_SELECTIONS; ++n) {
   11952 	free(screen->selected_cells[n].data_buffer);
   11953     }
   11954 
   11955     if (defaultTranslations != xtermClassRec.core_class.tm_table) {
   11956 	TRACE_FREE_LEAK(defaultTranslations);
   11957     }
   11958     TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table);
   11959     TRACE_FREE_LEAK(xw->keyboard.shift_escape_s);
   11960     TRACE_FREE_LEAK(xw->keyboard.extra_translations);
   11961     TRACE_FREE_LEAK(xw->keyboard.shell_translations);
   11962     TRACE_FREE_LEAK(xw->keyboard.xterm_translations);
   11963     TRACE_FREE_LEAK(xw->keyboard.print_translations);
   11964     UnmapSelections(xw);
   11965 
   11966     XtFree((void *) (xw->visInfo));
   11967 
   11968 #if OPT_WIDE_CHARS
   11969     FreeTypedBuffer(IChar);
   11970     FreeTypedBuffer(XChar2b);
   11971     FreeTypedBuffer(Char);
   11972 #endif
   11973 #if OPT_RENDERFONT
   11974 #if OPT_RENDERWIDE
   11975     FreeTypedBuffer(XftCharSpec);
   11976 #else
   11977     FreeTypedBuffer(XftChar8);
   11978 #endif
   11979 #endif
   11980 
   11981     TRACE_FREE_LEAK(myState.print_area);
   11982     TRACE_FREE_LEAK(myState.string_area);
   11983     memset(&myState, 0, sizeof(myState));
   11984 
   11985 #endif /* defined(NO_LEAKS) */
   11986 }
   11987 
   11988 #ifndef NO_ACTIVE_ICON
   11989 static void *
   11990 getProperty(Display *dpy,
   11991 	    Window w,
   11992 	    Atom req_type,
   11993 	    const char *prop_name)
   11994 {
   11995     Atom property;
   11996     Atom actual_return_type;
   11997     int actual_format_return = 0;
   11998     unsigned long nitems_return = 0;
   11999     unsigned long bytes_after_return = 0;
   12000     unsigned char *prop_return = NULL;
   12001     long long_length = 1024;
   12002     size_t limit;
   12003     char *result = NULL;
   12004 
   12005     TRACE(("getProperty %s(%s)\n", prop_name,
   12006 	   req_type ? TraceAtomName(dpy, req_type) : "?"));
   12007     property = CachedInternAtom(dpy, prop_name);
   12008 
   12009     if (!xtermGetWinProp(dpy,
   12010 			 w,
   12011 			 property,
   12012 			 0L,
   12013 			 long_length,
   12014 			 req_type,
   12015 			 &actual_return_type,
   12016 			 &actual_format_return,
   12017 			 &nitems_return,
   12018 			 &bytes_after_return,
   12019 			 &prop_return)) {
   12020 	TRACE((".. Cannot get %s property.\n", prop_name));
   12021     } else if (prop_return != NULL) {
   12022 
   12023 	if (nitems_return != 0 &&
   12024 	    actual_format_return != 0 &&
   12025 	    actual_return_type == req_type) {
   12026 	    /*
   12027 	     * Null-terminate the result to make string handling easier.
   12028 	     * The format==8 corresponds to strings, and the number of items
   12029 	     * is the number of characters.
   12030 	     */
   12031 	    if (actual_format_return == 8) {
   12032 		limit = nitems_return;
   12033 	    } else {
   12034 		/* manpage is misleading - X really uses 'long', not 32-bits */
   12035 		limit = sizeof(long) * nitems_return;
   12036 	    }
   12037 	    if ((result = malloc(limit + 1)) != NULL) {
   12038 		memcpy(result, prop_return, limit);
   12039 		result[limit] = '\0';
   12040 	    }
   12041 	    TRACE(("... result %s\n", result ? ("ok") : "null"));
   12042 	}
   12043 	XFree(prop_return);
   12044     } else {
   12045 	TRACE((".. no property returned\n"));
   12046     }
   12047     return (void *) result;
   12048 }
   12049 
   12050 /*
   12051  * Active icons are supported by fvwm.  This feature is not supported by
   12052  * metacity (gnome) or kwin (kde).  Both metacity and kwin support (in
   12053  * incompatible ways, e.g., one uses the icon theme as a fallback for window
   12054  * decorations but the other does not, etc, ...) an icon as part of the window
   12055  * decoration (usually on the upper-left of the window).
   12056  *
   12057  * In either case, xterm's icon will only be shown in the window decorations if
   12058  * xterm does not use the active icon feature.
   12059  *
   12060  * This function (tries to) determine the window manager's name, so that we can
   12061  * provide a useful automatic default for active icons.  It is based on reading
   12062  * wmctrl, which covers most of EWMH and ICCM.
   12063  */
   12064 static char *
   12065 getWindowManagerName(XtermWidget xw)
   12066 {
   12067     TScreen *screen = TScreenOf(xw);
   12068     Display *dpy = screen->display;
   12069     Window *sup_window = NULL;
   12070     char *result = NULL;
   12071 
   12072     TRACE(("getWindowManagerName\n"));
   12073 #define getWinProp(type, name) \
   12074     (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name)
   12075     if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == NULL) {
   12076 	sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK");
   12077     }
   12078 
   12079     /*
   12080      * If we found the supporting window, get the property containing the
   12081      * window manager's name.  EWMH defines _NET_WM_NAME, while ICCM defines
   12082      * WM_CLASS.  There is no standard for the names stored there;
   12083      * conventionally it is mixed case.  In practice, the former is more often
   12084      * set; the latter is not given (or is a lowercased version of the former).
   12085      */
   12086     if (sup_window != NULL) {
   12087 #define getStringProp(type,name) \
   12088 	(char *)getProperty(dpy, *sup_window, type, name)
   12089 	if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == NULL
   12090 	    && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == NULL
   12091 	    && (result = getStringProp(XA_STRING, "WM_CLASS")) == NULL) {
   12092 	    TRACE(("... window manager does not tell its name\n"));
   12093 	}
   12094 	free(sup_window);
   12095     } else {
   12096 	TRACE(("... Cannot get window manager info properties\n"));
   12097     }
   12098     if (result == NULL)
   12099 	result = x_strdup("unknown");
   12100     TRACE(("... window manager name is %s\n", result));
   12101     return result;
   12102 }
   12103 
   12104 static Boolean
   12105 discount_frame_extents(XtermWidget xw, int *high, int *wide)
   12106 {
   12107     TScreen *screen = TScreenOf(xw);
   12108     Display *dpy = screen->display;
   12109 
   12110     Atom atom_supported = CachedInternAtom(dpy, "_NET_FRAME_EXTENTS");
   12111     Atom actual_type;
   12112     int actual_format;
   12113     long long_offset = 0;
   12114     long long_length = 128;	/* number of items to ask for at a time */
   12115     unsigned long nitems;
   12116     unsigned long bytes_after;
   12117     unsigned char *args;
   12118     Boolean rc;
   12119 
   12120     rc = xtermGetWinProp(dpy,
   12121 			 VShellWindow(xw),
   12122 			 atom_supported,
   12123 			 long_offset,
   12124 			 long_length,
   12125 			 XA_CARDINAL,	/* req_type */
   12126 			 &actual_type,	/* actual_type_return */
   12127 			 &actual_format,	/* actual_format_return */
   12128 			 &nitems,	/* nitems_return */
   12129 			 &bytes_after,	/* bytes_after_return */
   12130 			 &args	/* prop_return */
   12131 	);
   12132 
   12133     if (rc && args && (nitems == 4) && (actual_format == 32)) {
   12134 	long *extents = (long *) (void *) args;
   12135 
   12136 	TRACE(("_NET_FRAME_EXTENTS:\n"));
   12137 	TRACE(("   left:   %ld\n", extents[0]));
   12138 	TRACE(("   right:  %ld\n", extents[1]));
   12139 	TRACE(("   top:    %ld\n", extents[2]));
   12140 	TRACE(("   bottom: %ld\n", extents[3]));
   12141 
   12142 	if (!x_strncasecmp(xw->work.wm_name, "gnome shell", 11)) {
   12143 	    *wide -= (int) (extents[0] + extents[1]);	/* -= (left+right) */
   12144 	    *high -= (int) (extents[2] + extents[3]);	/* -= (top+bottom) */
   12145 	    TRACE(("...applied extents %d,%d\n", *high, *wide));
   12146 	} else if (!x_strncasecmp(xw->work.wm_name, "compiz", 6)) {
   12147 	    /* Ubuntu 16.04 is really off-by-one */
   12148 	    *wide -= (int) (extents[0] + extents[1] - 1);
   12149 	    *high -= (int) (extents[2] + extents[3] - 1);
   12150 	    TRACE(("...applied extents %d,%d\n", *high, *wide));
   12151 	} else if (!x_strncasecmp(xw->work.wm_name, "fvwm", 4)) {
   12152 	    TRACE(("...skipping extents\n"));
   12153 	} else {
   12154 	    TRACE(("...ignoring extents\n"));
   12155 	    rc = False;
   12156 	}
   12157 	XFree(args);
   12158     } else {
   12159 	rc = False;
   12160     }
   12161     return rc;
   12162 }
   12163 #endif /* !NO_ACTIVE_ICON */
   12164 
   12165 void
   12166 initBorderGC(XtermWidget xw, VTwin *win)
   12167 {
   12168     TScreen *screen = TScreenOf(xw);
   12169     Pixel filler;
   12170 
   12171     TRACE(("initBorderGC(%s) core bg %#lx, bd %#lx text fg %#lx, bg %#lx %s\n",
   12172 	   (win == &(screen->fullVwin)) ? "full" : "icon",
   12173 	   xw->core.background_pixel,
   12174 	   xw->core.border_pixel,
   12175 	   T_COLOR(screen, TEXT_FG),
   12176 	   T_COLOR(screen, TEXT_BG),
   12177 	   xw->misc.re_verse ? "reverse" : "normal"));
   12178     if (xw->misc.color_inner_border
   12179 	&& (xw->core.background_pixel != xw->core.border_pixel)) {
   12180 	/*
   12181 	 * By default, try to match the inner window's background.
   12182 	 */
   12183 	if ((xw->core.background_pixel == T_COLOR(screen, TEXT_BG)) &&
   12184 	    (xw->core.border_pixel == T_COLOR(screen, TEXT_FG))) {
   12185 	    filler = T_COLOR(screen, TEXT_BG);
   12186 	} else {
   12187 	    filler = xw->core.border_pixel;
   12188 	}
   12189 	TRACE((" border %#lx\n", filler));
   12190 	setCgsFore(xw, win, gcBorder, filler);
   12191 	setCgsBack(xw, win, gcBorder, filler);
   12192 	win->border_gc = getCgsGC(xw, win, gcBorder);
   12193     }
   12194 #if USE_DOUBLE_BUFFER
   12195     else if (resource.buffered) {
   12196 	filler = T_COLOR(screen, TEXT_BG);
   12197 	TRACE((" border %#lx (buffered)\n", filler));
   12198 	setCgsFore(xw, win, gcBorder, filler);
   12199 	setCgsBack(xw, win, gcBorder, filler);
   12200 	win->border_gc = getCgsGC(xw, win, gcBorder);
   12201     }
   12202 #endif
   12203     else {
   12204 	TRACE((" border unused\n"));
   12205 	win->border_gc = NULL;
   12206     }
   12207 
   12208     /*
   12209      * Initialize a GC for double-buffering, needed for XFillRectangle call
   12210      * in xtermClear2().  When not double-buffering, the XClearArea call works,
   12211      * without requiring a separate GC.
   12212      */
   12213 #if USE_DOUBLE_BUFFER
   12214     if (resource.buffered) {
   12215 	filler = (((xw->flags & BG_COLOR) && (xw->cur_background >= 0))
   12216 		  ? getXtermBG(xw, xw->flags, xw->cur_background)
   12217 		  : T_COLOR(screen, TEXT_BG));
   12218 
   12219 	TRACE((" filler %#lx %s\n",
   12220 	       filler,
   12221 	       xw->misc.re_verse ? "reverse" : "normal"));
   12222 
   12223 	setCgsFore(xw, win, gcFiller, filler);
   12224 	setCgsBack(xw, win, gcFiller, filler);
   12225 
   12226 	win->filler_gc = getCgsGC(xw, win, gcFiller);
   12227     }
   12228 #endif
   12229 }
   12230 #if USE_DOUBLE_BUFFER
   12231 static Boolean
   12232 allocateDbe(XtermWidget xw, VTwin *target)
   12233 {
   12234     TScreen *screen = TScreenOf(xw);
   12235     Boolean result = False;
   12236 
   12237     target->drawable = target->window;
   12238 
   12239     if (resource.buffered) {
   12240 	Window win = target->window;
   12241 	Drawable d;
   12242 	int major, minor;
   12243 	if (XdbeQueryExtension(XtDisplay(xw), &major, &minor)) {
   12244 	    d = XdbeAllocateBackBufferName(XtDisplay(xw), win,
   12245 					   (XdbeSwapAction) XdbeCopied);
   12246 	    if (d == None) {
   12247 		fprintf(stderr, "Couldn't allocate a back buffer!\n");
   12248 		exit(3);
   12249 	    }
   12250 	    target->drawable = d;
   12251 	    screen->needSwap = 1;
   12252 	    TRACE(("initialized double-buffering\n"));
   12253 	    result = True;
   12254 	} else {
   12255 	    resource.buffered = False;
   12256 	}
   12257     }
   12258     return result;
   12259 }
   12260 #endif /* USE_DOUBLE_BUFFER */
   12261 
   12262 /*ARGSUSED*/
   12263 static void
   12264 VTRealize(Widget w,
   12265 	  XtValueMask * valuemask,
   12266 	  XSetWindowAttributes * values)
   12267 {
   12268     XtermWidget xw = (XtermWidget) w;
   12269     TScreen *screen = TScreenOf(xw);
   12270 
   12271     const VTFontNames *myfont;
   12272     struct Xinerama_geometry pos;
   12273     int pr;
   12274     Atom pid_atom;
   12275     int i;
   12276 
   12277     TRACE(("VTRealize " TRACE_L "\n"));
   12278 
   12279     TabReset(xw->tabs);
   12280 
   12281     if (screen->menu_font_number == fontMenu_default) {
   12282 	myfont = defaultVTFontNames(xw);
   12283     } else {
   12284 	myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number));
   12285     }
   12286     memset(screen->fnts, 0, sizeof(screen->fnts));
   12287 
   12288     if (!xtermLoadFont(xw,
   12289 		       myfont,
   12290 		       False,
   12291 		       screen->menu_font_number)) {
   12292 	if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) {
   12293 	    char *use_font = x_strdup(DEFFONT);
   12294 	    xtermWarning("unable to open font \"%s\", trying \"%s\"....\n",
   12295 			 myfont->f_n, use_font);
   12296 	    (void) xtermLoadFont(xw,
   12297 				 xtermFontName(use_font),
   12298 				 False,
   12299 				 screen->menu_font_number);
   12300 	    screen->MenuFontName(screen->menu_font_number) = use_font;
   12301 	}
   12302     }
   12303 
   12304     /* really screwed if we couldn't open default font */
   12305     if (!GetNormalFont(screen, fNorm)->fs) {
   12306 	xtermWarning("unable to locate a suitable font\n");
   12307 	Exit(ERROR_MISC);
   12308     }
   12309 #if OPT_WIDE_CHARS
   12310     if (screen->utf8_mode) {
   12311 	TRACE(("check if this is a wide font, if not try again\n"));
   12312 	if (xtermLoadWideFonts(xw, False)) {
   12313 	    SetVTFont(xw, screen->menu_font_number, True, NULL);
   12314 	    /* we will not be able to switch to ISO-8859-1 */
   12315 	    if (!screen->mergedVTFonts) {
   12316 		screen->utf8_fonts = uAlways;
   12317 		update_font_utf8_fonts();
   12318 	    }
   12319 	}
   12320     }
   12321 #endif
   12322 
   12323     xtermSetupPointer(xw, screen->pointer_shape);
   12324 
   12325     /* set defaults */
   12326     pos.x = 1;
   12327     pos.y = 1;
   12328     pos.w = 80;
   12329     pos.h = 24;
   12330 
   12331     TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry)));
   12332     pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos);
   12333     TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w));
   12334 
   12335     set_max_col(screen, (int) (pos.w - 1));	/* units in character cells */
   12336     set_max_row(screen, (int) (pos.h - 1));	/* units in character cells */
   12337     xtermUpdateFontInfo(xw, False);
   12338 
   12339     pos.w = screen->fullVwin.fullwidth;
   12340     pos.h = screen->fullVwin.fullheight;
   12341 
   12342     TRACE(("... BorderWidth: widget %d parent %d shell %d\n",
   12343 	   BorderWidth(xw),
   12344 	   BorderWidth(XtParent(xw)),
   12345 	   BorderWidth(SHELL_OF(xw))));
   12346 
   12347     if ((pr & XValue) && (XNegative & pr)) {
   12348 	pos.x = (Position) (pos.x + (pos.scr_w
   12349 				     - (int) pos.w
   12350 				     - (BorderWidth(XtParent(xw)) * 2)));
   12351     }
   12352     if ((pr & YValue) && (YNegative & pr)) {
   12353 	pos.y = (Position) (pos.y + (pos.scr_h
   12354 				     - (int) pos.h
   12355 				     - (BorderWidth(XtParent(xw)) * 2)));
   12356     }
   12357     pos.x = (Position) (pos.x + pos.scr_x);
   12358     pos.y = (Position) (pos.y + pos.scr_y);
   12359 
   12360     /* set up size hints for window manager; min 1 char by 1 char */
   12361     getXtermSizeHints(xw);
   12362     xtermSizeHints(xw, (xw->misc.scrollbar
   12363 			? (screen->scrollWidget->core.width
   12364 			   + BorderWidth(screen->scrollWidget))
   12365 			: 0));
   12366 
   12367     xw->hints.x = pos.x;
   12368     xw->hints.y = pos.y;
   12369 #if OPT_MAXIMIZE
   12370     /* assure single-increment resize for fullscreen */
   12371     if (xw->work.ewmh[0].mode) {
   12372 	xw->hints.width_inc = 1;
   12373 	xw->hints.height_inc = 1;
   12374     }
   12375 #endif
   12376     if ((XValue & pr) || (YValue & pr)) {
   12377 	xw->hints.flags |= USSize | USPosition;
   12378 	xw->hints.flags |= PWinGravity;
   12379 	switch (pr & (XNegative | YNegative)) {
   12380 	case 0:
   12381 	    xw->hints.win_gravity = NorthWestGravity;
   12382 	    break;
   12383 	case XNegative:
   12384 	    xw->hints.win_gravity = NorthEastGravity;
   12385 	    break;
   12386 	case YNegative:
   12387 	    xw->hints.win_gravity = SouthWestGravity;
   12388 	    break;
   12389 	default:
   12390 	    xw->hints.win_gravity = SouthEastGravity;
   12391 	    break;
   12392 	}
   12393     } else {
   12394 	/* set a default size, but do *not* set position */
   12395 	xw->hints.flags |= PSize;
   12396     }
   12397     xw->hints.height = xw->hints.base_height
   12398 	+ xw->hints.height_inc * MaxRows(screen);
   12399     xw->hints.width = xw->hints.base_width
   12400 	+ xw->hints.width_inc * MaxCols(screen);
   12401 
   12402     if ((WidthValue & pr) || (HeightValue & pr))
   12403 	xw->hints.flags |= USSize;
   12404     else
   12405 	xw->hints.flags |= PSize;
   12406 
   12407     /*
   12408      * Note that the size-hints are for the shell, while the resize-request
   12409      * is for the vt100 widget.  They are not the same size.
   12410      */
   12411     (void) REQ_RESIZE((Widget) xw,
   12412 		      (Dimension) pos.w, (Dimension) pos.h,
   12413 		      &xw->core.width, &xw->core.height);
   12414 
   12415     /* XXX This is bogus.  We are parsing geometries too late.  This
   12416      * is information that the shell widget ought to have before we get
   12417      * realized, so that it can do the right thing.
   12418      */
   12419     if (xw->hints.flags & USPosition)
   12420 	XMoveWindow(XtDisplay(xw), VShellWindow(xw),
   12421 		    xw->hints.x, xw->hints.y);
   12422 
   12423     TRACE(("%s@%d -- ", __FILE__, __LINE__));
   12424     TRACE_HINTS(&xw->hints);
   12425     XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints);
   12426     TRACE(("%s@%d -- ", __FILE__, __LINE__));
   12427     TRACE_WM_HINTS(xw);
   12428 
   12429     if ((pid_atom = CachedInternAtom(XtDisplay(xw), "_NET_WM_PID")) != None) {
   12430 	/* XChangeProperty format 32 really is "long" */
   12431 	unsigned long pid_l = (unsigned long) getpid();
   12432 	TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l));
   12433 	XChangeProperty(XtDisplay(xw), VShellWindow(xw),
   12434 			pid_atom, XA_CARDINAL, 32, PropModeReplace,
   12435 			(unsigned char *) &pid_l, 1);
   12436     }
   12437 
   12438     XFlush(XtDisplay(xw));	/* get it out to window manager */
   12439 
   12440     /* use ForgetGravity instead of SouthWestGravity because translating
   12441        the Expose events for ConfigureNotifys is too hard */
   12442     values->bit_gravity = (GravityIsNorthWest(xw)
   12443 			   ? NorthWestGravity
   12444 			   : ForgetGravity);
   12445     screen->fullVwin.window = XtWindow(xw) =
   12446 	XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)),
   12447 		      xw->core.x, xw->core.y,
   12448 		      xw->core.width, xw->core.height, BorderWidth(xw),
   12449 		      (int) xw->core.depth,
   12450 		      InputOutput, CopyFromParent,
   12451 		      *valuemask | CWBitGravity, values);
   12452 #if USE_DOUBLE_BUFFER
   12453     if (allocateDbe(xw, &(screen->fullVwin))) {
   12454 	screen->needSwap = 1;
   12455 	TRACE(("initialized full double-buffering\n"));
   12456     } else {
   12457 	resource.buffered = False;
   12458 	screen->fullVwin.drawable = screen->fullVwin.window;
   12459     }
   12460 #endif /* USE_DOUBLE_BUFFER */
   12461     screen->event_mask = values->event_mask;
   12462 
   12463 #ifndef NO_ACTIVE_ICON
   12464     /*
   12465      * Normally, the font-number for icon fonts does not correspond with any of
   12466      * the menu-selectable fonts.  If we cannot load the font given for the
   12467      * iconFont resource, try with font1 aka "Unreadable".
   12468      */
   12469     screen->icon_fontnum = -1;
   12470     if (getIconicFont(screen)->fs == NULL) {
   12471 	getIconicFont(screen)->fs =
   12472 	    xtermLoadQueryFont(xw, screen->MenuFontName(fontMenu_font1));
   12473 	ReportIcons(("%susing font1 '%s' as iconFont\n",
   12474 		     (getIconicFont(screen)->fs
   12475 		      ? ""
   12476 		      : "NOT "),
   12477 		     screen->MenuFontName(fontMenu_font1)));
   12478     }
   12479 #if OPT_RENDERFONT
   12480     /*
   12481      * If we still have no result from iconFont resource (perhaps because fonts
   12482      * are missing) but are using Xft, try to use that instead.  We prefer
   12483      * bitmap fonts in any case, since scaled fonts are usually less readable,
   12484      * particularly at small sizes.
   12485      */
   12486     if (UsingRenderFont(xw)
   12487 	&& getIconicFont(screen)->fs == NULL) {
   12488 	screen->icon_fontnum = fontMenu_default;
   12489 	getIconicFont(screen)->fs = GetNormalFont(screen, fNorm)->fs;	/* need for next-if */
   12490 	ReportIcons(("using TrueType font as iconFont\n"));
   12491     }
   12492 #endif
   12493     xw->work.wm_name = getWindowManagerName(xw);
   12494     if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) {
   12495 	ReportIcons(("window manager name is %s\n", xw->work.wm_name));
   12496 	if (x_strncasecmp(xw->work.wm_name, "fvwm", 4) &&
   12497 	    x_strncasecmp(xw->work.wm_name, "window maker", 12)) {
   12498 	    xw->work.active_icon = eiFalse;
   12499 	    TRACE(("... disable active_icon\n"));
   12500 	}
   12501     }
   12502     TRACE((".. if active_icon (%d), get its font\n", xw->work.active_icon));
   12503     if (xw->work.active_icon && getIconicFont(screen)->fs) {
   12504 	int iconX = 0, iconY = 0;
   12505 	Widget shell = SHELL_OF(xw);
   12506 	VTwin *win = &(screen->iconVwin);
   12507 	int save_fontnum = screen->menu_font_number;
   12508 
   12509 	ReportIcons(("initializing active-icon %d\n", screen->icon_fontnum));
   12510 	screen->menu_font_number = screen->icon_fontnum;
   12511 	XtVaGetValues(shell,
   12512 		      XtNiconX, &iconX,
   12513 		      XtNiconY, &iconY,
   12514 		      (XtPointer) 0);
   12515 	xtermComputeFontInfo(xw, &(screen->iconVwin),
   12516 			     getIconicFont(screen)->fs, 0);
   12517 	screen->menu_font_number = save_fontnum;
   12518 
   12519 	/* since only one client is permitted to select for Button
   12520 	 * events, we have to let the window manager get 'em...
   12521 	 */
   12522 	values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask);
   12523 	values->border_pixel = xw->misc.icon_border_pixel;
   12524 
   12525 	screen->iconVwin.window =
   12526 	    XCreateWindow(XtDisplay(xw),
   12527 			  RootWindowOfScreen(XtScreen(shell)),
   12528 			  iconX, iconY,
   12529 			  screen->iconVwin.fullwidth,
   12530 			  screen->iconVwin.fullheight,
   12531 			  xw->misc.icon_border_width,
   12532 			  (int) xw->core.depth,
   12533 			  InputOutput, CopyFromParent,
   12534 			  *valuemask | CWBitGravity | CWBorderPixel,
   12535 			  values);
   12536 #if USE_DOUBLE_BUFFER
   12537 	if (allocateDbe(xw, &(screen->iconVwin))) {
   12538 	    TRACE(("initialized icon double-buffering\n"));
   12539 	} else {
   12540 	    resource.buffered = False;
   12541 	    screen->iconVwin.drawable = screen->iconVwin.window;
   12542 	    screen->fullVwin.drawable = screen->fullVwin.window;
   12543 	}
   12544 #endif /* USE_DOUBLE_BUFFER */
   12545 	XtVaSetValues(shell,
   12546 		      XtNiconWindow, screen->iconVwin.window,
   12547 		      (XtPointer) 0);
   12548 	XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w);
   12549 
   12550 	setCgsFont(xw, win, gcNorm, getIconicFont(screen));
   12551 	setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG));
   12552 	setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG));
   12553 
   12554 	copyCgs(xw, win, gcBold, gcNorm);
   12555 
   12556 	setCgsFont(xw, win, gcNormReverse, getIconicFont(screen));
   12557 	setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG));
   12558 	setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG));
   12559 
   12560 	copyCgs(xw, win, gcBoldReverse, gcNormReverse);
   12561 
   12562 	initBorderGC(xw, win);
   12563     } else {
   12564 	ReportIcons(("disabled active-icon\n"));
   12565 	xw->work.active_icon = eiFalse;
   12566     }
   12567 #if OPT_TOOLBAR
   12568     update_activeicon();
   12569 #endif
   12570 #endif /* NO_ACTIVE_ICON */
   12571 
   12572 #if OPT_INPUT_METHOD
   12573     VTInitI18N(xw);
   12574 #endif
   12575 #if OPT_NUM_LOCK
   12576     VTInitModifiers(xw);
   12577 #if OPT_EXTRA_PASTE
   12578     if (xw->keyboard.extra_translations) {
   12579 	XtOverrideTranslations((Widget) xw,
   12580 			       XtParseTranslationTable(xw->keyboard.extra_translations));
   12581     }
   12582 #endif
   12583 #endif
   12584 
   12585     set_cursor_gcs(xw);
   12586     initBorderGC(xw, &(screen->fullVwin));
   12587 
   12588     /* Reset variables used by ANSI emulation. */
   12589 
   12590     resetCharsets(screen);
   12591 
   12592     XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor);
   12593 
   12594     set_cur_col(screen, 0);
   12595     set_cur_row(screen, 0);
   12596     set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1);
   12597     set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1);
   12598     resetMarginMode(xw);
   12599 
   12600     memset(screen->sc, 0, sizeof(screen->sc));
   12601 
   12602     /* Mark screen buffer as unallocated.  We wait until the run loop so
   12603        that the child process does not fork and exec with all the dynamic
   12604        memory it will never use.  If we were to do it here, the
   12605        swap space for new process would be huge for huge savelines. */
   12606 #if OPT_TEK4014
   12607     if (!tekWidget)		/* if not called after fork */
   12608 #endif
   12609     {
   12610 	screen->visbuf = NULL;
   12611 	screen->saveBuf_index = NULL;
   12612     }
   12613 
   12614     ResetWrap(screen);
   12615     screen->scrolls = screen->incopy = 0;
   12616     xtermSetCursorBox(screen);
   12617 
   12618     screen->savedlines = 0;
   12619 
   12620     for (i = 0; i < 2; ++i) {
   12621 	screen->whichBuf = !screen->whichBuf;
   12622 	CursorSave(xw);
   12623     }
   12624 
   12625 #ifndef NO_ACTIVE_ICON
   12626     if (!xw->work.active_icon)
   12627 #endif
   12628 	xtermLoadIcon(xw, resource.icon_hint);
   12629 
   12630     /*
   12631      * Do this last, since it may change the layout via a resize.
   12632      */
   12633     if (xw->misc.scrollbar) {
   12634 	screen->fullVwin.sb_info.width = 0;
   12635 	ScrollBarOn(xw, False);
   12636     }
   12637 
   12638     xtermSetWinSize(xw);
   12639     TRACE(("" TRACE_R " VTRealize\n"));
   12640 }
   12641 
   12642 #if OPT_INPUT_METHOD
   12643 
   12644 /* limit this feature to recent XFree86 since X11R6.x core dumps */
   12645 #if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING)
   12646 #define USE_XIM_INSTANTIATE_CB
   12647 
   12648 static void
   12649 xim_instantiate_cb(Display *display,
   12650 		   XPointer client_data GCC_UNUSED,
   12651 		   XPointer call_data GCC_UNUSED)
   12652 {
   12653     XtermWidget xw = term;
   12654 
   12655     TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data));
   12656 
   12657     if (display == XtDisplay(xw)) {
   12658 	VTInitI18N(xw);
   12659     }
   12660 }
   12661 
   12662 static void
   12663 xim_destroy_cb(XIM im GCC_UNUSED,
   12664 	       XPointer client_data GCC_UNUSED,
   12665 	       XPointer call_data GCC_UNUSED)
   12666 {
   12667     XtermWidget xw = term;
   12668     TInput *input = lookupTInput(xw, (Widget) xw);
   12669 
   12670     TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n",
   12671 	   (long) im, client_data, call_data));
   12672     if (input)
   12673 	input->xic = NULL;
   12674     XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
   12675 				   xim_instantiate_cb, NULL);
   12676 }
   12677 #endif /* X11R6+ */
   12678 
   12679 static Boolean
   12680 xim_create_fs(XtermWidget xw)
   12681 {
   12682     XFontStruct **fonts;
   12683     char **font_name_list;
   12684     char **missing_charset_list;
   12685     char *def_string;
   12686     int missing_charset_count;
   12687     unsigned i, j;
   12688 
   12689     if (xw->work.xim_fs == NULL) {
   12690 	xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
   12691 					 xw->misc.f_x,
   12692 					 &missing_charset_list,
   12693 					 &missing_charset_count,
   12694 					 &def_string);
   12695 	if (xw->work.xim_fs == NULL) {
   12696 	    xtermWarning("Preparation of font set "
   12697 			 "\"%s\" for XIM failed.\n", xw->misc.f_x);
   12698 	    xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
   12699 					     DEFXIMFONT,
   12700 					     &missing_charset_list,
   12701 					     &missing_charset_count,
   12702 					     &def_string);
   12703 	}
   12704     }
   12705     if (xw->work.xim_fs == NULL) {
   12706 	xtermWarning("Preparation of default font set "
   12707 		     "\"%s\" for XIM failed.\n", DEFXIMFONT);
   12708 	cleanupInputMethod(xw);
   12709 	xw->work.cannot_im = True;
   12710     } else {
   12711 	(void) XExtentsOfFontSet(xw->work.xim_fs);
   12712 	j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list);
   12713 	for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) {
   12714 	    if (xw->work.xim_fs_ascent < (*fonts)->ascent)
   12715 		xw->work.xim_fs_ascent = (*fonts)->ascent;
   12716 	}
   12717     }
   12718     return (Boolean) !(xw->work.cannot_im);
   12719 }
   12720 
   12721 static void
   12722 xim_create_xic(XtermWidget xw, Widget theInput)
   12723 {
   12724     Display *myDisplay = XtDisplay(theInput);
   12725     Window myWindow = XtWindow(theInput);
   12726     unsigned i, j;
   12727     char *p = NULL, *s, *t, *ns, *end, buf[32];
   12728     XIMStyles *xim_styles;
   12729     XIMStyle input_style = 0;
   12730     Bool found;
   12731     static struct {
   12732 	const char *name;
   12733 	unsigned long code;
   12734     } known_style[] = {
   12735 	{
   12736 	    "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing)
   12737 	},
   12738 	{
   12739 	    "OffTheSpot", (XIMPreeditArea | XIMStatusArea)
   12740 	},
   12741 	{
   12742 	    "Root", (XIMPreeditNothing | XIMStatusNothing)
   12743 	},
   12744     };
   12745     TInput *input = lookupTInput(xw, theInput);
   12746 
   12747     if (xw->work.cannot_im) {
   12748 	return;
   12749     }
   12750 
   12751     if (input == NULL) {
   12752 	for (i = 0; i < NINPUTWIDGETS; ++i) {
   12753 	    if (xw->work.inputs[i].w == NULL) {
   12754 		input = xw->work.inputs + i;
   12755 		input->w = theInput;
   12756 		break;
   12757 	    }
   12758 	}
   12759     }
   12760 
   12761     if (input == NULL) {
   12762 	xtermWarning("attempted to add too many input widgets\n");
   12763 	return;
   12764     }
   12765 
   12766     TRACE(("xim_real_init\n"));
   12767 
   12768     if (IsEmpty(xw->misc.input_method)) {
   12769 	if ((p = XSetLocaleModifiers("")) != NULL && *p) {
   12770 	    input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
   12771 	}
   12772     } else {
   12773 	s = xw->misc.input_method;
   12774 	i = 5 + (unsigned) strlen(s);
   12775 
   12776 	t = (char *) MyStackAlloc(i, buf);
   12777 	if (t == NULL) {
   12778 	    SysError(ERROR_VINIT);
   12779 	} else {
   12780 
   12781 	    for (ns = s; ns && *s;) {
   12782 		while (*s && isspace(CharOf(*s)))
   12783 		    s++;
   12784 		if (!*s)
   12785 		    break;
   12786 		if ((ns = end = strchr(s, ',')) == NULL)
   12787 		    end = s + strlen(s);
   12788 		while ((end != s) && isspace(CharOf(end[-1])))
   12789 		    end--;
   12790 
   12791 		if (end != s) {
   12792 		    strcpy(t, "@im=");
   12793 		    strncat(t, s, (size_t) (end - s));
   12794 
   12795 		    if ((p = XSetLocaleModifiers(t)) != NULL && *p
   12796 			&& (input->xim = XOpenIM(myDisplay,
   12797 						 NULL,
   12798 						 NULL,
   12799 						 NULL)) != NULL) {
   12800 			break;
   12801 		    }
   12802 
   12803 		}
   12804 		s = ns + 1;
   12805 	    }
   12806 	    MyStackFree(t, buf);
   12807 	}
   12808     }
   12809 
   12810     if (input->xim == NULL
   12811 	&& (p = XSetLocaleModifiers("@im=none")) != NULL
   12812 	&& *p) {
   12813 	input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
   12814     }
   12815 
   12816     if (!input->xim) {
   12817 	xtermWarning("Failed to open input method\n");
   12818 	return;
   12819     }
   12820     TRACE(("VTInitI18N opened input method:%s\n", NonNull(p)));
   12821 
   12822     if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0)
   12823 	|| !xim_styles
   12824 	|| !xim_styles->count_styles) {
   12825 	xtermWarning("input method doesn't support any style\n");
   12826 	cleanupInputMethod(xw);
   12827 	xw->work.cannot_im = True;
   12828 	return;
   12829     }
   12830 
   12831     found = False;
   12832     for (s = xw->misc.preedit_type; s && !found;) {
   12833 	while (*s && isspace(CharOf(*s)))
   12834 	    s++;
   12835 	if (!*s)
   12836 	    break;
   12837 	if ((ns = end = strchr(s, ',')) != NULL)
   12838 	    ns++;
   12839 	else
   12840 	    end = s + strlen(s);
   12841 	while ((end != s) && isspace(CharOf(end[-1])))
   12842 	    end--;
   12843 
   12844 	if (end != s) {		/* just in case we have a spurious comma */
   12845 	    TRACE(("looking for style '%.*s'\n", (int) (end - s), s));
   12846 	    for (i = 0; i < XtNumber(known_style); i++) {
   12847 		if ((int) strlen(known_style[i].name) == (end - s)
   12848 		    && !strncmp(s, known_style[i].name, (size_t) (end - s))) {
   12849 		    input_style = known_style[i].code;
   12850 		    for (j = 0; j < xim_styles->count_styles; j++) {
   12851 			if (input_style == xim_styles->supported_styles[j]) {
   12852 			    found = True;
   12853 			    break;
   12854 			}
   12855 		    }
   12856 		    if (found)
   12857 			break;
   12858 		}
   12859 	    }
   12860 	}
   12861 
   12862 	s = ns;
   12863     }
   12864     XFree(xim_styles);
   12865 
   12866     if (!found) {
   12867 	xtermWarning("input method doesn't support my preedit type (%s)\n",
   12868 		     xw->misc.preedit_type);
   12869 	cleanupInputMethod(xw);
   12870 	xw->work.cannot_im = True;
   12871 	return;
   12872     }
   12873 
   12874     /*
   12875      * Check for styles we do not yet support.
   12876      */
   12877     TRACE(("input_style %#lx\n", input_style));
   12878     if (input_style == (XIMPreeditArea | XIMStatusArea)) {
   12879 	xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n");
   12880 	cleanupInputMethod(xw);
   12881 	xw->work.cannot_im = True;
   12882 	return;
   12883     }
   12884 
   12885     /*
   12886      * For XIMPreeditPosition (or OverTheSpot), XIM client has to
   12887      * prepare a font.
   12888      * The font has to be locale-dependent XFontSet, whereas
   12889      * XTerm use Unicode font.  This leads a problem that the
   12890      * same font cannot be used for XIM preedit.
   12891      */
   12892     if (input_style != (XIMPreeditNothing | XIMStatusNothing)) {
   12893 	XVaNestedList p_list;
   12894 	XPoint spot =
   12895 	{0, 0};
   12896 
   12897 	if (xim_create_fs(xw)) {
   12898 	    p_list = XVaCreateNestedList(0,
   12899 					 XNSpotLocation, &spot,
   12900 					 XNFontSet, xw->work.xim_fs,
   12901 					 (void *) 0);
   12902 	    input->xic = XCreateIC(input->xim,
   12903 				   XNInputStyle, input_style,
   12904 				   XNClientWindow, myWindow,
   12905 				   XNFocusWindow, myWindow,
   12906 				   XNPreeditAttributes, p_list,
   12907 				   (void *) 0);
   12908 	}
   12909     } else {
   12910 	input->xic = XCreateIC(input->xim, XNInputStyle, input_style,
   12911 			       XNClientWindow, myWindow,
   12912 			       XNFocusWindow, myWindow,
   12913 			       (void *) 0);
   12914     }
   12915 
   12916     if (!input->xic) {
   12917 	xtermWarning("Failed to create input context\n");
   12918 	cleanupInputMethod(xw);
   12919     }
   12920 #if defined(USE_XIM_INSTANTIATE_CB)
   12921     else {
   12922 	XIMCallback destroy_cb;
   12923 
   12924 	destroy_cb.callback = xim_destroy_cb;
   12925 	destroy_cb.client_data = NULL;
   12926 	if (XSetIMValues(input->xim,
   12927 			 XNDestroyCallback,
   12928 			 &destroy_cb,
   12929 			 (void *) 0)) {
   12930 	    xtermWarning("Could not set destroy callback to IM\n");
   12931 	}
   12932     }
   12933 #endif
   12934 
   12935     return;
   12936 }
   12937 
   12938 static void
   12939 xim_real_init(XtermWidget xw)
   12940 {
   12941     xim_create_xic(xw, (Widget) xw);
   12942 }
   12943 
   12944 static void
   12945 VTInitI18N(XtermWidget xw)
   12946 {
   12947     if (xw->misc.open_im) {
   12948 	xim_real_init(xw);
   12949 
   12950 #if defined(USE_XIM_INSTANTIATE_CB)
   12951 	if (lookupTInput(xw, (Widget) xw) == NULL
   12952 	    && !xw->work.cannot_im
   12953 	    && xw->misc.retry_im-- > 0) {
   12954 	    sleep(3);
   12955 	    XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
   12956 					   xim_instantiate_cb, NULL);
   12957 	}
   12958 #endif
   12959     }
   12960 }
   12961 
   12962 TInput *
   12963 lookupTInput(XtermWidget xw, Widget w)
   12964 {
   12965     TInput *result = NULL;
   12966     unsigned n;
   12967 
   12968     for (n = 0; n < NINPUTWIDGETS; ++n) {
   12969 	if (xw->work.inputs[n].w == w) {
   12970 	    result = xw->work.inputs + n;
   12971 	    break;
   12972 	}
   12973     }
   12974 
   12975     return result;
   12976 }
   12977 #endif /* OPT_INPUT_METHOD */
   12978 
   12979 static void
   12980 set_cursor_outline_gc(XtermWidget xw,
   12981 		      Bool filled,
   12982 		      Pixel fg,
   12983 		      Pixel bg,
   12984 		      Pixel cc)
   12985 {
   12986     TScreen *screen = TScreenOf(xw);
   12987     VTwin *win = WhichVWin(screen);
   12988     CgsEnum cgsId = gcVTcursOutline;
   12989 
   12990     if (cc == bg)
   12991 	cc = fg;
   12992 
   12993     if (filled) {
   12994 	setCgsFore(xw, win, cgsId, bg);
   12995 	setCgsBack(xw, win, cgsId, cc);
   12996     } else {
   12997 	setCgsFore(xw, win, cgsId, cc);
   12998 	setCgsBack(xw, win, cgsId, bg);
   12999     }
   13000 }
   13001 
   13002 static Boolean
   13003 VTSetValues(Widget cur,
   13004 	    Widget request GCC_UNUSED,
   13005 	    Widget wnew,
   13006 	    ArgList args GCC_UNUSED,
   13007 	    Cardinal *num_args GCC_UNUSED)
   13008 {
   13009     XtermWidget curvt = (XtermWidget) cur;
   13010     XtermWidget newvt = (XtermWidget) wnew;
   13011     Boolean refresh_needed = False;
   13012     Boolean fonts_redone = False;
   13013 
   13014     if ((T_COLOR(TScreenOf(curvt), TEXT_BG) !=
   13015 	 T_COLOR(TScreenOf(newvt), TEXT_BG)) ||
   13016 	(T_COLOR(TScreenOf(curvt), TEXT_FG) !=
   13017 	 T_COLOR(TScreenOf(newvt), TEXT_FG)) ||
   13018 	(TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) !=
   13019 	 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) ||
   13020 	strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) {
   13021 	if (strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) {
   13022 	    TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt);
   13023 	}
   13024 	if (xtermLoadFont(newvt,
   13025 			  xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)),
   13026 			  True, TScreenOf(newvt)->menu_font_number)) {
   13027 	    /* resizing does the redisplay, so don't ask for it here */
   13028 	    refresh_needed = True;
   13029 	    fonts_redone = True;
   13030 	} else if (strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) {
   13031 	    TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt);
   13032 	}
   13033     }
   13034     if (!fonts_redone
   13035 	&& (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) !=
   13036 	    T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) {
   13037 	if (set_cursor_gcs(newvt))
   13038 	    refresh_needed = True;
   13039     }
   13040     if (curvt->misc.re_verse != newvt->misc.re_verse) {
   13041 	newvt->flags ^= REVERSE_VIDEO;
   13042 	ReverseVideo(newvt);
   13043 	/* ReverseVideo toggles */
   13044 	newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse);
   13045 	refresh_needed = True;
   13046     }
   13047     if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) !=
   13048 	 T_COLOR(TScreenOf(newvt), MOUSE_FG)) ||
   13049 	(T_COLOR(TScreenOf(curvt), MOUSE_BG) !=
   13050 	 T_COLOR(TScreenOf(newvt), MOUSE_BG))) {
   13051 	recolor_cursor(TScreenOf(newvt),
   13052 		       TScreenOf(newvt)->pointer_cursor,
   13053 		       T_COLOR(TScreenOf(newvt), MOUSE_FG),
   13054 		       T_COLOR(TScreenOf(newvt), MOUSE_BG));
   13055 	refresh_needed = True;
   13056     }
   13057     if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
   13058 	ToggleScrollBar(newvt);
   13059     }
   13060 
   13061     return refresh_needed;
   13062 }
   13063 
   13064 /*
   13065  * Given a font-slot and information about selection/reverse, find the
   13066  * corresponding cached-GC slot.
   13067  */
   13068 #if OPT_WIDE_ATTRS
   13069 static int
   13070 reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font)
   13071 {
   13072     TScreen *screen = TScreenOf(xw);
   13073     CgsEnum result = gcMAX;
   13074 
   13075     (void) screen;
   13076     if (ReverseOrHilite(screen, attr_flags, hilite)) {
   13077 	switch (font) {
   13078 	case fNorm:
   13079 	    result = gcNormReverse;
   13080 	    break;
   13081 	case fBold:
   13082 	    result = gcBoldReverse;
   13083 	    break;
   13084 #if OPT_WIDE_ATTRS || OPT_RENDERWIDE
   13085 	case fItal:
   13086 	    result = gcNormReverse;	/* FIXME */
   13087 	    break;
   13088 #endif
   13089 #if OPT_WIDE_CHARS
   13090 	case fWide:
   13091 	    result = gcWideReverse;
   13092 	    break;
   13093 	case fWBold:
   13094 	    result = gcWBoldReverse;
   13095 	    break;
   13096 	case fWItal:
   13097 	    result = gcWideReverse;	/* FIXME */
   13098 	    break;
   13099 #endif
   13100 	}
   13101     } else {
   13102 	switch (font) {
   13103 	case fNorm:
   13104 	    result = gcNorm;
   13105 	    break;
   13106 	case fBold:
   13107 	    result = gcBold;
   13108 	    break;
   13109 #if OPT_WIDE_ATTRS || OPT_RENDERWIDE
   13110 	case fItal:
   13111 	    result = gcNorm;	/* FIXME */
   13112 	    break;
   13113 #endif
   13114 #if OPT_WIDE_CHARS
   13115 	case fWide:
   13116 	    result = gcWide;
   13117 	    break;
   13118 	case fWBold:
   13119 	    result = gcWBold;
   13120 	    break;
   13121 	case fWItal:
   13122 	    result = gcWide;	/* FIXME */
   13123 	    break;
   13124 #endif
   13125 	}
   13126     }
   13127     return (int) result;
   13128 }
   13129 #endif
   13130 
   13131 #define setGC(code) set_at = __LINE__, currentCgs = code
   13132 
   13133 #define OutsideSelection(screen,srow,scol)  \
   13134 	 ((srow) > (screen)->endH.row || \
   13135 	  ((srow) == (screen)->endH.row && \
   13136 	   (scol) >= (screen)->endH.col) || \
   13137 	  (srow) < (screen)->startH.row || \
   13138 	  ((srow) == (screen)->startH.row && \
   13139 	   (scol) < (screen)->startH.col))
   13140 
   13141 /*
   13142  * Shows cursor at new cursor position in screen.
   13143  */
   13144 void
   13145 ShowCursor(XtermWidget xw)
   13146 {
   13147     TScreen *screen = TScreenOf(xw);
   13148     XTermDraw params;
   13149     IChar base;
   13150     unsigned flags;
   13151     CellColor fg_bg = initCColor;
   13152     GC currentGC;
   13153     GC outlineGC;
   13154     CgsEnum currentCgs = gcMAX;
   13155     VTwin *currentWin = WhichVWin(screen);
   13156     int set_at;
   13157     Bool in_selection;
   13158     Bool reversed;
   13159     Bool filled;
   13160     Pixel fg_pix;
   13161     Pixel bg_pix;
   13162     Pixel tmp;
   13163 #if OPT_HIGHLIGHT_COLOR
   13164     Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG);
   13165     Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG);
   13166     Boolean use_selbg;
   13167     Boolean use_selfg;
   13168 #endif
   13169 #if OPT_WIDE_CHARS
   13170     int my_col = 0;
   13171 #endif
   13172     int cursor_col;
   13173     CLineData *ld = NULL;
   13174 
   13175     if (screen->cursor_state == BLINKED_OFF)
   13176 	return;
   13177 
   13178     if (screen->eventMode != NORMAL)
   13179 	return;
   13180 
   13181     if (INX2ROW(screen, screen->cur_row) > screen->max_row)
   13182 	return;
   13183 
   13184     screen->cursorp.row = screen->cur_row;
   13185     cursor_col = screen->cursorp.col = screen->cur_col;
   13186     screen->cursor_moved = False;
   13187 
   13188 #ifndef NO_ACTIVE_ICON
   13189     if (IsIcon(screen)) {
   13190 	screen->cursor_state = ON;
   13191 	return;
   13192     }
   13193 #endif /* NO_ACTIVE_ICON */
   13194 
   13195     ld = getLineData(screen, screen->cur_row);
   13196 
   13197     base = ld->charData[cursor_col];
   13198     flags = ld->attribs[cursor_col];
   13199 
   13200     if_OPT_WIDE_CHARS(screen, {
   13201 	if (base == HIDDEN_CHAR && cursor_col > 0) {
   13202 	    /* if cursor points to non-initial part of wide character,
   13203 	     * back it up
   13204 	     */
   13205 	    --cursor_col;
   13206 	    base = ld->charData[cursor_col];
   13207 	}
   13208 	my_col = cursor_col;
   13209 	if (base == 0)
   13210 	    base = ' ';
   13211 	if (isWide((int) base))
   13212 	    my_col += 1;
   13213     });
   13214 
   13215     if (base == 0) {
   13216 	base = ' ';
   13217     }
   13218 #if OPT_ISO_COLORS
   13219 #ifdef EXP_BOGUS_FG
   13220     /*
   13221      * If the cursor happens to be on blanks, and we have not set both
   13222      * foreground and background color, do not treat it as a colored cell.
   13223      */
   13224     if (base == ' ') {
   13225 	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
   13226 	    TRACE(("ShowCursor - do not treat as a colored cell\n"));
   13227 	    flags &= ~(FG_COLOR | BG_COLOR);
   13228 	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
   13229 	    TRACE(("ShowCursor - should we treat as a colored cell?\n"));
   13230 	    if (!(xw->flags & FG_COLOR)) {
   13231 		if (CheckBogusForeground(screen, "ShowCursor")) {
   13232 		    flags &= ~(FG_COLOR | BG_COLOR);
   13233 		}
   13234 	    }
   13235 	}
   13236     }
   13237 #else /* !EXP_BOGUS_FG */
   13238     /*
   13239      * If the cursor happens to be on blanks, and the foreground color is set
   13240      * but not the background, do not treat it as a colored cell.
   13241      */
   13242     if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR
   13243 	&& base == ' ') {
   13244 	flags &= ~TERM_COLOR_FLAGS(xw);
   13245     }
   13246 #endif
   13247 #endif
   13248 
   13249     /*
   13250      * Compare the current cell to the last set of colors used for the
   13251      * cursor and update the GC's if needed.
   13252      */
   13253     (void) fg_bg;
   13254     if_OPT_ISO_COLORS(screen, {
   13255 	fg_bg = ld->color[cursor_col];
   13256     });
   13257 
   13258     fg_pix = getXtermFG(xw, flags, (int) extract_fg(xw, fg_bg, flags));
   13259     bg_pix = getXtermBG(xw, flags, (int) extract_bg(xw, fg_bg, flags));
   13260 
   13261     /*
   13262      * If we happen to have the same foreground/background colors, choose
   13263      * a workable foreground color from which we can obtain a visible cursor.
   13264      */
   13265     if (fg_pix == bg_pix) {
   13266 	long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG));
   13267 	long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG));
   13268 	if (bg_diff < 0)
   13269 	    bg_diff = -bg_diff;
   13270 	if (fg_diff < 0)
   13271 	    fg_diff = -fg_diff;
   13272 	if (bg_diff < fg_diff) {
   13273 	    fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG);
   13274 	} else {
   13275 	    fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG);
   13276 	}
   13277     }
   13278 
   13279     if (OutsideSelection(screen, screen->cur_row, screen->cur_col))
   13280 	in_selection = False;
   13281     else
   13282 	in_selection = True;
   13283 
   13284     reversed = ReverseOrHilite(screen, flags, in_selection);
   13285 
   13286     /* This is like updatedXtermGC(), except that we have to worry about
   13287      * whether the window has focus, since in that case we want just an
   13288      * outline for the cursor.
   13289      */
   13290     filled = (screen->select || screen->always_highlight) && isCursorBlock(screen);
   13291 #if OPT_HIGHLIGHT_COLOR
   13292     use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix);
   13293     use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix);
   13294 #endif
   13295     if (filled) {
   13296 	if (reversed) {		/* text is reverse video */
   13297 	    if (getCgsGC(xw, currentWin, gcVTcursNormal)) {
   13298 		setGC(gcVTcursNormal);
   13299 	    } else {
   13300 		if (flags & BOLDATTR(screen)) {
   13301 		    setGC(gcBold);
   13302 		} else {
   13303 		    setGC(gcNorm);
   13304 		}
   13305 	    }
   13306 	    EXCHANGE(fg_pix, bg_pix, tmp);
   13307 #if OPT_HIGHLIGHT_COLOR
   13308 	    if (screen->hilite_reverse) {
   13309 		if (use_selbg && !use_selfg)
   13310 		    fg_pix = bg_pix;
   13311 		if (use_selfg && !use_selbg)
   13312 		    bg_pix = fg_pix;
   13313 		if (use_selbg)
   13314 		    bg_pix = selbg_pix;
   13315 		if (use_selfg)
   13316 		    fg_pix = selfg_pix;
   13317 	    }
   13318 #endif
   13319 	} else {		/* normal video */
   13320 	    if (getCgsGC(xw, currentWin, gcVTcursReverse)) {
   13321 		setGC(gcVTcursReverse);
   13322 	    } else {
   13323 		if (flags & BOLDATTR(screen)) {
   13324 		    setGC(gcBoldReverse);
   13325 		} else {
   13326 		    setGC(gcNormReverse);
   13327 		}
   13328 	    }
   13329 	}
   13330 
   13331 #define CUR_XX T_COLOR(screen, TEXT_CURSOR)
   13332 #define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
   13333 #define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
   13334 
   13335 #define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground))
   13336 #define FIX_328 (CUR_XX == bg_pix)
   13337 #define FIX_330 (FIX_328 && reversed && in_selection)
   13338 
   13339 	if (FIX_330 || FIX_311) {
   13340 	    setCgsBack(xw, currentWin, currentCgs, fg_pix);
   13341 	}
   13342 	setCgsFore(xw, currentWin, currentCgs, bg_pix);
   13343     } else {			/* not selected */
   13344 	if (reversed) {		/* text is reverse video */
   13345 	    EXCHANGE(fg_pix, bg_pix, tmp);
   13346 	    setGC(gcNormReverse);
   13347 	} else {		/* normal video */
   13348 	    setGC(gcNorm);
   13349 	}
   13350 #if OPT_HIGHLIGHT_COLOR
   13351 	if (screen->hilite_reverse) {
   13352 	    if (in_selection && !reversed) {
   13353 		/* EMPTY */
   13354 		/* really INVERSE ... */
   13355 		;
   13356 	    } else if (in_selection || reversed) {
   13357 		if (use_selbg) {
   13358 		    if (use_selfg) {
   13359 			bg_pix = fg_pix;
   13360 		    } else {
   13361 			fg_pix = bg_pix;
   13362 			bg_pix = selbg_pix;
   13363 		    }
   13364 		}
   13365 		if (use_selfg) {
   13366 		    fg_pix = selfg_pix;
   13367 		}
   13368 	    }
   13369 	} else {
   13370 	    if (in_selection) {
   13371 		if (use_selbg) {
   13372 		    bg_pix = selbg_pix;
   13373 		}
   13374 		if (use_selfg) {
   13375 		    fg_pix = selfg_pix;
   13376 		}
   13377 	    }
   13378 	}
   13379 #endif
   13380 	setCgsFore(xw, currentWin, currentCgs, fg_pix);
   13381 	setCgsBack(xw, currentWin, currentCgs, bg_pix);
   13382     }
   13383 
   13384     if (screen->cursor_busy == 0
   13385 	&& (screen->cursor_state != ON || screen->cursor_GC != set_at)) {
   13386 	int x, y;
   13387 
   13388 	screen->cursor_GC = set_at;
   13389 	TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n",
   13390 	       screen->cur_row, screen->cur_col,
   13391 	       (filled ? "filled" : "outline"),
   13392 	       (isCursorBlock(screen) ? "box" :
   13393 		isCursorUnderline(screen) ? "underline" : "bar"),
   13394 	       set_at));
   13395 
   13396 	currentGC = getCgsGC(xw, currentWin, currentCgs);
   13397 	x = LineCursorX(screen, ld, cursor_col);
   13398 	y = CursorY(screen, screen->cur_row);
   13399 
   13400 	if (!isCursorBlock(screen)) {
   13401 	    /*
   13402 	     * Overriding the combination of filled, reversed, in_selection is
   13403 	     * too complicated since the underline or bar and the text-cell use
   13404 	     * different rules.  Just redraw the text-cell, and draw the
   13405 	     * underline or bar on top of it.
   13406 	     */
   13407 	    HideCursor(xw);
   13408 
   13409 	    /*
   13410 	     * Our current-GC is likely to have been modified in HideCursor().
   13411 	     * Set up a new request.
   13412 	     */
   13413 	    if (filled) {
   13414 		if (FIX_330 || FIX_311) {
   13415 		    setCgsBack(xw, currentWin, currentCgs, fg_pix);
   13416 		}
   13417 		setCgsFore(xw, currentWin, currentCgs, bg_pix);
   13418 	    } else {
   13419 		setCgsFore(xw, currentWin, currentCgs, fg_pix);
   13420 		setCgsBack(xw, currentWin, currentCgs, bg_pix);
   13421 	    }
   13422 	}
   13423 
   13424 	/*
   13425 	 * Update the outline-gc, to keep the cursor color distinct from the
   13426 	 * background color.
   13427 	 */
   13428 	set_cursor_outline_gc(xw,
   13429 			      filled,
   13430 			      fg_pix,
   13431 			      bg_pix,
   13432 			      T_COLOR(screen, TEXT_CURSOR));
   13433 
   13434 	outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline);
   13435 	if (outlineGC == NULL)
   13436 	    outlineGC = currentGC;
   13437 
   13438 	if (isCursorUnderline(screen)) {
   13439 
   13440 	    /*
   13441 	     * Finally, draw the underline.
   13442 	     */
   13443 	    screen->box->x = (short) x;
   13444 	    screen->box->y = (short) (y
   13445 				      + FontHeight(screen)
   13446 				      - screen->box[2].y);
   13447 	    XFillRectangle(screen->display, VDrawable(screen), outlineGC,
   13448 			   screen->box->x,
   13449 			   screen->box->y,
   13450 			   (unsigned) screen->box[1].x,
   13451 			   (unsigned) screen->box[2].y);
   13452 	} else if (isCursorBar(screen)) {
   13453 
   13454 	    /*
   13455 	     * Or draw the bar.
   13456 	     */
   13457 	    screen->box->x = (short) x;
   13458 	    screen->box->y = (short) y;
   13459 	    XFillRectangle(screen->display, VDrawable(screen), outlineGC,
   13460 			   screen->box->x,
   13461 			   screen->box->y,
   13462 			   (unsigned) screen->box[1].x,
   13463 			   (unsigned) screen->box[2].y);
   13464 	} else {
   13465 #if OPT_WIDE_ATTRS
   13466 	    int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0);
   13467 	    int italics_off = ((xw->flags & ATR_ITALIC) != 0);
   13468 	    int fix_italics = (italics_on != italics_off);
   13469 	    int which_font = ((xw->flags & BOLD) ? fBold : fNorm);
   13470 	    MyGetFont getter = italics_on ? getItalicFont : getNormalFont;
   13471 
   13472 	    if_OPT_WIDE_CHARS(screen, {
   13473 		if (isWide((int) base)) {
   13474 		    which_font = ((xw->flags & BOLD) ? fWBold : fWide);
   13475 		}
   13476 	    });
   13477 
   13478 	    if (fix_italics && UseItalicFont(screen)) {
   13479 		xtermLoadItalics(xw);
   13480 		setCgsFont(xw, currentWin, currentCgs,
   13481 			   getter(screen, which_font));
   13482 		getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen))
   13483 			  ? getItalicFont
   13484 			  : getNormalFont);
   13485 	    }
   13486 	    currentGC = getCgsGC(xw, currentWin, currentCgs);
   13487 #endif /* OPT_WIDE_ATTRS */
   13488 
   13489 	    /* *INDENT-EQLS* */
   13490 	    params.xw          = xw;
   13491 	    params.attr_flags  = (flags & DRAWX_MASK);
   13492 	    params.draw_flags  = 0;
   13493 	    params.this_chrset = LineCharSet(screen, ld);
   13494 	    params.real_chrset = CSET_SWL;
   13495 	    params.on_wide     = 0;
   13496 
   13497 	    drawXtermText(&params,
   13498 			  currentGC, x, y,
   13499 			  &base, 1);
   13500 
   13501 #if OPT_WIDE_CHARS
   13502 	    if_OPT_WIDE_CHARS(screen, {
   13503 		size_t off;
   13504 
   13505 		/* *INDENT-EQLS* */
   13506 		params.draw_flags = NOBACKGROUND;
   13507 		params.on_wide    = isWide((int) base);
   13508 
   13509 		for_each_combData(off, ld) {
   13510 		    if (!(ld->combData[off][my_col]))
   13511 			break;
   13512 		    drawXtermText(&params,
   13513 				  currentGC, x, y,
   13514 				  ld->combData[off] + my_col, 1);
   13515 		}
   13516 	    });
   13517 #endif
   13518 
   13519 	    if (!filled) {
   13520 		screen->box->x = (short) x;
   13521 		screen->box->y = (short) y;
   13522 		XDrawLines(screen->display, VDrawable(screen), outlineGC,
   13523 			   screen->box, NBOX, CoordModePrevious);
   13524 	    }
   13525 #if OPT_WIDE_ATTRS
   13526 	    if (fix_italics && UseItalicFont(screen)) {
   13527 		setCgsFont(xw, currentWin, currentCgs,
   13528 			   getter(screen, which_font));
   13529 	    }
   13530 #endif
   13531 	}
   13532     }
   13533     screen->cursor_state = ON;
   13534 
   13535     return;
   13536 }
   13537 
   13538 /*
   13539  * hide cursor at previous cursor position in screen.
   13540  */
   13541 void
   13542 HideCursor(XtermWidget xw)
   13543 {
   13544     TScreen *screen = TScreenOf(xw);
   13545     XTermDraw params;
   13546     GC currentGC;
   13547     int x, y;
   13548     IChar base;
   13549     unsigned flags;
   13550     CellColor fg_bg = initCColor;
   13551     Bool in_selection;
   13552 #if OPT_WIDE_CHARS
   13553     int my_col = 0;
   13554 #endif
   13555     int cursor_col;
   13556     CLineData *ld = NULL;
   13557 #if OPT_WIDE_ATTRS
   13558     int which_Cgs = gcMAX;
   13559     unsigned attr_flags;
   13560     int which_font = fNorm;
   13561     MyGetFont getter = getNormalFont;
   13562 #endif
   13563 
   13564     if (screen->cursor_state == OFF)
   13565 	return;
   13566     if (INX2ROW(screen, screen->cursorp.row) > screen->max_row)
   13567 	return;
   13568 
   13569     cursor_col = screen->cursorp.col;
   13570 
   13571 #ifndef NO_ACTIVE_ICON
   13572     if (IsIcon(screen)) {
   13573 	screen->cursor_state = OFF;
   13574 	return;
   13575     }
   13576 #endif /* NO_ACTIVE_ICON */
   13577 
   13578     ld = getLineData(screen, screen->cursorp.row);
   13579 
   13580     base = ld->charData[cursor_col];
   13581     flags = ld->attribs[cursor_col];
   13582 
   13583     if_OPT_WIDE_CHARS(screen, {
   13584 	if (base == HIDDEN_CHAR && cursor_col > 0) {
   13585 	    /* if cursor points to non-initial part of wide character,
   13586 	     * back it up
   13587 	     */
   13588 	    --cursor_col;
   13589 	    base = ld->charData[cursor_col];
   13590 	}
   13591 	my_col = cursor_col;
   13592 	if (base == 0)
   13593 	    base = ' ';
   13594 	if (isWide((int) base))
   13595 	    my_col += 1;
   13596     });
   13597 
   13598     if (base == 0) {
   13599 	base = ' ';
   13600     }
   13601 #ifdef EXP_BOGUS_FG
   13602     /*
   13603      * If the cursor happens to be on blanks, and we have not set both
   13604      * foreground and background color, do not treat it as a colored cell.
   13605      */
   13606 #if OPT_ISO_COLORS
   13607     if (base == ' ') {
   13608 	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
   13609 	    TRACE(("HideCursor - do not treat as a colored cell\n"));
   13610 	    flags &= ~(FG_COLOR | BG_COLOR);
   13611 	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
   13612 	    TRACE(("HideCursor - should we treat as a colored cell?\n"));
   13613 	    if (!(xw->flags & FG_COLOR))
   13614 		if (CheckBogusForeground(screen, "HideCursor"))
   13615 		    flags &= ~(FG_COLOR | BG_COLOR);
   13616 	}
   13617     }
   13618 #endif
   13619 #endif
   13620 
   13621     /*
   13622      * Compare the current cell to the last set of colors used for the
   13623      * cursor and update the GC's if needed.
   13624      */
   13625     if_OPT_ISO_COLORS(screen, {
   13626 	fg_bg = ld->color[cursor_col];
   13627     });
   13628 
   13629     if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col))
   13630 	in_selection = False;
   13631     else
   13632 	in_selection = True;
   13633 
   13634 #if OPT_WIDE_ATTRS
   13635     attr_flags = ld->attribs[cursor_col];
   13636     if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) {
   13637 	which_font = ((attr_flags & BOLD) ? fBold : fNorm);
   13638 	if ((attr_flags & ATR_ITALIC) && UseItalicFont(screen))
   13639 	    getter = getItalicFont;
   13640 
   13641 	if_OPT_WIDE_CHARS(screen, {
   13642 	    if (isWide((int) base)) {
   13643 		which_font = ((attr_flags & BOLD) ? fWBold : fWide);
   13644 	    }
   13645 	});
   13646 
   13647 	which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font);
   13648 	if (which_Cgs != gcMAX) {
   13649 	    setCgsFont(xw, WhichVWin(screen),
   13650 		       (CgsEnum) which_Cgs,
   13651 		       getter(screen, which_font));
   13652 	    getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen))
   13653 		      ? getItalicFont
   13654 		      : getNormalFont);
   13655 	}
   13656     }
   13657 #endif
   13658 
   13659     currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection);
   13660 
   13661     TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n",
   13662 	   screen->cursorp.row, screen->cursorp.col));
   13663 
   13664     x = LineCursorX(screen, ld, cursor_col);
   13665     y = CursorY(screen, screen->cursorp.row);
   13666 
   13667     /* *INDENT-EQLS* */
   13668     params.xw          = xw;
   13669     params.attr_flags  = (flags & DRAWX_MASK);
   13670     params.draw_flags  = 0;
   13671     params.this_chrset = LineCharSet(screen, ld);
   13672     params.real_chrset = CSET_SWL;
   13673     params.on_wide     = 0;
   13674 
   13675     drawXtermText(&params,
   13676 		  currentGC, x, y,
   13677 		  &base, 1);
   13678 
   13679 #if OPT_WIDE_CHARS
   13680     if_OPT_WIDE_CHARS(screen, {
   13681 	size_t off;
   13682 
   13683 	/* *INDENT-EQLS* */
   13684 	params.draw_flags  = NOBACKGROUND;
   13685 	params.on_wide     = isWide((int) base);
   13686 
   13687 	for_each_combData(off, ld) {
   13688 	    if (!(ld->combData[off][my_col]))
   13689 		break;
   13690 	    drawXtermText(&params,
   13691 			  currentGC, x, y,
   13692 			  ld->combData[off] + my_col, 1);
   13693 	}
   13694     });
   13695 #endif
   13696     screen->cursor_state = OFF;
   13697 
   13698 #if OPT_WIDE_ATTRS
   13699     if (which_Cgs != gcMAX) {
   13700 	setCgsFont(xw, WhichVWin(screen),
   13701 		   (CgsEnum) which_Cgs,
   13702 		   getter(screen, which_font));
   13703     }
   13704 #endif
   13705     resetXtermGC(xw, flags, in_selection);
   13706 
   13707     refresh_displayed_graphics(xw,
   13708 			       screen->cursorp.col,
   13709 			       screen->cursorp.row,
   13710 			       1, 1);
   13711 
   13712     return;
   13713 }
   13714 
   13715 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
   13716 static void
   13717 StartBlinking(XtermWidget xw)
   13718 {
   13719     TScreen *screen = TScreenOf(xw);
   13720 
   13721     if (screen->blink_timer == 0) {
   13722 	unsigned long interval = (unsigned long) ((screen->cursor_state == ON)
   13723 						  ? screen->blink_on
   13724 						  : screen->blink_off);
   13725 	if (interval == 0)	/* wow! */
   13726 	    interval = 1;	/* let's humor him anyway */
   13727 	screen->blink_timer = XtAppAddTimeOut(app_con,
   13728 					      interval,
   13729 					      HandleBlinking,
   13730 					      xw);
   13731     }
   13732 }
   13733 
   13734 static void
   13735 StopBlinking(XtermWidget xw)
   13736 {
   13737     TScreen *screen = TScreenOf(xw);
   13738 
   13739     if (screen->blink_timer) {
   13740 	XtRemoveTimeOut(screen->blink_timer);
   13741 	screen->blink_timer = 0;
   13742 	reallyStopBlinking(xw);
   13743     } else {
   13744 	screen->blink_timer = 0;
   13745     }
   13746 }
   13747 
   13748 #if OPT_BLINK_TEXT
   13749 Bool
   13750 LineHasBlinking(TScreen *screen, CLineData *ld)
   13751 {
   13752     Bool result = False;
   13753     if (ld != NULL) {
   13754 	int col;
   13755 
   13756 	for (col = 0; col < MaxCols(screen); ++col) {
   13757 	    if (ld->attribs[col] & BLINK) {
   13758 		result = True;
   13759 		break;
   13760 	    }
   13761 	}
   13762     }
   13763     return result;
   13764 }
   13765 #endif
   13766 
   13767 /*
   13768  * Blink the cursor by alternately showing/hiding cursor.  We leave the timer
   13769  * running all the time (even though that's a little inefficient) to make the
   13770  * logic simple.
   13771  */
   13772 static void
   13773 HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED)
   13774 {
   13775     XtermWidget xw = (XtermWidget) closure;
   13776     TScreen *screen = TScreenOf(xw);
   13777     Bool resume = False;
   13778 
   13779     screen->blink_timer = 0;
   13780     screen->blink_state = !screen->blink_state;
   13781 
   13782 #if OPT_BLINK_CURS
   13783     if (DoStartBlinking(screen)) {
   13784 	if (screen->cursor_state == ON) {
   13785 	    if (screen->select || screen->always_highlight) {
   13786 		HideCursor(xw);
   13787 		if (screen->cursor_state == OFF)
   13788 		    screen->cursor_state = BLINKED_OFF;
   13789 	    }
   13790 	} else if (screen->cursor_state == BLINKED_OFF) {
   13791 	    screen->cursor_state = OFF;
   13792 	    ShowCursor(xw);
   13793 	    if (screen->cursor_state == OFF)
   13794 		screen->cursor_state = BLINKED_OFF;
   13795 	}
   13796 	resume = True;
   13797     }
   13798 #endif
   13799 
   13800 #if OPT_BLINK_TEXT
   13801     /*
   13802      * Inspect the lines on the current screen to see if any have the BLINK flag
   13803      * associated with them.  Prune off any that have had the corresponding
   13804      * cells reset.  If any are left, repaint those lines with ScrnRefresh().
   13805      */
   13806     if (!(screen->blink_as_bold)) {
   13807 	int row;
   13808 	int start_row = LastRowNumber(screen);
   13809 	int first_row = start_row;
   13810 	int last_row = -1;
   13811 
   13812 	for (row = start_row; row >= 0; row--) {
   13813 	    LineData *ld = getLineData(screen, ROW2INX(screen, row));
   13814 
   13815 	    if (ld != NULL && LineTstBlinked(ld)) {
   13816 		if (LineHasBlinking(screen, ld)) {
   13817 		    resume = True;
   13818 		    if (row > last_row)
   13819 			last_row = row;
   13820 		    if (row < first_row)
   13821 			first_row = row;
   13822 		} else {
   13823 		    LineClrBlinked(ld);
   13824 		}
   13825 	    }
   13826 	}
   13827 	/*
   13828 	 * FIXME: this could be a little more efficient, e.g,. by limiting the
   13829 	 * columns which are updated.
   13830 	 */
   13831 	if (first_row <= last_row) {
   13832 	    ScrnRefresh(xw,
   13833 			first_row,
   13834 			0,
   13835 			last_row + 1 - first_row,
   13836 			MaxCols(screen),
   13837 			True);
   13838 	}
   13839     }
   13840 #endif
   13841 
   13842     /*
   13843      * If either the cursor or text is blinking, restart the timer.
   13844      */
   13845     if (resume)
   13846 	StartBlinking(xw);
   13847 }
   13848 #endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */
   13849 
   13850 void
   13851 RestartBlinking(XtermWidget xw)
   13852 {
   13853 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
   13854     TScreen *screen = TScreenOf(xw);
   13855 
   13856     if (screen->blink_timer == 0) {
   13857 	Bool resume = False;
   13858 
   13859 #if OPT_BLINK_CURS
   13860 	if (DoStartBlinking(screen)) {
   13861 	    resume = True;
   13862 	}
   13863 #endif
   13864 #if OPT_BLINK_TEXT
   13865 	if (!resume) {
   13866 	    int row;
   13867 
   13868 	    for (row = screen->max_row; row >= 0; row--) {
   13869 		CLineData *ld = getLineData(screen, ROW2INX(screen, row));
   13870 
   13871 		if (ld != NULL && LineTstBlinked(ld)) {
   13872 		    if (LineHasBlinking(screen, ld)) {
   13873 			resume = True;
   13874 			break;
   13875 		    }
   13876 		}
   13877 	    }
   13878 	}
   13879 #endif
   13880 	if (resume)
   13881 	    StartBlinking(xw);
   13882     }
   13883 #else
   13884     (void) xw;
   13885 #endif
   13886 }
   13887 
   13888 /*
   13889  * Implement soft or hard (full) reset of the VTxxx emulation.  There are a
   13890  * couple of differences from real DEC VTxxx terminals (to avoid breaking
   13891  * applications which have come to rely on xterm doing this):
   13892  *
   13893  *	+ autowrap mode should be reset (instead it's reset to the resource
   13894  *	  default).
   13895  *	+ the popup menu offers a choice of resetting the savedLines, or not.
   13896  *	  (but the control sequence does this anyway).
   13897  */
   13898 static void
   13899 ReallyReset(XtermWidget xw, Bool full, Bool saved)
   13900 {
   13901     TScreen *screen = TScreenOf(xw);
   13902     IFlags saveflags = xw->flags;
   13903 
   13904     TRACE(("ReallyReset %s, %s\n",
   13905 	   full ? "hard" : "soft",
   13906 	   saved ? "clear savedLines" : "keep savedLines"));
   13907 
   13908     if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) {
   13909 	Bell(xw, XkbBI_MinorError, 0);
   13910 	return;
   13911     }
   13912 
   13913     if (saved) {
   13914 	screen->savedlines = 0;
   13915 	ScrollBarDrawThumb(xw, 0);
   13916     }
   13917 
   13918     /* make cursor visible */
   13919     screen->cursor_set = ON;
   13920     InitCursorShape(screen, screen);
   13921     xtermSetCursorBox(screen);
   13922 #if OPT_BLINK_CURS
   13923     screen->cursor_blink_esc = 0;
   13924     SetCursorBlink(xw, screen->cursor_blink_i);
   13925     TRACE(("cursor_shape:%d blinks:%d\n",
   13926 	   screen->cursor_shape,
   13927 	   screen->cursor_blink));
   13928 #endif
   13929 #if OPT_STATUS_LINE
   13930     if (screen->vtXX_level >= 2) {
   13931 	if (full)
   13932 	    handle_DECSSDT(xw, 0);	/* DEC STD 070, page 14-10, RIS */
   13933 	else
   13934 	    handle_DECSASD(xw, 0);	/* DEC STD 070, page 14-9, DECSTR */
   13935     }
   13936 #endif
   13937 
   13938     /* reset scrolling region */
   13939     resetMarginMode(xw);
   13940 
   13941     bitclr(&xw->flags, ORIGIN);
   13942 
   13943     if_OPT_ISO_COLORS(screen, {
   13944 	static char empty[1];
   13945 	reset_SGR_Colors(xw);
   13946 	if (ResetAnsiColorRequest(xw, empty, 0))
   13947 	    xtermRepaint(xw);
   13948     });
   13949 
   13950     /* Reset character-sets to initial state */
   13951     resetCharsets(screen);
   13952 
   13953     UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM));
   13954     if (xw->misc.appcursorDefault)
   13955 	xw->keyboard.flags |= MODE_DECCKM;
   13956     if (xw->misc.appkeypadDefault)
   13957 	xw->keyboard.flags |= MODE_DECKPAM;
   13958 
   13959 #if OPT_MOD_FKEYS
   13960     /* Reset modifier-resources to initial state */
   13961     xw->keyboard.modify_now = xw->keyboard.modify_1st;
   13962 #endif
   13963 #if OPT_DEC_RECTOPS
   13964     screen->checksum_ext = screen->checksum_ext0;
   13965 #endif
   13966 
   13967     /* Reset DECSCA */
   13968     bitclr(&xw->flags, PROTECTED);
   13969     screen->protected_mode = OFF_PROTECT;
   13970 
   13971     if (full) {			/* RIS */
   13972 	if (screen->bellOnReset)
   13973 	    Bell(xw, XkbBI_TerminalBell, 0);
   13974 
   13975 	reset_displayed_graphics(screen);
   13976 
   13977 	/* reset the mouse mode */
   13978 	screen->send_mouse_pos = MOUSE_OFF;
   13979 	screen->send_focus_pos = OFF;
   13980 	screen->extend_coords = 0;
   13981 	screen->waitingForTrackInfo = False;
   13982 	screen->eventMode = NORMAL;
   13983 
   13984 	xtermShowPointer(xw, True);
   13985 
   13986 	TabReset(xw->tabs);
   13987 	xw->keyboard.flags |= MODE_SRM;
   13988 
   13989 	guard_keyboard_type = False;
   13990 	screen->old_fkeys = screen->old_fkeys0;
   13991 	decode_keyboard_type(xw, &resource);
   13992 	update_keyboard_type();
   13993 
   13994 	UIntClr(xw->keyboard.flags, MODE_DECBKM);
   13995 #if OPT_INITIAL_ERASE
   13996 	if (xw->keyboard.reset_DECBKM == 1)
   13997 	    xw->keyboard.flags |= MODE_DECBKM;
   13998 	else if (xw->keyboard.reset_DECBKM == 2)
   13999 #endif
   14000 	    if (screen->backarrow_key)
   14001 		xw->keyboard.flags |= MODE_DECBKM;
   14002 	TRACE(("full reset DECBKM %s\n",
   14003 	       BtoS(xw->keyboard.flags & MODE_DECBKM)));
   14004 
   14005 #if OPT_SCROLL_LOCK
   14006 	xtermClearLEDs(screen);
   14007 #endif
   14008 	screen->title_modes = screen->title_modes0;
   14009 	screen->pointer_mode = screen->pointer_mode0;
   14010 #if OPT_SIXEL_GRAPHICS
   14011 	if (screen->sixel_scrolling)
   14012 	    UIntClr(xw->keyboard.flags, MODE_DECSDM);
   14013 	else
   14014 	    UIntSet(xw->keyboard.flags, MODE_DECSDM);
   14015 	TRACE(("full reset DECSDM to %s (resource default is %s)\n",
   14016 	       BtoS(xw->keyboard.flags & MODE_DECSDM),
   14017 	       BtoS(!screen->sixel_scrolling)));
   14018 #endif
   14019 
   14020 #if OPT_GRAPHICS
   14021 	screen->privatecolorregisters = screen->privatecolorregisters0;
   14022 	TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s\n",
   14023 	       BtoS(screen->privatecolorregisters)));
   14024 	update_privatecolorregisters();
   14025 #endif
   14026 
   14027 #if OPT_SIXEL_GRAPHICS
   14028 	screen->sixel_scrolls_right = screen->sixel_scrolls_right0;
   14029 	TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s\n",
   14030 	       BtoS(screen->sixel_scrolls_right)));
   14031 #endif
   14032 
   14033 	update_appcursor();
   14034 	update_appkeypad();
   14035 	update_decbkm();
   14036 	update_decsdm();
   14037 	show_8bit_control(False);
   14038 	reset_decudk(xw);
   14039 
   14040 	FromAlternate(xw, True);
   14041 	ClearScreen(xw);
   14042 	screen->cursor_state = OFF;
   14043 
   14044 	if (xw->flags & REVERSE_VIDEO)
   14045 	    ReverseVideo(xw);
   14046 	ResetItalics(xw);
   14047 	xw->flags = xw->initflags;
   14048 
   14049 	update_reversevideo();
   14050 	update_autowrap();
   14051 	update_reversewrap();
   14052 	update_autolinefeed();
   14053 
   14054 	screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL));
   14055 	update_jumpscroll();
   14056 
   14057 #if OPT_DEC_RECTOPS
   14058 	screen->cur_decsace = 0;
   14059 #endif
   14060 #if OPT_PASTE64 || OPT_READLINE
   14061 	screen->paste_brackets = OFF;
   14062 #endif
   14063 #if OPT_READLINE
   14064 	screen->click1_moves = OFF;
   14065 	screen->paste_moves = OFF;
   14066 	screen->dclick3_deletes = OFF;
   14067 	screen->paste_quotes = OFF;
   14068 	screen->paste_literal_nl = OFF;
   14069 #endif /* OPT_READLINE */
   14070 
   14071 	if (screen->c132 && (saveflags & IN132COLUMNS)) {
   14072 	    TRACE(("Making resize-request to restore 80-columns %dx%d\n",
   14073 		   MaxRows(screen), MaxCols(screen)));
   14074 	    RequestResize(xw, MaxRows(screen), 80, True);
   14075 	    repairSizeHints();
   14076 	    XSync(screen->display, False);	/* synchronize */
   14077 	    if (xtermAppPending())
   14078 		xevents(xw);
   14079 	}
   14080 
   14081 	CursorSet(screen, 0, 0, xw->flags);
   14082 	CursorSave(xw);
   14083     } else {			/* DECSTR */
   14084 	bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP | REVERSEWRAP2);
   14085 	bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE);
   14086 	ResetItalics(xw);
   14087 	if_OPT_ISO_COLORS(screen, {
   14088 	    reset_SGR_Colors(xw);
   14089 	});
   14090 	update_appcursor();
   14091 	update_autowrap();
   14092 	update_reversewrap();
   14093 
   14094 	CursorSave(xw);
   14095 	screen->sc[screen->whichBuf].row =
   14096 	    screen->sc[screen->whichBuf].col = 0;
   14097     }
   14098 }
   14099 
   14100 void
   14101 VTReset(XtermWidget xw, Bool full, Bool saved)
   14102 {
   14103     ReallyReset(xw, full, saved);
   14104 
   14105     FreeAndNull(myState.string_area);
   14106     FreeAndNull(myState.print_area);
   14107 
   14108     longjmp(vtjmpbuf, 1);	/* force ground state in parser */
   14109 }
   14110 
   14111 typedef enum {
   14112     ccLO,
   14113     ccDASH,
   14114     ccHI,
   14115     ccCOLON,
   14116     ccID,
   14117     ccCOMMA
   14118 } CCLASS;
   14119 
   14120 /*
   14121  * set_character_class - takes a string of the form
   14122  *
   14123  *   low[-high][:id][,low[-high][:id][...]]
   14124  *
   14125  * and sets the indicated ranges to the indicated values.
   14126  */
   14127 static int
   14128 set_character_class(char *s)
   14129 {
   14130 #define FMT "%s in range string \"%s\" (position %d)\n"
   14131 
   14132     TRACE(("set_character_class(%s) " TRACE_L "\n", NonNull(s)));
   14133     if (IsEmpty(s)) {
   14134 	TRACE((TRACE_R " ERR set_character_class\n"));
   14135 	return -1;
   14136     } else {
   14137 	CCLASS state = ccLO;
   14138 	int arg[3];
   14139 	int i;
   14140 	int len = (int) strlen(s);
   14141 
   14142 	arg[0] =
   14143 	    arg[1] =
   14144 	    arg[2] = -1;
   14145 
   14146 	for (i = 0; i < len; ++i) {
   14147 	    int ch = CharOf(s[i]);
   14148 	    char *t = NULL;
   14149 	    long value = 0;
   14150 
   14151 	    if (isspace(ch))
   14152 		continue;
   14153 
   14154 	    switch (state) {
   14155 	    case ccLO:
   14156 	    case ccHI:
   14157 	    case ccID:
   14158 		if (!isdigit(ch)) {
   14159 		    xtermWarning(FMT, "missing number", s, i);
   14160 		    TRACE((TRACE_R " ERR set_character_class\n"));
   14161 		    return (-1);
   14162 		}
   14163 		value = strtol(s + i, &t, 0);
   14164 		i = (int) (t - s - 1);
   14165 		break;
   14166 	    case ccDASH:
   14167 	    case ccCOLON:
   14168 	    case ccCOMMA:
   14169 		break;
   14170 	    }
   14171 
   14172 	    switch (state) {
   14173 	    case ccLO:
   14174 		arg[0] =
   14175 		    arg[1] = (int) value;
   14176 		arg[2] = -1;
   14177 		state = ccDASH;
   14178 		break;
   14179 
   14180 	    case ccDASH:
   14181 		if (ch == '-') {
   14182 		    state = ccHI;
   14183 		} else {
   14184 		    goto parse_class;
   14185 		}
   14186 		break;
   14187 
   14188 	    case ccHI:
   14189 		arg[1] = (int) value;
   14190 		state = ccCOLON;
   14191 		break;
   14192 
   14193 	      parse_class:
   14194 		/* FALLTHRU */
   14195 	    case ccCOLON:
   14196 		if (ch == ':') {
   14197 		    state = ccID;
   14198 		} else if (ch == ',') {
   14199 		    goto apply_class;
   14200 		} else {
   14201 		    xtermWarning(FMT, "unexpected character", s, i);
   14202 		    TRACE((TRACE_R " ERR set_character_class\n"));
   14203 		    return (-1);
   14204 		}
   14205 		break;
   14206 
   14207 	    case ccID:
   14208 		arg[2] = (int) value;
   14209 		state = ccCOMMA;
   14210 		break;
   14211 
   14212 	      apply_class:
   14213 		/* FALLTHRU */
   14214 	    case ccCOMMA:
   14215 		if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
   14216 		    xtermWarning(FMT, "bad range", s, i);
   14217 		    TRACE((TRACE_R " ERR set_character_class\n"));
   14218 		    return -1;
   14219 		}
   14220 		state = ccLO;
   14221 		break;
   14222 	    }
   14223 	}
   14224 	if (state >= ccDASH) {
   14225 	    if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
   14226 		xtermWarning(FMT, "bad range", s, i);
   14227 		TRACE((TRACE_R " ERR set_character_class\n"));
   14228 		return -1;
   14229 	    }
   14230 	}
   14231     }
   14232 
   14233     TRACE((TRACE_R " OK set_character_class\n"));
   14234     return (0);
   14235 #undef FMT
   14236 }
   14237 
   14238 void
   14239 getKeymapResources(Widget w,
   14240 		   const char *mapName,
   14241 		   const char *mapClass,
   14242 		   const char *type,
   14243 		   void *result,
   14244 		   size_t size)
   14245 {
   14246     XtResource key_resources[1];
   14247     key_resources[0].resource_name = XtNtranslations;
   14248     key_resources[0].resource_class = XtCTranslations;
   14249     key_resources[0].resource_type = (char *) type;
   14250     key_resources[0].resource_size = (Cardinal) size;
   14251     key_resources[0].resource_offset = 0;
   14252     key_resources[0].default_type = key_resources[0].resource_type;
   14253     key_resources[0].default_addr = NULL;
   14254     XtGetSubresources(w, (XtPointer) result, mapName, mapClass,
   14255 		      key_resources, (Cardinal) 1, NULL, (Cardinal) 0);
   14256 }
   14257 
   14258 /* ARGSUSED */
   14259 static void
   14260 HandleKeymapChange(Widget w,
   14261 		   XEvent *event GCC_UNUSED,
   14262 		   String *params,
   14263 		   Cardinal *param_count)
   14264 {
   14265     static XtTranslations keymap, original;
   14266 
   14267     TRACE(("HandleKeymapChange(%#lx, %s)\n",
   14268 	   (unsigned long) w,
   14269 	   (*param_count
   14270 	    ? params[0]
   14271 	    : "missing")));
   14272 
   14273     if (*param_count != 1)
   14274 	return;
   14275 
   14276     if (original == NULL) {
   14277 	TRACE(("...saving original keymap-translations\n"));
   14278 	original = w->core.tm.translations;
   14279     }
   14280 
   14281     if (strcmp(params[0], "None") == 0) {
   14282 	TRACE(("...restoring original keymap-translations\n"));
   14283 	XtOverrideTranslations(w, original);
   14284     } else {
   14285 	char mapName[1000];
   14286 	char mapClass[1000];
   14287 	char *pmapName;
   14288 	char *pmapClass;
   14289 	size_t len;
   14290 
   14291 	len = strlen(params[0]) + 7;
   14292 
   14293 	pmapName = (char *) MyStackAlloc(len, mapName);
   14294 	pmapClass = (char *) MyStackAlloc(len, mapClass);
   14295 	if (pmapName == NULL
   14296 	    || pmapClass == NULL) {
   14297 	    SysError(ERROR_KMMALLOC1);
   14298 	} else {
   14299 
   14300 	    (void) sprintf(pmapName, "%sKeymap", params[0]);
   14301 	    (void) strcpy(pmapClass, pmapName);
   14302 	    if (islower(CharOf(pmapClass[0])))
   14303 		pmapClass[0] = x_toupper(pmapClass[0]);
   14304 	    getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable,
   14305 			       &keymap, sizeof(keymap));
   14306 	    if (keymap != NULL) {
   14307 		TRACE(("...applying keymap \"%s\"\n", pmapName));
   14308 		XtOverrideTranslations(w, keymap);
   14309 	    } else {
   14310 		TRACE(("...found no match for keymap \"%s\"\n", pmapName));
   14311 	    }
   14312 
   14313 	    MyStackFree(pmapName, mapName);
   14314 	    MyStackFree(pmapClass, mapClass);
   14315 	}
   14316     }
   14317 }
   14318 
   14319 /* ARGSUSED */
   14320 static void
   14321 HandleBell(Widget w GCC_UNUSED,
   14322 	   XEvent *event GCC_UNUSED,
   14323 	   String *params,	/* [0] = volume */
   14324 	   Cardinal *param_count)	/* 0 or 1 */
   14325 {
   14326     int percent = (*param_count) ? atoi(params[0]) : 0;
   14327 
   14328     Bell(term, XkbBI_TerminalBell, percent);
   14329 }
   14330 
   14331 /* ARGSUSED */
   14332 static void
   14333 HandleVisualBell(Widget w GCC_UNUSED,
   14334 		 XEvent *event GCC_UNUSED,
   14335 		 String *params GCC_UNUSED,
   14336 		 Cardinal *param_count GCC_UNUSED)
   14337 {
   14338     VisualBell();
   14339 }
   14340 
   14341 /* ARGSUSED */
   14342 static void
   14343 HandleIgnore(Widget w,
   14344 	     XEvent *event,
   14345 	     String *params GCC_UNUSED,
   14346 	     Cardinal *param_count GCC_UNUSED)
   14347 {
   14348     XtermWidget xw;
   14349 
   14350     TRACE(("Handle ignore for %p %s\n",
   14351 	   (void *) w, visibleEventType(event->type)));
   14352     if ((xw = getXtermWidget(w)) != NULL) {
   14353 	/* do nothing, but check for funny escape sequences */
   14354 	switch (event->type) {
   14355 	case ButtonPress:
   14356 	case ButtonRelease:
   14357 	case MotionNotify:
   14358 	    (void) SendMousePosition(xw, event);
   14359 	    break;
   14360 	}
   14361     }
   14362 }
   14363 
   14364 /* ARGSUSED */
   14365 static void
   14366 DoSetSelectedFont(Widget w,
   14367 		  XtPointer client_data GCC_UNUSED,
   14368 		  Atom *selection GCC_UNUSED,
   14369 		  Atom *type,
   14370 		  XtPointer value,
   14371 		  unsigned long *length,
   14372 		  int *format)
   14373 {
   14374     XtermWidget xw = getXtermWidget(w);
   14375 
   14376     if (xw == NULL) {
   14377 	xtermWarning("unexpected widget in DoSetSelectedFont\n");
   14378     } else if (*type != XA_STRING || *format != 8) {
   14379 	Bell(xw, XkbBI_MinorError, 0);
   14380     } else {
   14381 	Boolean failed = False;
   14382 	char *save = TScreenOf(xw)->SelectFontName();
   14383 	char *val;
   14384 	char *test;
   14385 	unsigned len = (unsigned) *length;
   14386 	unsigned tst;
   14387 
   14388 	/*
   14389 	 * Some versions of X deliver null-terminated selections, some do not.
   14390 	 */
   14391 	for (tst = 0; tst < len; ++tst) {
   14392 	    if (((char *) value)[tst] == '\0') {
   14393 		len = tst;
   14394 		break;
   14395 	    }
   14396 	}
   14397 
   14398 	if (len > 0 && (val = TypeMallocN(char, len + 1)) != NULL) {
   14399 	    char *used;
   14400 
   14401 	    memcpy(val, value, (size_t) len);
   14402 	    val[len] = '\0';
   14403 	    used = x_strtrim(val);
   14404 	    TRACE(("DoSetSelectedFont(%s)\n", used));
   14405 	    /* Do some sanity checking to avoid sending a long selection
   14406 	       back to the server in an OpenFont that is unlikely to succeed.
   14407 	       XLFD allows up to 255 characters and no control characters;
   14408 	       we are a little more liberal here. */
   14409 	    if (len < 1000
   14410 		&& used != NULL
   14411 		&& !strchr(used, '\n')
   14412 		&& (test = x_strdup(used)) != NULL) {
   14413 		TScreenOf(xw)->SelectFontName() = test;
   14414 		if (!xtermLoadFont(xw,
   14415 				   xtermFontName(used),
   14416 				   True,
   14417 				   fontMenu_fontsel)) {
   14418 		    failed = True;
   14419 		    free(test);
   14420 		    TScreenOf(xw)->SelectFontName() = save;
   14421 		}
   14422 	    } else {
   14423 		failed = True;
   14424 	    }
   14425 	    if (failed) {
   14426 		Bell(xw, XkbBI_MinorError, 0);
   14427 	    }
   14428 	    free(used);
   14429 	    free(val);
   14430 	}
   14431     }
   14432 }
   14433 
   14434 Bool
   14435 FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe)
   14436 {
   14437     TScreen *screen = TScreenOf(xw);
   14438     static AtomPtr *atoms;
   14439     static unsigned int atomCount = 0;
   14440     AtomPtr *pAtom;
   14441     unsigned a;
   14442     Atom target;
   14443 
   14444     if (!atom_name)
   14445 	atom_name = ((screen->mappedSelect && atomCount)
   14446 		     ? screen->mappedSelect[0]
   14447 		     : "PRIMARY");
   14448     TRACE(("FindFontSelection(%s)\n", atom_name));
   14449 
   14450     for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
   14451 	if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) {
   14452 	    TRACE(("...found atom %d:%s\n", a + 1, atom_name));
   14453 	    break;
   14454 	}
   14455     }
   14456     if (!a) {
   14457 	atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1);
   14458 	*(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name);
   14459 	++atomCount;
   14460 	TRACE(("...added atom %d:%s\n", atomCount, atom_name));
   14461     }
   14462 
   14463     target = XmuInternAtom(XtDisplay(xw), *pAtom);
   14464     if (justprobe) {
   14465 	screen->SelectFontName() =
   14466 	    XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : NULL;
   14467 	TRACE(("...selected fontname '%s'\n",
   14468 	       NonNull(screen->SelectFontName())));
   14469     } else {
   14470 	XtGetSelectionValue((Widget) xw, target, XA_STRING,
   14471 			    DoSetSelectedFont, NULL,
   14472 			    XtLastTimestampProcessed(XtDisplay(xw)));
   14473     }
   14474     return (screen->SelectFontName() != NULL) ? True : False;
   14475 }
   14476 
   14477 Bool
   14478 set_cursor_gcs(XtermWidget xw)
   14479 {
   14480     TScreen *screen = TScreenOf(xw);
   14481     VTwin *win = WhichVWin(screen);
   14482 
   14483     Pixel cc = T_COLOR(screen, TEXT_CURSOR);
   14484     Pixel fg = T_COLOR(screen, TEXT_FG);
   14485     Pixel bg = T_COLOR(screen, TEXT_BG);
   14486     Bool changed = False;
   14487 
   14488     /*
   14489      * Let's see, there are three things that have "color":
   14490      *
   14491      *     background
   14492      *     text
   14493      *     cursorblock
   14494      *
   14495      * And, there are four situations when drawing a cursor, if we decide
   14496      * that we like have a solid block of cursor color with the letter
   14497      * that it is highlighting shown in the background color to make it
   14498      * stand out:
   14499      *
   14500      *     selected window, normal video - background on cursor
   14501      *     selected window, reverse video - foreground on cursor
   14502      *     unselected window, normal video - foreground on background
   14503      *     unselected window, reverse video - background on foreground
   14504      *
   14505      * Since the last two are really just normalGC and reverseGC, we only
   14506      * need two new GC's.  Under monochrome, we get the same effect as
   14507      * above by setting cursor color to foreground.
   14508      */
   14509 
   14510     TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg));
   14511     if (win != NULL && (cc != bg)) {
   14512 	Pixel xx = ((fg == cc) ? bg : cc);
   14513 
   14514 	/* set the fonts to the current one */
   14515 	setCgsFont(xw, win, gcVTcursNormal, NULL);
   14516 	setCgsFont(xw, win, gcVTcursFilled, NULL);
   14517 	setCgsFont(xw, win, gcVTcursReverse, NULL);
   14518 	setCgsFont(xw, win, gcVTcursOutline, NULL);
   14519 
   14520 	/* we have a colored cursor */
   14521 	setCgsFore(xw, win, gcVTcursNormal, fg);
   14522 	setCgsBack(xw, win, gcVTcursNormal, xx);
   14523 
   14524 	setCgsFore(xw, win, gcVTcursFilled, xx);
   14525 	setCgsBack(xw, win, gcVTcursFilled, fg);
   14526 
   14527 	if (screen->always_highlight) {
   14528 	    /* both GC's use the same color */
   14529 	    setCgsFore(xw, win, gcVTcursReverse, bg);
   14530 	    setCgsBack(xw, win, gcVTcursReverse, cc);
   14531 	} else {
   14532 	    setCgsFore(xw, win, gcVTcursReverse, bg);
   14533 	    setCgsBack(xw, win, gcVTcursReverse, cc);
   14534 	}
   14535 	set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc);
   14536 	changed = True;
   14537 	FreeMarkGCs(xw);
   14538     }
   14539 
   14540     if (changed) {
   14541 	TRACE(("...set_cursor_gcs - done\n"));
   14542     }
   14543     return changed;
   14544 }
   14545 
   14546 /*
   14547  * Build up the default translations string, allowing the user to suppress
   14548  * some of the features.
   14549  */
   14550 void
   14551 VTInitTranslations(void)
   14552 {
   14553     /* *INDENT-OFF* */
   14554     static struct {
   14555 	Boolean wanted;
   14556 	const char *name;
   14557 	const char *value;
   14558     } table[] = {
   14559 #define DATA(name,value) { False, name, value }
   14560 	DATA("select",
   14561 "\
   14562          Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\
   14563          Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\
   14564 "
   14565 	),
   14566 #if OPT_MAXIMIZE
   14567 	DATA("fullscreen",
   14568 "\
   14569                  Alt <Key>Return:fullscreen() \n\
   14570 "
   14571 	),
   14572 #endif
   14573 #if OPT_SCROLL_LOCK
   14574 	DATA("scroll-lock",
   14575 "\
   14576         <KeyRelease> Scroll_Lock:scroll-lock() \n\
   14577 "
   14578 	),
   14579 #endif
   14580 #if OPT_SHIFT_FONTS
   14581 	DATA("shift-fonts",
   14582 "\
   14583     Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\
   14584     Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\
   14585     Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\
   14586 "
   14587 	),
   14588 #endif
   14589 	DATA("paging",
   14590 "\
   14591           Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
   14592            Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
   14593 "
   14594 	),
   14595 	/* This must be the last set mentioning "KeyPress" */
   14596 	DATA("keypress",
   14597 "\
   14598                 ~Meta <KeyPress>:insert-seven-bit() \n\
   14599                  Meta <KeyPress>:insert-eight-bit() \n\
   14600 "
   14601 	),
   14602 	DATA("popup-menu",
   14603 "\
   14604                 !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
   14605            !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
   14606  !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\
   14607      ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
   14608                 !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
   14609            !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
   14610  !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\
   14611      ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
   14612                 !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
   14613            !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
   14614  !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\
   14615      ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
   14616 "
   14617 	),
   14618 	/* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */
   14619 	DATA("reset",
   14620 "\
   14621                  Meta <Btn2Down>:clear-saved-lines() \n\
   14622 "
   14623 	),
   14624 	DATA("select",
   14625 "\
   14626                 ~Meta <Btn1Down>:select-start() \n\
   14627               ~Meta <Btn1Motion>:select-extend() \n\
   14628           ~Ctrl ~Meta <Btn2Down>:ignore() \n\
   14629             ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\
   14630           ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
   14631               ~Meta <Btn3Motion>:select-extend() \n\
   14632                          <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\
   14633 "
   14634 	),
   14635 #if OPT_BLOCK_SELECT
   14636 	DATA("block-select",
   14637 "\
   14638                  Meta <Btn1Down>:select-start(block) \n\
   14639 "
   14640 	),
   14641 #endif
   14642 	DATA("wheel-mouse",
   14643 "\
   14644                  Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
   14645             Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
   14646   Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
   14647        @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
   14648                       <Btn4Down>:scroll-back(5,line,m)     \n\
   14649                  Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
   14650             Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
   14651   Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
   14652        @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
   14653                       <Btn5Down>:scroll-forw(5,line,m)     \n\
   14654 "
   14655 	),
   14656 	DATA("pointer",
   14657 "\
   14658                      <BtnMotion>:pointer-motion() \n\
   14659                        <BtnDown>:pointer-button() \n\
   14660                          <BtnUp>:pointer-button() \n\
   14661 "
   14662 	),
   14663 	DATA("default",
   14664 "\
   14665                          <BtnUp>:ignore() \n\
   14666 "
   14667 	)
   14668     };
   14669 #undef DATA
   14670     /* *INDENT-ON* */
   14671 
   14672     char *result = NULL;
   14673 
   14674     int pass;
   14675     Cardinal item;
   14676 
   14677     TRACE(("VTInitTranslations\n"));
   14678     for (item = 0; item < XtNumber(table); ++item) {
   14679 	table[item].wanted = True;
   14680     }
   14681 #if OPT_MAXIMIZE
   14682     /*
   14683      * As a special case, allow for disabling the alt-enter translation if
   14684      * the resource settings prevent fullscreen from being used.  We would
   14685      * do the same for scroll-lock and shift-fonts if they were application
   14686      * resources too, rather than in the widget.
   14687      */
   14688     if (resource.fullscreen == esNever) {
   14689 	for (item = 0; item < XtNumber(table); ++item) {
   14690 	    if (!strcmp(table[item].name, "fullscreen")) {
   14691 		table[item].wanted = False;
   14692 		TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
   14693 	    }
   14694 	}
   14695     }
   14696 #endif
   14697     if (!IsEmpty(resource.omitTranslation)) {
   14698 	char *value;
   14699 	const char *source = resource.omitTranslation;
   14700 
   14701 	while (*source != '\0' && (value = ParseList(&source)) != NULL) {
   14702 	    size_t len = strlen(value);
   14703 
   14704 	    TRACE(("parsed:%s\n", value));
   14705 	    for (item = 0; item < XtNumber(table); ++item) {
   14706 		if (strlen(table[item].name) >= len
   14707 		    && x_strncasecmp(table[item].name,
   14708 				     value,
   14709 				     (unsigned) len) == 0) {
   14710 		    table[item].wanted = False;
   14711 		    TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
   14712 		    /* continue: "select", for instance is two chunks */
   14713 		}
   14714 	    }
   14715 	    free(value);
   14716 	}
   14717     }
   14718 
   14719     for (pass = 0; pass < 2; ++pass) {
   14720 	size_t needed = 0;
   14721 	for (item = 0; item < XtNumber(table); ++item) {
   14722 	    if (table[item].wanted) {
   14723 		if (pass) {
   14724 		    strcat(result, table[item].value);
   14725 		} else {
   14726 		    needed += strlen(table[item].value) + 1;
   14727 		}
   14728 	    }
   14729 	}
   14730 	if (!pass) {
   14731 	    result = XtMalloc((Cardinal) needed);
   14732 	    *result = '\0';
   14733 	}
   14734     }
   14735 
   14736     TRACE(("result:\n%s\n", result));
   14737 
   14738     defaultTranslations = result;
   14739     free((void *) xtermClassRec.core_class.tm_table);
   14740     xtermClassRec.core_class.tm_table = result;
   14741 }
   14742 
   14743 #ifdef NO_LEAKS
   14744 void
   14745 noleaks_charproc(void)
   14746 {
   14747     free(v_buffer);
   14748 }
   14749 #endif
   14750