charproc.c revision 913cc679
1/* $XTermId: charproc.c,v 1.1492 2017/06/19 08:34:54 tom Exp $ */
2
3/*
4 * Copyright 1999-2016,2017 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  The Open Group
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 Open Group 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 Open Group.
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/cursorfont.h>
87#include <X11/Xmu/Atoms.h>
88#include <X11/Xmu/CharSet.h>
89#include <X11/Xmu/Converters.h>
90
91#if OPT_INPUT_METHOD
92
93#if defined(HAVE_LIB_XAW)
94#include <X11/Xaw/XawImP.h>
95#elif defined(HAVE_LIB_XAW3D)
96#include <X11/Xaw3d/XawImP.h>
97#elif defined(HAVE_LIB_XAW3DXFT)
98#include <X11/Xaw3dxft/XawImP.h>
99#elif defined(HAVE_LIB_NEXTAW)
100#include <X11/neXtaw/XawImP.h>
101#elif defined(HAVE_LIB_XAWPLUS)
102#include <X11/XawPlus/XawImP.h>
103#endif
104
105#endif
106
107#if OPT_DOUBLE_BUFFER
108#include <X11/extensions/Xdbe.h>
109#endif
110
111#if OPT_WIDE_CHARS
112#include <xutf8.h>
113#include <wcwidth.h>
114#include <precompose.h>
115#ifdef HAVE_LANGINFO_CODESET
116#include <langinfo.h>
117#endif
118#endif
119
120#if OPT_INPUT_METHOD
121#include <X11/Xlocale.h>
122#endif
123
124#include <stdio.h>
125#include <ctype.h>
126#include <assert.h>
127
128#if defined(HAVE_SCHED_YIELD)
129#include <sched.h>
130#endif
131
132#include <VTparse.h>
133#include <data.h>
134#include <error.h>
135#include <menu.h>
136#include <main.h>
137#include <fontutils.h>
138#include <charclass.h>
139#include <xstrings.h>
140#include <graphics.h>
141
142typedef int (*BitFunc) (unsigned * /* p */ ,
143			unsigned /* mask */ );
144
145static IChar doinput(void);
146static int set_character_class(char * /*s */ );
147static void FromAlternate(XtermWidget /* xw */ );
148static void ReallyReset(XtermWidget /* xw */ ,
149			Bool /* full */ ,
150			Bool /* saved */ );
151static void RequestResize(XtermWidget /* xw */ ,
152			  int /* rows */ ,
153			  int /* cols */ ,
154			  Bool /* text */ );
155static void SwitchBufs(XtermWidget /* xw */ ,
156		       int /* toBuf */ ,
157		       Bool /* clearFirst */ );
158static void ToAlternate(XtermWidget /* xw */ ,
159			Bool /* clearFirst */ );
160static void ansi_modes(XtermWidget termw,
161		       BitFunc /* func */ );
162static int bitclr(unsigned *p, unsigned mask);
163static int bitcpy(unsigned *p, unsigned q, unsigned mask);
164static int bitset(unsigned *p, unsigned mask);
165static void dpmodes(XtermWidget /* xw */ ,
166		    BitFunc /* func */ );
167static void restoremodes(XtermWidget /* xw */ );
168static void savemodes(XtermWidget /* xw */ );
169static void window_ops(XtermWidget /* xw */ );
170
171#define DoStartBlinking(s) ((s)->cursor_blink ^ (s)->cursor_blink_esc)
172
173#if OPT_BLINK_CURS || OPT_BLINK_TEXT
174#define UpdateCursorBlink(screen) SetCursorBlink(screen, screen->cursor_blink)
175static void SetCursorBlink(TScreen * /* screen */ ,
176			   Bool /* enable */ );
177static void HandleBlinking(XtPointer /* closure */ ,
178			   XtIntervalId * /* id */ );
179static void StartBlinking(TScreen * /* screen */ );
180static void StopBlinking(TScreen * /* screen */ );
181#else
182#define StartBlinking(screen)	/* nothing */
183#define StopBlinking(screen)	/* nothing */
184#endif
185
186#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
187static void PreeditPosition(XtermWidget /* xw */ );
188#endif
189
190#define	DEFAULT		-1
191#define BELLSUPPRESSMSEC 200
192
193static ANSI reply;
194static PARAMS parms;
195
196#define nparam parms.count
197
198#define InitParams()  parms.count = parms.is_sub[0] = parms.has_subparams = 0
199#define GetParam(n)   parms.params[(n)]
200#define SetParam(n,v) parms.params[(n)] = v
201#define ParamPair(n)  nparam - (n), parms.params + (n)
202#define ParamsDone()  InitParams()
203
204static jmp_buf vtjmpbuf;
205
206/* event handlers */
207static void HandleBell PROTO_XT_ACTIONS_ARGS;
208static void HandleIgnore PROTO_XT_ACTIONS_ARGS;
209static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS;
210static void HandleVisualBell PROTO_XT_ACTIONS_ARGS;
211#if HANDLE_STRUCT_NOTIFY
212static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS;
213#endif
214
215/*
216 * NOTE: VTInitialize zeros out the entire ".screen" component of the
217 * XtermWidget, so make sure to add an assignment statement in VTInitialize()
218 * for each new ".screen" field added to this resource list.
219 */
220
221/* Defaults */
222#if OPT_ISO_COLORS
223
224/*
225 * If we default to colorMode enabled, compile-in defaults for the ANSI colors.
226 */
227#if DFT_COLORMODE
228#define DFT_COLOR(name) name
229#else
230#define DFT_COLOR(name) XtDefaultForeground
231#endif
232#endif
233
234static char _Font_Selected_[] = "yes";	/* string is arbitrary */
235
236static const char *defaultTranslations;
237/* *INDENT-OFF* */
238static XtActionsRec actionsList[] = {
239    { "allow-bold-fonts",	HandleAllowBoldFonts },
240    { "allow-send-events",	HandleAllowSends },
241    { "bell",			HandleBell },
242    { "clear-saved-lines",	HandleClearSavedLines },
243    { "copy-selection",		HandleCopySelection },
244    { "create-menu",		HandleCreateMenu },
245    { "delete-is-del",		HandleDeleteIsDEL },
246    { "dired-button",		DiredButton },
247    { "hard-reset",		HandleHardReset },
248    { "ignore",			HandleIgnore },
249    { "insert",			HandleKeyPressed },  /* alias for insert-seven-bit */
250    { "insert-eight-bit",	HandleEightBitKeyPressed },
251    { "insert-selection",	HandleInsertSelection },
252    { "insert-seven-bit",	HandleKeyPressed },
253    { "interpret",		HandleInterpret },
254    { "keymap",			HandleKeymapChange },
255    { "popup-menu",		HandlePopupMenu },
256    { "print",			HandlePrintScreen },
257    { "print-everything",	HandlePrintEverything },
258    { "print-redir",		HandlePrintControlMode },
259    { "quit",			HandleQuit },
260    { "redraw",			HandleRedraw },
261    { "scroll-back",		HandleScrollBack },
262    { "scroll-forw",		HandleScrollForward },
263    { "secure",			HandleSecure },
264    { "select-cursor-end",	HandleKeyboardSelectEnd },
265    { "select-cursor-extend",   HandleKeyboardSelectExtend },
266    { "select-cursor-start",	HandleKeyboardSelectStart },
267    { "select-end",		HandleSelectEnd },
268    { "select-extend",		HandleSelectExtend },
269    { "select-set",		HandleSelectSet },
270    { "select-start",		HandleSelectStart },
271    { "send-signal",		HandleSendSignal },
272    { "set-8-bit-control",	Handle8BitControl },
273    { "set-allow132",		HandleAllow132 },
274    { "set-altscreen",		HandleAltScreen },
275    { "set-appcursor",		HandleAppCursor },
276    { "set-appkeypad",		HandleAppKeypad },
277    { "set-autolinefeed",	HandleAutoLineFeed },
278    { "set-autowrap",		HandleAutoWrap },
279    { "set-backarrow",		HandleBackarrow },
280    { "set-bellIsUrgent",	HandleBellIsUrgent },
281    { "set-cursesemul",		HandleCursesEmul },
282    { "set-jumpscroll",		HandleJumpscroll },
283    { "set-keep-clipboard",	HandleKeepClipboard },
284    { "set-keep-selection",	HandleKeepSelection },
285    { "set-marginbell",		HandleMarginBell },
286    { "set-old-function-keys",	HandleOldFunctionKeys },
287    { "set-pop-on-bell",	HandleSetPopOnBell },
288    { "set-reverse-video",	HandleReverseVideo },
289    { "set-reversewrap",	HandleReverseWrap },
290    { "set-scroll-on-key",	HandleScrollKey },
291    { "set-scroll-on-tty-output", HandleScrollTtyOutput },
292    { "set-scrollbar",		HandleScrollbar },
293    { "set-select",		HandleSetSelect },
294    { "set-sun-keyboard",	HandleSunKeyboard },
295    { "set-titeInhibit",	HandleTiteInhibit },
296    { "set-visual-bell",	HandleSetVisualBell },
297    { "set-vt-font",		HandleSetFont },
298    { "soft-reset",		HandleSoftReset },
299    { "start-cursor-extend",	HandleKeyboardStartExtend },
300    { "start-extend",		HandleStartExtend },
301    { "string",			HandleStringEvent },
302    { "vi-button",		ViButton },
303    { "visual-bell",		HandleVisualBell },
304#ifdef ALLOWLOGGING
305    { "set-logging",		HandleLogging },
306#endif
307#if OPT_ALLOW_XXX_OPS
308    { "allow-color-ops",	HandleAllowColorOps },
309    { "allow-font-ops",		HandleAllowFontOps },
310    { "allow-mouse-ops",	HandleAllowMouseOps },
311    { "allow-tcap-ops",		HandleAllowTcapOps },
312    { "allow-title-ops",	HandleAllowTitleOps },
313    { "allow-window-ops",	HandleAllowWindowOps },
314#endif
315#if OPT_BLINK_CURS
316    { "set-cursorblink",	HandleCursorBlink },
317#endif
318#if OPT_BOX_CHARS
319    { "set-font-linedrawing",	HandleFontBoxChars },
320    { "set-font-packed",	HandleFontPacked },
321#endif
322#if OPT_DABBREV
323    { "dabbrev-expand",		HandleDabbrevExpand },
324#endif
325#if OPT_DEC_CHRSET
326    { "set-font-doublesize",	HandleFontDoublesize },
327#endif
328#if OPT_DEC_SOFTFONT
329    { "set-font-loading",	HandleFontLoading },
330#endif
331#if OPT_SCREEN_DUMPS
332    { "dump-html",	        HandleDumpHtml },
333    { "dump-svg",	        HandleDumpSvg },
334#endif
335#if OPT_EXEC_XTERM
336    { "spawn-new-terminal",	HandleSpawnTerminal },
337#endif
338#if OPT_HP_FUNC_KEYS
339    { "set-hp-function-keys",	HandleHpFunctionKeys },
340#endif
341#if OPT_LOAD_VTFONTS
342    { "load-vt-fonts",		HandleLoadVTFonts },
343#endif
344#if OPT_MAXIMIZE
345    { "deiconify",		HandleDeIconify },
346    { "fullscreen",		HandleFullscreen },
347    { "iconify",		HandleIconify },
348    { "maximize",		HandleMaximize },
349    { "restore",		HandleRestoreSize },
350#endif
351#if OPT_NUM_LOCK
352    { "alt-sends-escape",	HandleAltEsc },
353    { "meta-sends-escape",	HandleMetaEsc },
354    { "set-num-lock",		HandleNumLock },
355#endif
356#if OPT_READLINE
357    { "readline-button",	ReadLineButton },
358#endif
359#if OPT_RENDERFONT
360    { "set-render-font",	HandleRenderFont },
361#endif
362#if OPT_SCO_FUNC_KEYS
363    { "set-sco-function-keys",	HandleScoFunctionKeys },
364#endif
365#if OPT_SCROLL_LOCK
366    { "scroll-lock",		HandleScrollLock },
367#endif
368#if OPT_SELECTION_OPS
369    { "exec-formatted",		HandleExecFormatted },
370    { "exec-selectable",	HandleExecSelectable },
371    { "insert-formatted",	HandleInsertFormatted },
372    { "insert-selectable",	HandleInsertSelectable },
373#endif
374#if OPT_SHIFT_FONTS
375    { "larger-vt-font",		HandleLargerFont },
376    { "smaller-vt-font",	HandleSmallerFont },
377#endif
378#if OPT_SIXEL_GRAPHICS
379    { "set-sixel-scrolling",	HandleSixelScrolling },
380#endif
381#if OPT_GRAPHICS
382    { "set-private-colors",	HandleSetPrivateColorRegisters },
383#endif
384#if OPT_SUN_FUNC_KEYS
385    { "set-sun-function-keys",	HandleSunFunctionKeys },
386#endif
387#if OPT_TEK4014
388    { "set-terminal-type",	HandleSetTerminalType },
389    { "set-visibility",		HandleVisibility },
390    { "set-tek-text",		HandleSetTekText },
391    { "tek-page",		HandleTekPage },
392    { "tek-reset",		HandleTekReset },
393    { "tek-copy",		HandleTekCopy },
394#endif
395#if OPT_TOOLBAR
396    { "set-toolbar",		HandleToolbar },
397#endif
398#if OPT_WIDE_CHARS
399    { "set-utf8-mode",		HandleUTF8Mode },
400    { "set-utf8-fonts",		HandleUTF8Fonts },
401    { "set-utf8-title",		HandleUTF8Title },
402#endif
403};
404/* *INDENT-ON* */
405
406#define SPS screen.printer_state
407
408static XtResource xterm_resources[] =
409{
410    Bres(XtNallowPasteControls, XtCAllowPasteControls,
411	 screen.allowPasteControl0, False),
412    Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False),
413    Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR),
414    Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT),
415    Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE),
416    Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP),
417    Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE),
418    Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW),
419    Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False),
420    Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC),
421    Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True),
422    Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False),
423    Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False),
424    Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False),
425    Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False),
426    Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False),
427    Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True),
428    Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False),
429    Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False),
430    Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS),
431    Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False),
432    Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True),
433    Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True),
434    Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False),
435    Bres(XtNc132, XtCC132, screen.c132, False),
436    Bres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll, False),
437    Bres(XtNcurses, XtCCurses, screen.curses, False),
438    Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True),
439    Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine,
440	 screen.cutToBeginningOfLine, True),
441    Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL),
442    Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True),
443    Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False),
444    Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True),
445    Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True),
446    Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True),
447    Bres(XtNhighlightSelection, XtCHighlightSelection,
448	 screen.highlight_selection, False),
449    Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False),
450    Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False),
451    Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True),
452    Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False),
453    Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True),
454    Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False),
455    Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True),
456    Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False),
457    Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False),
458    Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC),
459    Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False),
460    Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False),
461    Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False),
462    Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False),
463    Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False),
464    Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False),
465    Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True),
466    Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False),
467    Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False),
468    Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False),
469    Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False),
470    Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False),
471    Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True),
472    Bres(XtNselectToClipboard, XtCSelectToClipboard,
473	 screen.selectToClipboard, False),
474    Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False),
475    Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False),
476    Bres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll, False),
477    Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False),
478    Bres(XtNunderLine, XtCUnderLine, screen.underline, True),
479    Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False),
480    Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False),
481
482    Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"),
483
484    Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC),
485    Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource),
486    Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER),
487    Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1),
488    Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME),
489    Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL),
490    Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE),
491    Ires(XtNprinterControlMode, XtCPrinterControlMode,
492	 SPS.printer_controlmode, 0),
493    Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES),
494    Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100),
495    Ires(XtNsaveLines, XtCSaveLines, screen.savelines, SAVELINES),
496    Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1),
497    Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, SCROLLLINES),
498
499    Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL),
500    Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL),
501    Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL),
502    Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL),
503    Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL),
504    Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL),
505    Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL),
506
507    Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""),
508    Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT),
509    Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL),
510    Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID),
511    Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"),
512    Sres(XtNdisallowedColorOps, XtCDisallowedColorOps,
513	 screen.disallowedColorOps, DEF_DISALLOWED_COLOR),
514    Sres(XtNdisallowedFontOps, XtCDisallowedFontOps,
515	 screen.disallowedFontOps, DEF_DISALLOWED_FONT),
516    Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps,
517	 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE),
518    Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps,
519	 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP),
520    Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps,
521	 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW),
522    Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META),
523    Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes,
524	 screen.eightbit_select_types, NULL),
525    Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT),
526    Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL),
527    Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT),
528    Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""),
529    Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL),
530
531    Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground),
532    Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground),
533    Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground),
534    Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground),
535    Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground),
536
537    {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
538     XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
539     XtRImmediate, (XtPointer) SouthWestGravity},
540
541    {XtNpointerShape, XtCCursor, XtRCursor, sizeof(Cursor),
542     XtOffsetOf(XtermWidgetRec, screen.pointer_cursor),
543     XtRString, (XtPointer) "xterm"},
544
545#ifdef ALLOWLOGGING
546    Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False),
547    Bres(XtNlogging, XtCLogging, misc.log_on, False),
548    Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL),
549#endif
550
551#ifndef NO_ACTIVE_ICON
552    Sres("activeIcon", "ActiveIcon", misc.active_icon_s, "default"),
553    Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2),
554    Sres("iconFont", "IconFont", screen.icon_fontname, "nil2"),
555    Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground),
556#endif				/* NO_ACTIVE_ICON */
557
558#if OPT_BLINK_CURS
559    Bres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink, False),
560#endif
561    Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False),
562
563#if OPT_BLINK_TEXT
564    Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD),
565#endif
566
567#if OPT_BLINK_CURS || OPT_BLINK_TEXT
568    Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600),
569    Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300),
570#endif
571
572#if OPT_BOX_CHARS
573    Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False),
574    Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True),
575    Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False),
576    Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True),
577#endif
578
579#if OPT_BROKEN_OSC
580    Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True),
581#endif
582
583#if OPT_BROKEN_ST
584    Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False),
585#endif
586
587#if OPT_C1_PRINT
588    Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False),
589#endif
590
591#if OPT_CLIP_BOLD
592    Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True),
593#endif
594
595#if OPT_DEC_CHRSET
596    Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True),
597    Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET),
598#endif
599
600#if OPT_HIGHLIGHT_COLOR
601    Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground),
602    Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground),
603    Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True),
604    Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe),
605#endif				/* OPT_HIGHLIGHT_COLOR */
606
607#if OPT_INPUT_METHOD
608    Bres(XtNopenIm, XtCOpenIm, misc.open_im, True),
609    Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL),
610    Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type,
611	 "OverTheSpot,Root"),
612    Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3),
613#endif
614
615#if OPT_ISO_COLORS
616    Bres(XtNboldColors, XtCColorMode, screen.boldColors, True),
617    Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0),
618    Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE),
619
620    Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False),
621    Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False),
622    Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False),
623    Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False),
624    Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False),
625    Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False),
626#if OPT_WIDE_ATTRS
627    Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False),
628#endif
629
630    COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")),
631    COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")),
632    COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")),
633    COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")),
634    COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)),
635    COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")),
636    COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")),
637    COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")),
638    COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")),
639    COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")),
640    COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")),
641    COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")),
642    COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)),
643    COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")),
644    COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")),
645    COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")),
646    COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)),
647    COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)),
648    COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)),
649    COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)),
650
651#if OPT_WIDE_ATTRS
652    COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)),
653#endif
654
655#if !OPT_COLOR_RES2
656#if OPT_256_COLORS
657# include <256colres.h>
658#elif OPT_88_COLORS
659# include <88colres.h>
660#endif
661#endif				/* !OPT_COLOR_RES2 */
662
663#endif				/* OPT_ISO_COLORS */
664
665    CLICK_RES("2", screen.onClick[1], "word"),
666    CLICK_RES("3", screen.onClick[2], "line"),
667    CLICK_RES("4", screen.onClick[3], 0),
668    CLICK_RES("5", screen.onClick[4], 0),
669
670#if OPT_MOD_FKEYS
671    Ires(XtNmodifyKeyboard, XtCModifyKeyboard,
672	 keyboard.modify_1st.allow_keys, 0),
673    Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys,
674	 keyboard.modify_1st.cursor_keys, 2),
675    Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys,
676	 keyboard.modify_1st.function_keys, 2),
677    Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys,
678	 keyboard.modify_1st.keypad_keys, 0),
679    Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys,
680	 keyboard.modify_1st.other_keys, 0),
681    Ires(XtNmodifyStringKeys, XtCModifyStringKeys,
682	 keyboard.modify_1st.string_keys, 0),
683    Ires(XtNformatOtherKeys, XtCFormatOtherKeys,
684	 keyboard.format_keys, 0),
685#endif
686
687#if OPT_NUM_LOCK
688    Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False),
689    Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True),
690#endif
691
692#if OPT_PRINT_COLORS
693    Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1),
694#endif
695
696#if OPT_REGIS_GRAPHICS
697    Sres(XtNregisDefaultFont, XtCRegisDefaultFont,
698	 screen.graphics_regis_default_font, ""),
699    Sres(XtNregisScreenSize, XtCRegisScreenSize,
700	 screen.graphics_regis_screensize, "auto"),
701#endif
702
703#if OPT_GRAPHICS
704    Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size,
705	 "1000x1000"),
706#endif
707
708#if OPT_SHIFT_FONTS
709    Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True),
710#endif
711
712#if OPT_SIXEL_GRAPHICS
713    Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, True),
714    Bres(XtNsixelScrollsRight, XtCSixelScrollsRight,
715	 screen.sixel_scrolls_right, False),
716#endif
717
718#if OPT_GRAPHICS
719    Ires(XtNnumColorRegisters, XtCNumColorRegisters,
720	 screen.numcolorregisters, 0),
721    Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters,
722	 screen.privatecolorregisters, True),
723#endif
724
725#if OPT_SUNPC_KBD
726    Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10),
727#endif
728
729#if OPT_TEK4014
730    Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False),
731    Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False),
732    Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False),
733#endif
734
735#if OPT_TOOLBAR
736    Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0),
737    Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25),
738#endif
739
740#if OPT_WIDE_CHARS
741    Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False),
742    Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False),
743    Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True),
744    Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False),
745    Bres(XtNutf8Title, XtCUtf8Title, screen.utf8_title, False),
746    Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True),
747    Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False),
748    Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2),
749    Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655),
750    Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536),
751    Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"),
752    Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"),
753    Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT),
754    Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT),
755    Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL),
756#endif
757
758#if OPT_LUIT_PROG
759    Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"),
760    Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER),
761#endif
762
763#if OPT_INPUT_METHOD
764    Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT),
765#endif
766
767#if OPT_SCROLL_LOCK
768    Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False),
769#endif
770
771    /* these are used only for testing ncurses, not in the manual page */
772#if OPT_XMC_GLITCH
773    Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False),
774    Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True),
775    Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1),
776    Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0),
777#endif
778
779#ifdef SCROLLBAR_RIGHT
780    Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False),
781#endif
782
783#if OPT_RENDERFONT
784#define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0")
785    RES_FACESIZE(1),
786    RES_FACESIZE(2),
787    RES_FACESIZE(3),
788    RES_FACESIZE(4),
789    RES_FACESIZE(5),
790    RES_FACESIZE(6),
791    Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE),
792    Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME),
793    Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"),
794#if OPT_RENDERWIDE
795    Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME),
796#endif
797#endif
798};
799
800static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg,
801			   ArgList args, Cardinal *num_args);
802static void VTClassInit(void);
803static void VTDestroy(Widget w);
804static void VTExpose(Widget w, XEvent *event, Region region);
805static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args,
806			 Cardinal *num_args);
807static void VTRealize(Widget w, XtValueMask * valuemask,
808		      XSetWindowAttributes * values);
809static void VTResize(Widget w);
810
811#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
812static void VTInitI18N(XtermWidget);
813#endif
814
815#ifdef VMS
816globaldef {
817    "xtermclassrec"
818} noshare
819
820#else
821static
822#endif				/* VMS */
823WidgetClassRec xtermClassRec =
824{
825    {
826	/* core_class fields */
827	(WidgetClass) & widgetClassRec,		/* superclass   */
828	"VT100",		/* class_name                   */
829	sizeof(XtermWidgetRec),	/* widget_size                  */
830	VTClassInit,		/* class_initialize             */
831	NULL,			/* class_part_initialize        */
832	False,			/* class_inited                 */
833	VTInitialize,		/* initialize                   */
834	NULL,			/* initialize_hook              */
835	VTRealize,		/* realize                      */
836	actionsList,		/* actions                      */
837	XtNumber(actionsList),	/* num_actions                  */
838	xterm_resources,	/* resources                    */
839	XtNumber(xterm_resources),	/* num_resources        */
840	NULLQUARK,		/* xrm_class                    */
841	True,			/* compress_motion              */
842	False,			/* compress_exposure            */
843	True,			/* compress_enterleave          */
844	False,			/* visible_interest             */
845	VTDestroy,		/* destroy                      */
846	VTResize,		/* resize                       */
847	VTExpose,		/* expose                       */
848	VTSetValues,		/* set_values                   */
849	NULL,			/* set_values_hook              */
850	XtInheritSetValuesAlmost,	/* set_values_almost    */
851	NULL,			/* get_values_hook              */
852	NULL,			/* accept_focus                 */
853	XtVersion,		/* version                      */
854	NULL,			/* callback_offsets             */
855	0,			/* tm_table                     */
856	XtInheritQueryGeometry,	/* query_geometry               */
857	XtInheritDisplayAccelerator,	/* display_accelerator  */
858	NULL			/* extension                    */
859    }
860};
861
862#ifdef VMS
863globaldef {
864    "xtermwidgetclass"
865}
866noshare
867#endif /* VMS */
868WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec;
869
870/*
871 * Add input-actions for widgets that are overlooked (scrollbar and toolbar):
872 *
873 *	a) Sometimes the scrollbar passes through translations, sometimes it
874 *	   doesn't.  We add the KeyPress translations here, just to be sure.
875 *	b) In the normal (non-toolbar) configuration, the xterm widget covers
876 *	   almost all of the window.  With a toolbar, there's a relatively
877 *	   large area that the user would expect to enter keystrokes since the
878 *	   program can get the focus.
879 */
880void
881xtermAddInput(Widget w)
882{
883    /* *INDENT-OFF* */
884    XtActionsRec input_actions[] = {
885	{ "insert",		    HandleKeyPressed }, /* alias */
886	{ "insert-eight-bit",	    HandleEightBitKeyPressed },
887	{ "insert-seven-bit",	    HandleKeyPressed },
888	{ "secure",		    HandleSecure },
889	{ "string",		    HandleStringEvent },
890	{ "scroll-back",	    HandleScrollBack },
891	{ "scroll-forw",	    HandleScrollForward },
892	{ "select-cursor-end",	    HandleKeyboardSelectEnd },
893	{ "select-cursor-extend",   HandleKeyboardSelectExtend },
894	{ "select-cursor-start",    HandleKeyboardSelectStart },
895	{ "insert-selection",	    HandleInsertSelection },
896	{ "select-start",	    HandleSelectStart },
897	{ "select-extend",	    HandleSelectExtend },
898	{ "start-extend",	    HandleStartExtend },
899	{ "select-end",		    HandleSelectEnd },
900	{ "clear-saved-lines",	    HandleClearSavedLines },
901	{ "popup-menu",		    HandlePopupMenu },
902	{ "bell",		    HandleBell },
903	{ "ignore",		    HandleIgnore },
904#if OPT_DABBREV
905	{ "dabbrev-expand",	    HandleDabbrevExpand },
906#endif
907#if OPT_MAXIMIZE
908	{ "fullscreen",		    HandleFullscreen },
909#endif
910#if OPT_SCROLL_LOCK
911	{ "scroll-lock",	    HandleScrollLock },
912#endif
913#if OPT_SHIFT_FONTS
914	{ "larger-vt-font",	    HandleLargerFont },
915	{ "smaller-vt-font",	    HandleSmallerFont },
916#endif
917    };
918    /* *INDENT-ON* */
919
920    TRACE_TRANS("BEFORE", w);
921    XtAppAddActions(app_con, input_actions, XtNumber(input_actions));
922    XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations));
923    TRACE_TRANS("AFTER:", w);
924
925#if OPT_EXTRA_PASTE
926    if (term && term->keyboard.extra_translations)
927	XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations));
928#endif
929}
930
931#if OPT_ISO_COLORS
932#ifdef EXP_BOGUS_FG
933static Bool
934CheckBogusForeground(TScreen *screen, const char *tag)
935{
936    int row = -1, col = -1, pass;
937    Bool isClear = True;
938
939    (void) tag;
940    for (pass = 0; pass < 2; ++pass) {
941	row = screen->cur_row;
942	for (; isClear && (row <= screen->max_row); ++row) {
943	    CLineData *ld = getLineData(screen, row);
944
945	    if (ld != 0) {
946		IAttr *attribs = ld->attribs;
947
948		col = (row == screen->cur_row) ? screen->cur_col : 0;
949		for (; isClear && (col <= screen->max_col); ++col) {
950		    unsigned flags = attribs[col];
951		    if (pass) {
952			flags &= ~FG_COLOR;
953			attribs[col] = (IAttr) flags;
954		    } else if ((flags & BG_COLOR)) {
955			isClear = False;
956		    } else if ((flags & FG_COLOR)) {
957			unsigned ch = ld->charData[col];
958			isClear = ((ch == ' ') || (ch == 0));
959		    } else {
960			isClear = False;
961		    }
962		}
963	    }
964	}
965    }
966    TRACE(("%s checked %d,%d to %d,%d %s pass %d\n",
967	   tag, screen->cur_row, screen->cur_col,
968	   row, col,
969	   isClear && pass ? "cleared" : "unchanged",
970	   pass));
971
972    return isClear;
973}
974#endif
975
976/*
977 * The terminal's foreground and background colors are set via two mechanisms:
978 *	text (cur_foreground, cur_background values that are passed down to
979 *		XDrawImageString and XDrawString)
980 *	area (X11 graphics context used in XClearArea and XFillRectangle)
981 */
982void
983SGR_Foreground(XtermWidget xw, int color)
984{
985    TScreen *screen = TScreenOf(xw);
986    Pixel fg;
987
988    if (color >= 0) {
989	UIntSet(xw->flags, FG_COLOR);
990    } else {
991	UIntClr(xw->flags, FG_COLOR);
992    }
993    fg = getXtermForeground(xw, xw->flags, color);
994    xw->cur_foreground = color;
995
996    setCgsFore(xw, WhichVWin(screen), gcNorm, fg);
997    setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg);
998
999    setCgsFore(xw, WhichVWin(screen), gcBold, fg);
1000    setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg);
1001
1002#ifdef EXP_BOGUS_FG
1003    /*
1004     * If we've just turned off the foreground color, check for blank cells
1005     * which have no background color, but do have foreground color.  This
1006     * could happen due to setting the foreground color just before scrolling.
1007     *
1008     * Those cells look uncolored, but will confuse ShowCursor(), which looks
1009     * for the colors in the current cell, and will see the foreground color.
1010     * In that case, remove the foreground color from the blank cells.
1011     */
1012    if (color < 0) {
1013	CheckBogusForeground(screen, "SGR_Foreground");
1014    }
1015#endif
1016}
1017
1018void
1019SGR_Background(XtermWidget xw, int color)
1020{
1021    TScreen *screen = TScreenOf(xw);
1022    Pixel bg;
1023
1024    /*
1025     * An indexing operation may have set screen->scroll_amt, which would
1026     * normally result in calling FlushScroll() in WriteText().  However,
1027     * if we're changing the background color now, then the new value
1028     * should not apply to the pending blank lines.
1029     */
1030    if (screen->scroll_amt && (color != xw->cur_background))
1031	FlushScroll(xw);
1032
1033    if (color >= 0) {
1034	UIntSet(xw->flags, BG_COLOR);
1035    } else {
1036	UIntClr(xw->flags, BG_COLOR);
1037    }
1038    bg = getXtermBackground(xw, xw->flags, color);
1039    xw->cur_background = color;
1040
1041    setCgsBack(xw, WhichVWin(screen), gcNorm, bg);
1042    setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg);
1043
1044    setCgsBack(xw, WhichVWin(screen), gcBold, bg);
1045    setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg);
1046}
1047
1048/* Invoked after updating bold/underline flags, computes the extended color
1049 * index to use for foreground.  (See also 'extract_fg()').
1050 */
1051static void
1052setExtendedFG(XtermWidget xw)
1053{
1054    int fg = xw->sgr_foreground;
1055
1056    if (TScreenOf(xw)->colorAttrMode
1057	|| (fg < 0)) {
1058	fg = MapToColorMode(fg, TScreenOf(xw), xw->flags);
1059    }
1060
1061    /* This implements the IBM PC-style convention of 8-colors, with one
1062     * bit for bold, thus mapping the 0-7 codes to 8-15.  It won't make
1063     * much sense for 16-color applications, but we keep it to retain
1064     * compatiblity with ANSI-color applications.
1065     */
1066#if OPT_PC_COLORS		/* XXXJTL should be settable at runtime (resource or OSC?) */
1067    if (TScreenOf(xw)->boldColors
1068	&& (!xw->sgr_extended)
1069	&& (fg >= 0)
1070	&& (fg < 8)
1071	&& (xw->flags & BOLD))
1072	fg |= 8;
1073#endif
1074
1075    SGR_Foreground(xw, fg);
1076}
1077
1078/* Invoked after updating inverse flag, computes the extended color
1079 * index to use for background.  (See also 'extract_bg()').
1080 */
1081static void
1082setExtendedBG(XtermWidget xw)
1083{
1084    int bg = xw->sgr_background;
1085
1086    if (TScreenOf(xw)->colorAttrMode
1087	|| (bg < 0)) {
1088	if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE))
1089	    bg = COLOR_RV;
1090    }
1091
1092    SGR_Background(xw, bg);
1093}
1094
1095static void
1096reset_SGR_Foreground(XtermWidget xw)
1097{
1098    xw->sgr_foreground = -1;
1099    xw->sgr_extended = False;
1100    setExtendedFG(xw);
1101}
1102
1103static void
1104reset_SGR_Background(XtermWidget xw)
1105{
1106    xw->sgr_background = -1;
1107    setExtendedBG(xw);
1108}
1109
1110static void
1111reset_SGR_Colors(XtermWidget xw)
1112{
1113    reset_SGR_Foreground(xw);
1114    reset_SGR_Background(xw);
1115}
1116#endif /* OPT_ISO_COLORS */
1117
1118#if OPT_WIDE_ATTRS
1119/*
1120 * Call this before changing the state of ATR_ITALIC, to update the GC fonts.
1121 */
1122static void
1123setItalicFont(XtermWidget xw, Bool enable)
1124{
1125    if (enable) {
1126	if ((xw->flags & ATR_ITALIC) == 0) {
1127	    xtermLoadItalics(xw);
1128	    TRACE(("setItalicFont: enabling Italics\n"));
1129	    xtermUpdateFontGCs(xw, True);
1130	}
1131    } else if ((xw->flags & ATR_ITALIC) != 0) {
1132	TRACE(("setItalicFont: disabling Italics\n"));
1133	xtermUpdateFontGCs(xw, False);
1134    }
1135}
1136#endif
1137
1138void
1139resetCharsets(TScreen *screen)
1140{
1141    TRACE(("resetCharsets\n"));
1142
1143    screen->gsets[0] = nrc_ASCII;
1144    screen->gsets[1] = nrc_ASCII;
1145    screen->gsets[2] = nrc_ASCII;
1146    screen->gsets[3] = nrc_ASCII;
1147
1148    screen->curgl = 0;		/* G0 => GL.            */
1149    screen->curgr = 2;		/* G2 => GR.            */
1150    screen->curss = 0;		/* No single shift.     */
1151
1152#if OPT_VT52_MODE
1153    if (screen->vtXX_level == 0)
1154	screen->gsets[1] = nrc_DEC_Spec_Graphic;	/* Graphics */
1155#endif
1156}
1157
1158static void
1159modified_DECNRCM(XtermWidget xw)
1160{
1161#if OPT_WIDE_CHARS
1162    TScreen *screen = TScreenOf(xw);
1163    if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) {
1164	int enabled = ((xw->flags & NATIONAL) != 0);
1165	int modefix;
1166	EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix);
1167	switchPtyData(screen, !enabled);
1168	TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF"));
1169    }
1170#endif
1171}
1172
1173/*
1174 * VT300 and up support three ANSI conformance levels, defined according to
1175 * the dpANSI X3.134.1 standard.  DEC's manuals equate levels 1 and 2, and
1176 * are unclear.  This code is written based on the manuals.
1177 */
1178static void
1179set_ansi_conformance(TScreen *screen, int level)
1180{
1181    TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n",
1182	   level,
1183	   screen->vtXX_level * 100,
1184	   screen->terminal_id,
1185	   screen->ansi_level));
1186    if (screen->vtXX_level >= 3) {
1187	switch (screen->ansi_level = level) {
1188	case 1:
1189	    /* FALLTHRU */
1190	case 2:
1191	    screen->gsets[0] = nrc_ASCII;	/* G0 is ASCII */
1192	    screen->gsets[1] = nrc_ASCII;	/* G1 is ISO Latin-1 */
1193	    screen->curgl = 0;
1194	    screen->curgr = 1;
1195	    break;
1196	case 3:
1197	    screen->gsets[0] = nrc_ASCII;	/* G0 is ASCII */
1198	    screen->curgl = 0;
1199	    break;
1200	}
1201    }
1202}
1203
1204/*
1205 * Set scrolling margins.  VTxxx terminals require that the top/bottom are
1206 * different, so we have at least two lines in the scrolling region.
1207 */
1208void
1209set_tb_margins(TScreen *screen, int top, int bottom)
1210{
1211    TRACE(("set_tb_margins %d..%d, prior %d..%d\n",
1212	   top, bottom,
1213	   screen->top_marg,
1214	   screen->bot_marg));
1215    if (bottom > top) {
1216	screen->top_marg = top;
1217	screen->bot_marg = bottom;
1218    }
1219    if (screen->top_marg > screen->max_row)
1220	screen->top_marg = screen->max_row;
1221    if (screen->bot_marg > screen->max_row)
1222	screen->bot_marg = screen->max_row;
1223}
1224
1225void
1226set_lr_margins(TScreen *screen, int left, int right)
1227{
1228    TRACE(("set_lr_margins %d..%d, prior %d..%d\n",
1229	   left, right,
1230	   screen->lft_marg,
1231	   screen->rgt_marg));
1232    if (right > left) {
1233	screen->lft_marg = left;
1234	screen->rgt_marg = right;
1235    }
1236    if (screen->lft_marg > screen->max_col)
1237	screen->lft_marg = screen->max_col;
1238    if (screen->rgt_marg > screen->max_col)
1239	screen->rgt_marg = screen->max_col;
1240}
1241
1242#define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row)
1243#define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col)
1244
1245static void
1246reset_margins(TScreen *screen)
1247{
1248    reset_tb_margins(screen);
1249    reset_lr_margins(screen);
1250}
1251
1252void
1253set_max_col(TScreen *screen, int cols)
1254{
1255    TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col));
1256    if (cols < 0)
1257	cols = 0;
1258    screen->max_col = cols;
1259}
1260
1261void
1262set_max_row(TScreen *screen, int rows)
1263{
1264    TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row));
1265    if (rows < 0)
1266	rows = 0;
1267    screen->max_row = rows;
1268}
1269
1270#if OPT_MOD_FKEYS
1271static void
1272set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled)
1273{
1274#define SET_MOD_FKEYS(field) \
1275    xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \
1276				     ? xw->keyboard.modify_1st.field \
1277				     : what; \
1278    TRACE(("set modify_now.%s to %d\n", #field, \
1279	   xw->keyboard.modify_now.field));
1280
1281    switch (which) {
1282    case 0:
1283	SET_MOD_FKEYS(allow_keys);
1284	break;
1285    case 1:
1286	SET_MOD_FKEYS(cursor_keys);
1287	break;
1288    case 2:
1289	SET_MOD_FKEYS(function_keys);
1290	break;
1291    case 3:
1292	SET_MOD_FKEYS(keypad_keys);
1293	break;
1294    case 4:
1295	SET_MOD_FKEYS(other_keys);
1296	break;
1297    case 5:
1298	SET_MOD_FKEYS(string_keys);
1299	break;
1300    }
1301}
1302#endif /* OPT_MOD_FKEYS */
1303
1304#if OPT_TRACE
1305#define DATA(name) { name, #name }
1306static const struct {
1307    Const PARSE_T *table;
1308    const char *name;
1309} all_tables[] = {
1310
1311    DATA(ansi_table)
1312	,DATA(cigtable)
1313	,DATA(csi2_table)
1314	,DATA(csi_ex_table)
1315	,DATA(csi_quo_table)
1316	,DATA(csi_table)
1317	,DATA(dec2_table)
1318	,DATA(dec3_table)
1319	,DATA(dec_table)
1320	,DATA(eigtable)
1321	,DATA(esc_sp_table)
1322	,DATA(esc_table)
1323	,DATA(scrtable)
1324	,DATA(scs96table)
1325	,DATA(scstable)
1326	,DATA(sos_table)
1327#if OPT_BLINK_CURS
1328	,DATA(csi_sp_table)
1329#endif
1330#if OPT_DEC_LOCATOR
1331	,DATA(csi_tick_table)
1332#endif
1333#if OPT_DEC_RECTOPS
1334	,DATA(csi_dollar_table)
1335	,DATA(csi_star_table)
1336	,DATA(csi_dec_dollar_table)
1337#endif
1338#if OPT_WIDE_CHARS
1339	,DATA(esc_pct_table)
1340	,DATA(scs_pct_table)
1341#endif
1342#if OPT_VT52_MODE
1343	,DATA(vt52_table)
1344	,DATA(vt52_esc_table)
1345	,DATA(vt52_ignore_table)
1346#endif
1347#undef DATA
1348};
1349
1350#define WHICH_TABLE(name) if (table == name) result = #name
1351static const char *
1352which_table(Const PARSE_T * table)
1353{
1354    const char *result = "?";
1355    Cardinal n;
1356    for (n = 0; n < XtNumber(all_tables); ++n) {
1357	if (table == all_tables[n].table) {
1358	    result = all_tables[n].name;
1359	    break;
1360	}
1361    }
1362
1363    return result;
1364}
1365
1366static void
1367check_tables(void)
1368{
1369    Cardinal n;
1370    int ch;
1371
1372    TRACE(("** check_tables\n"));
1373    for (n = 0; n < XtNumber(all_tables); ++n) {
1374	Const PARSE_T *table = all_tables[n].table;
1375	TRACE(("*** %s\n", all_tables[n].name));
1376	/*
1377	 * Most of the tables should use the same codes in 0..31, 128..159
1378	 * as the "ansi" table.
1379	 */
1380	if (strncmp(all_tables[n].name, "ansi", 4) &&
1381	    strncmp(all_tables[n].name, "sos_", 4) &&
1382	    strncmp(all_tables[n].name, "vt52", 4)) {
1383	    for (ch = 0; ch < 32; ++ch) {
1384		int c1 = ch + 128;
1385		PARSE_T st_l = table[ch];
1386		PARSE_T st_r = table[c1];
1387		if (st_l != ansi_table[ch]) {
1388		    TRACE(("  %3d: %d vs %d\n", ch, st_l, ansi_table[ch]));
1389		}
1390		if (st_r != ansi_table[c1]) {
1391		    TRACE(("  %3d: %d vs %d\n", c1, st_r, ansi_table[c1]));
1392		}
1393	    }
1394	}
1395	/*
1396	 * All of the tables should have their GL/GR parts encoded the same.
1397	 */
1398	for (ch = 32; ch < 127; ++ch) {
1399	    PARSE_T st_l = table[ch];
1400	    PARSE_T st_r = table[ch + 128];
1401	    if (st_l != st_r) {
1402		if (st_r == CASE_IGNORE &&
1403		    !strncmp(all_tables[n].name, "vt52", 4)) {
1404		    ;
1405		} else {
1406		    TRACE(("  %3d: %d vs %d\n", ch, st_l, st_r));
1407		}
1408	    }
1409	}
1410    }
1411}
1412#endif
1413
1414#if OPT_TRACE > 0
1415static void
1416dump_params(void)
1417{
1418    int n;
1419    int arg;
1420    TRACE(("params %d (%d)\n", nparam, parms.has_subparams));
1421    for (arg = 1, n = 0; n < nparam; ++n) {
1422	TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n]));
1423	if (!parms.is_sub[n])
1424	    ++arg;
1425    }
1426}
1427#define DumpParams() dump_params()
1428#else
1429#define DumpParams()		/* nothing */
1430#endif
1431
1432	/* allocate larger buffer if needed/possible */
1433#define SafeAlloc(type, area, used, size) \
1434		type *new_string = area; \
1435		size_t new_length = size; \
1436		if (new_length == 0) { \
1437		    new_length = 256; \
1438		    new_string = TypeMallocN(type, new_length); \
1439		} else if (used+1 >= new_length) { \
1440		    new_length = size * 2; \
1441		    new_string = TypeMallocN(type, new_length); \
1442		    if (new_string != 0 \
1443		     && area != 0 \
1444		     && used != 0) { \
1445			memcpy(new_string, area, used * sizeof(type)); \
1446		     } \
1447		}
1448#define SafeFree(area, size) \
1449		if (area != new_string) { \
1450		    free(area); \
1451		    area = new_string; \
1452		} \
1453		size = new_length
1454
1455#define WriteNow() {						\
1456	    unsigned single = 0;				\
1457								\
1458	    if (screen->curss) {				\
1459		dotext(xw,					\
1460		       screen->gsets[(int) (screen->curss)],	\
1461		       sp->print_area,				\
1462		       (Cardinal) 1);				\
1463		screen->curss = 0;				\
1464		single++;					\
1465	    }							\
1466	    if (sp->print_used > single) {			\
1467		dotext(xw,					\
1468		       screen->gsets[(int) (screen->curgl)],	\
1469		       sp->print_area + single,			\
1470		       (Cardinal) (sp->print_used - single));	\
1471	    }							\
1472	    sp->print_used = 0;					\
1473	}							\
1474
1475struct ParseState {
1476#if OPT_VT52_MODE
1477    Bool vt52_cup;
1478#endif
1479    Const PARSE_T *groundtable;
1480    Const PARSE_T *parsestate;
1481    int scstype;
1482    int scssize;
1483    Bool private_function;	/* distinguish private-mode from standard */
1484    int string_mode;		/* nonzero iff we're processing a string */
1485    int lastchar;		/* positive iff we had a graphic character */
1486    int nextstate;
1487#if OPT_WIDE_CHARS
1488    int last_was_wide;
1489#endif
1490    /* Buffer for processing printable text */
1491    IChar *print_area;
1492    size_t print_size;
1493    size_t print_used;
1494    /* Buffer for processing strings (e.g., OSC ... ST) */
1495    Char *string_area;
1496    size_t string_size;
1497    size_t string_used;
1498};
1499
1500static struct ParseState myState;
1501
1502static void
1503init_groundtable(TScreen *screen, struct ParseState *sp)
1504{
1505    (void) screen;
1506
1507#if OPT_VT52_MODE
1508    if (!(screen->vtXX_level)) {
1509	sp->groundtable = vt52_table;
1510    } else if (screen->terminal_id >= 100)
1511#endif
1512    {
1513	sp->groundtable = ansi_table;
1514    }
1515}
1516
1517static void
1518select_charset(struct ParseState *sp, int type, int size)
1519{
1520    TRACE(("select_charset %d %d\n", type, size));
1521    sp->scstype = type;
1522    sp->scssize = size;
1523    if (size == 94) {
1524	sp->parsestate = scstable;
1525    } else {
1526	sp->parsestate = scs96table;
1527    }
1528}
1529
1530static void
1531decode_scs(XtermWidget xw, int which, int prefix, int suffix)
1532{
1533    /* *INDENT-OFF* */
1534    static struct {
1535	DECNRCM_codes result;
1536	int prefix;
1537	int suffix;
1538	int min_level;
1539	int max_level;
1540	int need_nrc;
1541    } table[] = {
1542	{ nrc_ASCII,             0,   'B', 1, 9, 0 },
1543	{ nrc_British,           0,   'A', 1, 9, 0 },
1544	{ nrc_DEC_Spec_Graphic,  0,   '0', 1, 9, 0 },
1545	{ nrc_DEC_Alt_Chars,     0,   '1', 1, 1, 0 },
1546	{ nrc_DEC_Alt_Graphics,  0,   '2', 1, 1, 0 },
1547	/* VT2xx */
1548	{ nrc_DEC_Supp,          0,   '<', 2, 9, 0 },
1549	{ nrc_Dutch,             0,   '4', 2, 9, 1 },
1550	{ nrc_Finnish,           0,   '5', 2, 9, 1 },
1551	{ nrc_Finnish2,          0,   'C', 2, 9, 1 },
1552	{ nrc_French,            0,   'R', 2, 9, 1 },
1553	{ nrc_French2,           0,   'f', 2, 9, 1 },
1554	{ nrc_French_Canadian,   0,   'Q', 2, 9, 1 },
1555	{ nrc_German,            0,   'K', 2, 9, 1 },
1556	{ nrc_Italian,           0,   'Y', 2, 9, 1 },
1557	{ nrc_Norwegian_Danish2, 0,   'E', 2, 9, 1 },
1558	{ nrc_Norwegian_Danish3, 0,   '6', 2, 9, 1 },
1559	{ nrc_Spanish,           0,   'Z', 2, 9, 1 },
1560	{ nrc_Swedish,           0,   '7', 2, 9, 1 },
1561	{ nrc_Swedish2,          0,   'H', 2, 9, 1 },
1562	{ nrc_Swiss,             0,   '=', 2, 9, 1 },
1563	/* VT3xx */
1564	{ nrc_British_Latin_1,   0,   'A', 3, 9, 1 },
1565	{ nrc_DEC_Supp_Graphic,  '%', '5', 3, 9, 0 },
1566	{ nrc_DEC_Technical,     0,   '>', 3, 9, 0 },
1567	{ nrc_French_Canadian2,  0,   '9', 3, 9, 1 },
1568	{ nrc_Norwegian_Danish,  0,   '`', 3, 9, 1 },
1569	{ nrc_Portugese,         '%', '6', 3, 9, 1 },
1570#if 0
1571	/* VT5xx (not implemented) */
1572	{ nrc_Cyrillic,          '&', '4', 5, 9, 0 },
1573	{ nrc_Greek,             '"', '?', 5, 9, 0 },
1574	{ nrc_Greek_Supp,        0,   'F', 5, 9, 0 },
1575	{ nrc_Hebrew,            '"', '4', 5, 9, 0 },
1576	{ nrc_Hebrew2,           '%', '=', 5, 9, 1 },
1577	{ nrc_Hebrew_Supp,       0,   'H', 5, 9, 0 },
1578	{ nrc_Latin_5_Supp,      0,   'M', 5, 9, 0 },
1579	{ nrc_Latin_Cyrillic,    0,   'L', 5, 9, 0 },
1580	{ nrc_Russian,           '&', '5', 5, 9, 1 },
1581	{ nrc_SCS_NRCS,          '%', '3', 5, 9, 0 },
1582	{ nrc_Turkish,           '%', '0', 5, 9, 0 },
1583	{ nrc_Turkish2,		 '%', '2', 5, 9, 1 },
1584#endif
1585    };
1586    /* *INDENT-ON* */
1587
1588    TScreen *screen = TScreenOf(xw);
1589    Cardinal n;
1590    DECNRCM_codes result = nrc_Unknown;
1591
1592    suffix &= 0x7f;
1593    for (n = 0; n < XtNumber(table); ++n) {
1594	if (prefix == table[n].prefix
1595	    && suffix == table[n].suffix
1596	    && screen->vtXX_level >= table[n].min_level
1597	    && screen->vtXX_level <= table[n].max_level
1598	    && (table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) {
1599	    result = table[n].result;
1600	    break;
1601	}
1602    }
1603    if (result != nrc_Unknown) {
1604	screen->gsets[which] = result;
1605	TRACE(("setting G%d to %s\n", which, visibleScsCode((int) result)));
1606    } else {
1607	TRACE(("...unknown GSET\n"));
1608    }
1609}
1610
1611/*
1612 * Given a parameter number, and subparameter (starting in each case from zero)
1613 * return the corresponding index into the parameter array.  If the combination
1614 * is not found, return -1.
1615 */
1616static int
1617subparam_index(int p, int s)
1618{
1619    int result = -1;
1620    int j, p2, s2;
1621
1622    for (j = p2 = 0; j < nparam; ++j, ++p2) {
1623	if (parms.is_sub[j]) {
1624	    s2 = 0;
1625
1626	    do {
1627		if ((p == p2) && (s == s2)) {
1628		    result = j;
1629		    break;
1630		}
1631		++s2;
1632	    } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j]));
1633
1634	    if (result >= 0)
1635		break;
1636
1637	    --j;		/* undo the last "while" */
1638	} else if (p == p2) {
1639	    if (s == 0) {
1640		result = j;
1641	    }
1642	    break;
1643	}
1644    }
1645    TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result));
1646    return result;
1647}
1648
1649/*
1650 * Check if the given item in the parameter array has subparameters.
1651 * If so, return the number of subparameters to use as a loop limit, etc.
1652 */
1653static int
1654param_has_subparams(int item)
1655{
1656    int result = 0;
1657    if (parms.has_subparams) {
1658	int n = subparam_index(item, 0);
1659	if (n >= 0 && parms.is_sub[n]) {
1660	    while (n++ < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) {
1661		result++;
1662	    }
1663	}
1664    }
1665    TRACE(("...param_has_subparams(%d) ->%d\n", item, result));
1666    return result;
1667}
1668
1669#if OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS
1670/*
1671 * Given an index into the parameter array, return the corresponding parameter
1672 * number (starting from zero).
1673 */
1674static int
1675param_number(int item)
1676{
1677    int result = -1;
1678    int j, p;
1679
1680    for (j = p = 0; j < nparam; ++j, ++p) {
1681	if (p >= item) {
1682	    result = j;
1683	    break;
1684	}
1685	if (parms.is_sub[j]) {
1686	    while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) {
1687		/* EMPTY */
1688	    }
1689	    --j;
1690	}
1691    }
1692
1693    TRACE2(("...param_number(%d) = %d\n", item, result));
1694    return result;
1695}
1696
1697static int
1698get_subparam(int p, int s)
1699{
1700    int item = subparam_index(p, s);
1701    int result = (item >= 0) ? parms.params[item] : DEFAULT;
1702    TRACE(("...get_subparam[%d] = %d\n", item, result));
1703    return result;
1704}
1705
1706/*
1707 * Some background -
1708 *
1709 * Todd Larason provided the initial changes to support 256-colors in July 1999.
1710 * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and
1711 * was unsure if there would be some standard using those codes.  His response
1712 * was that this was documented (it turns out, in equally vague terms) in ITU
1713 * T.416
1714 *
1715 * Discussing this with Todd Larason in mid-1999, my point was that given the
1716 * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going
1717 * to be effective (more than $100 then, more than $200 in 2012)
1718 *
1719 * We overlooked the detail about ":" as a subparameter delimiter (documented
1720 * in 5.4.t2 in ECMA-48).  Some discussion in KDE in mid-2006 led Lars Doelle
1721 * to discuss the issue with me.  Lars' initial concern dealt with the fact
1722 * that a sequence such as
1723 *	CSI 38 ; 5 ; 1 m
1724 * violated the principle that SGR parameters could be used in any order.
1725 * Further discussion (see KDE #107487) resolved that the standard expected
1726 * that the sequence would look like
1727 *	CSI 38 ; 5 : 1 m
1728 * which still violates that principle, since the "5:1" parameter has to
1729 * follow the "38" to be useful.
1730 *
1731 * This function accepts either format (per request by Paul Leonerd Evans).
1732 * It also accepts
1733 *	CSI 38 : 5 : 1 m
1734 * according to Lars' original assumption.
1735 *
1736 * By the way - all of the parameters are decimal integers.
1737 */
1738#define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0))
1739static Boolean
1740parse_extended_colors(XtermWidget xw, int *colorp, int *itemp)
1741{
1742    Boolean result = False;
1743    int item = *itemp;
1744    int next = item;
1745    int base = param_number(item);
1746    int code = -1;
1747    int values[3];		/* maximum number of subparameters */
1748    int need = 0;		/* number of subparameters needed */
1749    int have;
1750    int n;
1751
1752    /*
1753     * On entry, 'item' points to the 38/48 code in the parameter array.
1754     * If that has subparameters, we will expect all of the values to
1755     * be subparameters of that item.
1756     */
1757    if ((have = param_has_subparams(item)) != 0) {
1758	/* accept CSI 38 : 5 : 1 m */
1759	/* accept CSI 38 : 2 : 1 : 2 : 3 m */
1760	code = get_subparam(base, 1);
1761	need = extended_colors_limit(code);
1762	next = item + have;
1763	for (n = 0; n < need && n < 3; ++n) {
1764	    values[n] = get_subparam(base, 2 + n);
1765	}
1766    } else if (++item < nparam) {
1767	++base;
1768	if ((have = param_has_subparams(item)) != 0) {
1769	    /* accept CSI 38 ; 5 : 1 m */
1770	    /* accept CSI 38 ; 2 : 1 : 2 : 3 m */
1771	    code = get_subparam(base, 0);
1772	    need = extended_colors_limit(code);
1773	    next = base + have;
1774	    for (n = 0; n < need && n < 3; ++n) {
1775		values[n] = get_subparam(base, 1 + n);
1776	    }
1777	} else {
1778	    /* accept CSI 38 ; 5 ; 1 m */
1779	    /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */
1780	    code = GetParam(item);
1781	    need = extended_colors_limit(code);
1782	    next = item + need;
1783	    for (n = 0; n < need && n < 3; ++n) {
1784		values[n] = GetParam(item + 1 + n);
1785	    }
1786	}
1787    }
1788    item = next;
1789
1790    switch (code) {
1791    case 2:
1792	/* direct color in rgb space */
1793	if ((values[0] >= 0 && values[0] < 256) &&
1794	    (values[1] >= 0 && values[1] < 256) &&
1795	    (values[2] >= 0 && values[2] < 256)) {
1796	    *colorp = xtermClosestColor(xw, values[0], values[1], values[2]);
1797	} else {
1798	    *colorp = -1;
1799	}
1800	break;
1801    case 5:
1802	/* indexed color */
1803	*colorp = values[0];
1804	break;
1805    default:
1806	*colorp = -1;
1807	break;
1808    }
1809
1810    result = (*colorp >= 0 && *colorp < NUM_ANSI_COLORS);
1811    TRACE(("...resulting color %d/%d %s\n",
1812	   *colorp, NUM_ANSI_COLORS,
1813	   result ? "OK" : "ERR"));
1814
1815    *itemp = item;
1816    return result;
1817}
1818#endif /* ...extended_colors */
1819
1820static int
1821optional_param(int which)
1822{
1823    return (nparam > which) ? GetParam(which) : DEFAULT;
1824}
1825
1826static int
1827zero_if_default(int which)
1828{
1829    int result = (nparam > which) ? GetParam(which) : 0;
1830    if (result <= 0)
1831	result = 0;
1832    return result;
1833}
1834
1835static int
1836one_if_default(int which)
1837{
1838    int result = (nparam > which) ? GetParam(which) : 0;
1839    if (result <= 0)
1840	result = 1;
1841    return result;
1842}
1843
1844/*
1845 * Color palette changes using the OSC controls require a repaint of the
1846 * screen - but not immediately.  Do the repaint as soon as we detect a
1847 * state which will not lead to another color palette change.
1848 */
1849static void
1850repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp)
1851{
1852    Boolean ignore = False;
1853
1854    switch (sp->nextstate) {
1855    case CASE_ESC:
1856	ignore = ((sp->parsestate == ansi_table) ||
1857		  (sp->parsestate == sos_table));
1858	break;
1859    case CASE_OSC:
1860	ignore = ((sp->parsestate == ansi_table) ||
1861		  (sp->parsestate == esc_table));
1862	break;
1863    case CASE_IGNORE:
1864	ignore = (sp->parsestate == sos_table);
1865	break;
1866    case CASE_ST:
1867	ignore = ((sp->parsestate == esc_table) ||
1868		  (sp->parsestate == sos_table));
1869	break;
1870    case CASE_ESC_DIGIT:
1871	ignore = (sp->parsestate == csi_table);
1872	break;
1873    case CASE_ESC_SEMI:
1874	ignore = (sp->parsestate == csi2_table);
1875	break;
1876    }
1877
1878    if (!ignore) {
1879	TRACE(("repaintWhenPaletteChanged\n"));
1880	xw->work.palette_changed = False;
1881	xtermRepaint(xw);
1882    }
1883}
1884
1885#if OPT_C1_PRINT || OPT_WIDE_CHARS
1886#define ParseSOS(screen) ((screen)->c1_printable == 0)
1887#else
1888#define ParseSOS(screen) 0
1889#endif
1890
1891#define ResetState(sp) ParamsDone(), (sp)->parsestate = (sp)->groundtable
1892
1893static void
1894illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp)
1895{
1896    ResetState(sp);
1897    sp->nextstate = sp->parsestate[E2A(c)];
1898    Bell(xw, XkbBI_MinorError, 0);
1899}
1900
1901static void
1902init_parser(XtermWidget xw, struct ParseState *sp)
1903{
1904    TScreen *screen = TScreenOf(xw);
1905
1906    memset(sp, 0, sizeof(*sp));
1907    sp->scssize = 94;		/* number of printable/nonspace ASCII */
1908    sp->lastchar = -1;		/* not a legal IChar */
1909    sp->nextstate = -1;		/* not a legal state */
1910
1911    init_groundtable(screen, sp);
1912    ResetState(sp);
1913}
1914
1915static void
1916init_reply(unsigned type)
1917{
1918    memset(&reply, 0, sizeof(reply));
1919    reply.a_type = (Char) type;
1920}
1921
1922static Boolean
1923doparsing(XtermWidget xw, unsigned c, struct ParseState *sp)
1924{
1925    TScreen *screen = TScreenOf(xw);
1926    int item;
1927    int count;
1928    int value;
1929    int laststate;
1930    int thischar = -1;
1931    XTermRect myRect;
1932
1933    do {
1934#if OPT_WIDE_CHARS
1935	int this_is_wide = 0;
1936
1937	/*
1938	 * Handle zero-width combining characters.  Make it faster by noting
1939	 * that according to the Unicode charts, the majority of Western
1940	 * character sets do not use this feature.  There are some unassigned
1941	 * codes at 0x242, but no zero-width characters until past 0x300.
1942	 */
1943	if (c >= 0x300
1944	    && screen->wide_chars
1945	    && my_wcwidth((wchar_t) c) == 0
1946	    && !isWideControl(c)) {
1947	    int prev, test;
1948	    Boolean used = True;
1949	    int use_row;
1950	    int use_col;
1951
1952	    WriteNow();
1953	    use_row = (screen->char_was_written
1954		       ? screen->last_written_row
1955		       : screen->cur_row);
1956	    use_col = (screen->char_was_written
1957		       ? screen->last_written_col
1958		       : screen->cur_col);
1959
1960	    /*
1961	     * Check if the latest data can be added to the base character.
1962	     * If there is already a combining character stored for the cell,
1963	     * we cannot, since that would change the order.
1964	     */
1965	    if (screen->normalized_c
1966		&& !IsCellCombined(screen, use_row, use_col)) {
1967		prev = (int) XTERM_CELL(use_row, use_col);
1968		test = do_precomposition(prev, (int) c);
1969		TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n",
1970		       prev, my_wcwidth((wchar_t) prev),
1971		       (int) c, my_wcwidth((wchar_t) c),
1972		       test, my_wcwidth((wchar_t) test)));
1973	    } else {
1974		prev = -1;
1975		test = -1;
1976	    }
1977
1978	    /* substitute combined character with precomposed character
1979	     * only if it does not change the width of the base character
1980	     */
1981	    if (test != -1
1982		&& my_wcwidth((wchar_t) test) == my_wcwidth((wchar_t) prev)) {
1983		putXtermCell(screen, use_row, use_col, test);
1984	    } else if (screen->char_was_written
1985		       || getXtermCell(screen, use_row, use_col) > ' ') {
1986		addXtermCombining(screen, use_row, use_col, c);
1987	    } else {
1988		/*
1989		 * none of the above... we will add the combining character as
1990		 * a base character.
1991		 */
1992		used = False;
1993	    }
1994
1995	    if (used) {
1996		if (!screen->scroll_amt)
1997		    ScrnUpdate(xw, use_row, use_col, 1, 1, 1);
1998		continue;
1999	    }
2000	}
2001#endif
2002
2003	/* Intercept characters for printer controller mode */
2004	if (PrinterOf(screen).printer_controlmode == 2) {
2005	    if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0)
2006		continue;
2007	}
2008
2009	/*
2010	 * VT52 is a little ugly in the one place it has a parameterized
2011	 * control sequence, since the parameter falls after the character
2012	 * that denotes the type of sequence.
2013	 */
2014#if OPT_VT52_MODE
2015	if (sp->vt52_cup) {
2016	    if (nparam < NPARAM - 1) {
2017		SetParam(nparam++, (int) (c & 0x7f) - 32);
2018		parms.is_sub[nparam] = 0;
2019	    }
2020	    if (nparam < 2)
2021		continue;
2022	    sp->vt52_cup = False;
2023	    CursorSet(screen, zero_if_default(0), zero_if_default(1), xw->flags);
2024	    sp->parsestate = vt52_table;
2025	    SetParam(0, 0);
2026	    SetParam(1, 0);
2027	    continue;
2028	}
2029#endif
2030
2031	laststate = sp->nextstate;
2032	if (c == ANSI_DEL
2033	    && sp->parsestate == sp->groundtable
2034	    && sp->scssize == 96
2035	    && sp->scstype != 0) {
2036	    /*
2037	     * Handle special case of shifts for 96-character sets by checking
2038	     * if we have a DEL.  The other special case for SPACE will always
2039	     * be printable.
2040	     */
2041	    sp->nextstate = CASE_PRINT;
2042	} else
2043#if OPT_WIDE_CHARS
2044	if (c > 255) {
2045	    /*
2046	     * The parsing tables all have 256 entries.  If we're supporting
2047	     * wide characters, we handle them by treating them the same as
2048	     * printing characters.
2049	     */
2050	    if (sp->parsestate == sp->groundtable) {
2051		sp->nextstate = CASE_PRINT;
2052	    } else if (sp->parsestate == sos_table) {
2053		c &= 0xffff;
2054		if (c > 255) {
2055		    TRACE(("Found code > 255 while in SOS state: %04X\n", c));
2056		    c = '?';
2057		}
2058	    } else {
2059		sp->nextstate = CASE_GROUND_STATE;
2060	    }
2061	} else
2062#endif
2063	    sp->nextstate = sp->parsestate[E2A(c)];
2064
2065#if OPT_BROKEN_OSC
2066	/*
2067	 * Linux console palette escape sequences start with an OSC, but do
2068	 * not terminate correctly.  Some scripts do not check before writing
2069	 * them, making xterm appear to hang (it's awaiting a valid string
2070	 * terminator).  Just ignore these if we see them - there's no point
2071	 * in emulating bad code.
2072	 */
2073	if (screen->brokenLinuxOSC
2074	    && sp->parsestate == sos_table) {
2075	    if (sp->string_used) {
2076		switch (sp->string_area[0]) {
2077		case 'P':
2078		    if (sp->string_used <= 7)
2079			break;
2080		    /* FALLTHRU */
2081		case 'R':
2082		    illegal_parse(xw, c, sp);
2083		    TRACE(("Reset to ground state (brokenLinuxOSC)\n"));
2084		    break;
2085		}
2086	    }
2087	}
2088#endif
2089
2090#if OPT_BROKEN_ST
2091	/*
2092	 * Before patch #171, carriage control embedded within an OSC string
2093	 * would terminate it.  Some (buggy, of course) applications rely on
2094	 * this behavior.  Accommodate them by allowing one to compile xterm
2095	 * and emulate the old behavior.
2096	 */
2097	if (screen->brokenStringTerm
2098	    && sp->parsestate == sos_table
2099	    && c < 32) {
2100	    switch (c) {
2101	    case ANSI_EOT:	/* FALLTHRU */
2102	    case ANSI_BS:	/* FALLTHRU */
2103	    case ANSI_HT:	/* FALLTHRU */
2104	    case ANSI_LF:	/* FALLTHRU */
2105	    case ANSI_VT:	/* FALLTHRU */
2106	    case ANSI_FF:	/* FALLTHRU */
2107	    case ANSI_CR:	/* FALLTHRU */
2108	    case ANSI_SO:	/* FALLTHRU */
2109	    case ANSI_SI:	/* FALLTHRU */
2110	    case ANSI_XON:	/* FALLTHRU */
2111	    case ANSI_CAN:
2112		illegal_parse(xw, c, sp);
2113		TRACE(("Reset to ground state (brokenStringTerm)\n"));
2114		break;
2115	    }
2116	}
2117#endif
2118
2119#if OPT_C1_PRINT
2120	/*
2121	 * This is not completely foolproof, but will allow an application
2122	 * with values in the C1 range to use them as printable characters,
2123	 * provided that they are not intermixed with an escape sequence.
2124	 */
2125	if (screen->c1_printable
2126	    && (c >= 128 && c < 256)) {
2127	    sp->nextstate = (sp->parsestate == esc_table
2128			     ? CASE_ESC_IGNORE
2129			     : sp->parsestate[E2A(160)]);
2130	    TRACE(("allowC1Printable %04X %s ->%s\n",
2131		   c, which_table(sp->parsestate),
2132		   visibleVTparse(sp->nextstate)));
2133	}
2134#endif
2135
2136#if OPT_WIDE_CHARS
2137	/*
2138	 * If we have a C1 code and the c1_printable flag is not set, simply
2139	 * ignore it when it was translated from UTF-8.  That is because the
2140	 * value could not have been present as-is in the UTF-8.
2141	 *
2142	 * To see that CASE_IGNORE is a consistent value, note that it is
2143	 * always used for NUL and other uninteresting C0 controls.
2144	 */
2145#if OPT_C1_PRINT
2146	if (!screen->c1_printable)
2147#endif
2148	    if (screen->wide_chars
2149		&& (c >= 128 && c < 160)) {
2150		sp->nextstate = CASE_IGNORE;
2151	    }
2152
2153	/*
2154	 * If this character is a different width than the last one, put the
2155	 * previous text into the buffer and draw it now.
2156	 */
2157	this_is_wide = isWide((int) c);
2158	if (this_is_wide != sp->last_was_wide) {
2159	    WriteNow();
2160	}
2161#endif
2162
2163	/*
2164	 * Accumulate string for printable text.  This may be 8/16-bit
2165	 * characters.
2166	 */
2167	if (sp->nextstate == CASE_PRINT) {
2168	    SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size);
2169	    if (new_string == 0) {
2170		xtermWarning("Cannot allocate %lu bytes for printable text\n",
2171			     (unsigned long) new_length);
2172		continue;
2173	    }
2174	    SafeFree(sp->print_area, sp->print_size);
2175#if OPT_VT52_MODE
2176	    /*
2177	     * Strip output text to 7-bits for VT52.  We should do this for
2178	     * VT100 also (which is a 7-bit device), but xterm has been
2179	     * doing this for so long we shouldn't change this behavior.
2180	     */
2181	    if (screen->vtXX_level < 1)
2182		c &= 0x7f;
2183#endif
2184	    sp->print_area[sp->print_used++] = (IChar) c;
2185	    sp->lastchar = thischar = (int) c;
2186#if OPT_WIDE_CHARS
2187	    sp->last_was_wide = this_is_wide;
2188#endif
2189	    if (morePtyData(screen, VTbuffer)) {
2190		continue;
2191	    }
2192	}
2193
2194	if (sp->nextstate == CASE_PRINT
2195	    || (laststate == CASE_PRINT && sp->print_used)) {
2196	    WriteNow();
2197	}
2198
2199	/*
2200	 * Accumulate string for APC, DCS, PM, OSC, SOS controls
2201	 * This should always be 8-bit characters.
2202	 */
2203	if (sp->parsestate == sos_table) {
2204	    SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size);
2205	    if (new_string == 0) {
2206		xtermWarning("Cannot allocate %lu bytes for string mode %d\n",
2207			     (unsigned long) new_length, sp->string_mode);
2208		continue;
2209	    }
2210	    SafeFree(sp->string_area, sp->string_size);
2211#if OPT_WIDE_CHARS
2212	    /*
2213	     * We cannot display codes above 255, but let's try to
2214	     * accommodate the application a little by not aborting the
2215	     * string.
2216	     */
2217	    if ((c & 0xffff) > 255) {
2218		sp->nextstate = CASE_PRINT;
2219		c = '?';
2220	    }
2221#endif
2222	    sp->string_area[(sp->string_used)++] = CharOf(c);
2223	} else if (sp->parsestate != esc_table) {
2224	    /* if we were accumulating, we're not any more */
2225	    sp->string_mode = 0;
2226	    sp->string_used = 0;
2227	}
2228
2229	DumpParams();
2230	TRACE(("parse %04X -> %s %s (used=%lu)\n",
2231	       c, visibleVTparse(sp->nextstate),
2232	       which_table(sp->parsestate),
2233	       (unsigned long) sp->string_used));
2234
2235	/*
2236	 * If the parameter list has subparameters (tokens separated by ":")
2237	 * reject any controls that do not accept subparameters.
2238	 */
2239	if (parms.has_subparams) {
2240	    switch (sp->nextstate) {
2241	    case CASE_GROUND_STATE:
2242	    case CASE_CSI_IGNORE:
2243		/* FALLTHRU */
2244
2245	    case CASE_ESC_DIGIT:
2246	    case CASE_ESC_SEMI:
2247	    case CASE_ESC_COLON:
2248		/* these states are required to parse parameter lists */
2249		break;
2250
2251	    case CASE_SGR:
2252		TRACE(("...possible subparam usage\n"));
2253		break;
2254
2255	    case CASE_CSI_DEC_DOLLAR_STATE:
2256	    case CASE_CSI_DOLLAR_STATE:
2257	    case CASE_CSI_EX_STATE:
2258	    case CASE_CSI_QUOTE_STATE:
2259	    case CASE_CSI_SPACE_STATE:
2260	    case CASE_CSI_STAR_STATE:
2261	    case CASE_CSI_TICK_STATE:
2262	    case CASE_DEC2_STATE:
2263	    case CASE_DEC3_STATE:
2264	    case CASE_DEC_STATE:
2265		/* use this branch when we do not yet have the final character */
2266		TRACE(("...unexpected subparam usage\n"));
2267		ParamsDone();
2268		sp->nextstate = CASE_CSI_IGNORE;
2269		break;
2270
2271	    default:
2272		/* use this branch for cases where we have the final character
2273		 * in the table that processed the parameter list.
2274		 */
2275		TRACE(("...unexpected subparam usage\n"));
2276		ResetState(sp);
2277		continue;
2278	    }
2279	}
2280
2281	if (xw->work.palette_changed) {
2282	    repaintWhenPaletteChanged(xw, sp);
2283	}
2284
2285	switch (sp->nextstate) {
2286	case CASE_PRINT:
2287	    TRACE(("CASE_PRINT - printable characters\n"));
2288	    break;
2289
2290	case CASE_GROUND_STATE:
2291	    TRACE(("CASE_GROUND_STATE - exit ignore mode\n"));
2292	    ResetState(sp);
2293	    break;
2294
2295	case CASE_IGNORE:
2296	    TRACE(("CASE_IGNORE - Ignore character %02X\n", c));
2297	    break;
2298
2299	case CASE_ENQ:
2300	    TRACE(("CASE_ENQ - answerback\n"));
2301	    for (count = 0; screen->answer_back[count] != 0; count++)
2302		unparseputc(xw, screen->answer_back[count]);
2303	    unparse_end(xw);
2304	    break;
2305
2306	case CASE_BELL:
2307	    TRACE(("CASE_BELL - bell\n"));
2308	    if (sp->string_mode == ANSI_OSC) {
2309		if (sp->string_used)
2310		    sp->string_area[--(sp->string_used)] = '\0';
2311		do_osc(xw, sp->string_area, sp->string_used, (int) c);
2312		ResetState(sp);
2313	    } else {
2314		/* bell */
2315		Bell(xw, XkbBI_TerminalBell, 0);
2316	    }
2317	    break;
2318
2319	case CASE_BS:
2320	    TRACE(("CASE_BS - backspace\n"));
2321	    CursorBack(xw, 1);
2322	    break;
2323
2324	case CASE_CR:
2325	    TRACE(("CASE_CR\n"));
2326	    CarriageReturn(xw);
2327	    break;
2328
2329	case CASE_ESC:
2330	    if_OPT_VT52_MODE(screen, {
2331		sp->parsestate = vt52_esc_table;
2332		break;
2333	    });
2334	    sp->parsestate = esc_table;
2335	    break;
2336
2337#if OPT_VT52_MODE
2338	case CASE_VT52_CUP:
2339	    TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n"));
2340	    sp->vt52_cup = True;
2341	    InitParams();
2342	    break;
2343
2344	case CASE_VT52_IGNORE:
2345	    TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n"));
2346	    sp->parsestate = vt52_ignore_table;
2347	    break;
2348#endif
2349
2350	case CASE_VMOT:
2351	    TRACE(("CASE_VMOT\n"));
2352	    /*
2353	     * form feed, line feed, vertical tab
2354	     */
2355	    xtermAutoPrint(xw, c);
2356	    xtermIndex(xw, 1);
2357	    if (xw->flags & LINEFEED)
2358		CarriageReturn(xw);
2359	    else
2360		do_xevents();
2361	    break;
2362
2363	case CASE_CBT:
2364	    TRACE(("CASE_CBT\n"));
2365	    /* cursor backward tabulation */
2366	    count = one_if_default(0);
2367	    while ((count-- > 0)
2368		   && (TabToPrevStop(xw))) ;
2369	    ResetState(sp);
2370	    break;
2371
2372	case CASE_CHT:
2373	    TRACE(("CASE_CHT\n"));
2374	    /* cursor forward tabulation */
2375	    count = one_if_default(0);
2376	    while ((count-- > 0)
2377		   && (TabToNextStop(xw))) ;
2378	    ResetState(sp);
2379	    break;
2380
2381	case CASE_TAB:
2382	    /* tab */
2383	    TabToNextStop(xw);
2384	    break;
2385
2386	case CASE_SI:
2387	    screen->curgl = 0;
2388	    if_OPT_VT52_MODE(screen, {
2389		ResetState(sp);
2390	    });
2391	    break;
2392
2393	case CASE_SO:
2394	    screen->curgl = 1;
2395	    if_OPT_VT52_MODE(screen, {
2396		ResetState(sp);
2397	    });
2398	    break;
2399
2400	case CASE_DECDHL:
2401	    xterm_DECDHL(xw, c == '3');
2402	    ResetState(sp);
2403	    break;
2404
2405	case CASE_DECSWL:
2406	    xterm_DECSWL(xw);
2407	    ResetState(sp);
2408	    break;
2409
2410	case CASE_DECDWL:
2411	    xterm_DECDWL(xw);
2412	    ResetState(sp);
2413	    break;
2414
2415	case CASE_SCR_STATE:
2416	    /* enter scr state */
2417	    sp->parsestate = scrtable;
2418	    break;
2419
2420	case CASE_SCS0_STATE:
2421	    /* enter scs state 0 */
2422	    select_charset(sp, 0, 94);
2423	    break;
2424
2425	case CASE_SCS1_STATE:
2426	    /* enter scs state 1 */
2427	    select_charset(sp, 1, 94);
2428	    break;
2429
2430	case CASE_SCS2_STATE:
2431	    /* enter scs state 2 */
2432	    select_charset(sp, 2, 94);
2433	    break;
2434
2435	case CASE_SCS3_STATE:
2436	    /* enter scs state 3 */
2437	    select_charset(sp, 3, 94);
2438	    break;
2439
2440	case CASE_SCS1A_STATE:
2441	    /* enter scs state 1 */
2442	    select_charset(sp, 1, 96);
2443	    break;
2444
2445	case CASE_SCS2A_STATE:
2446	    /* enter scs state 2 */
2447	    select_charset(sp, 2, 96);
2448	    break;
2449
2450	case CASE_SCS3A_STATE:
2451	    /* enter scs state 3 */
2452	    select_charset(sp, 3, 96);
2453	    break;
2454
2455	case CASE_ESC_IGNORE:
2456	    /* unknown escape sequence */
2457	    sp->parsestate = eigtable;
2458	    break;
2459
2460	case CASE_ESC_DIGIT:
2461	    /* digit in csi or dec mode */
2462	    if (nparam > 0) {
2463		value = zero_if_default(nparam - 1);
2464		SetParam(nparam - 1, (10 * value) + ((int) c - '0'));
2465		if (GetParam(nparam - 1) > 65535)
2466		    SetParam(nparam - 1, 65535);
2467		if (sp->parsestate == csi_table)
2468		    sp->parsestate = csi2_table;
2469	    }
2470	    break;
2471
2472	case CASE_ESC_SEMI:
2473	    /* semicolon in csi or dec mode */
2474	    if (nparam < NPARAM) {
2475		parms.is_sub[nparam] = 0;
2476		SetParam(nparam++, DEFAULT);
2477	    }
2478	    if (sp->parsestate == csi_table)
2479		sp->parsestate = csi2_table;
2480	    break;
2481
2482	    /*
2483	     * A _few_ commands accept colon-separated subparameters.
2484	     * Mark the parameter list so that we can exclude (most) bogus
2485	     * commands with simple/fast checks.
2486	     */
2487	case CASE_ESC_COLON:
2488	    if (nparam < NPARAM) {
2489		parms.has_subparams = 1;
2490		if (nparam == 0) {
2491		    parms.is_sub[nparam] = 1;
2492		    SetParam(nparam++, DEFAULT);
2493		} else if (parms.is_sub[nparam - 1] == 0) {
2494		    parms.is_sub[nparam - 1] = 1;
2495		    parms.is_sub[nparam] = 2;
2496		    parms.params[nparam] = 0;
2497		    ++nparam;
2498		} else {
2499		    parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1];
2500		    parms.params[nparam] = 0;
2501		    ++nparam;
2502		}
2503	    }
2504	    break;
2505
2506	case CASE_DEC_STATE:
2507	    /* enter dec mode */
2508	    sp->parsestate = dec_table;
2509	    break;
2510
2511	case CASE_DEC2_STATE:
2512	    /* enter dec2 mode */
2513	    sp->parsestate = dec2_table;
2514	    break;
2515
2516	case CASE_DEC3_STATE:
2517	    /* enter dec3 mode */
2518	    sp->parsestate = dec3_table;
2519	    break;
2520
2521	case CASE_ICH:
2522	    TRACE(("CASE_ICH - insert char\n"));
2523	    InsertChar(xw, (unsigned) one_if_default(0));
2524	    ResetState(sp);
2525	    break;
2526
2527	case CASE_CUU:
2528	    TRACE(("CASE_CUU - cursor up\n"));
2529	    CursorUp(screen, one_if_default(0));
2530	    ResetState(sp);
2531	    break;
2532
2533	case CASE_CUD:
2534	    TRACE(("CASE_CUD - cursor down\n"));
2535	    CursorDown(screen, one_if_default(0));
2536	    ResetState(sp);
2537	    break;
2538
2539	case CASE_CUF:
2540	    TRACE(("CASE_CUF - cursor forward\n"));
2541	    CursorForward(xw, one_if_default(0));
2542	    ResetState(sp);
2543	    break;
2544
2545	case CASE_CUB:
2546	    TRACE(("CASE_CUB - cursor backward\n"));
2547	    CursorBack(xw, one_if_default(0));
2548	    ResetState(sp);
2549	    break;
2550
2551	case CASE_CUP:
2552	    TRACE(("CASE_CUP - cursor position\n"));
2553	    if_OPT_XMC_GLITCH(screen, {
2554		Jump_XMC(xw);
2555	    });
2556	    CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags);
2557	    ResetState(sp);
2558	    break;
2559
2560	case CASE_VPA:
2561	    TRACE(("CASE_VPA - vertical position absolute\n"));
2562	    CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags);
2563	    ResetState(sp);
2564	    break;
2565
2566	case CASE_HPA:
2567	    TRACE(("CASE_HPA - horizontal position absolute\n"));
2568	    CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags);
2569	    ResetState(sp);
2570	    break;
2571
2572	case CASE_VPR:
2573	    TRACE(("CASE_VPR - vertical position relative\n"));
2574	    CursorSet(screen,
2575		      CursorRow(xw) + one_if_default(0),
2576		      CursorCol(xw),
2577		      xw->flags);
2578	    ResetState(sp);
2579	    break;
2580
2581	case CASE_HPR:
2582	    TRACE(("CASE_HPR - horizontal position relative\n"));
2583	    CursorSet(screen,
2584		      CursorRow(xw),
2585		      CursorCol(xw) + one_if_default(0),
2586		      xw->flags);
2587	    ResetState(sp);
2588	    break;
2589
2590	case CASE_HP_BUGGY_LL:
2591	    TRACE(("CASE_HP_BUGGY_LL\n"));
2592	    /* Some HP-UX applications have the bug that they
2593	       assume ESC F goes to the lower left corner of
2594	       the screen, regardless of what terminfo says. */
2595	    if (screen->hp_ll_bc)
2596		CursorSet(screen, screen->max_row, 0, xw->flags);
2597	    ResetState(sp);
2598	    break;
2599
2600	case CASE_ED:
2601	    TRACE(("CASE_ED - erase display\n"));
2602	    do_cd_xtra_scroll(xw);
2603	    do_erase_display(xw, zero_if_default(0), OFF_PROTECT);
2604	    ResetState(sp);
2605	    break;
2606
2607	case CASE_EL:
2608	    TRACE(("CASE_EL - erase line\n"));
2609	    do_erase_line(xw, zero_if_default(0), OFF_PROTECT);
2610	    ResetState(sp);
2611	    break;
2612
2613	case CASE_ECH:
2614	    TRACE(("CASE_ECH - erase char\n"));
2615	    /* ECH */
2616	    ClearRight(xw, one_if_default(0));
2617	    ResetState(sp);
2618	    break;
2619
2620	case CASE_IL:
2621	    TRACE(("CASE_IL - insert line\n"));
2622	    set_cur_col(screen, ScrnLeftMargin(xw));
2623	    InsertLine(xw, one_if_default(0));
2624	    ResetState(sp);
2625	    break;
2626
2627	case CASE_DL:
2628	    TRACE(("CASE_DL - delete line\n"));
2629	    set_cur_col(screen, ScrnLeftMargin(xw));
2630	    DeleteLine(xw, one_if_default(0));
2631	    ResetState(sp);
2632	    break;
2633
2634	case CASE_DCH:
2635	    TRACE(("CASE_DCH - delete char\n"));
2636	    DeleteChar(xw, (unsigned) one_if_default(0));
2637	    ResetState(sp);
2638	    break;
2639
2640	case CASE_TRACK_MOUSE:
2641	    /*
2642	     * A single parameter other than zero is always scroll-down.
2643	     * A zero-parameter is used to reset the mouse mode, and is
2644	     * not useful for scrolling anyway.
2645	     */
2646	    if (nparam > 1 || GetParam(0) == 0) {
2647		CELL start;
2648
2649		TRACE(("CASE_TRACK_MOUSE\n"));
2650		/* Track mouse as long as in window and between
2651		 * specified rows
2652		 */
2653		start.row = one_if_default(2) - 1;
2654		start.col = GetParam(1) - 1;
2655		TrackMouse(xw,
2656			   GetParam(0),
2657			   &start,
2658			   GetParam(3) - 1, GetParam(4) - 2);
2659	    } else {
2660		TRACE(("CASE_SD - scroll down\n"));
2661		/* SD */
2662		RevScroll(xw, one_if_default(0));
2663		do_xevents();
2664	    }
2665	    ResetState(sp);
2666	    break;
2667
2668	case CASE_DECID:
2669	    TRACE(("CASE_DECID\n"));
2670	    if_OPT_VT52_MODE(screen, {
2671		unparseputc(xw, ANSI_ESC);
2672		unparseputc(xw, '/');
2673		unparseputc(xw, 'Z');
2674		unparse_end(xw);
2675		ResetState(sp);
2676		break;
2677	    });
2678	    SetParam(0, DEFAULT);	/* Default ID parameter */
2679	    /* FALLTHRU */
2680	case CASE_DA1:
2681	    TRACE(("CASE_DA1\n"));
2682	    if (GetParam(0) <= 0) {	/* less than means DEFAULT */
2683		count = 0;
2684		init_reply(ANSI_CSI);
2685		reply.a_pintro = '?';
2686
2687		/*
2688		 * The first parameter corresponds to the highest operating
2689		 * level (i.e., service level) of the emulation.  A DEC
2690		 * terminal can be setup to respond with a different DA
2691		 * response, but there's no control sequence that modifies
2692		 * this.  We set it via a resource.
2693		 */
2694		if (screen->terminal_id < 200) {
2695		    switch (screen->terminal_id) {
2696		    case 125:
2697			reply.a_param[count++] = 12;	/* VT125 */
2698#if OPT_REGIS_GRAPHICS
2699			reply.a_param[count++] = 0 | 2 | 1;	/* no STP, AVO, GPO (ReGIS) */
2700#else
2701			reply.a_param[count++] = 0 | 2 | 0;	/* no STP, AVO, no GPO (ReGIS) */
2702#endif
2703			reply.a_param[count++] = 0;	/* no printer */
2704			reply.a_param[count++] = XTERM_PATCH;	/* ROM version */
2705			break;
2706		    case 102:
2707			reply.a_param[count++] = 6;	/* VT102 */
2708			break;
2709		    case 101:
2710			reply.a_param[count++] = 1;	/* VT101 */
2711			reply.a_param[count++] = 0;	/* no options */
2712			break;
2713		    default:	/* VT100 */
2714			reply.a_param[count++] = 1;	/* VT100 */
2715			reply.a_param[count++] = 0 | 2 | 0;	/* no STP, AVO, no GPO (ReGIS) */
2716			break;
2717		    }
2718		} else {
2719		    reply.a_param[count++] = (ParmType) (60
2720							 + screen->terminal_id
2721							 / 100);
2722		    reply.a_param[count++] = 1;		/* 132-columns */
2723		    reply.a_param[count++] = 2;		/* printer */
2724#if OPT_REGIS_GRAPHICS
2725		    if (screen->terminal_id == 240 ||
2726			screen->terminal_id == 241 ||
2727			screen->terminal_id == 330 ||
2728			screen->terminal_id == 340) {
2729			reply.a_param[count++] = 3;	/* ReGIS graphics */
2730		    }
2731#endif
2732#if OPT_SIXEL_GRAPHICS
2733		    if (screen->terminal_id == 240 ||
2734			screen->terminal_id == 241 ||
2735			screen->terminal_id == 330 ||
2736			screen->terminal_id == 340 ||
2737			screen->terminal_id == 382) {
2738			reply.a_param[count++] = 4;	/* sixel graphics */
2739		    }
2740#endif
2741		    reply.a_param[count++] = 6;		/* selective-erase */
2742#if OPT_SUNPC_KBD
2743		    if (xw->keyboard.type == keyboardIsVT220)
2744#endif
2745			reply.a_param[count++] = 8;	/* user-defined-keys */
2746		    reply.a_param[count++] = 9;		/* national replacement charsets */
2747		    reply.a_param[count++] = 15;	/* technical characters */
2748		    if (screen->terminal_id >= 400) {
2749			reply.a_param[count++] = 18;	/* windowing capability */
2750			reply.a_param[count++] = 21;	/* horizontal scrolling */
2751		    }
2752		    if_OPT_ISO_COLORS(screen, {
2753			reply.a_param[count++] = 22;	/* ANSI color, VT525 */
2754		    });
2755#if OPT_DEC_LOCATOR
2756		    reply.a_param[count++] = 29;	/* ANSI text locator */
2757#endif
2758		}
2759		reply.a_nparam = (ParmType) count;
2760		reply.a_inters = 0;
2761		reply.a_final = 'c';
2762		unparseseq(xw, &reply);
2763	    }
2764	    ResetState(sp);
2765	    break;
2766
2767	case CASE_DA2:
2768	    TRACE(("CASE_DA2\n"));
2769	    if (GetParam(0) <= 0) {	/* less than means DEFAULT */
2770		count = 0;
2771		init_reply(ANSI_CSI);
2772		reply.a_pintro = '>';
2773
2774		if (screen->terminal_id >= 200) {
2775		    switch (screen->terminal_id) {
2776		    case 220:
2777		    default:
2778			reply.a_param[count++] = 1;	/* VT220 */
2779			break;
2780		    case 240:
2781			/* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */
2782			reply.a_param[count++] = 2;	/* VT240 */
2783			break;
2784		    case 320:
2785			/* http://www.vt100.net/docs/vt320-uu/appendixe.html */
2786			reply.a_param[count++] = 24;	/* VT320 */
2787			break;
2788		    case 330:
2789			reply.a_param[count++] = 18;	/* VT330 */
2790			break;
2791		    case 340:
2792			reply.a_param[count++] = 19;	/* VT340 */
2793			break;
2794		    case 420:
2795			reply.a_param[count++] = 41;	/* VT420 */
2796			break;
2797		    case 510:
2798			/* http://www.vt100.net/docs/vt510-rm/DA2 */
2799			reply.a_param[count++] = 61;	/* VT510 */
2800			break;
2801		    case 520:
2802			reply.a_param[count++] = 64;	/* VT520 */
2803			break;
2804		    case 525:
2805			reply.a_param[count++] = 65;	/* VT525 */
2806			break;
2807		    }
2808		} else {
2809		    reply.a_param[count++] = 0;		/* VT100 (nonstandard) */
2810		}
2811		reply.a_param[count++] = XTERM_PATCH;	/* Version */
2812		reply.a_param[count++] = 0;	/* options (none) */
2813		reply.a_nparam = (ParmType) count;
2814		reply.a_inters = 0;
2815		reply.a_final = 'c';
2816		unparseseq(xw, &reply);
2817	    }
2818	    ResetState(sp);
2819	    break;
2820
2821	case CASE_DECRPTUI:
2822	    TRACE(("CASE_DECRPTUI\n"));
2823	    if ((screen->vtXX_level >= 4)
2824		&& (GetParam(0) <= 0)) {	/* less than means DEFAULT */
2825		unparseputc1(xw, ANSI_DCS);
2826		unparseputc(xw, '!');
2827		unparseputc(xw, '|');
2828		unparseputc(xw, '0');
2829		unparseputc1(xw, ANSI_ST);
2830		unparse_end(xw);
2831	    }
2832	    ResetState(sp);
2833	    break;
2834
2835	case CASE_TBC:
2836	    TRACE(("CASE_TBC - tab clear\n"));
2837	    if ((value = GetParam(0)) <= 0)	/* less than means default */
2838		TabClear(xw->tabs, screen->cur_col);
2839	    else if (value == 3)
2840		TabZonk(xw->tabs);
2841	    ResetState(sp);
2842	    break;
2843
2844	case CASE_SET:
2845	    TRACE(("CASE_SET - set mode\n"));
2846	    ansi_modes(xw, bitset);
2847	    ResetState(sp);
2848	    break;
2849
2850	case CASE_RST:
2851	    TRACE(("CASE_RST - reset mode\n"));
2852	    ansi_modes(xw, bitclr);
2853	    ResetState(sp);
2854	    break;
2855
2856	case CASE_SGR:
2857	    for (item = 0; item < nparam; ++item) {
2858		int op = GetParam(item);
2859
2860		if_OPT_XMC_GLITCH(screen, {
2861		    Mark_XMC(xw, op);
2862		});
2863		TRACE(("CASE_SGR %d\n", op));
2864
2865		/*
2866		 * Only SGR 38/48 accept subparameters, and in those cases
2867		 * the values will not be seen at this point.
2868		 */
2869		if (param_has_subparams(item)) {
2870		    switch (op) {
2871		    case 38:
2872			/* FALLTHRU */
2873		    case 48:
2874			if_OPT_ISO_COLORS(screen, {
2875			    break;
2876			});
2877			/* FALLTHRU */
2878		    default:
2879			TRACE(("...unexpected subparameter in SGR\n"));
2880			op = 9999;
2881			ResetState(sp);
2882			break;
2883		    }
2884		}
2885
2886		switch (op) {
2887		case DEFAULT:
2888		    /* FALLTHRU */
2889		case 0:
2890#if OPT_WIDE_ATTRS
2891		    setItalicFont(xw, False);
2892#endif
2893		    UIntClr(xw->flags,
2894			    (SGR_MASK | SGR_MASK2 | INVISIBLE));
2895		    if_OPT_ISO_COLORS(screen, {
2896			reset_SGR_Colors(xw);
2897		    });
2898		    break;
2899		case 1:	/* Bold                 */
2900		    UIntSet(xw->flags, BOLD);
2901		    if_OPT_ISO_COLORS(screen, {
2902			setExtendedFG(xw);
2903		    });
2904		    break;
2905#if OPT_WIDE_ATTRS
2906		case 2:	/* faint, decreased intensity or second colour */
2907		    UIntSet(xw->flags, ATR_FAINT);
2908		    if_OPT_ISO_COLORS(screen, {
2909			setExtendedFG(xw);
2910		    });
2911		    break;
2912		case 3:	/* italicized */
2913		    setItalicFont(xw, UseItalicFont(screen));
2914		    UIntSet(xw->flags, ATR_ITALIC);
2915		    if_OPT_ISO_COLORS(screen, {
2916			setExtendedFG(xw);
2917		    });
2918		    break;
2919#endif
2920		case 4:	/* Underscore           */
2921		    UIntSet(xw->flags, UNDERLINE);
2922		    if_OPT_ISO_COLORS(screen, {
2923			setExtendedFG(xw);
2924		    });
2925		    break;
2926		case 5:	/* Blink                */
2927		    UIntSet(xw->flags, BLINK);
2928		    StartBlinking(screen);
2929		    if_OPT_ISO_COLORS(screen, {
2930			setExtendedFG(xw);
2931		    });
2932		    break;
2933		case 7:
2934		    UIntSet(xw->flags, INVERSE);
2935		    if_OPT_ISO_COLORS(screen, {
2936			setExtendedBG(xw);
2937		    });
2938		    break;
2939		case 8:
2940		    UIntSet(xw->flags, INVISIBLE);
2941		    break;
2942#if OPT_WIDE_ATTRS
2943		case 9:	/* crossed-out characters */
2944		    UIntSet(xw->flags, ATR_STRIKEOUT);
2945		    break;
2946#endif
2947#if OPT_WIDE_ATTRS
2948		case 21:	/* doubly-underlined */
2949		    UIntSet(xw->flags, ATR_DBL_UNDER);
2950		    break;
2951#endif
2952		case 22:	/* reset 'bold' */
2953		    UIntClr(xw->flags, BOLD);
2954#if OPT_WIDE_ATTRS
2955		    UIntClr(xw->flags, ATR_FAINT);
2956#endif
2957		    if_OPT_ISO_COLORS(screen, {
2958			setExtendedFG(xw);
2959		    });
2960		    break;
2961#if OPT_WIDE_ATTRS
2962		case 23:	/* not italicized */
2963		    setItalicFont(xw, False);
2964		    UIntClr(xw->flags, ATR_ITALIC);
2965		    if_OPT_ISO_COLORS(screen, {
2966			setExtendedFG(xw);
2967		    });
2968		    break;
2969#endif
2970		case 24:
2971		    UIntClr(xw->flags, UNDERLINE);
2972#if OPT_WIDE_ATTRS
2973		    UIntClr(xw->flags, ATR_DBL_UNDER);
2974#endif
2975		    if_OPT_ISO_COLORS(screen, {
2976			setExtendedFG(xw);
2977		    });
2978		    break;
2979		case 25:	/* reset 'blink' */
2980		    UIntClr(xw->flags, BLINK);
2981		    if_OPT_ISO_COLORS(screen, {
2982			setExtendedFG(xw);
2983		    });
2984		    break;
2985		case 27:
2986		    UIntClr(xw->flags, INVERSE);
2987		    if_OPT_ISO_COLORS(screen, {
2988			setExtendedBG(xw);
2989		    });
2990		    break;
2991		case 28:
2992		    UIntClr(xw->flags, INVISIBLE);
2993		    break;
2994#if OPT_WIDE_ATTRS
2995		case 29:	/* not crossed out */
2996		    UIntClr(xw->flags, ATR_STRIKEOUT);
2997		    break;
2998#endif
2999		case 30:
3000		    /* FALLTHRU */
3001		case 31:
3002		    /* FALLTHRU */
3003		case 32:
3004		    /* FALLTHRU */
3005		case 33:
3006		    /* FALLTHRU */
3007		case 34:
3008		    /* FALLTHRU */
3009		case 35:
3010		    /* FALLTHRU */
3011		case 36:
3012		    /* FALLTHRU */
3013		case 37:
3014		    if_OPT_ISO_COLORS(screen, {
3015			xw->sgr_foreground = (op - 30);
3016			xw->sgr_extended = False;
3017			setExtendedFG(xw);
3018		    });
3019		    break;
3020		case 38:
3021		    /* This is more complicated than I'd like, but it should
3022		     * properly eat all the parameters for unsupported modes.
3023		     */
3024		    if_OPT_ISO_COLORS(screen, {
3025			if (parse_extended_colors(xw, &value, &item)) {
3026			    xw->sgr_foreground = value;
3027			    xw->sgr_extended = True;
3028			    setExtendedFG(xw);
3029			}
3030		    });
3031		    break;
3032		case 39:
3033		    if_OPT_ISO_COLORS(screen, {
3034			reset_SGR_Foreground(xw);
3035		    });
3036		    break;
3037		case 40:
3038		    /* FALLTHRU */
3039		case 41:
3040		    /* FALLTHRU */
3041		case 42:
3042		    /* FALLTHRU */
3043		case 43:
3044		    /* FALLTHRU */
3045		case 44:
3046		    /* FALLTHRU */
3047		case 45:
3048		    /* FALLTHRU */
3049		case 46:
3050		    /* FALLTHRU */
3051		case 47:
3052		    if_OPT_ISO_COLORS(screen, {
3053			xw->sgr_background = (op - 40);
3054			setExtendedBG(xw);
3055		    });
3056		    break;
3057		case 48:
3058		    if_OPT_ISO_COLORS(screen, {
3059			if (parse_extended_colors(xw, &value, &item)) {
3060			    xw->sgr_background = value;
3061			    setExtendedBG(xw);
3062			}
3063		    });
3064		    break;
3065		case 49:
3066		    if_OPT_ISO_COLORS(screen, {
3067			reset_SGR_Background(xw);
3068		    });
3069		    break;
3070		case 90:
3071		    /* FALLTHRU */
3072		case 91:
3073		    /* FALLTHRU */
3074		case 92:
3075		    /* FALLTHRU */
3076		case 93:
3077		    /* FALLTHRU */
3078		case 94:
3079		    /* FALLTHRU */
3080		case 95:
3081		    /* FALLTHRU */
3082		case 96:
3083		    /* FALLTHRU */
3084		case 97:
3085		    if_OPT_AIX_COLORS(screen, {
3086			xw->sgr_foreground = (op - 90 + 8);
3087			xw->sgr_extended = False;
3088			setExtendedFG(xw);
3089		    });
3090		    break;
3091		case 100:
3092#if !OPT_AIX_COLORS
3093		    if_OPT_ISO_COLORS(screen, {
3094			reset_SGR_Foreground(xw);
3095			reset_SGR_Background(xw);
3096		    });
3097		    break;
3098#endif
3099		case 101:
3100		    /* FALLTHRU */
3101		case 102:
3102		    /* FALLTHRU */
3103		case 103:
3104		    /* FALLTHRU */
3105		case 104:
3106		    /* FALLTHRU */
3107		case 105:
3108		    /* FALLTHRU */
3109		case 106:
3110		    /* FALLTHRU */
3111		case 107:
3112		    if_OPT_AIX_COLORS(screen, {
3113			xw->sgr_background = (op - 100 + 8);
3114			setExtendedBG(xw);
3115		    });
3116		    break;
3117		}
3118	    }
3119	    ResetState(sp);
3120	    break;
3121
3122	    /* DSR (except for the '?') is a superset of CPR */
3123	case CASE_DSR:
3124	    sp->private_function = True;
3125
3126	    /* FALLTHRU */
3127	case CASE_CPR:
3128	    TRACE(("CASE_DSR - device status report\n"));
3129	    count = 0;
3130	    init_reply(ANSI_CSI);
3131	    reply.a_pintro = CharOf(sp->private_function ? '?' : 0);
3132	    reply.a_inters = 0;
3133	    reply.a_final = 'n';
3134
3135	    switch (GetParam(0)) {
3136	    case 5:
3137		TRACE(("...request operating status\n"));
3138		/* operating status */
3139		reply.a_param[count++] = 0;	/* (no malfunction ;-) */
3140		break;
3141	    case 6:
3142		TRACE(("...request %s\n",
3143		       (sp->private_function
3144			? "DECXCPR"
3145			: "CPR")));
3146		/* CPR */
3147		/* DECXCPR (with page=1) */
3148		value = (screen->cur_row + 1);
3149		if ((xw->flags & ORIGIN) != 0) {
3150		    value -= screen->top_marg;
3151		}
3152		reply.a_param[count++] = (ParmType) value;
3153
3154		value = (screen->cur_col + 1);
3155		if ((xw->flags & ORIGIN) != 0) {
3156		    value -= screen->lft_marg;
3157		}
3158		reply.a_param[count++] = (ParmType) value;
3159
3160		if (sp->private_function
3161		    && screen->vtXX_level >= 4) {	/* VT420 */
3162		    reply.a_param[count++] = 1;
3163		}
3164		reply.a_final = 'R';
3165		break;
3166	    case 15:
3167		TRACE(("...request printer status\n"));
3168		if (sp->private_function
3169		    && screen->vtXX_level >= 2) {	/* VT220 */
3170		    reply.a_param[count++] = 13;	/* no printer detected */
3171		}
3172		break;
3173	    case 25:
3174		TRACE(("...request UDK status\n"));
3175		if (sp->private_function
3176		    && screen->vtXX_level >= 2) {	/* VT220 */
3177		    reply.a_param[count++] = 20;	/* UDK always unlocked */
3178		}
3179		break;
3180	    case 26:
3181		TRACE(("...request keyboard status\n"));
3182		if (sp->private_function
3183		    && screen->vtXX_level >= 2) {	/* VT220 */
3184		    reply.a_param[count++] = 27;
3185		    reply.a_param[count++] = 1;		/* North American */
3186		    if (screen->vtXX_level >= 4) {	/* VT420 */
3187			reply.a_param[count++] = 0;	/* ready */
3188			reply.a_param[count++] = 0;	/* LK201 */
3189		    }
3190		}
3191		break;
3192	    case 53:		/* according to existing xterm handling */
3193		/* FALLTHRU */
3194	    case 55:		/* according to the VT330/VT340 Text Programming Manual */
3195		TRACE(("...request locator status\n"));
3196		if (sp->private_function
3197		    && screen->vtXX_level >= 2) {	/* VT220 */
3198#if OPT_DEC_LOCATOR
3199		    reply.a_param[count++] = 50;	/* locator ready */
3200#else
3201		    reply.a_param[count++] = 53;	/* no locator */
3202#endif
3203		}
3204		break;
3205	    case 56:
3206		TRACE(("...request locator type\n"));
3207		if (sp->private_function
3208		    && screen->vtXX_level >= 3) {	/* VT330 (FIXME: what about VT220?) */
3209		    reply.a_param[count++] = 57;
3210#if OPT_DEC_LOCATOR
3211		    reply.a_param[count++] = 1;		/* mouse */
3212#else
3213		    reply.a_param[count++] = 0;		/* unknown */
3214#endif
3215		}
3216		break;
3217	    case 62:
3218		TRACE(("...request DECMSR - macro space\n"));
3219		if (sp->private_function
3220		    && screen->vtXX_level >= 4) {	/* VT420 */
3221		    reply.a_pintro = 0;
3222		    reply.a_radix[count] = 16;	/* no data */
3223		    reply.a_param[count++] = 0;		/* no space for macros */
3224		    reply.a_inters = '*';
3225		    reply.a_final = L_CURL;
3226		}
3227		break;
3228	    case 63:
3229		TRACE(("...request DECCKSR - memory checksum\n"));
3230		/* DECCKSR - Memory checksum */
3231		if (sp->private_function
3232		    && screen->vtXX_level >= 4) {	/* VT420 */
3233		    init_reply(ANSI_DCS);
3234		    reply.a_param[count++] = (ParmType) GetParam(1);	/* PID */
3235		    reply.a_delim = "!~";	/* delimiter */
3236		    reply.a_radix[count] = 16;	/* use hex */
3237		    reply.a_param[count++] = 0;		/* no data */
3238		}
3239		break;
3240	    case 75:
3241		TRACE(("...request data integrity\n"));
3242		if (sp->private_function
3243		    && screen->vtXX_level >= 4) {	/* VT420 */
3244		    reply.a_param[count++] = 70;	/* no errors */
3245		}
3246		break;
3247	    case 85:
3248		TRACE(("...request multi-session configuration\n"));
3249		if (sp->private_function
3250		    && screen->vtXX_level >= 4) {	/* VT420 */
3251		    reply.a_param[count++] = 83;	/* not configured */
3252		}
3253		break;
3254	    default:
3255		break;
3256	    }
3257
3258	    if ((reply.a_nparam = (ParmType) count) != 0)
3259		unparseseq(xw, &reply);
3260
3261	    ResetState(sp);
3262	    sp->private_function = False;
3263	    break;
3264
3265	case CASE_MC:
3266	    TRACE(("CASE_MC - media control\n"));
3267	    xtermMediaControl(xw, GetParam(0), False);
3268	    ResetState(sp);
3269	    break;
3270
3271	case CASE_DEC_MC:
3272	    TRACE(("CASE_DEC_MC - DEC media control\n"));
3273	    xtermMediaControl(xw, GetParam(0), True);
3274	    ResetState(sp);
3275	    break;
3276
3277	case CASE_HP_MEM_LOCK:
3278	    /* FALLTHRU */
3279	case CASE_HP_MEM_UNLOCK:
3280	    TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK)
3281			    ? "CASE_HP_MEM_LOCK"
3282			    : "CASE_HP_MEM_UNLOCK")));
3283	    if (screen->scroll_amt)
3284		FlushScroll(xw);
3285	    if (sp->parsestate[c] == CASE_HP_MEM_LOCK)
3286		set_tb_margins(screen, screen->cur_row, screen->bot_marg);
3287	    else
3288		set_tb_margins(screen, 0, screen->bot_marg);
3289	    ResetState(sp);
3290	    break;
3291
3292	case CASE_DECSTBM:
3293	    TRACE(("CASE_DECSTBM - set scrolling region\n"));
3294	    {
3295		int top;
3296		int bot;
3297		top = one_if_default(0);
3298		if (nparam < 2 || (bot = GetParam(1)) == DEFAULT
3299		    || bot > MaxRows(screen)
3300		    || bot == 0)
3301		    bot = MaxRows(screen);
3302		if (bot > top) {
3303		    if (screen->scroll_amt)
3304			FlushScroll(xw);
3305		    set_tb_margins(screen, top - 1, bot - 1);
3306		    CursorSet(screen, 0, 0, xw->flags);
3307		}
3308		ResetState(sp);
3309	    }
3310	    break;
3311
3312	case CASE_DECREQTPARM:
3313	    TRACE(("CASE_DECREQTPARM\n"));
3314	    if (screen->terminal_id < 200) {	/* VT102 */
3315		value = zero_if_default(0);
3316		if (value == 0 || value == 1) {
3317		    init_reply(ANSI_CSI);
3318		    reply.a_pintro = 0;
3319		    reply.a_nparam = 7;
3320		    reply.a_param[0] = (ParmType) (value + 2);
3321		    reply.a_param[1] = 1;	/* no parity */
3322		    reply.a_param[2] = 1;	/* eight bits */
3323		    reply.a_param[3] = 128;	/* transmit 38.4k baud */
3324		    reply.a_param[4] = 128;	/* receive 38.4k baud */
3325		    reply.a_param[5] = 1;	/* clock multiplier ? */
3326		    reply.a_param[6] = 0;	/* STP flags ? */
3327		    reply.a_inters = 0;
3328		    reply.a_final = 'x';
3329		    unparseseq(xw, &reply);
3330		}
3331	    }
3332	    ResetState(sp);
3333	    break;
3334
3335	case CASE_DECSET:
3336	    /* DECSET */
3337#if OPT_VT52_MODE
3338	    if (screen->vtXX_level != 0)
3339#endif
3340		dpmodes(xw, bitset);
3341	    ResetState(sp);
3342#if OPT_TEK4014
3343	    if (TEK4014_ACTIVE(xw)) {
3344		TRACE(("Tek4014 is now active...\n"));
3345		return False;
3346	    }
3347#endif
3348	    break;
3349
3350	case CASE_DECRST:
3351	    /* DECRST */
3352	    dpmodes(xw, bitclr);
3353	    init_groundtable(screen, sp);
3354	    ResetState(sp);
3355	    break;
3356
3357	case CASE_DECALN:
3358	    TRACE(("CASE_DECALN - alignment test\n"));
3359	    if (screen->cursor_state)
3360		HideCursor();
3361	    reset_margins(screen);
3362	    CursorSet(screen, 0, 0, xw->flags);
3363	    xtermParseRect(xw, 0, 0, &myRect);
3364	    ScrnFillRectangle(xw, &myRect, 'E', 0, False);
3365	    ResetState(sp);
3366	    break;
3367
3368	case CASE_GSETS:
3369	    TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
3370	    decode_scs(xw, sp->scstype, 0, (int) c);
3371	    ResetState(sp);
3372	    break;
3373
3374	case CASE_ANSI_SC:
3375	    if (IsLeftRightMode(xw)) {
3376		int left;
3377		int right;
3378
3379		TRACE(("CASE_DECSLRM - set left and right margin\n"));
3380		left = one_if_default(0);
3381		if (nparam < 2 || (right = GetParam(1)) == DEFAULT
3382		    || right > MaxCols(screen)
3383		    || right == 0)
3384		    right = MaxCols(screen);
3385		if (right > left) {
3386		    set_lr_margins(screen, left - 1, right - 1);
3387		    CursorSet(screen, 0, 0, xw->flags);
3388		}
3389	    } else {
3390		TRACE(("CASE_ANSI_SC - save cursor\n"));
3391		CursorSave(xw);
3392	    }
3393	    ResetState(sp);
3394	    break;
3395
3396	case CASE_DECSC:
3397	    TRACE(("CASE_DECSC - save cursor\n"));
3398	    CursorSave(xw);
3399	    ResetState(sp);
3400	    break;
3401
3402	case CASE_ANSI_RC:
3403	    /* FALLTHRU */
3404	case CASE_DECRC:
3405	    TRACE(("CASE_%sRC - restore cursor\n",
3406		   (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_"));
3407	    CursorRestore(xw);
3408	    if_OPT_ISO_COLORS(screen, {
3409		setExtendedFG(xw);
3410	    });
3411	    ResetState(sp);
3412	    break;
3413
3414	case CASE_DECKPAM:
3415	    TRACE(("CASE_DECKPAM\n"));
3416	    xw->keyboard.flags |= MODE_DECKPAM;
3417	    update_appkeypad();
3418	    ResetState(sp);
3419	    break;
3420
3421	case CASE_DECKPNM:
3422	    TRACE(("CASE_DECKPNM\n"));
3423	    UIntClr(xw->keyboard.flags, MODE_DECKPAM);
3424	    update_appkeypad();
3425	    ResetState(sp);
3426	    break;
3427
3428	case CASE_CSI_QUOTE_STATE:
3429	    sp->parsestate = csi_quo_table;
3430	    break;
3431
3432#if OPT_BLINK_CURS
3433	case CASE_CSI_SPACE_STATE:
3434	    sp->parsestate = csi_sp_table;
3435	    break;
3436
3437	case CASE_DECSCUSR:
3438	    TRACE(("CASE_DECSCUSR\n"));
3439	    {
3440		Boolean change = True;
3441		Boolean blinks = screen->cursor_blink_esc;
3442
3443		HideCursor();
3444
3445		switch (GetParam(0)) {
3446		case DEFAULT:
3447		    /* FALLTHRU */
3448		case DEFAULT_STYLE:
3449		    /* FALLTHRU */
3450		case BLINK_BLOCK:
3451		    blinks = True;
3452		    screen->cursor_shape = CURSOR_BLOCK;
3453		    break;
3454		case STEADY_BLOCK:
3455		    blinks = False;
3456		    screen->cursor_shape = CURSOR_BLOCK;
3457		    break;
3458		case BLINK_UNDERLINE:
3459		    blinks = True;
3460		    screen->cursor_shape = CURSOR_UNDERLINE;
3461		    break;
3462		case STEADY_UNDERLINE:
3463		    blinks = False;
3464		    screen->cursor_shape = CURSOR_UNDERLINE;
3465		    break;
3466		case BLINK_BAR:
3467		    blinks = True;
3468		    screen->cursor_shape = CURSOR_BAR;
3469		    break;
3470		case STEADY_BAR:
3471		    blinks = False;
3472		    screen->cursor_shape = CURSOR_BAR;
3473		    break;
3474		default:
3475		    change = False;
3476		    break;
3477		}
3478		TRACE(("cursor_shape:%d blinks:%s\n",
3479		       screen->cursor_shape, BtoS(blinks)));
3480		if (change) {
3481		    xtermSetCursorBox(screen);
3482		    screen->cursor_blink_esc = blinks;
3483		    UpdateCursorBlink(screen);
3484		}
3485	    }
3486	    ResetState(sp);
3487	    break;
3488#endif
3489
3490#if OPT_SCROLL_LOCK
3491	case CASE_DECLL:
3492	    TRACE(("CASE_DECLL\n"));
3493	    if (nparam > 0) {
3494		for (count = 0; count < nparam; ++count) {
3495		    int op = zero_if_default(count);
3496		    switch (op) {
3497		    case 0:
3498		    case DEFAULT:
3499			xtermClearLEDs(screen);
3500			break;
3501		    case 1:
3502			/* FALLTHRU */
3503		    case 2:
3504			/* FALLTHRU */
3505		    case 3:
3506			xtermShowLED(screen,
3507				     (Cardinal) op,
3508				     True);
3509			break;
3510		    case 21:
3511			/* FALLTHRU */
3512		    case 22:
3513			/* FALLTHRU */
3514		    case 23:
3515			xtermShowLED(screen,
3516				     (Cardinal) (op - 20),
3517				     True);
3518			break;
3519		    }
3520		}
3521	    } else {
3522		xtermClearLEDs(screen);
3523	    }
3524	    ResetState(sp);
3525	    break;
3526#endif
3527
3528#if OPT_VT52_MODE
3529	case CASE_VT52_FINISH:
3530	    TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n",
3531		   screen->terminal_id,
3532		   screen->vtXX_level));
3533	    if (screen->terminal_id >= 100
3534		&& screen->vtXX_level == 0) {
3535		sp->groundtable =
3536		    sp->parsestate = ansi_table;
3537		/*
3538		 * On restore, the terminal does not recognize DECRQSS for
3539		 * DECSCL (per vttest).
3540		 */
3541		screen->vtXX_level = 1;
3542		screen->curgl = screen->vt52_save_curgl;
3543		screen->curgr = screen->vt52_save_curgr;
3544		screen->curss = screen->vt52_save_curss;
3545		memmove(screen->gsets, screen->vt52_save_gsets, sizeof(screen->gsets));
3546	    }
3547	    break;
3548#endif
3549
3550	case CASE_ANSI_LEVEL_1:
3551	    TRACE(("CASE_ANSI_LEVEL_1\n"));
3552	    set_ansi_conformance(screen, 1);
3553	    ResetState(sp);
3554	    break;
3555
3556	case CASE_ANSI_LEVEL_2:
3557	    TRACE(("CASE_ANSI_LEVEL_2\n"));
3558	    set_ansi_conformance(screen, 2);
3559	    ResetState(sp);
3560	    break;
3561
3562	case CASE_ANSI_LEVEL_3:
3563	    TRACE(("CASE_ANSI_LEVEL_3\n"));
3564	    set_ansi_conformance(screen, 3);
3565	    ResetState(sp);
3566	    break;
3567
3568	case CASE_DECSCL:
3569	    TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1)));
3570	    /*
3571	     * This changes the emulation level, and is not recognized by
3572	     * VT100s.
3573	     */
3574	    if (screen->terminal_id >= 200) {
3575		/*
3576		 * Disallow unrecognized parameters, as well as attempts to set
3577		 * the operating level higher than the given terminal-id.
3578		 */
3579		if (GetParam(0) >= 61
3580		    && GetParam(0) <= 60 + (screen->terminal_id / 100)) {
3581		    int new_vtXX_level = GetParam(0) - 60;
3582		    int case_value = zero_if_default(1);
3583		    /*
3584		     * VT300, VT420, VT520 manuals claim that DECSCL does a
3585		     * hard reset (RIS).  VT220 manual states that it is a soft
3586		     * reset.  Perhaps both are right (unlikely).  Kermit says
3587		     * it's soft.
3588		     */
3589		    ReallyReset(xw, False, False);
3590		    init_parser(xw, sp);
3591		    screen->vtXX_level = new_vtXX_level;
3592		    if (new_vtXX_level > 1) {
3593			switch (case_value) {
3594			case 1:
3595			    show_8bit_control(False);
3596			    break;
3597			case 0:
3598			case 2:
3599			    show_8bit_control(True);
3600			    break;
3601			}
3602		    }
3603		}
3604	    }
3605	    ResetState(sp);
3606	    break;
3607
3608	case CASE_DECSCA:
3609	    TRACE(("CASE_DECSCA\n"));
3610	    screen->protected_mode = DEC_PROTECT;
3611	    if (GetParam(0) <= 0 || GetParam(0) == 2) {
3612		UIntClr(xw->flags, PROTECTED);
3613		TRACE(("...clear PROTECTED\n"));
3614	    } else if (GetParam(0) == 1) {
3615		xw->flags |= PROTECTED;
3616		TRACE(("...set PROTECTED\n"));
3617	    }
3618	    ResetState(sp);
3619	    break;
3620
3621	case CASE_DECSED:
3622	    TRACE(("CASE_DECSED\n"));
3623	    do_erase_display(xw, zero_if_default(0), DEC_PROTECT);
3624	    ResetState(sp);
3625	    break;
3626
3627	case CASE_DECSEL:
3628	    TRACE(("CASE_DECSEL\n"));
3629	    do_erase_line(xw, zero_if_default(0), DEC_PROTECT);
3630	    ResetState(sp);
3631	    break;
3632
3633	case CASE_GRAPHICS_ATTRIBUTES:
3634#if OPT_GRAPHICS
3635	    TRACE(("CASE_GRAPHICS_ATTRIBUTES\n"));
3636	    {
3637		/* request: item, action, value */
3638		/* reply: item, status, value */
3639		if (nparam != 3) {
3640		    TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam));
3641		} else {
3642		    int status = 3;
3643		    int result = 0;
3644		    int result2 = 0;
3645
3646		    TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n",
3647			   GetParam(0), GetParam(1), GetParam(2)));
3648		    switch (GetParam(0)) {
3649		    case 1:	/* color register count */
3650			switch (GetParam(1)) {
3651			case 1:	/* read */
3652			    status = 0;
3653			    result = (int) get_color_register_count(screen);
3654			    break;
3655			case 2:	/* reset */
3656			    screen->numcolorregisters = 0;
3657			    status = 0;
3658			    result = (int) get_color_register_count(screen);
3659			    break;
3660			case 3:	/* set */
3661			    if (GetParam(2) > 1 &&
3662				(unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) {
3663				screen->numcolorregisters = GetParam(2);
3664				status = 0;
3665				result = (int) get_color_register_count(screen);
3666			    }
3667			    break;
3668			case 4:	/* read maximum */
3669			    status = 0;
3670			    result = MAX_COLOR_REGISTERS;
3671			    break;
3672			default:
3673			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n",
3674				   GetParam(1)));
3675			    status = 2;
3676			    break;
3677			}
3678			break;
3679		    case 2:	/* graphics geometry */
3680			switch (GetParam(1)) {
3681			case 1:	/* read */
3682			    status = 0;
3683			    result = screen->graphics_max_wide;
3684			    result2 = screen->graphics_max_high;
3685			    break;
3686			case 2:	/* reset */
3687			    /* FALLTHRU */
3688			case 3:	/* set */
3689			    /* FALLTHRU */
3690			case 4:	/* read maximum */
3691			    /* not implemented */
3692			    break;
3693			default:
3694			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n",
3695				   GetParam(1)));
3696			    status = 2;
3697			    break;
3698			}
3699			break;
3700# if OPT_REGIS_GRAPHICS
3701		    case 3:	/* ReGIS geometry */
3702			switch (GetParam(1)) {
3703			case 1:	/* read */
3704			    status = 0;
3705			    result = screen->graphics_regis_def_wide;
3706			    result2 = screen->graphics_regis_def_high;
3707			    break;
3708			case 2:	/* reset */
3709			    /* FALLTHRU */
3710			case 3:	/* set */
3711			    /* FALLTHRU */
3712			case 4:	/* read maximum */
3713			    /* not implemented */
3714			    break;
3715			default:
3716			    TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n",
3717				   GetParam(1)));
3718			    status = 2;
3719			    break;
3720			}
3721			break;
3722#endif
3723		    default:
3724			TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n",
3725			       GetParam(0)));
3726			status = 1;
3727			break;
3728		    }
3729
3730		    init_reply(ANSI_CSI);
3731		    reply.a_pintro = '?';
3732		    count = 0;
3733		    reply.a_param[count++] = (ParmType) GetParam(0);
3734		    reply.a_param[count++] = (ParmType) status;
3735		    reply.a_param[count++] = (ParmType) result;
3736		    if (GetParam(0) >= 2)
3737			reply.a_param[count++] = (ParmType) result2;
3738		    reply.a_nparam = (ParmType) count;
3739		    reply.a_inters = 0;
3740		    reply.a_final = 'S';
3741		    unparseseq(xw, &reply);
3742		}
3743	    }
3744#endif
3745	    ResetState(sp);
3746	    break;
3747
3748	case CASE_ST:
3749	    TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n",
3750		   (unsigned long) sp->string_used,
3751		   sp->string_mode));
3752	    ResetState(sp);
3753	    if (!sp->string_used)
3754		break;
3755	    sp->string_area[--(sp->string_used)] = '\0';
3756	    switch (sp->string_mode) {
3757	    case ANSI_APC:
3758		/* ignored */
3759		break;
3760	    case ANSI_DCS:
3761		do_dcs(xw, sp->string_area, sp->string_used);
3762		break;
3763	    case ANSI_OSC:
3764		do_osc(xw, sp->string_area, sp->string_used, ANSI_ST);
3765		break;
3766	    case ANSI_PM:
3767		/* ignored */
3768		break;
3769	    case ANSI_SOS:
3770		/* ignored */
3771		break;
3772	    default:
3773		TRACE(("unknown mode\n"));
3774		break;
3775	    }
3776	    break;
3777
3778	case CASE_SOS:
3779	    TRACE(("CASE_SOS: Start of String\n"));
3780	    if (ParseSOS(screen)) {
3781		sp->string_mode = ANSI_SOS;
3782		sp->parsestate = sos_table;
3783	    } else {
3784		illegal_parse(xw, c, sp);
3785	    }
3786	    break;
3787
3788	case CASE_PM:
3789	    TRACE(("CASE_PM: Privacy Message\n"));
3790	    if (ParseSOS(screen)) {
3791		sp->string_mode = ANSI_PM;
3792		sp->parsestate = sos_table;
3793	    } else {
3794		illegal_parse(xw, c, sp);
3795	    }
3796	    break;
3797
3798	case CASE_DCS:
3799	    TRACE(("CASE_DCS: Device Control String\n"));
3800	    sp->string_mode = ANSI_DCS;
3801	    sp->parsestate = sos_table;
3802	    break;
3803
3804	case CASE_APC:
3805	    TRACE(("CASE_APC: Application Program Command\n"));
3806	    if (ParseSOS(screen)) {
3807		sp->string_mode = ANSI_APC;
3808		sp->parsestate = sos_table;
3809	    } else {
3810		illegal_parse(xw, c, sp);
3811	    }
3812	    break;
3813
3814	case CASE_SPA:
3815	    TRACE(("CASE_SPA - start protected area\n"));
3816	    screen->protected_mode = ISO_PROTECT;
3817	    xw->flags |= PROTECTED;
3818	    ResetState(sp);
3819	    break;
3820
3821	case CASE_EPA:
3822	    TRACE(("CASE_EPA - end protected area\n"));
3823	    UIntClr(xw->flags, PROTECTED);
3824	    ResetState(sp);
3825	    break;
3826
3827	case CASE_SU:
3828	    TRACE(("CASE_SU - scroll up\n"));
3829	    xtermScroll(xw, one_if_default(0));
3830	    ResetState(sp);
3831	    break;
3832
3833	case CASE_SL:		/* ISO 6429, non-DEC */
3834	    TRACE(("CASE_SL - scroll left\n"));
3835	    xtermScrollLR(xw, one_if_default(0), True);
3836	    ResetState(sp);
3837	    break;
3838
3839	case CASE_SR:		/* ISO 6429, non-DEC */
3840	    TRACE(("CASE_SR - scroll right\n"));
3841	    xtermScrollLR(xw, one_if_default(0), False);
3842	    ResetState(sp);
3843	    break;
3844
3845	case CASE_DECDC:
3846	    TRACE(("CASE_DC - delete column\n"));
3847	    if (screen->vtXX_level >= 4) {
3848		xtermColScroll(xw, one_if_default(0), True, screen->cur_col);
3849	    }
3850	    ResetState(sp);
3851	    break;
3852
3853	case CASE_DECIC:
3854	    TRACE(("CASE_IC - insert column\n"));
3855	    if (screen->vtXX_level >= 4) {
3856		xtermColScroll(xw, one_if_default(0), False, screen->cur_col);
3857	    }
3858	    ResetState(sp);
3859	    break;
3860
3861	case CASE_DECBI:
3862	    TRACE(("CASE_BI - back index\n"));
3863	    if (screen->vtXX_level >= 4) {
3864		xtermColIndex(xw, True);
3865	    }
3866	    ResetState(sp);
3867	    break;
3868
3869	case CASE_DECFI:
3870	    TRACE(("CASE_FI - forward index\n"));
3871	    if (screen->vtXX_level >= 4) {
3872		xtermColIndex(xw, False);
3873	    }
3874	    ResetState(sp);
3875	    break;
3876
3877	case CASE_IND:
3878	    TRACE(("CASE_IND - index\n"));
3879	    xtermIndex(xw, 1);
3880	    do_xevents();
3881	    ResetState(sp);
3882	    break;
3883
3884	case CASE_CPL:
3885	    TRACE(("CASE_CPL - cursor prev line\n"));
3886	    CursorPrevLine(xw, one_if_default(0));
3887	    ResetState(sp);
3888	    break;
3889
3890	case CASE_CNL:
3891	    TRACE(("CASE_CNL - cursor next line\n"));
3892	    CursorNextLine(xw, one_if_default(0));
3893	    ResetState(sp);
3894	    break;
3895
3896	case CASE_NEL:
3897	    TRACE(("CASE_NEL\n"));
3898	    xtermIndex(xw, 1);
3899	    CarriageReturn(xw);
3900	    ResetState(sp);
3901	    break;
3902
3903	case CASE_HTS:
3904	    TRACE(("CASE_HTS - horizontal tab set\n"));
3905	    TabSet(xw->tabs, screen->cur_col);
3906	    ResetState(sp);
3907	    break;
3908
3909	case CASE_RI:
3910	    TRACE(("CASE_RI - reverse index\n"));
3911	    RevIndex(xw, 1);
3912	    ResetState(sp);
3913	    break;
3914
3915	case CASE_SS2:
3916	    TRACE(("CASE_SS2\n"));
3917	    screen->curss = 2;
3918	    ResetState(sp);
3919	    break;
3920
3921	case CASE_SS3:
3922	    TRACE(("CASE_SS3\n"));
3923	    screen->curss = 3;
3924	    ResetState(sp);
3925	    break;
3926
3927	case CASE_CSI_STATE:
3928	    /* enter csi state */
3929	    InitParams();
3930	    SetParam(nparam++, DEFAULT);
3931	    sp->parsestate = csi_table;
3932	    break;
3933
3934	case CASE_ESC_SP_STATE:
3935	    /* esc space */
3936	    sp->parsestate = esc_sp_table;
3937	    break;
3938
3939	case CASE_CSI_EX_STATE:
3940	    /* csi exclamation */
3941	    sp->parsestate = csi_ex_table;
3942	    break;
3943
3944	case CASE_CSI_TICK_STATE:
3945	    /* csi tick (') */
3946	    sp->parsestate = csi_tick_table;
3947	    break;
3948
3949#if OPT_DEC_LOCATOR
3950	case CASE_DECEFR:
3951	    TRACE(("CASE_DECEFR - Enable Filter Rectangle\n"));
3952	    if (okSendMousePos(xw) == DEC_LOCATOR) {
3953		MotionOff(screen, xw);
3954		if ((screen->loc_filter_top = GetParam(0)) < 1)
3955		    screen->loc_filter_top = LOC_FILTER_POS;
3956		if (nparam < 2
3957		    || (screen->loc_filter_left = GetParam(1)) < 1)
3958		    screen->loc_filter_left = LOC_FILTER_POS;
3959		if (nparam < 3
3960		    || (screen->loc_filter_bottom = GetParam(2)) < 1)
3961		    screen->loc_filter_bottom = LOC_FILTER_POS;
3962		if (nparam < 4
3963		    || (screen->loc_filter_right = GetParam(3)) < 1)
3964		    screen->loc_filter_right = LOC_FILTER_POS;
3965		InitLocatorFilter(xw);
3966	    }
3967	    ResetState(sp);
3968	    break;
3969
3970	case CASE_DECELR:
3971	    MotionOff(screen, xw);
3972	    if (GetParam(0) <= 0 || GetParam(0) > 2) {
3973		screen->send_mouse_pos = MOUSE_OFF;
3974		TRACE(("DECELR - Disable Locator Reports\n"));
3975	    } else {
3976		TRACE(("DECELR - Enable Locator Reports\n"));
3977		screen->send_mouse_pos = DEC_LOCATOR;
3978		xtermShowPointer(xw, True);
3979		if (GetParam(0) == 2) {
3980		    screen->locator_reset = True;
3981		} else {
3982		    screen->locator_reset = False;
3983		}
3984		if (nparam < 2 || GetParam(1) != 1) {
3985		    screen->locator_pixels = False;
3986		} else {
3987		    screen->locator_pixels = True;
3988		}
3989		screen->loc_filter = False;
3990	    }
3991	    ResetState(sp);
3992	    break;
3993
3994	case CASE_DECSLE:
3995	    TRACE(("DECSLE - Select Locator Events\n"));
3996	    for (count = 0; count < nparam; ++count) {
3997		switch (zero_if_default(count)) {
3998		case 0:
3999		    MotionOff(screen, xw);
4000		    screen->loc_filter = False;
4001		    screen->locator_events = 0;
4002		    break;
4003		case 1:
4004		    screen->locator_events |= LOC_BTNS_DN;
4005		    break;
4006		case 2:
4007		    UIntClr(screen->locator_events, LOC_BTNS_DN);
4008		    break;
4009		case 3:
4010		    screen->locator_events |= LOC_BTNS_UP;
4011		    break;
4012		case 4:
4013		    UIntClr(screen->locator_events, LOC_BTNS_UP);
4014		    break;
4015		}
4016	    }
4017	    ResetState(sp);
4018	    break;
4019
4020	case CASE_DECRQLP:
4021	    TRACE(("DECRQLP - Request Locator Position\n"));
4022	    if (GetParam(0) < 2) {
4023		/* Issue DECLRP Locator Position Report */
4024		GetLocatorPosition(xw);
4025	    }
4026	    ResetState(sp);
4027	    break;
4028#endif /* OPT_DEC_LOCATOR */
4029
4030#if OPT_DEC_RECTOPS
4031	case CASE_CSI_DOLLAR_STATE:
4032	    TRACE(("CASE_CSI_DOLLAR_STATE\n"));
4033	    /* csi dollar ($) */
4034	    if (screen->vtXX_level >= 3)
4035		sp->parsestate = csi_dollar_table;
4036	    else
4037		sp->parsestate = eigtable;
4038	    break;
4039
4040	case CASE_CSI_STAR_STATE:
4041	    TRACE(("CASE_CSI_STAR_STATE\n"));
4042	    /* csi star (*) */
4043	    if (screen->vtXX_level >= 4)
4044		sp->parsestate = csi_star_table;
4045	    else
4046		sp->parsestate = eigtable;
4047	    break;
4048
4049	case CASE_DECRQCRA:
4050	    if (screen->vtXX_level >= 4) {
4051		int checksum;
4052
4053		TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n"));
4054		xtermCheckRect(xw, ParamPair(0), &checksum);
4055		init_reply(ANSI_DCS);
4056		count = 0;
4057		reply.a_param[count++] = (ParmType) GetParam(1);	/* PID */
4058		reply.a_delim = "!~";	/* delimiter */
4059		reply.a_radix[count] = 16;
4060		reply.a_param[count++] = (ParmType) checksum;
4061		reply.a_nparam = (ParmType) count;
4062		unparseseq(xw, &reply);
4063	    }
4064	    ResetState(sp);
4065	    break;
4066
4067	case CASE_DECCRA:
4068	    if (screen->vtXX_level >= 4) {
4069		TRACE(("CASE_DECCRA - Copy rectangular area\n"));
4070		xtermParseRect(xw, ParamPair(0), &myRect);
4071		ScrnCopyRectangle(xw, &myRect, ParamPair(5));
4072	    }
4073	    ResetState(sp);
4074	    break;
4075
4076	case CASE_DECERA:
4077	    if (screen->vtXX_level >= 4) {
4078		TRACE(("CASE_DECERA - Erase rectangular area\n"));
4079		xtermParseRect(xw, ParamPair(0), &myRect);
4080		ScrnFillRectangle(xw, &myRect, ' ', 0, True);
4081	    }
4082	    ResetState(sp);
4083	    break;
4084
4085	case CASE_DECFRA:
4086	    if (screen->vtXX_level >= 4) {
4087		value = zero_if_default(0);
4088
4089		TRACE(("CASE_DECFRA - Fill rectangular area\n"));
4090		if (nparam > 0
4091		    && ((value >= 32 && value <= 126)
4092			|| (value >= 160 && value <= 255))) {
4093		    xtermParseRect(xw, ParamPair(1), &myRect);
4094		    ScrnFillRectangle(xw, &myRect, value, xw->flags, True);
4095		}
4096	    }
4097	    ResetState(sp);
4098	    break;
4099
4100	case CASE_DECSERA:
4101	    if (screen->vtXX_level >= 4) {
4102		TRACE(("CASE_DECSERA - Selective erase rectangular area\n"));
4103		xtermParseRect(xw, ParamPair(0), &myRect);
4104		ScrnWipeRectangle(xw, &myRect);
4105	    }
4106	    ResetState(sp);
4107	    break;
4108
4109	case CASE_DECSACE:
4110	    TRACE(("CASE_DECSACE - Select attribute change extent\n"));
4111	    screen->cur_decsace = zero_if_default(0);
4112	    ResetState(sp);
4113	    break;
4114
4115	case CASE_DECCARA:
4116	    if (screen->vtXX_level >= 4) {
4117		TRACE(("CASE_DECCARA - Change attributes in rectangular area\n"));
4118		xtermParseRect(xw, ParamPair(0), &myRect);
4119		ScrnMarkRectangle(xw, &myRect, False, ParamPair(4));
4120	    }
4121	    ResetState(sp);
4122	    break;
4123
4124	case CASE_DECRARA:
4125	    if (screen->vtXX_level >= 4) {
4126		TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n"));
4127		xtermParseRect(xw, ParamPair(0), &myRect);
4128		ScrnMarkRectangle(xw, &myRect, True, ParamPair(4));
4129	    }
4130	    ResetState(sp);
4131	    break;
4132
4133	case CASE_RQM:
4134	    TRACE(("CASE_RQM\n"));
4135	    do_rpm(xw, ParamPair(0));
4136	    ResetState(sp);
4137	    break;
4138
4139	case CASE_DECRQM:
4140	    TRACE(("CASE_DECRQM\n"));
4141	    do_decrpm(xw, ParamPair(0));
4142	    ResetState(sp);
4143	    break;
4144
4145	case CASE_CSI_DEC_DOLLAR_STATE:
4146	    TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n"));
4147	    /* csi ? dollar ($) */
4148	    sp->parsestate = csi_dec_dollar_table;
4149	    break;
4150#else
4151	case CASE_CSI_DOLLAR_STATE:
4152	    /* csi dollar ($) */
4153	    sp->parsestate = eigtable;
4154	    break;
4155
4156	case CASE_CSI_STAR_STATE:
4157	    /* csi dollar (*) */
4158	    sp->parsestate = eigtable;
4159	    break;
4160
4161	case CASE_CSI_DEC_DOLLAR_STATE:
4162	    /* csi ? dollar ($) */
4163	    sp->parsestate = eigtable;
4164	    break;
4165#endif /* OPT_DEC_RECTOPS */
4166
4167	case CASE_S7C1T:
4168	    TRACE(("CASE_S7C1T\n"));
4169	    if (screen->vtXX_level >= 2) {
4170		show_8bit_control(False);
4171		ResetState(sp);
4172	    }
4173	    break;
4174
4175	case CASE_S8C1T:
4176	    TRACE(("CASE_S8C1T\n"));
4177	    if (screen->vtXX_level >= 2) {
4178#if OPT_VT52_MODE
4179		if (screen->vtXX_level <= 1)
4180		    break;
4181#endif
4182		show_8bit_control(True);
4183		ResetState(sp);
4184	    }
4185	    break;
4186
4187	case CASE_OSC:
4188	    TRACE(("CASE_OSC: Operating System Command\n"));
4189	    sp->parsestate = sos_table;
4190	    sp->string_mode = ANSI_OSC;
4191	    break;
4192
4193	case CASE_RIS:
4194	    TRACE(("CASE_RIS\n"));
4195	    VTReset(xw, True, True);
4196	    /* NOTREACHED */
4197
4198	case CASE_DECSTR:
4199	    TRACE(("CASE_DECSTR\n"));
4200	    VTReset(xw, False, False);
4201	    /* NOTREACHED */
4202
4203	case CASE_REP:
4204	    TRACE(("CASE_REP\n"));
4205	    if (sp->lastchar >= 0 &&
4206		sp->lastchar < 256 &&
4207		sp->groundtable[E2A(sp->lastchar)] == CASE_PRINT) {
4208		IChar repeated[2];
4209		count = one_if_default(0);
4210		repeated[0] = (IChar) sp->lastchar;
4211		while (count-- > 0) {
4212		    dotext(xw,
4213			   screen->gsets[(int) (screen->curgl)],
4214			   repeated, 1);
4215		}
4216	    }
4217	    ResetState(sp);
4218	    break;
4219
4220	case CASE_LS2:
4221	    TRACE(("CASE_LS2\n"));
4222	    screen->curgl = 2;
4223	    ResetState(sp);
4224	    break;
4225
4226	case CASE_LS3:
4227	    TRACE(("CASE_LS3\n"));
4228	    screen->curgl = 3;
4229	    ResetState(sp);
4230	    break;
4231
4232	case CASE_LS3R:
4233	    TRACE(("CASE_LS3R\n"));
4234	    screen->curgr = 3;
4235	    ResetState(sp);
4236	    break;
4237
4238	case CASE_LS2R:
4239	    TRACE(("CASE_LS2R\n"));
4240	    screen->curgr = 2;
4241	    ResetState(sp);
4242	    break;
4243
4244	case CASE_LS1R:
4245	    TRACE(("CASE_LS1R\n"));
4246	    screen->curgr = 1;
4247	    ResetState(sp);
4248	    break;
4249
4250	case CASE_XTERM_SAVE:
4251	    savemodes(xw);
4252	    ResetState(sp);
4253	    break;
4254
4255	case CASE_XTERM_RESTORE:
4256	    restoremodes(xw);
4257	    ResetState(sp);
4258	    break;
4259
4260	case CASE_XTERM_WINOPS:
4261	    TRACE(("CASE_XTERM_WINOPS\n"));
4262	    window_ops(xw);
4263	    ResetState(sp);
4264	    break;
4265#if OPT_WIDE_CHARS
4266	case CASE_ESC_PERCENT:
4267	    TRACE(("CASE_ESC_PERCENT\n"));
4268	    sp->parsestate = esc_pct_table;
4269	    break;
4270
4271	case CASE_UTF8:
4272	    /* If we did not set UTF-8 mode from resource or the
4273	     * command-line, allow it to be enabled/disabled by
4274	     * control sequence.
4275	     */
4276	    TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n",
4277		   screen->wide_chars,
4278		   screen->utf8_mode,
4279		   BtoS(c == 'G')));
4280	    if ((!screen->wide_chars) && (c == 'G')) {
4281		WriteNow();
4282		ChangeToWide(xw);
4283	    }
4284	    if (screen->wide_chars
4285		&& !screen->utf8_always) {
4286		switchPtyData(screen, c == 'G');
4287		TRACE(("UTF8 mode %s\n",
4288		       BtoS(screen->utf8_mode)));
4289	    } else {
4290		TRACE(("UTF8 mode NOT turned %s (%s)\n",
4291		       BtoS(c == 'G'),
4292		       (screen->utf8_mode == uAlways)
4293		       ? "UTF-8 mode set from command-line"
4294		       : "wideChars resource was not set"));
4295	    }
4296	    ResetState(sp);
4297	    break;
4298
4299	case CASE_SCS_PERCENT:
4300	    TRACE(("CASE_SCS_PERCENT\n"));
4301	    sp->parsestate = scs_pct_table;
4302	    break;
4303
4304	case CASE_GSETS_PERCENT:
4305	    TRACE(("CASE_GSETS_PERCENT(%d) = '%c'\n", sp->scstype, c));
4306	    decode_scs(xw, sp->scstype, '%', (int) c);
4307	    ResetState(sp);
4308	    break;
4309#endif
4310#if OPT_MOD_FKEYS
4311	case CASE_SET_MOD_FKEYS:
4312	    TRACE(("CASE_SET_MOD_FKEYS\n"));
4313	    if (nparam >= 1) {
4314		set_mod_fkeys(xw,
4315			      GetParam(0),
4316			      ((nparam > 1)
4317			       ? GetParam(1)
4318			       : DEFAULT),
4319			      True);
4320	    } else {
4321		for (value = 1; value <= 5; ++value)
4322		    set_mod_fkeys(xw, value, DEFAULT, True);
4323	    }
4324	    break;
4325	case CASE_SET_MOD_FKEYS0:
4326	    TRACE(("CASE_SET_MOD_FKEYS0\n"));
4327	    if (nparam >= 1 && GetParam(0) != DEFAULT) {
4328		set_mod_fkeys(xw, GetParam(0), -1, False);
4329	    } else {
4330		xw->keyboard.modify_now.function_keys = -1;
4331	    }
4332	    break;
4333#endif
4334	case CASE_HIDE_POINTER:
4335	    TRACE(("CASE_HIDE_POINTER\n"));
4336	    if (nparam >= 1 && GetParam(0) != DEFAULT) {
4337		screen->pointer_mode = GetParam(0);
4338	    } else {
4339		screen->pointer_mode = DEF_POINTER_MODE;
4340	    }
4341	    break;
4342
4343	case CASE_SM_TITLE:
4344	    TRACE(("CASE_SM_TITLE\n"));
4345	    if (nparam >= 1) {
4346		int n;
4347		for (n = 0; n < nparam; ++n) {
4348		    if (GetParam(n) != DEFAULT)
4349			screen->title_modes |= (1 << GetParam(n));
4350		}
4351	    } else {
4352		screen->title_modes = DEF_TITLE_MODES;
4353	    }
4354	    TRACE(("...title_modes %#x\n", screen->title_modes));
4355	    break;
4356
4357	case CASE_RM_TITLE:
4358	    TRACE(("CASE_RM_TITLE\n"));
4359	    if (nparam >= 1) {
4360		int n;
4361		for (n = 0; n < nparam; ++n) {
4362		    if (GetParam(n) != DEFAULT)
4363			screen->title_modes &= ~(1 << GetParam(n));
4364		}
4365	    } else {
4366		screen->title_modes = DEF_TITLE_MODES;
4367	    }
4368	    TRACE(("...title_modes %#x\n", screen->title_modes));
4369	    break;
4370
4371	case CASE_CSI_IGNORE:
4372	    sp->parsestate = cigtable;
4373	    break;
4374
4375	case CASE_DECSWBV:
4376	    TRACE(("CASE_DECSWBV\n"));
4377	    switch (zero_if_default(0)) {
4378	    case 2:
4379		/* FALLTHRU */
4380	    case 3:
4381		/* FALLTHRU */
4382	    case 4:
4383		screen->warningVolume = bvLow;
4384		break;
4385	    case 5:
4386		/* FALLTHRU */
4387	    case 6:
4388		/* FALLTHRU */
4389	    case 7:
4390		/* FALLTHRU */
4391	    case 8:
4392		screen->warningVolume = bvHigh;
4393		break;
4394	    default:
4395		screen->warningVolume = bvOff;
4396		break;
4397	    }
4398	    TRACE(("...warningVolume %d\n", screen->warningVolume));
4399	    ResetState(sp);
4400	    break;
4401
4402	case CASE_DECSMBV:
4403	    TRACE(("CASE_DECSMBV\n"));
4404	    switch (zero_if_default(0)) {
4405	    case 2:
4406		/* FALLTHRU */
4407	    case 3:
4408		/* FALLTHRU */
4409	    case 4:
4410		screen->marginVolume = bvLow;
4411		break;
4412	    case 0:
4413		/* FALLTHRU */
4414	    case 5:
4415		/* FALLTHRU */
4416	    case 6:
4417		/* FALLTHRU */
4418	    case 7:
4419		/* FALLTHRU */
4420	    case 8:
4421		screen->marginVolume = bvHigh;
4422		break;
4423	    default:
4424		screen->marginVolume = bvOff;
4425		break;
4426	    }
4427	    TRACE(("...marginVolume %d\n", screen->marginVolume));
4428	    ResetState(sp);
4429	    break;
4430	}
4431	if (sp->parsestate == sp->groundtable)
4432	    sp->lastchar = thischar;
4433    } while (0);
4434
4435#if OPT_WIDE_CHARS
4436    screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse)
4437				      && (sp->parsestate != sos_table));
4438#endif
4439
4440    return True;
4441}
4442
4443static void
4444VTparse(XtermWidget xw)
4445{
4446    /* We longjmp back to this point in VTReset() */
4447    (void) setjmp(vtjmpbuf);
4448    init_parser(xw, &myState);
4449
4450    do {
4451    } while (doparsing(xw, doinput(), &myState));
4452}
4453
4454static Char *v_buffer;		/* pointer to physical buffer */
4455static Char *v_bufstr = NULL;	/* beginning of area to write */
4456static Char *v_bufptr;		/* end of area to write */
4457static Char *v_bufend;		/* end of physical buffer */
4458
4459/* Write data to the pty as typed by the user, pasted with the mouse,
4460   or generated by us in response to a query ESC sequence. */
4461
4462void
4463v_write(int f, const Char *data, unsigned len)
4464{
4465    TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len)));
4466    if (v_bufstr == NULL) {
4467	if (len > 0) {
4468	    v_buffer = (Char *) XtMalloc((Cardinal) len);
4469	    v_bufstr = v_buffer;
4470	    v_bufptr = v_buffer;
4471	    v_bufend = v_buffer + len;
4472	}
4473	if (v_bufstr == NULL) {
4474	    return;
4475	}
4476    }
4477    if_DEBUG({
4478	fprintf(stderr, "v_write called with %u bytes (%ld left over)",
4479		len, (long) (v_bufptr - v_bufstr));
4480	if (len > 1 && len < 10)
4481	    fprintf(stderr, " \"%.*s\"", len, (const char *) data);
4482	fprintf(stderr, "\n");
4483    });
4484
4485#ifdef VMS
4486    if ((1 << f) != pty_mask) {
4487	tt_write((const char *) data, len);
4488	return;
4489    }
4490#else /* VMS */
4491    if (!FD_ISSET(f, &pty_mask)) {
4492	IGNORE_RC(write(f, (const char *) data, (size_t) len));
4493	return;
4494    }
4495#endif /* VMS */
4496
4497    /*
4498     * Append to the block we already have.
4499     * Always doing this simplifies the code, and
4500     * isn't too bad, either.  If this is a short
4501     * block, it isn't too expensive, and if this is
4502     * a long block, we won't be able to write it all
4503     * anyway.
4504     */
4505
4506    if (len > 0) {
4507#if OPT_DABBREV
4508	TScreenOf(term)->dabbrev_working = False;	/* break dabbrev sequence */
4509#endif
4510	if (v_bufend < v_bufptr + len) {	/* we've run out of room */
4511	    if (v_bufstr != v_buffer) {
4512		/* there is unused space, move everything down */
4513		/* possibly overlapping memmove here */
4514		if_DEBUG({
4515		    fprintf(stderr, "moving data down %ld\n",
4516			    (long) (v_bufstr - v_buffer));
4517		});
4518		memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr));
4519		v_bufptr -= v_bufstr - v_buffer;
4520		v_bufstr = v_buffer;
4521	    }
4522	    if (v_bufend < v_bufptr + len) {
4523		/* still won't fit: get more space */
4524		/* Don't use XtRealloc because an error is not fatal. */
4525		unsigned size = (unsigned) (v_bufptr - v_buffer);
4526		v_buffer = TypeRealloc(Char, size + len, v_buffer);
4527		if (v_buffer) {
4528		    if_DEBUG({
4529			fprintf(stderr, "expanded buffer to %u\n",
4530				size + len);
4531		    });
4532		    v_bufstr = v_buffer;
4533		    v_bufptr = v_buffer + size;
4534		    v_bufend = v_bufptr + len;
4535		} else {
4536		    /* no memory: ignore entire write request */
4537		    xtermWarning("cannot allocate buffer space\n");
4538		    v_buffer = v_bufstr;	/* restore clobbered pointer */
4539		}
4540	    }
4541	}
4542	if (v_bufend >= v_bufptr + len) {
4543	    /* new stuff will fit */
4544	    memmove(v_bufptr, data, (size_t) len);
4545	    v_bufptr += len;
4546	}
4547    }
4548
4549    /*
4550     * Write out as much of the buffer as we can.
4551     * Be careful not to overflow the pty's input silo.
4552     * We are conservative here and only write
4553     * a small amount at a time.
4554     *
4555     * If we can't push all the data into the pty yet, we expect write
4556     * to return a non-negative number less than the length requested
4557     * (if some data written) or -1 and set errno to EAGAIN,
4558     * EWOULDBLOCK, or EINTR (if no data written).
4559     *
4560     * (Not all systems do this, sigh, so the code is actually
4561     * a little more forgiving.)
4562     */
4563
4564#define MAX_PTY_WRITE 128	/* 1/2 POSIX minimum MAX_INPUT */
4565
4566    if (v_bufptr > v_bufstr) {
4567	int riten;
4568
4569#ifdef VMS
4570	riten = tt_write(v_bufstr,
4571			 ((v_bufptr - v_bufstr <= VMS_TERM_BUFFER_SIZE)
4572			  ? v_bufptr - v_bufstr
4573			  : VMS_TERM_BUFFER_SIZE));
4574	if (riten == 0)
4575	    return (riten);
4576#else /* VMS */
4577	riten = (int) write(f, v_bufstr,
4578			    (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE)
4579				      ? v_bufptr - v_bufstr
4580				      : MAX_PTY_WRITE));
4581	if (riten < 0)
4582#endif /* VMS */
4583	{
4584	    if_DEBUG({
4585		perror("write");
4586	    });
4587	    riten = 0;
4588	}
4589	if_DEBUG({
4590	    fprintf(stderr, "write called with %ld, wrote %d\n",
4591		    ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE)
4592		     ? (long) (v_bufptr - v_bufstr)
4593		     : MAX_PTY_WRITE),
4594		    riten);
4595	});
4596	v_bufstr += riten;
4597	if (v_bufstr >= v_bufptr)	/* we wrote it all */
4598	    v_bufstr = v_bufptr = v_buffer;
4599    }
4600
4601    /*
4602     * If we have lots of unused memory allocated, return it
4603     */
4604    if (v_bufend - v_bufptr > 1024) {	/* arbitrary hysteresis */
4605	/* save pointers across realloc */
4606	int start = (int) (v_bufstr - v_buffer);
4607	int size = (int) (v_bufptr - v_buffer);
4608	unsigned allocsize = (unsigned) (size ? size : 1);
4609
4610	v_buffer = TypeRealloc(Char, allocsize, v_buffer);
4611	if (v_buffer) {
4612	    v_bufstr = v_buffer + start;
4613	    v_bufptr = v_buffer + size;
4614	    v_bufend = v_buffer + allocsize;
4615	    if_DEBUG({
4616		fprintf(stderr, "shrunk buffer to %u\n", allocsize);
4617	    });
4618	} else {
4619	    /* should we print a warning if couldn't return memory? */
4620	    v_buffer = v_bufstr - start;	/* restore clobbered pointer */
4621	}
4622    }
4623}
4624
4625static void
4626updateCursor(TScreen *screen)
4627{
4628    if (screen->cursor_set != screen->cursor_state) {
4629	if (screen->cursor_set)
4630	    ShowCursor();
4631	else
4632	    HideCursor();
4633    }
4634}
4635
4636#if OPT_BLINK_CURS || OPT_BLINK_TEXT
4637static void
4638reallyStopBlinking(TScreen *screen)
4639{
4640    if (screen->cursor_state == BLINKED_OFF) {
4641	/* force cursor to display if it is enabled */
4642	screen->cursor_state = !screen->cursor_set;
4643	updateCursor(screen);
4644	xevents();
4645    }
4646}
4647#endif
4648
4649#ifdef VMS
4650#define	ptymask()	(v_bufptr > v_bufstr ? pty_mask : 0)
4651
4652static void
4653in_put(XtermWidget xw)
4654{
4655    static PtySelect select_mask;
4656    static PtySelect write_mask;
4657    int update = VTbuffer->update;
4658    int size;
4659
4660    int status;
4661    Dimension replyWidth, replyHeight;
4662    XtGeometryResult stat;
4663
4664    TScreen *screen = TScreenOf(xw);
4665    char *cp;
4666    int i;
4667
4668    select_mask = pty_mask;	/* force initial read */
4669    for (;;) {
4670
4671	/* if the terminal changed size, resize the widget */
4672	if (tt_changed) {
4673	    tt_changed = False;
4674
4675	    stat = REQ_RESIZE((Widget) xw,
4676			      ((Dimension) FontWidth(screen)
4677			       * (tt_width)
4678			       + 2 * screen->border
4679			       + screen->fullVwin.sb_info.width),
4680			      ((Dimension) FontHeight(screen)
4681			       * (tt_length)
4682			       + 2 * screen->border),
4683			      &replyWidth, &replyHeight);
4684
4685	    if (stat == XtGeometryYes || stat == XtGeometryDone) {
4686		xw->core.width = replyWidth;
4687		xw->core.height = replyHeight;
4688
4689		ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
4690	    }
4691	    repairSizeHints();
4692	}
4693
4694	if (screen->eventMode == NORMAL
4695	    && readPtyData(xw, &select_mask, VTbuffer)) {
4696	    if (screen->scrollWidget
4697		&& screen->scrollttyoutput
4698		&& screen->topline < 0)
4699		/* Scroll to bottom */
4700		WindowScroll(xw, 0, False);
4701	    break;
4702	}
4703	if (screen->scroll_amt)
4704	    FlushScroll(xw);
4705	if (screen->cursor_set && CursorMoved(screen)) {
4706	    if (screen->cursor_state)
4707		HideCursor();
4708	    ShowCursor();
4709#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
4710	    PreeditPosition(xw);
4711#endif
4712	} else {
4713	    updateCursor(screen);
4714	}
4715
4716	if (QLength(screen->display)) {
4717	    select_mask = X_mask;
4718	} else {
4719	    write_mask = ptymask();
4720	    XFlush(screen->display);
4721	    select_mask = Select_mask;
4722	    if (screen->eventMode != NORMAL)
4723		select_mask = X_mask;
4724	}
4725	if (write_mask & ptymask()) {
4726	    v_write(screen->respond, 0, 0);	/* flush buffer */
4727	}
4728
4729	if (select_mask & X_mask) {
4730	    xevents();
4731	    if (VTbuffer->update != update)
4732		break;
4733	}
4734    }
4735}
4736#else /* VMS */
4737
4738static void
4739in_put(XtermWidget xw)
4740{
4741    static PtySelect select_mask;
4742    static PtySelect write_mask;
4743
4744    TScreen *screen = TScreenOf(xw);
4745    int i;
4746    int update = VTbuffer->update;
4747#if OPT_DOUBLE_BUFFER
4748    int should_wait = 1;
4749#endif
4750
4751    static struct timeval select_timeout;
4752
4753#if OPT_BLINK_CURS
4754    /*
4755     * Compute the timeout for the blinking cursor to be much smaller than
4756     * the "on" or "off" interval.
4757     */
4758    int tick = ((screen->blink_on < screen->blink_off)
4759		? screen->blink_on
4760		: screen->blink_off);
4761    tick *= (1000 / 8);		/* 1000 for msec/usec, 8 for "much" smaller */
4762    if (tick < 1)
4763	tick = 1;
4764#endif
4765
4766    for (;;) {
4767	int size;
4768	int time_select;
4769
4770	if (screen->eventMode == NORMAL
4771	    && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) {
4772	    if (screen->scrollWidget
4773		&& screen->scrollttyoutput
4774		&& screen->topline < 0)
4775		WindowScroll(xw, 0, False);	/* Scroll to bottom */
4776	    /* stop speed reading at some point to look for X stuff */
4777	    TRACE(("VTbuffer uses %ld/%d\n",
4778		   (long) (VTbuffer->last - VTbuffer->buffer),
4779		   BUF_SIZE));
4780	    if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) {
4781		FD_CLR(screen->respond, &select_mask);
4782		break;
4783	    }
4784#if OPT_DOUBLE_BUFFER
4785	    if (should_wait) {
4786		/* wait 25 msec for potential extra data (avoids some bogus flickering) */
4787		/* that's only 40 FPS but hey, it's still lower than the input lag on some consoles! :) */
4788		usleep(25000);
4789		should_wait = 0;
4790	    }
4791	    select_timeout.tv_sec = 0;
4792	    i = Select(max_plus1, &select_mask, &write_mask, 0,
4793		       &select_timeout);
4794	    if (i > 0 && FD_ISSET(screen->respond, &select_mask))
4795		continue;
4796	    else
4797		break;
4798#elif defined(HAVE_SCHED_YIELD)
4799	    /*
4800	     * If we've read a full (small/fragment) buffer, let the operating
4801	     * system have a turn, and we'll resume reading until we've either
4802	     * read only a fragment of the buffer, or we've filled the large
4803	     * buffer (see above).  Doing this helps keep up with large bursts
4804	     * of output.
4805	     */
4806	    if (size == FRG_SIZE) {
4807		select_timeout.tv_sec = 0;
4808		i = Select(max_plus1, &select_mask, &write_mask, 0,
4809			   &select_timeout);
4810		if (i > 0 && FD_ISSET(screen->respond, &select_mask)) {
4811		    sched_yield();
4812		} else
4813		    break;
4814	    } else {
4815		break;
4816	    }
4817#else
4818	    (void) size;	/* unused in this branch */
4819	    break;
4820#endif
4821	}
4822	/* update the screen */
4823	if (screen->scroll_amt)
4824	    FlushScroll(xw);
4825	if (screen->cursor_set && CursorMoved(screen)) {
4826	    if (screen->cursor_state)
4827		HideCursor();
4828	    ShowCursor();
4829#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
4830	    PreeditPosition(xw);
4831#endif
4832	} else {
4833	    updateCursor(screen);
4834	}
4835
4836	XFlush(screen->display);	/* always flush writes before waiting */
4837
4838	/* Update the masks and, unless X events are already in the queue,
4839	   wait for I/O to be possible. */
4840	XFD_COPYSET(&Select_mask, &select_mask);
4841	/* in selection mode xterm does not read pty */
4842	if (screen->eventMode != NORMAL)
4843	    FD_CLR(screen->respond, &select_mask);
4844
4845	if (v_bufptr > v_bufstr) {
4846	    XFD_COPYSET(&pty_mask, &write_mask);
4847	} else
4848	    FD_ZERO(&write_mask);
4849	select_timeout.tv_sec = 0;
4850	time_select = 0;
4851
4852	/*
4853	 * if there's either an XEvent or an XtTimeout pending, just take
4854	 * a quick peek, i.e. timeout from the select() immediately.  If
4855	 * there's nothing pending, let select() block a little while, but
4856	 * for a shorter interval than the arrow-style scrollbar timeout.
4857	 * The blocking is optional, because it tends to increase the load
4858	 * on the host.
4859	 */
4860	if (xtermAppPending()) {
4861	    select_timeout.tv_usec = 0;
4862	    time_select = 1;
4863	} else if (screen->awaitInput) {
4864	    select_timeout.tv_usec = 50000;
4865	    time_select = 1;
4866#if OPT_BLINK_CURS
4867	} else if ((screen->blink_timer != 0 &&
4868		    ((screen->select & FOCUS) || screen->always_highlight)) ||
4869		   (screen->cursor_state == BLINKED_OFF)) {
4870	    select_timeout.tv_usec = tick;
4871	    while (select_timeout.tv_usec > 1000000) {
4872		select_timeout.tv_usec -= 1000000;
4873		select_timeout.tv_sec++;
4874	    }
4875	    time_select = 1;
4876#endif
4877#if OPT_SESSION_MGT
4878	} else if (resource.sessionMgt) {
4879	    if (ice_fd >= 0)
4880		FD_SET(ice_fd, &select_mask);
4881#endif
4882	}
4883	if (need_cleanup)
4884	    NormalExit();
4885#if OPT_DOUBLE_BUFFER
4886	if (screen->needSwap) {
4887	    XdbeSwapInfo swap;
4888	    swap.swap_window = VWindow(screen);
4889	    swap.swap_action = XdbeCopied;
4890	    XdbeSwapBuffers(XtDisplay(term), &swap, 1);
4891	    XFlush(XtDisplay(xw));
4892	    screen->needSwap = 0;
4893	}
4894#endif
4895	i = Select(max_plus1, &select_mask, &write_mask, 0,
4896		   (time_select ? &select_timeout : 0));
4897	if (i < 0) {
4898	    if (errno != EINTR)
4899		SysError(ERROR_SELECT);
4900	    continue;
4901	}
4902
4903	/* if there is room to write more data to the pty, go write more */
4904	if (FD_ISSET(screen->respond, &write_mask)) {
4905	    v_write(screen->respond, (Char *) 0, 0);	/* flush buffer */
4906	}
4907
4908	/* if there are X events already in our queue, it
4909	   counts as being readable */
4910	if (xtermAppPending() ||
4911	    FD_ISSET(ConnectionNumber(screen->display), &select_mask)) {
4912	    xevents();
4913	    if (VTbuffer->update != update)	/* HandleInterpret */
4914		break;
4915	}
4916
4917    }
4918}
4919#endif /* VMS */
4920
4921static IChar
4922doinput(void)
4923{
4924    TScreen *screen = TScreenOf(term);
4925
4926    while (!morePtyData(screen, VTbuffer))
4927	in_put(term);
4928    return nextPtyData(screen, VTbuffer);
4929}
4930
4931#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
4932/*
4933 *  For OverTheSpot, client has to inform the position for XIM preedit.
4934 */
4935static void
4936PreeditPosition(XtermWidget xw)
4937{
4938    TInput *input = lookupTInput(xw, (Widget) xw);
4939    TScreen *screen = TScreenOf(xw);
4940    CLineData *ld;
4941    XPoint spot;
4942    XVaNestedList list;
4943
4944    if (input && input->xic
4945	&& (ld = getLineData(screen, screen->cur_row)) != 0) {
4946	spot.x = (short) LineCursorX(screen, ld, screen->cur_col);
4947	spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent);
4948	list = XVaCreateNestedList(0,
4949				   XNSpotLocation, &spot,
4950				   XNForeground, T_COLOR(screen, TEXT_FG),
4951				   XNBackground, T_COLOR(screen, TEXT_BG),
4952				   (void *) 0);
4953	XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0);
4954	XFree(list);
4955    }
4956}
4957#endif
4958
4959static void
4960WrapLine(XtermWidget xw)
4961{
4962    TScreen *screen = TScreenOf(xw);
4963    LineData *ld = getLineData(screen, screen->cur_row);
4964
4965    if (ld != 0) {
4966	/* mark that we had to wrap this line */
4967	LineSetFlag(ld, LINEWRAPPED);
4968	if (screen->show_wrap_marks) {
4969	    ShowWrapMarks(xw, screen->cur_row, ld);
4970	}
4971	xtermAutoPrint(xw, '\n');
4972	xtermIndex(xw, 1);
4973	set_cur_col(screen, ScrnLeftMargin(xw));
4974    }
4975}
4976
4977/*
4978 * process a string of characters according to the character set indicated
4979 * by charset.  worry about end of line conditions (wraparound if selected).
4980 */
4981void
4982dotext(XtermWidget xw,
4983       int charset,
4984       IChar *buf,		/* start of characters to process */
4985       Cardinal len)		/* end */
4986{
4987    TScreen *screen = TScreenOf(xw);
4988#if OPT_WIDE_CHARS
4989    Cardinal chars_chomped = 1;
4990    int next_col = screen->cur_col;
4991#else
4992    int next_col, this_col;	/* must be signed */
4993#endif
4994    Cardinal offset;
4995    int right = ScrnRightMargin(xw);
4996
4997    /*
4998     * It is possible to use CUP, etc., to move outside margins.  In that
4999     * case, the right-margin is ineffective.
5000     */
5001    if (screen->cur_col > right) {
5002	right = screen->max_col;
5003    }
5004#if OPT_WIDE_CHARS
5005    if (screen->vt100_graphics)
5006#endif
5007	if (!xtermCharSetOut(xw, buf, buf + len, charset))
5008	    return;
5009
5010    if_OPT_XMC_GLITCH(screen, {
5011	Cardinal n;
5012	if (charset != '?') {
5013	    for (n = 0; n < len; n++) {
5014		if (buf[n] == XMC_GLITCH)
5015		    buf[n] = XMC_GLITCH + 1;
5016	    }
5017	}
5018    });
5019
5020#if OPT_WIDE_CHARS
5021    for (offset = 0;
5022	 offset < len && (chars_chomped > 0 || screen->do_wrap);
5023	 offset += chars_chomped) {
5024	int width_available = right + 1 - screen->cur_col;
5025	int width_here = 0;
5026	Boolean force_wrap;
5027	Boolean need_wrap;
5028	Boolean did_wrap;
5029	int last_chomp = 0;
5030	chars_chomped = 0;
5031
5032	do {
5033	    force_wrap = False;
5034	    need_wrap = False;
5035	    did_wrap = False;
5036
5037	    if (screen->do_wrap) {
5038		screen->do_wrap = False;
5039		if ((xw->flags & WRAPAROUND)) {
5040		    WrapLine(xw);
5041		    width_available = right + 1 - screen->cur_col;
5042		    next_col = screen->cur_col;
5043		    did_wrap = True;
5044		}
5045	    }
5046
5047	    /*
5048	     * This can happen with left/right margins...
5049	     */
5050	    if (width_available <= 0) {
5051		break;
5052	    }
5053
5054	    /*
5055	     * Regarding the soft-hyphen aberration, see
5056	     * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html
5057	     */
5058	    while (width_here <= width_available
5059		   && chars_chomped < (len - offset)) {
5060		Cardinal n = chars_chomped + offset;
5061		if (!screen->utf8_mode
5062		    || (screen->vt100_graphics && charset == '0')) {
5063		    last_chomp = 1;
5064		} else if (screen->c1_printable &&
5065			   buf[n] >= 0x80 &&
5066			   buf[n] <= 0xa0) {
5067		    last_chomp = 1;
5068		} else {
5069		    last_chomp = my_wcwidth((wchar_t) buf[n]);
5070		    if (last_chomp <= 0) {
5071			IChar ch = buf[n];
5072			Bool eat_it = (ch > 127);
5073			if (ch == 0xad) {
5074			    /*
5075			     * Only display soft-hyphen if it happens to be at
5076			     * the right-margin.  While that means that only
5077			     * the displayed character could be selected for
5078			     * pasting, a well-behaved application would never
5079			     * send this, anyway...
5080			     */
5081			    if (width_here < width_available - 1) {
5082				eat_it = True;
5083			    } else {
5084				last_chomp = 1;
5085				eat_it = False;
5086			    }
5087			    TRACE(("...will%s display soft-hyphen\n",
5088				   eat_it ? " not" : ""));
5089			}
5090			/*
5091			 * Supposedly we dealt with combining characters and
5092			 * control characters in doparse().  Anything left over
5093			 * is junk that we will not attempt to display.
5094			 */
5095			if (eat_it) {
5096			    TRACE(("...will not display U+%04X\n", ch));
5097			    --len;
5098			    while (n < len) {
5099				buf[n] = buf[n + 1];
5100				++n;
5101			    }
5102			    last_chomp = 0;
5103			    chars_chomped--;
5104			}
5105		    }
5106		}
5107		width_here += last_chomp;
5108		chars_chomped++;
5109	    }
5110
5111	    if (width_here > width_available) {
5112		if (last_chomp > right + 1) {
5113		    break;	/* give up - it is too big */
5114		} else if (chars_chomped-- == 0) {
5115		    /* This can happen with left/right margins... */
5116		    break;
5117		}
5118		width_here -= last_chomp;
5119		if (chars_chomped > 0) {
5120		    if (!(xw->flags & WRAPAROUND)) {
5121			buf[chars_chomped + offset - 1] = buf[len - 1];
5122		    } else {
5123			need_wrap = True;
5124		    }
5125		}
5126	    } else if (width_here == width_available) {
5127		need_wrap = True;
5128	    } else if (chars_chomped != (len - offset)) {
5129		need_wrap = True;
5130	    }
5131
5132	    if (chars_chomped != 0 && next_col <= screen->max_col) {
5133		WriteText(xw, buf + offset, chars_chomped);
5134	    } else if (!did_wrap
5135		       && len > 0
5136		       && (xw->flags & WRAPAROUND)
5137		       && screen->cur_col > ScrnLeftMargin(xw)) {
5138		force_wrap = True;
5139		need_wrap = True;
5140	    }
5141	    next_col += width_here;
5142	    screen->do_wrap = need_wrap;
5143	} while (force_wrap);
5144    }
5145
5146    /*
5147     * Remember that we wrote something to the screen, for use as a base of
5148     * combining characters.  The logic above may have called cursor-forward
5149     * or carriage-return operations which resets this flag, so we set it at
5150     * the very end.
5151     */
5152    screen->char_was_written = True;
5153#else /* ! OPT_WIDE_CHARS */
5154
5155    for (offset = 0; offset < len; offset += (Cardinal) this_col) {
5156#if OPT_DEC_CHRSET
5157	CLineData *ld = getLineData(screen, screen->cur_row);
5158#endif
5159
5160	int last_col = LineMaxCol(screen, ld);
5161	if (last_col > (right + 1))
5162	    last_col = right + 1;
5163	this_col = last_col - screen->cur_col + 1;
5164	if (this_col <= 1) {
5165	    if (screen->do_wrap) {
5166		screen->do_wrap = False;
5167		if ((xw->flags & WRAPAROUND)) {
5168		    WrapLine(xw);
5169		}
5170	    }
5171	    this_col = 1;
5172	}
5173	if (offset + (Cardinal) this_col > len) {
5174	    this_col = (int) (len - offset);
5175	}
5176	next_col = screen->cur_col + this_col;
5177
5178	WriteText(xw, buf + offset, (unsigned) this_col);
5179
5180	/*
5181	 * The call to WriteText updates screen->cur_col.
5182	 * If screen->cur_col is less than next_col, we must have
5183	 * hit the right margin - so set the do_wrap flag.
5184	 */
5185	screen->do_wrap = (Boolean) (screen->cur_col < next_col);
5186    }
5187
5188#endif /* OPT_WIDE_CHARS */
5189}
5190
5191#if OPT_WIDE_CHARS
5192unsigned
5193visual_width(const IChar *str, Cardinal len)
5194{
5195    /* returns the visual width of a string (doublewide characters count
5196       as 2, normalwide characters count as 1) */
5197    unsigned my_len = 0;
5198    while (len) {
5199	int ch = (int) *str++;
5200	if (isWide(ch))
5201	    my_len += 2;
5202	else
5203	    my_len++;
5204	len--;
5205    }
5206    return my_len;
5207}
5208#endif
5209
5210#if HANDLE_STRUCT_NOTIFY
5211/* Flag icon name with "***" on window output when iconified.
5212 */
5213static void
5214HandleStructNotify(Widget w GCC_UNUSED,
5215		   XtPointer closure GCC_UNUSED,
5216		   XEvent *event,
5217		   Boolean *cont GCC_UNUSED)
5218{
5219    XtermWidget xw = term;
5220
5221    switch (event->type) {
5222    case MapNotify:
5223	TRACE(("HandleStructNotify(MapNotify) %#lx\n", event->xmap.window));
5224	resetZIconBeep(xw);
5225	mapstate = !IsUnmapped;
5226	break;
5227    case UnmapNotify:
5228	TRACE(("HandleStructNotify(UnmapNotify) %#lx\n", event->xunmap.window));
5229	mapstate = IsUnmapped;
5230	break;
5231    case ConfigureNotify:
5232	if (event->xconfigure.window == XtWindow(toplevel)) {
5233#if !OPT_TOOLBAR
5234	    int height, width;
5235
5236	    height = event->xconfigure.height;
5237	    width = event->xconfigure.width;
5238#endif
5239	    TRACE(("HandleStructNotify(ConfigureNotify) %#lx %d,%d %dx%d\n",
5240		   event->xconfigure.window,
5241		   event->xconfigure.y, event->xconfigure.x,
5242		   event->xconfigure.height, event->xconfigure.width));
5243
5244#if OPT_TOOLBAR
5245	    /*
5246	     * The notification is for the top-level widget, but we care about
5247	     * vt100 (ignore the tek4014 window).
5248	     */
5249	    if (TScreenOf(xw)->Vshow) {
5250		VTwin *Vwin = WhichVWin(TScreenOf(xw));
5251		TbInfo *info = &(Vwin->tb_info);
5252		TbInfo save = *info;
5253
5254		if (info->menu_bar) {
5255		    XtVaGetValues(info->menu_bar,
5256				  XtNheight, &info->menu_height,
5257				  XtNborderWidth, &info->menu_border,
5258				  (XtPointer) 0);
5259
5260		    if (save.menu_height != info->menu_height
5261			|| save.menu_border != info->menu_border) {
5262
5263			TRACE(("...menu_height %d\n", info->menu_height));
5264			TRACE(("...menu_border %d\n", info->menu_border));
5265			TRACE(("...had height  %d, border %d\n",
5266			       save.menu_height,
5267			       save.menu_border));
5268
5269			/*
5270			 * Window manager still may be using the old values.
5271			 * Try to fool it.
5272			 */
5273			REQ_RESIZE((Widget) xw,
5274				   TScreenOf(xw)->fullVwin.fullwidth,
5275				   (Dimension) (info->menu_height
5276						- save.menu_height
5277						+ TScreenOf(xw)->fullVwin.fullheight),
5278				   NULL, NULL);
5279			repairSizeHints();
5280		    }
5281		}
5282	    }
5283#else
5284	    if (height != xw->hints.height || width != xw->hints.width)
5285		RequestResize(xw, height, width, False);
5286#endif /* OPT_TOOLBAR */
5287	}
5288	break;
5289    case ReparentNotify:
5290	TRACE(("HandleStructNotify(ReparentNotify) %#lx\n", event->xreparent.window));
5291	break;
5292    default:
5293	TRACE(("HandleStructNotify(event %s) %#lx\n",
5294	       visibleEventType(event->type),
5295	       event->xany.window));
5296	break;
5297    }
5298}
5299#endif /* HANDLE_STRUCT_NOTIFY */
5300
5301#if OPT_BLINK_CURS
5302static void
5303SetCursorBlink(TScreen *screen, Bool enable)
5304{
5305    screen->cursor_blink = (Boolean) enable;
5306    if (DoStartBlinking(screen)) {
5307	StartBlinking(screen);
5308    } else {
5309	/* EMPTY */
5310#if OPT_BLINK_TEXT
5311	reallyStopBlinking(screen);
5312#else
5313	StopBlinking(screen);
5314#endif
5315    }
5316    update_cursorblink();
5317}
5318
5319void
5320ToggleCursorBlink(TScreen *screen)
5321{
5322    SetCursorBlink(screen, (Bool) (!(screen->cursor_blink)));
5323}
5324#endif
5325
5326/*
5327 * process ANSI modes set, reset
5328 */
5329static void
5330ansi_modes(XtermWidget xw, BitFunc func)
5331{
5332    int i;
5333
5334    for (i = 0; i < nparam; ++i) {
5335	switch (GetParam(i)) {
5336	case 2:		/* KAM (if set, keyboard locked */
5337	    (*func) (&xw->keyboard.flags, MODE_KAM);
5338	    break;
5339
5340	case 4:		/* IRM                          */
5341	    (*func) (&xw->flags, INSERT);
5342	    break;
5343
5344	case 12:		/* SRM (if set, local echo      */
5345	    (*func) (&xw->keyboard.flags, MODE_SRM);
5346	    break;
5347
5348	case 20:		/* LNM                          */
5349	    (*func) (&xw->flags, LINEFEED);
5350	    update_autolinefeed();
5351	    break;
5352	}
5353    }
5354}
5355
5356#define IsSM() (func == bitset)
5357
5358#define set_bool_mode(flag) \
5359	flag = (Boolean) IsSM()
5360
5361static void
5362really_set_mousemode(XtermWidget xw,
5363		     Bool enabled,
5364		     XtermMouseModes mode)
5365{
5366    TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF;
5367    if (okSendMousePos(xw) != MOUSE_OFF)
5368	xtermShowPointer(xw, True);
5369}
5370
5371#define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode)
5372
5373#if OPT_READLINE
5374#define set_mouseflag(f)		\
5375	(IsSM()				\
5376	 ? SCREEN_FLAG_set(screen, f)	\
5377	 : SCREEN_FLAG_unset(screen, f))
5378#endif
5379
5380/*
5381 * process DEC private modes set, reset
5382 */
5383static void
5384dpmodes(XtermWidget xw, BitFunc func)
5385{
5386    TScreen *screen = TScreenOf(xw);
5387    int i, j;
5388    unsigned myflags;
5389
5390    TRACE(("changing %d DEC private modes\n", nparam));
5391    for (i = 0; i < nparam; ++i) {
5392	int code = GetParam(i);
5393
5394	TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code));
5395	switch ((DECSET_codes) code) {
5396	case srm_DECCKM:
5397	    (*func) (&xw->keyboard.flags, MODE_DECCKM);
5398	    update_appcursor();
5399	    break;
5400	case srm_DECANM:	/* ANSI/VT52 mode      */
5401	    if (IsSM()) {	/* ANSI (VT100) */
5402		/*
5403		 * Setting DECANM should have no effect, since this function
5404		 * cannot be reached from vt52 mode.
5405		 */
5406		/* EMPTY */ ;
5407	    }
5408#if OPT_VT52_MODE
5409	    else if (screen->terminal_id >= 100) {	/* VT52 */
5410		TRACE(("DECANM terminal_id %d, vtXX_level %d\n",
5411		       screen->terminal_id,
5412		       screen->vtXX_level));
5413		screen->vtXX_level = 0;
5414		screen->vt52_save_curgl = screen->curgl;
5415		screen->vt52_save_curgr = screen->curgr;
5416		screen->vt52_save_curss = screen->curss;
5417		memmove(screen->vt52_save_gsets, screen->gsets, sizeof(screen->gsets));
5418		resetCharsets(screen);
5419		InitParams();	/* ignore the remaining params, if any */
5420	    }
5421#endif
5422	    break;
5423	case srm_DECCOLM:
5424	    if (screen->c132) {
5425		if (!(xw->flags & NOCLEAR_COLM))
5426		    ClearScreen(xw);
5427		CursorSet(screen, 0, 0, xw->flags);
5428		if ((j = IsSM()? 132 : 80) !=
5429		    ((xw->flags & IN132COLUMNS) ? 132 : 80) ||
5430		    j != MaxCols(screen))
5431		    RequestResize(xw, -1, j, True);
5432		(*func) (&xw->flags, IN132COLUMNS);
5433		if (xw->flags & IN132COLUMNS) {
5434		    UIntClr(xw->flags, LEFT_RIGHT);
5435		    reset_lr_margins(screen);
5436		}
5437	    }
5438	    break;
5439	case srm_DECSCLM:	/* (slow scroll)        */
5440	    if (IsSM()) {
5441		screen->jumpscroll = 0;
5442		if (screen->scroll_amt)
5443		    FlushScroll(xw);
5444	    } else
5445		screen->jumpscroll = 1;
5446	    (*func) (&xw->flags, SMOOTHSCROLL);
5447	    update_jumpscroll();
5448	    break;
5449	case srm_DECSCNM:
5450	    myflags = xw->flags;
5451	    (*func) (&xw->flags, REVERSE_VIDEO);
5452	    if ((xw->flags ^ myflags) & REVERSE_VIDEO)
5453		ReverseVideo(xw);
5454	    /* update_reversevideo done in RevVid */
5455	    break;
5456
5457	case srm_DECOM:
5458	    (*func) (&xw->flags, ORIGIN);
5459	    CursorSet(screen, 0, 0, xw->flags);
5460	    break;
5461
5462	case srm_DECAWM:
5463	    (*func) (&xw->flags, WRAPAROUND);
5464	    update_autowrap();
5465	    break;
5466	case srm_DECARM:
5467	    /* ignore autorepeat
5468	     * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only
5469	     * for the whole display - not limited to a given window.
5470	     */
5471	    break;
5472	case srm_X10_MOUSE:	/* MIT bogus sequence           */
5473	    MotionOff(screen, xw);
5474	    set_mousemode(X10_MOUSE);
5475	    break;
5476#if OPT_TOOLBAR
5477	case srm_RXVT_TOOLBAR:
5478	    ShowToolbar(IsSM());
5479	    break;
5480#endif
5481#if OPT_BLINK_CURS
5482	case srm_ATT610_BLINK:	/* att610: Start/stop blinking cursor */
5483	    if (screen->cursor_blink_res) {
5484		set_bool_mode(screen->cursor_blink_esc);
5485		UpdateCursorBlink(screen);
5486	    }
5487	    break;
5488#endif
5489	case srm_DECPFF:	/* print form feed */
5490	    set_bool_mode(PrinterOf(screen).printer_formfeed);
5491	    break;
5492	case srm_DECPEX:	/* print extent */
5493	    set_bool_mode(PrinterOf(screen).printer_extent);
5494	    break;
5495	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
5496	    set_bool_mode(screen->cursor_set);
5497	    break;
5498	case srm_RXVT_SCROLLBAR:
5499	    if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF))
5500		ToggleScrollBar(xw);
5501	    break;
5502#if OPT_SHIFT_FONTS
5503	case srm_RXVT_FONTSIZE:
5504	    set_bool_mode(xw->misc.shift_fonts);
5505	    break;
5506#endif
5507#if OPT_TEK4014
5508	case srm_DECTEK:
5509	    if (IsSM() && !(screen->inhibit & I_TEK)) {
5510		FlushLog(xw);
5511		TEK4014_ACTIVE(xw) = True;
5512		TRACE(("Tek4014 is now active...\n"));
5513		update_vttekmode();
5514	    }
5515	    break;
5516#endif
5517	case srm_132COLS:	/* 132 column mode              */
5518	    set_bool_mode(screen->c132);
5519	    update_allow132();
5520	    break;
5521	case srm_CURSES_HACK:
5522	    set_bool_mode(screen->curses);
5523	    update_cursesemul();
5524	    break;
5525	case srm_DECNRCM:	/* national charset (VT220) */
5526	    if (screen->vtXX_level >= 2) {
5527		if ((*func) (&xw->flags, NATIONAL)) {
5528		    modified_DECNRCM(xw);
5529		}
5530	    }
5531	    break;
5532	case srm_MARGIN_BELL:	/* margin bell                  */
5533	    set_bool_mode(screen->marginbell);
5534	    if (!screen->marginbell)
5535		screen->bellArmed = -1;
5536	    update_marginbell();
5537	    break;
5538	case srm_REVERSEWRAP:	/* reverse wraparound   */
5539	    (*func) (&xw->flags, REVERSEWRAP);
5540	    update_reversewrap();
5541	    break;
5542#ifdef ALLOWLOGGING
5543	case srm_ALLOWLOGGING:	/* logging              */
5544#ifdef ALLOWLOGFILEONOFF
5545	    /*
5546	     * if this feature is enabled, logging may be
5547	     * enabled and disabled via escape sequences.
5548	     */
5549	    if (IsSM())
5550		StartLog(xw);
5551	    else
5552		CloseLog(xw);
5553#else
5554	    Bell(xw, XkbBI_Info, 0);
5555	    Bell(xw, XkbBI_Info, 0);
5556#endif /* ALLOWLOGFILEONOFF */
5557	    break;
5558#endif
5559	case srm_OPT_ALTBUF_CURSOR:	/* alternate buffer & cursor */
5560	    if (!xw->misc.titeInhibit) {
5561		if (IsSM()) {
5562		    CursorSave(xw);
5563		    ToAlternate(xw, True);
5564		    ClearScreen(xw);
5565		} else {
5566		    FromAlternate(xw);
5567		    CursorRestore(xw);
5568		}
5569	    } else if (IsSM()) {
5570		do_ti_xtra_scroll(xw);
5571	    }
5572	    break;
5573	case srm_OPT_ALTBUF:
5574	    /* FALLTHRU */
5575	case srm_ALTBUF:	/* alternate buffer */
5576	    if (!xw->misc.titeInhibit) {
5577		if (IsSM()) {
5578		    ToAlternate(xw, False);
5579		} else {
5580		    if (screen->whichBuf
5581			&& (code == 1047))
5582			ClearScreen(xw);
5583		    FromAlternate(xw);
5584		}
5585	    } else if (IsSM()) {
5586		do_ti_xtra_scroll(xw);
5587	    }
5588	    break;
5589	case srm_DECNKM:
5590	    (*func) (&xw->keyboard.flags, MODE_DECKPAM);
5591	    update_appkeypad();
5592	    break;
5593	case srm_DECBKM:
5594	    /* back-arrow mapped to backspace or delete(D) */
5595	    (*func) (&xw->keyboard.flags, MODE_DECBKM);
5596	    TRACE(("DECSET DECBKM %s\n",
5597		   BtoS(xw->keyboard.flags & MODE_DECBKM)));
5598	    update_decbkm();
5599	    break;
5600	case srm_DECLRMM:
5601	    if (screen->vtXX_level >= 4) {	/* VT420 */
5602		(*func) (&xw->flags, LEFT_RIGHT);
5603		if (IsLeftRightMode(xw)) {
5604		    xterm_ResetDouble(xw);
5605		} else {
5606		    reset_lr_margins(screen);
5607		}
5608	    }
5609	    break;
5610#if OPT_SIXEL_GRAPHICS
5611	case srm_DECSDM:	/* sixel scrolling */
5612	    if (screen->terminal_id == 240 ||	/* FIXME: VT24x did not scroll sixel graphics */
5613		screen->terminal_id == 241 ||
5614		screen->terminal_id == 330 ||
5615		screen->terminal_id == 340 ||
5616		screen->terminal_id == 382) {
5617		(*func) (&xw->keyboard.flags, MODE_DECSDM);
5618		TRACE(("DECSET/DECRST DECSDM %s (resource default is %d)\n",
5619		       BtoS(xw->keyboard.flags & MODE_DECSDM),
5620		       TScreenOf(xw)->sixel_scrolling));
5621		update_decsdm();
5622	    }
5623	    break;
5624#endif
5625	case srm_DECNCSM:
5626	    if (screen->vtXX_level >= 5) {	/* VT510 */
5627		(*func) (&xw->flags, NOCLEAR_COLM);
5628	    }
5629	    break;
5630	case srm_VT200_MOUSE:	/* xterm bogus sequence         */
5631	    MotionOff(screen, xw);
5632	    set_mousemode(VT200_MOUSE);
5633	    break;
5634	case srm_VT200_HIGHLIGHT_MOUSE:	/* xterm sequence w/hilite tracking */
5635	    MotionOff(screen, xw);
5636	    set_mousemode(VT200_HIGHLIGHT_MOUSE);
5637	    break;
5638	case srm_BTN_EVENT_MOUSE:
5639	    MotionOff(screen, xw);
5640	    set_mousemode(BTN_EVENT_MOUSE);
5641	    break;
5642	case srm_ANY_EVENT_MOUSE:
5643	    set_mousemode(ANY_EVENT_MOUSE);
5644	    if (screen->send_mouse_pos == MOUSE_OFF) {
5645		MotionOff(screen, xw);
5646	    } else {
5647		MotionOn(screen, xw);
5648	    }
5649	    break;
5650#if OPT_FOCUS_EVENT
5651	case srm_FOCUS_EVENT_MOUSE:
5652	    set_bool_mode(screen->send_focus_pos);
5653	    break;
5654#endif
5655	case srm_EXT_MODE_MOUSE:
5656	    /* FALLTHRU */
5657	case srm_SGR_EXT_MODE_MOUSE:
5658	    /* FALLTHRU */
5659	case srm_URXVT_EXT_MODE_MOUSE:
5660	    /*
5661	     * Rather than choose an arbitrary precedence among the coordinate
5662	     * modes, they are mutually exclusive.  For consistency, a reset is
5663	     * only effective against the matching mode.
5664	     */
5665	    if (IsSM()) {
5666		screen->extend_coords = code;
5667	    } else if (screen->extend_coords == code) {
5668		screen->extend_coords = 0;
5669	    }
5670	    break;
5671	case srm_ALTERNATE_SCROLL:
5672	    set_bool_mode(screen->alternateScroll);
5673	    break;
5674	case srm_RXVT_SCROLL_TTY_OUTPUT:
5675	    set_bool_mode(screen->scrollttyoutput);
5676	    update_scrollttyoutput();
5677	    break;
5678	case srm_RXVT_SCROLL_TTY_KEYPRESS:
5679	    set_bool_mode(screen->scrollkey);
5680	    update_scrollkey();
5681	    break;
5682	case srm_EIGHT_BIT_META:
5683	    if (screen->eight_bit_meta != ebNever) {
5684		set_bool_mode(screen->eight_bit_meta);
5685	    }
5686	    break;
5687#if OPT_NUM_LOCK
5688	case srm_REAL_NUMLOCK:
5689	    set_bool_mode(xw->misc.real_NumLock);
5690	    update_num_lock();
5691	    break;
5692	case srm_META_SENDS_ESC:
5693	    set_bool_mode(screen->meta_sends_esc);
5694	    update_meta_esc();
5695	    break;
5696#endif
5697	case srm_DELETE_IS_DEL:
5698	    set_bool_mode(screen->delete_is_del);
5699	    update_delete_del();
5700	    break;
5701#if OPT_NUM_LOCK
5702	case srm_ALT_SENDS_ESC:
5703	    set_bool_mode(screen->alt_sends_esc);
5704	    update_alt_esc();
5705	    break;
5706#endif
5707	case srm_KEEP_SELECTION:
5708	    set_bool_mode(screen->keepSelection);
5709	    update_keepSelection();
5710	    break;
5711	case srm_SELECT_TO_CLIPBOARD:
5712	    set_bool_mode(screen->selectToClipboard);
5713	    update_selectToClipboard();
5714	    break;
5715	case srm_BELL_IS_URGENT:
5716	    set_bool_mode(screen->bellIsUrgent);
5717	    update_bellIsUrgent();
5718	    break;
5719	case srm_POP_ON_BELL:
5720	    set_bool_mode(screen->poponbell);
5721	    update_poponbell();
5722	    break;
5723	case srm_KEEP_CLIPBOARD:
5724	    set_bool_mode(screen->keepClipboard);
5725	    update_keepClipboard();
5726	    break;
5727	case srm_TITE_INHIBIT:
5728	    if (!xw->misc.titeInhibit) {
5729		if (IsSM())
5730		    CursorSave(xw);
5731		else
5732		    CursorRestore(xw);
5733	    }
5734	    break;
5735#if OPT_TCAP_FKEYS
5736	case srm_TCAP_FKEYS:
5737	    set_keyboard_type(xw, keyboardIsTermcap, IsSM());
5738	    break;
5739#endif
5740#if OPT_SUN_FUNC_KEYS
5741	case srm_SUN_FKEYS:
5742	    set_keyboard_type(xw, keyboardIsSun, IsSM());
5743	    break;
5744#endif
5745#if OPT_HP_FUNC_KEYS
5746	case srm_HP_FKEYS:
5747	    set_keyboard_type(xw, keyboardIsHP, IsSM());
5748	    break;
5749#endif
5750#if OPT_SCO_FUNC_KEYS
5751	case srm_SCO_FKEYS:
5752	    set_keyboard_type(xw, keyboardIsSCO, IsSM());
5753	    break;
5754#endif
5755	case srm_LEGACY_FKEYS:
5756	    set_keyboard_type(xw, keyboardIsLegacy, IsSM());
5757	    break;
5758#if OPT_SUNPC_KBD
5759	case srm_VT220_FKEYS:
5760	    set_keyboard_type(xw, keyboardIsVT220, IsSM());
5761	    break;
5762#endif
5763#if OPT_READLINE
5764	case srm_BUTTON1_MOVE_POINT:
5765	    set_mouseflag(click1_moves);
5766	    break;
5767	case srm_BUTTON2_MOVE_POINT:
5768	    set_mouseflag(paste_moves);
5769	    break;
5770	case srm_DBUTTON3_DELETE:
5771	    set_mouseflag(dclick3_deletes);
5772	    break;
5773	case srm_PASTE_IN_BRACKET:
5774	    set_mouseflag(paste_brackets);
5775	    break;
5776	case srm_PASTE_QUOTE:
5777	    set_mouseflag(paste_quotes);
5778	    break;
5779	case srm_PASTE_LITERAL_NL:
5780	    set_mouseflag(paste_literal_nl);
5781	    break;
5782#endif /* OPT_READLINE */
5783#if OPT_GRAPHICS
5784	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
5785	    TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n",
5786		   BtoS(screen->privatecolorregisters),
5787		   BtoS(TScreenOf(xw)->privatecolorregisters)));
5788	    set_bool_mode(screen->privatecolorregisters);
5789	    update_privatecolorregisters();
5790	    break;
5791#endif
5792#if OPT_SIXEL_GRAPHICS
5793	case srm_SIXEL_SCROLLS_RIGHT:	/* sixel scrolling moves cursor to right */
5794	    if (screen->terminal_id == 240 ||	/* FIXME: VT24x did not scroll sixel graphics */
5795		screen->terminal_id == 241 ||
5796		screen->terminal_id == 330 ||
5797		screen->terminal_id == 340 ||
5798		screen->terminal_id == 382) {
5799		set_bool_mode(screen->sixel_scrolls_right);
5800		TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n",
5801		       BtoS(screen->sixel_scrolls_right),
5802		       BtoS(TScreenOf(xw)->sixel_scrolls_right)));
5803	    }
5804	    break;
5805#endif
5806	default:
5807	    TRACE(("DATA_ERROR: unknown private code %d\n", code));
5808	    break;
5809	}
5810    }
5811}
5812
5813/*
5814 * process xterm private modes save
5815 */
5816static void
5817savemodes(XtermWidget xw)
5818{
5819    TScreen *screen = TScreenOf(xw);
5820    int i;
5821
5822    for (i = 0; i < nparam; i++) {
5823	int code = GetParam(i);
5824
5825	TRACE(("savemodes %d\n", code));
5826	switch ((DECSET_codes) code) {
5827	case srm_DECCKM:
5828	    DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM);
5829	    break;
5830	case srm_DECANM:	/* ANSI/VT52 mode      */
5831	    /* no effect */
5832	    break;
5833	case srm_DECCOLM:
5834	    if (screen->c132)
5835		DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS);
5836	    break;
5837	case srm_DECSCLM:	/* (slow scroll)        */
5838	    DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL);
5839	    break;
5840	case srm_DECSCNM:
5841	    DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO);
5842	    break;
5843	case srm_DECOM:
5844	    DoSM(DP_DECOM, xw->flags & ORIGIN);
5845	    break;
5846	case srm_DECAWM:
5847	    DoSM(DP_DECAWM, xw->flags & WRAPAROUND);
5848	    break;
5849	case srm_DECARM:
5850	    /* ignore autorepeat */
5851	    break;
5852	case srm_X10_MOUSE:	/* mouse bogus sequence */
5853	    DoSM(DP_X_X10MSE, screen->send_mouse_pos);
5854	    break;
5855#if OPT_TOOLBAR
5856	case srm_RXVT_TOOLBAR:
5857	    DoSM(DP_TOOLBAR, resource.toolBar);
5858	    break;
5859#endif
5860#if OPT_BLINK_CURS
5861	case srm_ATT610_BLINK:	/* att610: Start/stop blinking cursor */
5862	    if (screen->cursor_blink_res) {
5863		DoSM(DP_CRS_BLINK, screen->cursor_blink_esc);
5864	    }
5865	    break;
5866#endif
5867	case srm_DECPFF:	/* print form feed */
5868	    DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
5869	    break;
5870	case srm_DECPEX:	/* print extent */
5871	    DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
5872	    break;
5873	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
5874	    DoSM(DP_CRS_VISIBLE, screen->cursor_set);
5875	    break;
5876	case srm_RXVT_SCROLLBAR:
5877	    DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0));
5878	    break;
5879#if OPT_SHIFT_FONTS
5880	case srm_RXVT_FONTSIZE:
5881	    DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
5882	    break;
5883#endif
5884#if OPT_TEK4014
5885	case srm_DECTEK:
5886	    DoSM(DP_DECTEK, TEK4014_ACTIVE(xw));
5887	    break;
5888#endif
5889	case srm_132COLS:	/* 132 column mode              */
5890	    DoSM(DP_X_DECCOLM, screen->c132);
5891	    break;
5892	case srm_CURSES_HACK:	/* curses hack                  */
5893	    DoSM(DP_X_MORE, screen->curses);
5894	    break;
5895	case srm_DECNRCM:	/* national charset (VT220) */
5896	    if (screen->vtXX_level >= 2) {
5897		DoSM(DP_DECNRCM, xw->flags & NATIONAL);
5898	    }
5899	    break;
5900	case srm_MARGIN_BELL:	/* margin bell                  */
5901	    DoSM(DP_X_MARGIN, screen->marginbell);
5902	    break;
5903	case srm_REVERSEWRAP:	/* reverse wraparound   */
5904	    DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP);
5905	    break;
5906#ifdef ALLOWLOGGING
5907	case srm_ALLOWLOGGING:	/* logging              */
5908	    DoSM(DP_X_LOGGING, screen->logging);
5909	    break;
5910#endif
5911	case srm_OPT_ALTBUF_CURSOR:
5912	    /* FALLTHRU */
5913	case srm_OPT_ALTBUF:
5914	    /* FALLTHRU */
5915	case srm_ALTBUF:	/* alternate buffer             */
5916	    DoSM(DP_X_ALTSCRN, screen->whichBuf);
5917	    break;
5918	case srm_DECNKM:
5919	    DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM);
5920	    break;
5921	case srm_DECBKM:	/* backarrow mapping */
5922	    DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM);
5923	    break;
5924	case srm_DECLRMM:	/* left-right */
5925	    DoSM(DP_X_LRMM, LEFT_RIGHT);
5926	    break;
5927#if OPT_SIXEL_GRAPHICS
5928	case srm_DECSDM:	/* sixel scrolling */
5929	    DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM);
5930	    update_decsdm();
5931	    break;
5932#endif
5933	case srm_DECNCSM:	/* noclear */
5934	    DoSM(DP_X_NCSM, NOCLEAR_COLM);
5935	    break;
5936	case srm_VT200_MOUSE:	/* mouse bogus sequence         */
5937	    /* FALLTHRU */
5938	case srm_VT200_HIGHLIGHT_MOUSE:
5939	    /* FALLTHRU */
5940	case srm_BTN_EVENT_MOUSE:
5941	    /* FALLTHRU */
5942	case srm_ANY_EVENT_MOUSE:
5943	    DoSM(DP_X_MOUSE, screen->send_mouse_pos);
5944	    break;
5945#if OPT_FOCUS_EVENT
5946	case srm_FOCUS_EVENT_MOUSE:
5947	    DoSM(DP_X_FOCUS, screen->send_focus_pos);
5948	    break;
5949#endif
5950	case srm_EXT_MODE_MOUSE:
5951	    /* FALLTHRU */
5952	case srm_SGR_EXT_MODE_MOUSE:
5953	    /* FALLTHRU */
5954	case srm_URXVT_EXT_MODE_MOUSE:
5955	    DoSM(DP_X_EXT_MOUSE, screen->extend_coords);
5956	    break;
5957	case srm_ALTERNATE_SCROLL:
5958	    DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
5959	    break;
5960	case srm_RXVT_SCROLL_TTY_OUTPUT:
5961	    DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
5962	    break;
5963	case srm_RXVT_SCROLL_TTY_KEYPRESS:
5964	    DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
5965	    break;
5966	case srm_EIGHT_BIT_META:
5967	    DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
5968	    break;
5969#if OPT_NUM_LOCK
5970	case srm_REAL_NUMLOCK:
5971	    DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
5972	    break;
5973	case srm_META_SENDS_ESC:
5974	    DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc);
5975	    break;
5976#endif
5977	case srm_DELETE_IS_DEL:
5978	    DoSM(DP_DELETE_IS_DEL, screen->delete_is_del);
5979	    break;
5980#if OPT_NUM_LOCK
5981	case srm_ALT_SENDS_ESC:
5982	    DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
5983	    break;
5984#endif
5985	case srm_KEEP_SELECTION:
5986	    DoSM(DP_KEEP_SELECTION, screen->keepSelection);
5987	    break;
5988	case srm_SELECT_TO_CLIPBOARD:
5989	    DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
5990	    break;
5991	case srm_BELL_IS_URGENT:
5992	    DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
5993	    break;
5994	case srm_POP_ON_BELL:
5995	    DoSM(DP_POP_ON_BELL, screen->poponbell);
5996	    break;
5997	case srm_KEEP_CLIPBOARD:
5998	    DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
5999	    break;
6000#if OPT_TCAP_FKEYS
6001	case srm_TCAP_FKEYS:
6002	    /* FALLTHRU */
6003#endif
6004#if OPT_SUN_FUNC_KEYS
6005	case srm_SUN_FKEYS:
6006	    /* FALLTHRU */
6007#endif
6008#if OPT_HP_FUNC_KEYS
6009	case srm_HP_FKEYS:
6010	    /* FALLTHRU */
6011#endif
6012#if OPT_SCO_FUNC_KEYS
6013	case srm_SCO_FKEYS:
6014	    /* FALLTHRU */
6015#endif
6016#if OPT_SUNPC_KBD
6017	case srm_VT220_FKEYS:
6018	    /* FALLTHRU */
6019#endif
6020	case srm_LEGACY_FKEYS:
6021	    DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type);
6022	    break;
6023	case srm_TITE_INHIBIT:
6024	    if (!xw->misc.titeInhibit) {
6025		CursorSave(xw);
6026	    }
6027	    break;
6028#if OPT_READLINE
6029	case srm_BUTTON1_MOVE_POINT:
6030	    SCREEN_FLAG_save(screen, click1_moves);
6031	    break;
6032	case srm_BUTTON2_MOVE_POINT:
6033	    SCREEN_FLAG_save(screen, paste_moves);
6034	    break;
6035	case srm_DBUTTON3_DELETE:
6036	    SCREEN_FLAG_save(screen, dclick3_deletes);
6037	    break;
6038	case srm_PASTE_IN_BRACKET:
6039	    SCREEN_FLAG_save(screen, paste_brackets);
6040	    break;
6041	case srm_PASTE_QUOTE:
6042	    SCREEN_FLAG_save(screen, paste_quotes);
6043	    break;
6044	case srm_PASTE_LITERAL_NL:
6045	    SCREEN_FLAG_save(screen, paste_literal_nl);
6046	    break;
6047#endif /* OPT_READLINE */
6048#if OPT_GRAPHICS
6049	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
6050	    TRACE(("save PRIVATE_COLOR_REGISTERS %s\n",
6051		   BtoS(screen->privatecolorregisters)));
6052	    DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
6053	    update_privatecolorregisters();
6054	    break;
6055#endif
6056#if OPT_SIXEL_GRAPHICS
6057	case srm_SIXEL_SCROLLS_RIGHT:
6058	    TRACE(("save SIXEL_SCROLLS_RIGHT %s\n",
6059		   BtoS(screen->sixel_scrolls_right)));
6060	    DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
6061	    break;
6062#endif
6063	}
6064    }
6065}
6066
6067/*
6068 * process xterm private modes restore
6069 */
6070static void
6071restoremodes(XtermWidget xw)
6072{
6073    TScreen *screen = TScreenOf(xw);
6074    int i, j;
6075
6076    for (i = 0; i < nparam; i++) {
6077	int code = GetParam(i);
6078
6079	TRACE(("restoremodes %d\n", code));
6080	switch ((DECSET_codes) code) {
6081	case srm_DECCKM:
6082	    bitcpy(&xw->keyboard.flags,
6083		   screen->save_modes[DP_DECCKM], MODE_DECCKM);
6084	    update_appcursor();
6085	    break;
6086	case srm_DECANM:	/* ANSI/VT52 mode      */
6087	    /* no effect */
6088	    break;
6089	case srm_DECCOLM:
6090	    if (screen->c132) {
6091		if (!(xw->flags & NOCLEAR_COLM))
6092		    ClearScreen(xw);
6093		CursorSet(screen, 0, 0, xw->flags);
6094		if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS)
6095		     ? 132 : 80) != ((xw->flags & IN132COLUMNS)
6096				     ? 132 : 80) || j != MaxCols(screen))
6097		    RequestResize(xw, -1, j, True);
6098		bitcpy(&xw->flags,
6099		       screen->save_modes[DP_DECCOLM],
6100		       IN132COLUMNS);
6101	    }
6102	    break;
6103	case srm_DECSCLM:	/* (slow scroll)        */
6104	    if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) {
6105		screen->jumpscroll = 0;
6106		if (screen->scroll_amt)
6107		    FlushScroll(xw);
6108	    } else
6109		screen->jumpscroll = 1;
6110	    bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL);
6111	    update_jumpscroll();
6112	    break;
6113	case srm_DECSCNM:
6114	    if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) {
6115		bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO);
6116		ReverseVideo(xw);
6117		/* update_reversevideo done in RevVid */
6118	    }
6119	    break;
6120	case srm_DECOM:
6121	    bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN);
6122	    CursorSet(screen, 0, 0, xw->flags);
6123	    break;
6124
6125	case srm_DECAWM:
6126	    bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND);
6127	    update_autowrap();
6128	    break;
6129	case srm_DECARM:
6130	    /* ignore autorepeat */
6131	    break;
6132	case srm_X10_MOUSE:	/* MIT bogus sequence           */
6133	    DoRM0(DP_X_X10MSE, screen->send_mouse_pos);
6134	    really_set_mousemode(xw,
6135				 screen->send_mouse_pos != MOUSE_OFF,
6136				 (XtermMouseModes) screen->send_mouse_pos);
6137	    break;
6138#if OPT_TOOLBAR
6139	case srm_RXVT_TOOLBAR:
6140	    DoRM(DP_TOOLBAR, resource.toolBar);
6141	    ShowToolbar(resource.toolBar);
6142	    break;
6143#endif
6144#if OPT_BLINK_CURS
6145	case srm_ATT610_BLINK:	/* Start/stop blinking cursor */
6146	    if (screen->cursor_blink_res) {
6147		DoRM(DP_CRS_BLINK, screen->cursor_blink_esc);
6148		UpdateCursorBlink(screen);
6149	    }
6150	    break;
6151#endif
6152	case srm_DECPFF:	/* print form feed */
6153	    DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
6154	    break;
6155	case srm_DECPEX:	/* print extent */
6156	    DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
6157	    break;
6158	case srm_DECTCEM:	/* Show/hide cursor (VT200) */
6159	    DoRM(DP_CRS_VISIBLE, screen->cursor_set);
6160	    break;
6161	case srm_RXVT_SCROLLBAR:
6162	    if ((screen->fullVwin.sb_info.width != 0) !=
6163		screen->save_modes[DP_RXVT_SCROLLBAR]) {
6164		ToggleScrollBar(xw);
6165	    }
6166	    break;
6167#if OPT_SHIFT_FONTS
6168	case srm_RXVT_FONTSIZE:
6169	    DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
6170	    break;
6171#endif
6172#if OPT_TEK4014
6173	case srm_DECTEK:
6174	    if (!(screen->inhibit & I_TEK) &&
6175		(TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) {
6176		FlushLog(xw);
6177		TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK];
6178		update_vttekmode();
6179	    }
6180	    break;
6181#endif
6182	case srm_132COLS:	/* 132 column mode              */
6183	    DoRM(DP_X_DECCOLM, screen->c132);
6184	    update_allow132();
6185	    break;
6186	case srm_CURSES_HACK:	/* curses hack                  */
6187	    DoRM(DP_X_MORE, screen->curses);
6188	    update_cursesemul();
6189	    break;
6190	case srm_DECNRCM:	/* national charset (VT220) */
6191	    if (screen->vtXX_level >= 2) {
6192		if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL))
6193		    modified_DECNRCM(xw);
6194	    }
6195	    break;
6196	case srm_MARGIN_BELL:	/* margin bell                  */
6197	    if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0)
6198		screen->bellArmed = -1;
6199	    update_marginbell();
6200	    break;
6201	case srm_REVERSEWRAP:	/* reverse wraparound   */
6202	    bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP);
6203	    update_reversewrap();
6204	    break;
6205#ifdef ALLOWLOGGING
6206	case srm_ALLOWLOGGING:	/* logging              */
6207#ifdef ALLOWLOGFILEONOFF
6208	    if (screen->save_modes[DP_X_LOGGING])
6209		StartLog(xw);
6210	    else
6211		CloseLog(xw);
6212#endif /* ALLOWLOGFILEONOFF */
6213	    /* update_logging done by StartLog and CloseLog */
6214	    break;
6215#endif
6216	case srm_OPT_ALTBUF_CURSOR:	/* alternate buffer & cursor */
6217	    /* FALLTHRU */
6218	case srm_OPT_ALTBUF:
6219	    /* FALLTHRU */
6220	case srm_ALTBUF:	/* alternate buffer */
6221	    if (!xw->misc.titeInhibit) {
6222		if (screen->save_modes[DP_X_ALTSCRN])
6223		    ToAlternate(xw, False);
6224		else
6225		    FromAlternate(xw);
6226		/* update_altscreen done by ToAlt and FromAlt */
6227	    } else if (screen->save_modes[DP_X_ALTSCRN]) {
6228		do_ti_xtra_scroll(xw);
6229	    }
6230	    break;
6231	case srm_DECNKM:
6232	    bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM);
6233	    update_appkeypad();
6234	    break;
6235	case srm_DECBKM:	/* backarrow mapping */
6236	    bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM);
6237	    update_decbkm();
6238	    break;
6239	case srm_DECLRMM:	/* left-right */
6240	    bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT);
6241	    if (IsLeftRightMode(xw)) {
6242		xterm_ResetDouble(xw);
6243	    } else {
6244		reset_lr_margins(screen);
6245	    }
6246	    break;
6247#if OPT_SIXEL_GRAPHICS
6248	case srm_DECSDM:	/* sixel scrolling */
6249	    bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM);
6250	    update_decsdm();
6251	    break;
6252#endif
6253	case srm_DECNCSM:	/* noclear */
6254	    bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM);
6255	    break;
6256	case srm_VT200_MOUSE:	/* mouse bogus sequence         */
6257	    /* FALLTHRU */
6258	case srm_VT200_HIGHLIGHT_MOUSE:
6259	    /* FALLTHRU */
6260	case srm_BTN_EVENT_MOUSE:
6261	    /* FALLTHRU */
6262	case srm_ANY_EVENT_MOUSE:
6263	    DoRM0(DP_X_MOUSE, screen->send_mouse_pos);
6264	    really_set_mousemode(xw,
6265				 screen->send_mouse_pos != MOUSE_OFF,
6266				 (XtermMouseModes) screen->send_mouse_pos);
6267	    break;
6268#if OPT_FOCUS_EVENT
6269	case srm_FOCUS_EVENT_MOUSE:
6270	    DoRM(DP_X_FOCUS, screen->send_focus_pos);
6271	    break;
6272#endif
6273	case srm_EXT_MODE_MOUSE:
6274	    /* FALLTHRU */
6275	case srm_SGR_EXT_MODE_MOUSE:
6276	    /* FALLTHRU */
6277	case srm_URXVT_EXT_MODE_MOUSE:
6278	    DoRM(DP_X_EXT_MOUSE, screen->extend_coords);
6279	    break;
6280	case srm_TITE_INHIBIT:
6281	    if (!xw->misc.titeInhibit) {
6282		CursorRestore(xw);
6283	    }
6284	    break;
6285	case srm_ALTERNATE_SCROLL:
6286	    DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
6287	    break;
6288	case srm_RXVT_SCROLL_TTY_OUTPUT:
6289	    DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
6290	    update_scrollttyoutput();
6291	    break;
6292	case srm_RXVT_SCROLL_TTY_KEYPRESS:
6293	    DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
6294	    update_scrollkey();
6295	    break;
6296	case srm_EIGHT_BIT_META:
6297	    DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
6298	    break;
6299#if OPT_NUM_LOCK
6300	case srm_REAL_NUMLOCK:
6301	    DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
6302	    update_num_lock();
6303	    break;
6304	case srm_META_SENDS_ESC:
6305	    DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc);
6306	    update_meta_esc();
6307	    break;
6308#endif
6309	case srm_DELETE_IS_DEL:
6310	    DoRM(DP_DELETE_IS_DEL, screen->delete_is_del);
6311	    update_delete_del();
6312	    break;
6313#if OPT_NUM_LOCK
6314	case srm_ALT_SENDS_ESC:
6315	    DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
6316	    update_alt_esc();
6317	    break;
6318#endif
6319	case srm_KEEP_SELECTION:
6320	    DoRM(DP_KEEP_SELECTION, screen->keepSelection);
6321	    update_keepSelection();
6322	    break;
6323	case srm_SELECT_TO_CLIPBOARD:
6324	    DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
6325	    update_selectToClipboard();
6326	    break;
6327	case srm_BELL_IS_URGENT:
6328	    DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
6329	    update_bellIsUrgent();
6330	    break;
6331	case srm_POP_ON_BELL:
6332	    DoRM(DP_POP_ON_BELL, screen->poponbell);
6333	    update_poponbell();
6334	    break;
6335	case srm_KEEP_CLIPBOARD:
6336	    DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
6337	    update_keepClipboard();
6338	    break;
6339#if OPT_TCAP_FKEYS
6340	case srm_TCAP_FKEYS:
6341	    /* FALLTHRU */
6342#endif
6343#if OPT_SUN_FUNC_KEYS
6344	case srm_SUN_FKEYS:
6345	    /* FALLTHRU */
6346#endif
6347#if OPT_HP_FUNC_KEYS
6348	case srm_HP_FKEYS:
6349	    /* FALLTHRU */
6350#endif
6351#if OPT_SCO_FUNC_KEYS
6352	case srm_SCO_FKEYS:
6353	    /* FALLTHRU */
6354#endif
6355#if OPT_SUNPC_KBD
6356	case srm_VT220_FKEYS:
6357	    /* FALLTHRU */
6358#endif
6359	case srm_LEGACY_FKEYS:
6360	    xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE];
6361	    break;
6362#if OPT_READLINE
6363	case srm_BUTTON1_MOVE_POINT:
6364	    SCREEN_FLAG_restore(screen, click1_moves);
6365	    break;
6366	case srm_BUTTON2_MOVE_POINT:
6367	    SCREEN_FLAG_restore(screen, paste_moves);
6368	    break;
6369	case srm_DBUTTON3_DELETE:
6370	    SCREEN_FLAG_restore(screen, dclick3_deletes);
6371	    break;
6372	case srm_PASTE_IN_BRACKET:
6373	    SCREEN_FLAG_restore(screen, paste_brackets);
6374	    break;
6375	case srm_PASTE_QUOTE:
6376	    SCREEN_FLAG_restore(screen, paste_quotes);
6377	    break;
6378	case srm_PASTE_LITERAL_NL:
6379	    SCREEN_FLAG_restore(screen, paste_literal_nl);
6380	    break;
6381#endif /* OPT_READLINE */
6382#if OPT_GRAPHICS
6383	case srm_PRIVATE_COLOR_REGISTERS:	/* private color registers for each graphic */
6384	    TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n",
6385		   BtoS(screen->privatecolorregisters)));
6386	    DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
6387	    TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n",
6388		   BtoS(screen->privatecolorregisters)));
6389	    update_privatecolorregisters();
6390	    break;
6391#endif
6392#if OPT_SIXEL_GRAPHICS
6393	case srm_SIXEL_SCROLLS_RIGHT:
6394	    TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n",
6395		   BtoS(screen->sixel_scrolls_right)));
6396	    DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
6397	    TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n",
6398		   BtoS(screen->sixel_scrolls_right)));
6399	    break;
6400#endif
6401	}
6402    }
6403}
6404
6405/*
6406 * Convert an XTextProperty to a string.
6407 *
6408 * This frees the data owned by the XTextProperty, and returns in its place the
6409 * string, which must be freed by the caller.
6410 */
6411static char *
6412property_to_string(XtermWidget xw, XTextProperty * text)
6413{
6414    TScreen *screen = TScreenOf(xw);
6415    Display *dpy = screen->display;
6416    char *result = 0;
6417    char **list;
6418    int length = 0;
6419    int rc;
6420
6421    TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n",
6422	   text->value,
6423	   TraceAtomName(dpy, text->encoding),
6424	   text->format,
6425	   text->nitems));
6426
6427#if OPT_WIDE_CHARS
6428    /*
6429     * We will use the XmbTextPropertyToTextList call to extract UTF-8 data.
6430     * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to
6431     * ISO-8859-1.
6432     */
6433    if ((text->format != 8)
6434	|| IsTitleMode(xw, tmGetUtf8)
6435	|| (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0)
6436#endif
6437	if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0)
6438	    rc = XTextPropertyToStringList(text, &list, &length);
6439
6440    if (rc >= 0) {
6441	int n, c, pass;
6442	size_t need = 0;
6443
6444	for (pass = 0; pass < 2; ++pass) {
6445	    for (n = 0, need = 0; n < length; n++) {
6446		char *s = list[n];
6447		while ((c = *s++) != '\0') {
6448		    if (pass)
6449			result[need] = (char) c;
6450		    ++need;
6451		}
6452	    }
6453	    if (pass)
6454		result[need] = '\0';
6455	    else
6456		result = malloc(need + 1);
6457	    if (result == 0)
6458		break;
6459	}
6460	XFreeStringList(list);
6461    }
6462    if (text->value != 0)
6463	XFree(text->value);
6464
6465    return result;
6466}
6467
6468static char *
6469get_icon_label(XtermWidget xw)
6470{
6471    XTextProperty text;
6472    char *result = 0;
6473
6474    if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
6475	result = property_to_string(xw, &text);
6476    }
6477    return result;
6478}
6479
6480static char *
6481get_window_label(XtermWidget xw)
6482{
6483    XTextProperty text;
6484    char *result = 0;
6485
6486    if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
6487	result = property_to_string(xw, &text);
6488    }
6489    return result;
6490}
6491
6492/*
6493 * Report window label (icon or title) in dtterm protocol
6494 * ESC ] code label ESC backslash
6495 */
6496static void
6497report_win_label(XtermWidget xw,
6498		 int code,
6499		 char *text)
6500{
6501    unparseputc(xw, ANSI_ESC);
6502    unparseputc(xw, ']');
6503    unparseputc(xw, code);
6504
6505    if (text != 0) {
6506	int copy = IsTitleMode(xw, tmGetBase16);
6507	if (copy) {
6508	    TRACE(("Encoding hex:%s\n", text));
6509	    text = x_encode_hex(text);
6510	}
6511	unparseputs(xw, text);
6512	if (copy)
6513	    free(text);
6514    }
6515
6516    unparseputc(xw, ANSI_ESC);
6517    unparseputc(xw, '\\');	/* should be ST */
6518    unparse_end(xw);
6519}
6520
6521/*
6522 * Window operations (from CDE dtterm description, as well as extensions).
6523 * See also "allowWindowOps" resource.
6524 */
6525static void
6526window_ops(XtermWidget xw)
6527{
6528    TScreen *screen = TScreenOf(xw);
6529    XWindowChanges values;
6530    XWindowAttributes win_attrs;
6531#if OPT_MAXIMIZE
6532    unsigned root_width;
6533    unsigned root_height;
6534#endif
6535    int code = zero_if_default(0);
6536    char *label;
6537
6538    TRACE(("window_ops %d\n", code));
6539    switch (code) {
6540    case ewRestoreWin:		/* Restore (de-iconify) window */
6541	if (AllowWindowOps(xw, ewRestoreWin)) {
6542	    TRACE(("...de-iconify window\n"));
6543	    XMapWindow(screen->display,
6544		       VShellWindow(xw));
6545	}
6546	break;
6547
6548    case ewMinimizeWin:	/* Minimize (iconify) window */
6549	if (AllowWindowOps(xw, ewMinimizeWin)) {
6550	    TRACE(("...iconify window\n"));
6551	    XIconifyWindow(screen->display,
6552			   VShellWindow(xw),
6553			   DefaultScreen(screen->display));
6554	}
6555	break;
6556
6557    case ewSetWinPosition:	/* Move the window to the given position */
6558	if (AllowWindowOps(xw, ewSetWinPosition)) {
6559	    unsigned value_mask;
6560
6561	    values.x = zero_if_default(1);
6562	    values.y = zero_if_default(2);
6563	    TRACE(("...move window to %d,%d\n", values.x, values.y));
6564	    value_mask = (CWX | CWY);
6565	    XReconfigureWMWindow(screen->display,
6566				 VShellWindow(xw),
6567				 DefaultScreen(screen->display),
6568				 value_mask,
6569				 &values);
6570	}
6571	break;
6572
6573    case ewSetWinSizePixels:	/* Resize the window to given size in pixels */
6574	if (AllowWindowOps(xw, ewSetWinSizePixels)) {
6575	    RequestResize(xw, optional_param(1), optional_param(2), False);
6576	}
6577	break;
6578
6579    case ewRaiseWin:		/* Raise the window to the front of the stack */
6580	if (AllowWindowOps(xw, ewRaiseWin)) {
6581	    TRACE(("...raise window\n"));
6582	    XRaiseWindow(screen->display, VShellWindow(xw));
6583	}
6584	break;
6585
6586    case ewLowerWin:		/* Lower the window to the bottom of the stack */
6587	if (AllowWindowOps(xw, ewLowerWin)) {
6588	    TRACE(("...lower window\n"));
6589	    XLowerWindow(screen->display, VShellWindow(xw));
6590	}
6591	break;
6592
6593    case ewRefreshWin:		/* Refresh the window */
6594	if (AllowWindowOps(xw, ewRefreshWin)) {
6595	    TRACE(("...redraw window\n"));
6596	    Redraw();
6597	}
6598	break;
6599
6600    case ewSetWinSizeChars:	/* Resize the text-area, in characters */
6601	if (AllowWindowOps(xw, ewSetWinSizeChars)) {
6602	    RequestResize(xw, optional_param(1), optional_param(2), True);
6603	}
6604	break;
6605
6606#if OPT_MAXIMIZE
6607    case ewMaximizeWin:	/* Maximize or restore */
6608	if (AllowWindowOps(xw, ewMaximizeWin)) {
6609	    RequestMaximize(xw, zero_if_default(1));
6610	}
6611	break;
6612    case ewFullscreenWin:	/* Fullscreen or restore */
6613	if (AllowWindowOps(xw, ewFullscreenWin)) {
6614	    FullScreen(xw, zero_if_default(1));
6615	}
6616	break;
6617#endif
6618
6619    case ewGetWinState:	/* Report the window's state */
6620	if (AllowWindowOps(xw, ewGetWinState)) {
6621	    TRACE(("...get window attributes\n"));
6622	    xtermGetWinAttrs(screen->display,
6623			     VWindow(screen),
6624			     &win_attrs);
6625	    init_reply(ANSI_CSI);
6626	    reply.a_pintro = 0;
6627	    reply.a_nparam = 1;
6628	    reply.a_param[0] = (ParmType) ((win_attrs.map_state == IsViewable)
6629					   ? 1
6630					   : 2);
6631	    reply.a_inters = 0;
6632	    reply.a_final = 't';
6633	    unparseseq(xw, &reply);
6634	}
6635	break;
6636
6637    case ewGetWinPosition:	/* Report the window's position */
6638	if (AllowWindowOps(xw, ewGetWinPosition)) {
6639	    TRACE(("...get window position\n"));
6640	    xtermGetWinAttrs(screen->display,
6641			     WMFrameWindow(xw),
6642			     &win_attrs);
6643	    init_reply(ANSI_CSI);
6644	    reply.a_pintro = 0;
6645	    reply.a_nparam = 3;
6646	    reply.a_param[0] = 3;
6647	    reply.a_param[1] = (ParmType) win_attrs.x;
6648	    reply.a_param[2] = (ParmType) win_attrs.y;
6649	    reply.a_inters = 0;
6650	    reply.a_final = 't';
6651	    unparseseq(xw, &reply);
6652	}
6653	break;
6654
6655    case ewGetWinSizePixels:	/* Report the window's size in pixels */
6656	if (AllowWindowOps(xw, ewGetWinSizePixels)) {
6657	    TRACE(("...get window size in pixels\n"));
6658	    init_reply(ANSI_CSI);
6659	    reply.a_pintro = 0;
6660	    reply.a_nparam = 3;
6661	    reply.a_param[0] = 4;
6662	    reply.a_param[1] = (ParmType) Height(screen);
6663	    reply.a_param[2] = (ParmType) Width(screen);
6664	    reply.a_inters = 0;
6665	    reply.a_final = 't';
6666	    unparseseq(xw, &reply);
6667	}
6668	break;
6669
6670    case ewGetWinSizeChars:	/* Report the text's size in characters */
6671	if (AllowWindowOps(xw, ewGetWinSizeChars)) {
6672	    TRACE(("...get window size in characters\n"));
6673	    init_reply(ANSI_CSI);
6674	    reply.a_pintro = 0;
6675	    reply.a_nparam = 3;
6676	    reply.a_param[0] = 8;
6677	    reply.a_param[1] = (ParmType) MaxRows(screen);
6678	    reply.a_param[2] = (ParmType) MaxCols(screen);
6679	    reply.a_inters = 0;
6680	    reply.a_final = 't';
6681	    unparseseq(xw, &reply);
6682	}
6683	break;
6684
6685#if OPT_MAXIMIZE
6686    case ewGetScreenSizeChars:	/* Report the screen's size, in characters */
6687	if (AllowWindowOps(xw, ewGetScreenSizeChars)) {
6688	    TRACE(("...get screen size in characters\n"));
6689	    TRACE(("...using font size %dx%d\n",
6690		   FontHeight(screen),
6691		   FontWidth(screen)));
6692	    (void) QueryMaximize(xw, &root_width, &root_height);
6693	    init_reply(ANSI_CSI);
6694	    reply.a_pintro = 0;
6695	    reply.a_nparam = 3;
6696	    reply.a_param[0] = 9;
6697	    reply.a_param[1] = (ParmType) (root_height
6698					   / (unsigned) FontHeight(screen));
6699	    reply.a_param[2] = (ParmType) (root_width
6700					   / (unsigned) FontWidth(screen));
6701	    reply.a_inters = 0;
6702	    reply.a_final = 't';
6703	    unparseseq(xw, &reply);
6704	}
6705	break;
6706#endif
6707
6708    case ewGetIconTitle:	/* Report the icon's label */
6709	if (AllowWindowOps(xw, ewGetIconTitle)) {
6710	    TRACE(("...get icon's label\n"));
6711	    report_win_label(xw, 'L', label = get_icon_label(xw));
6712	    free(label);
6713	}
6714	break;
6715
6716    case ewGetWinTitle:	/* Report the window's title */
6717	if (AllowWindowOps(xw, ewGetWinTitle)) {
6718	    TRACE(("...get window's label\n"));
6719	    report_win_label(xw, 'l', label = get_window_label(xw));
6720	    free(label);
6721	}
6722	break;
6723
6724    case ewPushTitle:		/* save the window's title(s) on stack */
6725	if (AllowWindowOps(xw, ewPushTitle)) {
6726	    SaveTitle *last = screen->save_title;
6727	    SaveTitle *item = TypeCalloc(SaveTitle);
6728
6729	    TRACE(("...push title onto stack\n"));
6730	    if (item != 0) {
6731		switch (zero_if_default(1)) {
6732		case 0:
6733		    item->iconName = get_icon_label(xw);
6734		    item->windowName = get_window_label(xw);
6735		    break;
6736		case 1:
6737		    item->iconName = get_icon_label(xw);
6738		    break;
6739		case 2:
6740		    item->windowName = get_window_label(xw);
6741		    break;
6742		}
6743		item->next = last;
6744		if (item->iconName == 0) {
6745		    item->iconName = ((last == 0)
6746				      ? get_icon_label(xw)
6747				      : x_strdup(last->iconName));
6748		}
6749		if (item->windowName == 0) {
6750		    item->windowName = ((last == 0)
6751					? get_window_label(xw)
6752					: x_strdup(last->windowName));
6753		}
6754		screen->save_title = item;
6755	    }
6756	}
6757	break;
6758
6759    case ewPopTitle:		/* restore the window's title(s) from stack */
6760	if (AllowWindowOps(xw, ewPopTitle)) {
6761	    SaveTitle *item = screen->save_title;
6762
6763	    TRACE(("...pop title off stack\n"));
6764	    if (item != 0) {
6765		switch (zero_if_default(1)) {
6766		case 0:
6767		    ChangeIconName(xw, item->iconName);
6768		    ChangeTitle(xw, item->windowName);
6769		    break;
6770		case 1:
6771		    ChangeIconName(xw, item->iconName);
6772		    break;
6773		case 2:
6774		    ChangeTitle(xw, item->windowName);
6775		    break;
6776		}
6777		screen->save_title = item->next;
6778		free(item->iconName);
6779		free(item->windowName);
6780		free(item);
6781	    }
6782	}
6783	break;
6784
6785    default:			/* DECSLPP (24, 25, 36, 48, 72, 144) */
6786	if (AllowWindowOps(xw, ewSetWinLines)) {
6787	    if (code >= 24)
6788		RequestResize(xw, code, -1, True);
6789	}
6790	break;
6791    }
6792}
6793
6794/*
6795 * set a bit in a word given a pointer to the word and a mask.
6796 */
6797static int
6798bitset(unsigned *p, unsigned mask)
6799{
6800    unsigned before = *p;
6801    *p |= mask;
6802    return (before != *p);
6803}
6804
6805/*
6806 * clear a bit in a word given a pointer to the word and a mask.
6807 */
6808static int
6809bitclr(unsigned *p, unsigned mask)
6810{
6811    unsigned before = *p;
6812    *p &= ~mask;
6813    return (before != *p);
6814}
6815
6816/*
6817 * Copy bits from one word to another, given a mask
6818 */
6819static int
6820bitcpy(unsigned *p, unsigned q, unsigned mask)
6821{
6822    unsigned before = *p;
6823    bitclr(p, mask);
6824    bitset(p, q & mask);
6825    return (before != *p);
6826}
6827
6828void
6829unparseputc1(XtermWidget xw, int c)
6830{
6831    if (c >= 0x80 && c <= 0x9F) {
6832	if (!TScreenOf(xw)->control_eight_bits) {
6833	    unparseputc(xw, A2E(ANSI_ESC));
6834	    c = A2E(c - 0x40);
6835	}
6836    }
6837    unparseputc(xw, c);
6838}
6839
6840void
6841unparseseq(XtermWidget xw, ANSI *ap)
6842{
6843    int c;
6844
6845    unparseputc1(xw, c = ap->a_type);
6846    if (c == ANSI_ESC
6847	|| c == ANSI_DCS
6848	|| c == ANSI_CSI
6849	|| c == ANSI_OSC
6850	|| c == ANSI_PM
6851	|| c == ANSI_APC
6852	|| c == ANSI_SS3) {
6853	int i;
6854	int inters;
6855
6856	if (ap->a_pintro != 0)
6857	    unparseputc(xw, ap->a_pintro);
6858	for (i = 0; i < ap->a_nparam; ++i) {
6859	    if (i != 0) {
6860		if (ap->a_delim) {
6861		    unparseputs(xw, ap->a_delim);
6862		} else {
6863		    unparseputc(xw, ';');
6864		}
6865	    }
6866	    if (ap->a_radix[i]) {
6867		char temp[8];
6868		sprintf(temp, "%04X", ap->a_param[i] & 0xffff);
6869		unparseputs(xw, temp);
6870	    } else {
6871		unparseputn(xw, (unsigned int) ap->a_param[i]);
6872	    }
6873	}
6874	if ((inters = ap->a_inters) != 0) {
6875	    for (i = 3; i >= 0; --i) {
6876		c = CharOf(inters >> (8 * i));
6877		if (c != 0)
6878		    unparseputc(xw, c);
6879	    }
6880	}
6881	switch (ap->a_type) {
6882	case ANSI_DCS:
6883	    /* FALLTHRU */
6884	case ANSI_OSC:
6885	    /* FALLTHRU */
6886	case ANSI_PM:
6887	    /* FALLTHRU */
6888	case ANSI_APC:
6889	    unparseputc1(xw, ANSI_ST);
6890	    break;
6891	default:
6892	    unparseputc(xw, (char) ap->a_final);
6893	    break;
6894	}
6895    }
6896    unparse_end(xw);
6897}
6898
6899void
6900unparseputn(XtermWidget xw, unsigned int n)
6901{
6902    unsigned int q;
6903
6904    q = n / 10;
6905    if (q != 0)
6906	unparseputn(xw, q);
6907    unparseputc(xw, (char) ('0' + (n % 10)));
6908}
6909
6910void
6911unparseputs(XtermWidget xw, const char *s)
6912{
6913    if (s != 0) {
6914	while (*s)
6915	    unparseputc(xw, *s++);
6916    }
6917}
6918
6919void
6920unparseputc(XtermWidget xw, int c)
6921{
6922    TScreen *screen = TScreenOf(xw);
6923    IChar *buf = screen->unparse_bfr;
6924    unsigned len;
6925
6926    if ((screen->unparse_len + 2) >= sizeof(screen->unparse_bfr) / sizeof(IChar))
6927	  unparse_end(xw);
6928
6929    len = screen->unparse_len;
6930
6931#if OPT_TCAP_QUERY
6932    /*
6933     * If we're returning a termcap string, it has to be translated since
6934     * a DCS must not contain any characters except for the normal 7-bit
6935     * printable ASCII (counting tab, carriage return, etc).  For now,
6936     * just use hexadecimal for the whole thing.
6937     */
6938    if (screen->tc_query_code >= 0) {
6939	char tmp[3];
6940	sprintf(tmp, "%02X", c & 0xFF);
6941	buf[len++] = CharOf(tmp[0]);
6942	buf[len++] = CharOf(tmp[1]);
6943    } else
6944#endif
6945    if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) {
6946	buf[len++] = '\n';
6947    }
6948
6949    screen->unparse_len = len;
6950
6951    /* If send/receive mode is reset, we echo characters locally */
6952    if ((xw->keyboard.flags & MODE_SRM) == 0) {
6953	(void) doparsing(xw, (unsigned) c, &myState);
6954    }
6955}
6956
6957void
6958unparse_end(XtermWidget xw)
6959{
6960    TScreen *screen = TScreenOf(xw);
6961
6962    if (screen->unparse_len) {
6963#ifdef VMS
6964	tt_write(screen->unparse_bfr, screen->unparse_len);
6965#else /* VMS */
6966	writePtyData(screen->respond, screen->unparse_bfr, screen->unparse_len);
6967#endif /* VMS */
6968	screen->unparse_len = 0;
6969    }
6970}
6971
6972void
6973ToggleAlternate(XtermWidget xw)
6974{
6975    if (TScreenOf(xw)->whichBuf)
6976	FromAlternate(xw);
6977    else
6978	ToAlternate(xw, False);
6979}
6980
6981static void
6982ToAlternate(XtermWidget xw, Bool clearFirst)
6983{
6984    TScreen *screen = TScreenOf(xw);
6985
6986    if (screen->whichBuf == 0) {
6987	TRACE(("ToAlternate\n"));
6988	if (!screen->editBuf_index[1])
6989	    screen->editBuf_index[1] = allocScrnBuf(xw,
6990						    (unsigned) MaxRows(screen),
6991						    (unsigned) MaxCols(screen),
6992						    &screen->editBuf_data[1]);
6993	SwitchBufs(xw, 1, clearFirst);
6994#if OPT_SAVE_LINES
6995	screen->visbuf = screen->editBuf_index[screen->whichBuf];
6996#endif
6997	update_altscreen();
6998    }
6999}
7000
7001static void
7002FromAlternate(XtermWidget xw)
7003{
7004    TScreen *screen = TScreenOf(xw);
7005
7006    if (screen->whichBuf != 0) {
7007	TRACE(("FromAlternate\n"));
7008	if (screen->scroll_amt)
7009	    FlushScroll(xw);
7010	SwitchBufs(xw, 0, False);
7011#if OPT_SAVE_LINES
7012	screen->visbuf = screen->editBuf_index[screen->whichBuf];
7013#endif
7014	update_altscreen();
7015    }
7016}
7017
7018static void
7019SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst)
7020{
7021    TScreen *screen = TScreenOf(xw);
7022    int rows, top;
7023
7024    screen->whichBuf = toBuf;
7025    if (screen->cursor_state)
7026	HideCursor();
7027
7028    rows = MaxRows(screen);
7029    SwitchBufPtrs(screen, toBuf);
7030
7031    if ((top = INX2ROW(screen, 0)) < rows) {
7032	if (screen->scroll_amt) {
7033	    FlushScroll(xw);
7034	}
7035#if OPT_DOUBLE_BUFFER
7036	XFillRectangle(screen->display,
7037		       VDrawable(screen),
7038		       ReverseGC(xw, screen),
7039		       (int) OriginX(screen),
7040		       (int) top * FontHeight(screen) + screen->border,
7041		       (unsigned) Width(screen),
7042		       (unsigned) ((rows - top) * FontHeight(screen)));
7043#else
7044	XClearArea(screen->display,
7045		   VWindow(screen),
7046		   (int) OriginX(screen),
7047		   (int) top * FontHeight(screen) + screen->border,
7048		   (unsigned) Width(screen),
7049		   (unsigned) ((rows - top) * FontHeight(screen)),
7050		   False);
7051#endif
7052	if (clearFirst) {
7053	    ClearBufRows(xw, top, rows);
7054	}
7055    }
7056    ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False);
7057}
7058
7059Bool
7060CheckBufPtrs(TScreen *screen)
7061{
7062    return (screen->visbuf != 0
7063#if OPT_SAVE_LINES
7064	    && screen->editBuf_index[0] != 0
7065#endif
7066	    && screen->editBuf_index[1] != 0);
7067}
7068
7069/*
7070 * Swap buffer line pointers between alternate and regular screens.
7071 */
7072void
7073SwitchBufPtrs(TScreen *screen, int toBuf GCC_UNUSED)
7074{
7075    if (CheckBufPtrs(screen)) {
7076#if OPT_SAVE_LINES
7077	screen->visbuf = screen->editBuf_index[toBuf];
7078#else
7079	size_t len = ScrnPointers(screen, (size_t) MaxRows(screen));
7080
7081	memcpy(screen->save_ptr, screen->visbuf, len);
7082	memcpy(screen->visbuf, screen->editBuf_index[1], len);
7083	memcpy(screen->editBuf_index[1], screen->save_ptr, len);
7084#endif
7085    }
7086}
7087
7088void
7089VTRun(XtermWidget xw)
7090{
7091    TScreen *screen = TScreenOf(xw);
7092
7093    TRACE(("VTRun ...\n"));
7094
7095    if (!screen->Vshow) {
7096	set_vt_visibility(True);
7097    }
7098    update_vttekmode();
7099    update_vtshow();
7100    update_tekshow();
7101    set_vthide_sensitivity();
7102
7103    ScrnAllocBuf(xw);
7104
7105    screen->cursor_state = OFF;
7106    screen->cursor_set = ON;
7107#if OPT_BLINK_CURS
7108    if (DoStartBlinking(screen))
7109	StartBlinking(screen);
7110#endif
7111
7112#if OPT_TEK4014
7113    if (Tpushb > Tpushback) {
7114	fillPtyData(xw, VTbuffer, (char *) Tpushback, (int) (Tpushb - Tpushback));
7115	Tpushb = Tpushback;
7116    }
7117#endif
7118    screen->is_running = True;
7119    if (screen->embed_high && screen->embed_wide) {
7120	ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags));
7121    }
7122#if OPT_MAXIMIZE
7123    else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways)
7124	FullScreen(term, True);
7125#endif
7126    if (!setjmp(VTend))
7127	VTparse(xw);
7128    StopBlinking(screen);
7129    HideCursor();
7130    screen->cursor_set = OFF;
7131    TRACE(("... VTRun\n"));
7132}
7133
7134/*ARGSUSED*/
7135static void
7136VTExpose(Widget w GCC_UNUSED,
7137	 XEvent *event,
7138	 Region region GCC_UNUSED)
7139{
7140    DEBUG_MSG("Expose\n");
7141    if (event->type == Expose)
7142	HandleExposure(term, event);
7143}
7144
7145static void
7146VTGraphicsOrNoExpose(XEvent *event)
7147{
7148    TScreen *screen = TScreenOf(term);
7149    if (screen->incopy <= 0) {
7150	screen->incopy = 1;
7151	if (screen->scrolls > 0)
7152	    screen->scrolls--;
7153    }
7154    if (event->type == GraphicsExpose)
7155	if (HandleExposure(term, event))
7156	    screen->cursor_state = OFF;
7157    if ((event->type == NoExpose)
7158	|| ((XGraphicsExposeEvent *) event)->count == 0) {
7159	if (screen->incopy <= 0 && screen->scrolls > 0)
7160	    screen->scrolls--;
7161	if (screen->scrolls)
7162	    screen->incopy = -1;
7163	else
7164	    screen->incopy = 0;
7165    }
7166}
7167
7168/*ARGSUSED*/
7169static void
7170VTNonMaskableEvent(Widget w GCC_UNUSED,
7171		   XtPointer closure GCC_UNUSED,
7172		   XEvent *event,
7173		   Boolean *cont GCC_UNUSED)
7174{
7175    switch (event->type) {
7176    case GraphicsExpose:
7177	/* FALLTHRU */
7178    case NoExpose:
7179	VTGraphicsOrNoExpose(event);
7180	break;
7181    }
7182}
7183
7184static void
7185VTResize(Widget w)
7186{
7187    if (XtIsRealized(w)) {
7188	XtermWidget xw = (XtermWidget) w;
7189	ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags);
7190    }
7191}
7192
7193#define okDimension(src,dst) ((src <= 32767) \
7194			  && ((dst = (Dimension) src) == src))
7195
7196static void
7197RequestResize(XtermWidget xw, int rows, int cols, Bool text)
7198{
7199    TScreen *screen = TScreenOf(xw);
7200    Dimension replyWidth, replyHeight;
7201    Dimension askedWidth, askedHeight;
7202    XtGeometryResult status;
7203    XWindowAttributes attrs;
7204
7205    TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text));
7206
7207    /* check first if the row/column values fit into a Dimension */
7208    if (cols > 0) {
7209	if ((int) (askedWidth = (Dimension) cols) < cols) {
7210	    TRACE(("... cols too large for Dimension\n"));
7211	    return;
7212	}
7213    } else {
7214	askedWidth = 0;
7215    }
7216    if (rows > 0) {
7217	if ((int) (askedHeight = (Dimension) rows) < rows) {
7218	    TRACE(("... rows too large for Dimension\n"));
7219	    return;
7220	}
7221    } else {
7222	askedHeight = 0;
7223    }
7224
7225    if (askedHeight == 0
7226	|| askedWidth == 0
7227	|| xw->misc.limit_resize > 0) {
7228	xtermGetWinAttrs(XtDisplay(xw),
7229			 RootWindowOfScreen(XtScreen(xw)), &attrs);
7230    }
7231
7232    if (text) {
7233	unsigned long value;
7234
7235	if ((value = (unsigned long) rows) != 0) {
7236	    if (rows < 0)
7237		value = (unsigned long) MaxRows(screen);
7238	    value *= (unsigned long) FontHeight(screen);
7239	    value += (unsigned long) (2 * screen->border);
7240	    if (!okDimension(value, askedHeight))
7241		return;
7242	}
7243
7244	if ((value = (unsigned long) cols) != 0) {
7245	    if (cols < 0)
7246		value = (unsigned long) MaxCols(screen);
7247	    value *= (unsigned long) FontWidth(screen);
7248	    value += (unsigned long) ((2 * screen->border)
7249				      + ScrollbarWidth(screen));
7250	    if (!okDimension(value, askedWidth))
7251		return;
7252	}
7253
7254    } else {
7255	if (rows < 0)
7256	    askedHeight = FullHeight(screen);
7257	if (cols < 0)
7258	    askedWidth = FullWidth(screen);
7259    }
7260
7261    if (rows == 0)
7262	askedHeight = (Dimension) attrs.height;
7263    if (cols == 0)
7264	askedWidth = (Dimension) attrs.width;
7265
7266    if (xw->misc.limit_resize > 0) {
7267	Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height);
7268	Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width);
7269	if ((int) high < attrs.height)
7270	    high = (Dimension) attrs.height;
7271	if (askedHeight > high)
7272	    askedHeight = high;
7273	if ((int) wide < attrs.width)
7274	    wide = (Dimension) attrs.width;
7275	if (askedWidth > wide)
7276	    askedWidth = wide;
7277    }
7278#ifndef nothack
7279    getXtermSizeHints(xw);
7280#endif
7281
7282    TRACE(("...requesting resize %dx%d\n", askedHeight, askedWidth));
7283    status = REQ_RESIZE((Widget) xw,
7284			askedWidth, askedHeight,
7285			&replyWidth, &replyHeight);
7286
7287    if (status == XtGeometryYes ||
7288	status == XtGeometryDone) {
7289	ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
7290    }
7291#ifndef nothack
7292    /*
7293     * XtMakeResizeRequest() has the undesirable side-effect of clearing
7294     * the window manager's hints, even on a failed request.  This would
7295     * presumably be fixed if the shell did its own work.
7296     */
7297    if (xw->hints.flags
7298	&& replyHeight
7299	&& replyWidth) {
7300	xw->hints.height = replyHeight;
7301	xw->hints.width = replyWidth;
7302
7303	TRACE(("%s@%d -- ", __FILE__, __LINE__));
7304	TRACE_HINTS(&xw->hints);
7305	XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints);
7306	TRACE(("%s@%d -- ", __FILE__, __LINE__));
7307	TRACE_WM_HINTS(xw);
7308    }
7309#endif
7310
7311    XSync(screen->display, False);	/* synchronize */
7312    if (xtermAppPending())
7313	xevents();
7314
7315    TRACE(("...RequestResize done\n"));
7316}
7317
7318static String xterm_trans =
7319"<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
7320     <MappingNotify>: KeyboardMapping()\n";
7321
7322int
7323VTInit(XtermWidget xw)
7324{
7325    Widget vtparent = SHELL_OF(xw);
7326
7327    TRACE(("VTInit {{\n"));
7328
7329    XtRealizeWidget(vtparent);
7330    XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
7331    (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent),
7332			   &wm_delete_window, 1);
7333    TRACE_TRANS("shell", vtparent);
7334    TRACE_TRANS("vt100", (Widget) (xw));
7335
7336    ScrnAllocBuf(xw);
7337
7338    TRACE(("...}} VTInit\n"));
7339    return (1);
7340}
7341
7342static void
7343VTClassInit(void)
7344{
7345    XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
7346		   (XtConvertArgList) NULL, (Cardinal) 0);
7347}
7348
7349#if OPT_COLOR_RES
7350/*
7351 * Override the use of XtDefaultForeground/XtDefaultBackground to make some
7352 * colors, such as cursor color, use the actual foreground/background value
7353 * if there is no explicit resource value used.
7354 */
7355static Pixel
7356fill_Tres(XtermWidget target, XtermWidget source, int offset)
7357{
7358    char *name;
7359    ScrnColors temp;
7360    TScreen *src = TScreenOf(source);
7361    TScreen *dst = TScreenOf(target);
7362
7363    dst->Tcolors[offset] = src->Tcolors[offset];
7364    dst->Tcolors[offset].mode = False;
7365
7366    if ((name = x_strtrim(dst->Tcolors[offset].resource)) != 0)
7367	dst->Tcolors[offset].resource = name;
7368
7369    if (name == 0) {
7370	dst->Tcolors[offset].value = target->dft_foreground;
7371    } else if (isDefaultForeground(name)) {
7372	dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
7373				      ? target->dft_foreground
7374				      : dst->Tcolors[TEXT_FG].value);
7375    } else if (isDefaultBackground(name)) {
7376	dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
7377				      ? target->dft_background
7378				      : dst->Tcolors[TEXT_BG].value);
7379    } else {
7380	memset(&temp, 0, sizeof(temp));
7381	if (AllocateTermColor(target, &temp, offset, name, True)) {
7382	    if (COLOR_DEFINED(&(temp), offset))
7383		free(temp.names[offset]);
7384	    dst->Tcolors[offset].value = temp.colors[offset];
7385	} else if (offset == TEXT_FG || offset == TEXT_BG) {
7386	    free(name);
7387	    dst->Tcolors[offset].resource = 0;
7388	}
7389    }
7390    return dst->Tcolors[offset].value;
7391}
7392
7393/*
7394 * If one or both of the foreground/background colors cannot be allocated,
7395 * e.g., due to gross misconfiguration, recover by setting both to the
7396 * display's default values.
7397 */
7398static void
7399repairColors(XtermWidget target)
7400{
7401    TScreen *screen = TScreenOf(target);
7402
7403    if (screen->Tcolors[TEXT_FG].resource == 0 ||
7404	screen->Tcolors[TEXT_BG].resource == 0) {
7405	xtermWarning("unable to allocate fg/bg colors\n");
7406	screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground);
7407	screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground);
7408	if (screen->Tcolors[TEXT_FG].resource == 0 ||
7409	    screen->Tcolors[TEXT_BG].resource == 0) {
7410	    Exit(1);
7411	}
7412	screen->Tcolors[TEXT_FG].value = target->dft_foreground;
7413	screen->Tcolors[TEXT_BG].value = target->dft_background;
7414    }
7415}
7416#else
7417#define fill_Tres(target, source, offset) \
7418	TScreenOf(target)->Tcolors[offset] = TScreenOf(source)->Tcolors[offset]
7419#define repairColors(target)	/* nothing */
7420#endif
7421
7422#if OPT_WIDE_CHARS
7423static void
7424VTInitialize_locale(XtermWidget xw)
7425{
7426    TScreen *screen = TScreenOf(xw);
7427    Bool is_utf8 = xtermEnvUTF8();
7428
7429    TRACE(("VTInitialize_locale\n"));
7430    TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode));
7431    TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts));
7432
7433    screen->utf8_always = (screen->utf8_mode == uAlways);
7434    if (screen->utf8_mode < 0)
7435	screen->utf8_mode = uFalse;
7436
7437    if (screen->utf8_mode > 3)
7438	screen->utf8_mode = uDefault;
7439
7440    screen->latin9_mode = 0;
7441    screen->unicode_font = 0;
7442#if OPT_LUIT_PROG
7443    xw->misc.callfilter = 0;
7444    xw->misc.use_encoding = 0;
7445
7446    TRACE(("... setup for luit:\n"));
7447    TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str));
7448
7449    if (screen->utf8_mode == uFalse) {
7450	TRACE(("... command-line +u8 overrides\n"));
7451    } else
7452#if OPT_MINI_LUIT
7453    if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) {
7454	int fl = (int) strlen(DefaultFontN(xw));
7455	if (fl > 11
7456	    && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) {
7457	    screen->unicode_font = 1;
7458	    /* unicode font, use True */
7459#ifdef HAVE_LANGINFO_CODESET
7460	    if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968")
7461		|| !strcmp(xtermEnvEncoding(), "ISO-8859-1")) {
7462		if (screen->utf8_mode == uDefault)
7463		    screen->utf8_mode = uFalse;
7464	    } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) {
7465		if (screen->utf8_mode == uDefault)
7466		    screen->utf8_mode = uFalse;
7467		screen->latin9_mode = 1;
7468	    } else {
7469		xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
7470		screen->utf8_mode = uAlways;
7471	    }
7472#else
7473	    xw->misc.callfilter = is_utf8 ? 0 : 1;
7474	    screen->utf8_mode = uAlways;
7475#endif
7476	} else {
7477	    /* other encoding, use False */
7478	    if (screen->utf8_mode == uDefault) {
7479		screen->utf8_mode = is_utf8 ? uAlways : uFalse;
7480	    }
7481	}
7482    } else
7483#endif /* OPT_MINI_LUIT */
7484	if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 ||
7485	    x_strcasecmp(xw->misc.locale_str, "ON") == 0 ||
7486	    x_strcasecmp(xw->misc.locale_str, "YES") == 0 ||
7487	    x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 ||
7488	    strcmp(xw->misc.locale_str, "1") == 0) {
7489	/* when true ... fully obeying LC_CTYPE locale */
7490	xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
7491	screen->utf8_mode = uAlways;
7492    } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 ||
7493	       x_strcasecmp(xw->misc.locale_str, "OFF") == 0 ||
7494	       x_strcasecmp(xw->misc.locale_str, "NO") == 0 ||
7495	       strcmp(xw->misc.locale_str, "0") == 0) {
7496	/* when false ... original value of utf8_mode is effective */
7497	if (screen->utf8_mode == uDefault) {
7498	    screen->utf8_mode = is_utf8 ? uAlways : uFalse;
7499	}
7500    } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 ||
7501	       x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) {
7502	/* when medium ... obeying locale only for UTF-8 and Asian */
7503	if (is_utf8) {
7504	    screen->utf8_mode = uAlways;
7505	} else if (
7506#ifdef MB_CUR_MAX
7507		      MB_CUR_MAX > 1 ||
7508#else
7509		      !strncmp(xtermEnvLocale(), "ja", (size_t) 2) ||
7510		      !strncmp(xtermEnvLocale(), "ko", (size_t) 2) ||
7511		      !strncmp(xtermEnvLocale(), "zh", (size_t) 2) ||
7512#endif
7513		      !strncmp(xtermEnvLocale(), "th", (size_t) 2) ||
7514		      !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) {
7515	    xw->misc.callfilter = 1;
7516	    screen->utf8_mode = uAlways;
7517	} else {
7518	    screen->utf8_mode = uFalse;
7519	}
7520    } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 ||
7521	       x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) {
7522	/* when UTF-8 ... UTF-8 mode */
7523	screen->utf8_mode = uAlways;
7524    } else {
7525	/* other words are regarded as encoding name passed to luit */
7526	xw->misc.callfilter = 1;
7527	screen->utf8_mode = uAlways;
7528	xw->misc.use_encoding = 1;
7529    }
7530    TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter)));
7531    TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding)));
7532#else
7533    if (screen->utf8_mode == uDefault) {
7534	screen->utf8_mode = is_utf8 ? uAlways : uFalse;
7535    }
7536#endif /* OPT_LUIT_PROG */
7537
7538    if (screen->utf8_fonts == uDefault) {
7539	switch (screen->utf8_mode) {
7540	case uFalse:
7541	    /* FALLTHRU */
7542	case uTrue:
7543	    screen->utf8_fonts = screen->utf8_mode;
7544	    break;
7545	case uDefault:
7546	    /* should not happen */
7547	    screen->utf8_fonts = uTrue;
7548	    break;
7549	case uAlways:
7550	    /* use this to disable menu entry */
7551	    break;
7552	}
7553    }
7554
7555    screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse);
7556
7557    TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode));
7558    TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts));
7559    TRACE(("...VTInitialize_locale done\n"));
7560}
7561#endif
7562
7563void
7564lookupSelectUnit(XtermWidget xw, Cardinal item, String value)
7565{
7566    /* *INDENT-OFF* */
7567    static const struct {
7568	const char *	name;
7569	SelectUnit	code;
7570    } table[] = {
7571    	{ "char",	Select_CHAR },
7572    	{ "word",	Select_WORD },
7573    	{ "line",	Select_LINE },
7574    	{ "group",	Select_GROUP },
7575    	{ "page",	Select_PAGE },
7576    	{ "all",	Select_ALL },
7577#if OPT_SELECT_REGEX
7578    	{ "regex",	Select_REGEX },
7579#endif
7580    };
7581    /* *INDENT-ON* */
7582
7583    TScreen *screen = TScreenOf(xw);
7584    String next = x_skip_nonblanks(value);
7585    Cardinal n;
7586
7587    screen->selectMap[item] = NSELECTUNITS;
7588    for (n = 0; n < XtNumber(table); ++n) {
7589	if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) {
7590	    screen->selectMap[item] = table[n].code;
7591#if OPT_SELECT_REGEX
7592	    if (table[n].code == Select_REGEX) {
7593		screen->selectExpr[item] = x_strtrim(next);
7594		TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item]));
7595	    }
7596#endif
7597	    break;
7598	}
7599    }
7600}
7601
7602static void
7603ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item)
7604{
7605    lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]);
7606}
7607
7608/*
7609 * Parse a comma-separated list, returning a string which the caller must
7610 * free, and updating the source pointer.
7611 */
7612static char *
7613ParseList(const char **source)
7614{
7615    const char *base = *source;
7616    const char *next;
7617    char *value = 0;
7618    char *result;
7619
7620    /* ignore empty values */
7621    while (*base == ',')
7622	++base;
7623
7624    if (*base != '\0') {
7625	size_t size;
7626
7627	next = base;
7628	while (*next != '\0' && *next != ',')
7629	    ++next;
7630	size = (size_t) (1 + next - base);
7631	value = malloc(size);
7632	if (value != 0) {
7633	    memcpy(value, base, size);
7634	    value[size - 1] = '\0';
7635	}
7636	*source = next;
7637    } else {
7638	*source = base;
7639    }
7640    result = x_strtrim(value);
7641    free(value);
7642    return result;
7643}
7644
7645static void
7646set_flags_from_list(char *target,
7647		    const char *source,
7648		    const FlagList * list)
7649{
7650    Cardinal n;
7651    int value = -1;
7652
7653    while (!IsEmpty(source)) {
7654	char *next = ParseList(&source);
7655	Boolean found = False;
7656
7657	if (next == 0)
7658	    break;
7659	if (isdigit(CharOf(*next))) {
7660	    char *temp;
7661
7662	    value = (int) strtol(next, &temp, 0);
7663	    if (!FullS2L(next, temp)) {
7664		xtermWarning("Expected a number: %s\n", next);
7665	    } else {
7666		for (n = 0; list[n].name != 0; ++n) {
7667		    if (list[n].code == value) {
7668			target[value] = 1;
7669			found = True;
7670			TRACE(("...found %s (%d)\n", list[n].name, value));
7671			break;
7672		    }
7673		}
7674	    }
7675	} else {
7676	    for (n = 0; list[n].name != 0; ++n) {
7677		if (!x_wildstrcmp(next, list[n].name)) {
7678		    value = list[n].code;
7679		    target[value] = 1;
7680		    found = True;
7681		    TRACE(("...found %s (%d)\n", list[n].name, value));
7682		}
7683	    }
7684	}
7685	if (!found) {
7686	    xtermWarning("Unrecognized keyword: %s\n", next);
7687	}
7688	free(next);
7689    }
7690}
7691
7692#define InitCursorShape(target, source) \
7693    target->cursor_shape = source->cursor_underline \
7694	? CURSOR_UNDERLINE \
7695	: CURSOR_BLOCK
7696
7697/* ARGSUSED */
7698static void
7699VTInitialize(Widget wrequest,
7700	     Widget new_arg,
7701	     ArgList args GCC_UNUSED,
7702	     Cardinal *num_args GCC_UNUSED)
7703{
7704#define Kolor(name) TScreenOf(wnew)->name.resource
7705#define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name))
7706#define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name))
7707#define DftFg(name) isDefaultForeground(Kolor(name))
7708#define DftBg(name) isDefaultBackground(Kolor(name))
7709
7710#define DATA_END   { NULL,  -1       }
7711#define DATA(name) { #name, ec##name }
7712    static const FlagList tblColorOps[] =
7713    {
7714	DATA(SetColor)
7715	,DATA(GetColor)
7716	,DATA(GetAnsiColor)
7717	,DATA_END
7718    };
7719#undef DATA
7720
7721#define DATA(name) { #name, ef##name }
7722    static const FlagList tblFontOps[] =
7723    {
7724	DATA(SetFont)
7725	,DATA(GetFont)
7726	,DATA_END
7727    };
7728#undef DATA
7729
7730#define DATA(name) { #name, em##name }
7731    static const FlagList tblMouseOps[] =
7732    {
7733	DATA(X10)
7734	,DATA(Locator)
7735	,DATA(VT200Click)
7736	,DATA(VT200Hilite)
7737	,DATA(AnyButton)
7738	,DATA(AnyEvent)
7739	,DATA(FocusEvent)
7740	,DATA(Extended)
7741	,DATA(SGR)
7742	,DATA(URXVT)
7743	,DATA(AlternateScroll)
7744	,DATA_END
7745    };
7746#undef DATA
7747
7748#define DATA(name) { #name, et##name }
7749    static const FlagList tblTcapOps[] =
7750    {
7751	DATA(SetTcap)
7752	,DATA(GetTcap)
7753	,DATA_END
7754    };
7755#undef DATA
7756
7757#define DATA(name) { #name, ew##name }
7758    static const FlagList tblWindowOps[] =
7759    {
7760	DATA(RestoreWin)
7761	,DATA(MinimizeWin)
7762	,DATA(SetWinPosition)
7763	,DATA(SetWinSizePixels)
7764	,DATA(RaiseWin)
7765	,DATA(LowerWin)
7766	,DATA(RefreshWin)
7767	,DATA(SetWinSizeChars)
7768#if OPT_MAXIMIZE
7769	,DATA(MaximizeWin)
7770	,DATA(FullscreenWin)
7771#endif
7772	,DATA(GetWinState)
7773	,DATA(GetWinPosition)
7774	,DATA(GetWinSizePixels)
7775	,DATA(GetWinSizeChars)
7776#if OPT_MAXIMIZE
7777	,DATA(GetScreenSizeChars)
7778#endif
7779	,DATA(GetIconTitle)
7780	,DATA(GetWinTitle)
7781	,DATA(PushTitle)
7782	,DATA(PopTitle)
7783	,DATA(SetWinLines)
7784	,DATA(SetXprop)
7785	,DATA(GetSelection)
7786	,DATA(SetSelection)
7787	,DATA_END
7788    };
7789#undef DATA
7790
7791#if OPT_RENDERFONT
7792#define DATA(name) { #name, er##name }
7793    static const FlagList tblRenderFont[] =
7794    {
7795	DATA(Default)
7796	,DATA_END
7797    };
7798#undef DATA
7799#endif
7800
7801#if OPT_WIDE_CHARS
7802#define DATA(name) { #name, u##name }
7803    static const FlagList tblUtf8Mode[] =
7804    {
7805	DATA(Always)
7806	,DATA(Default)
7807	,DATA_END
7808    };
7809#undef DATA
7810#endif
7811
7812#ifndef NO_ACTIVE_ICON
7813#define DATA(name) { #name, ei##name }
7814    static const FlagList tblAIconOps[] =
7815    {
7816	DATA(Default)
7817	,DATA_END
7818    };
7819#undef DATA
7820#endif
7821
7822#define DATA(name) { #name, eb##name }
7823    static const FlagList tbl8BitMeta[] =
7824    {
7825	DATA(Never)
7826	,DATA(Locale)
7827	,DATA_END
7828    };
7829#undef DATA
7830
7831    XtermWidget request = (XtermWidget) wrequest;
7832    XtermWidget wnew = (XtermWidget) new_arg;
7833    Widget my_parent = SHELL_OF(wnew);
7834    int i;
7835    const char *s;
7836
7837#if OPT_ISO_COLORS
7838    Bool color_ok;
7839#endif
7840
7841#if OPT_COLOR_RES2
7842    static XtResource fake_resources[] =
7843    {
7844#if OPT_256_COLORS
7845# include <256colres.h>
7846#elif OPT_88_COLORS
7847# include <88colres.h>
7848#endif
7849    };
7850#endif /* OPT_COLOR_RES2 */
7851    TScreen *screen = TScreenOf(wnew);
7852
7853#if OPT_TRACE
7854    check_tables();
7855#endif
7856
7857    TRACE(("VTInitialize wnew %p, %d / %d resources\n",
7858	   (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES));
7859    assert(XtNumber(xterm_resources) < MAXRESOURCES);
7860
7861    /* Zero out the entire "screen" component of "wnew" widget, then do
7862     * field-by-field assignment of "screen" fields that are named in the
7863     * resource list.
7864     */
7865    memset(screen, 0, sizeof(wnew->screen));
7866
7867    /* DESCO Sys#67660
7868     * Zero out the entire "keyboard" component of "wnew" widget.
7869     */
7870    memset(&wnew->keyboard, 0, sizeof(wnew->keyboard));
7871
7872    /*
7873     * The workspace has no resources - clear it.
7874     */
7875    memset(&wnew->work, 0, sizeof(wnew->work));
7876
7877    /* dummy values so that we don't try to Realize the parent shell with height
7878     * or width of 0, which is illegal in X.  The real size is computed in the
7879     * xtermWidget's Realize proc, but the shell's Realize proc is called first,
7880     * and must see a valid size.
7881     */
7882    wnew->core.height = wnew->core.width = 1;
7883
7884    /*
7885     * The definition of -rv now is that it changes the definition of
7886     * XtDefaultForeground and XtDefaultBackground.  So, we no longer
7887     * need to do anything special.
7888     */
7889    screen->display = wnew->core.screen->display;
7890
7891    /* prep getVisualInfo() */
7892    wnew->visInfo = 0;
7893    wnew->numVisuals = 0;
7894    (void) getVisualInfo(wnew);
7895
7896    /*
7897     * We use the default foreground/background colors to compare/check if a
7898     * color-resource has been set.
7899     */
7900#define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy))
7901#define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy))
7902
7903    if (request->misc.re_verse) {
7904	wnew->dft_foreground = MyWhitePixel(screen->display);
7905	wnew->dft_background = MyBlackPixel(screen->display);
7906    } else {
7907	wnew->dft_foreground = MyBlackPixel(screen->display);
7908	wnew->dft_background = MyWhitePixel(screen->display);
7909    }
7910
7911    init_Tres(TEXT_FG);
7912    init_Tres(TEXT_BG);
7913    repairColors(wnew);
7914
7915    wnew->old_foreground = T_COLOR(screen, TEXT_FG);
7916    wnew->old_background = T_COLOR(screen, TEXT_BG);
7917
7918    TRACE(("Color resource initialization:\n"));
7919    TRACE(("   Default foreground 0x%06lx\n", wnew->dft_foreground));
7920    TRACE(("   Default background 0x%06lx\n", wnew->dft_background));
7921    TRACE(("   Screen foreground  0x%06lx\n", T_COLOR(screen, TEXT_FG)));
7922    TRACE(("   Screen background  0x%06lx\n", T_COLOR(screen, TEXT_BG)));
7923    TRACE(("   Actual  foreground 0x%06lx\n", wnew->old_foreground));
7924    TRACE(("   Actual  background 0x%06lx\n", wnew->old_background));
7925
7926    screen->mouse_button = 0;
7927    screen->mouse_row = -1;
7928    screen->mouse_col = -1;
7929
7930#if OPT_BOX_CHARS
7931    init_Bres(screen.force_box_chars);
7932    init_Bres(screen.force_packed);
7933    init_Bres(screen.force_all_chars);
7934    init_Bres(screen.assume_all_chars);
7935#endif
7936    init_Bres(screen.free_bold_box);
7937    init_Bres(screen.allowBoldFonts);
7938
7939    init_Bres(screen.c132);
7940    init_Bres(screen.curses);
7941    init_Bres(screen.hp_ll_bc);
7942#if OPT_XMC_GLITCH
7943    init_Ires(screen.xmc_glitch);
7944    init_Ires(screen.xmc_attributes);
7945    init_Bres(screen.xmc_inline);
7946    init_Bres(screen.move_sgr_ok);
7947#endif
7948#if OPT_BLINK_CURS
7949    init_Bres(screen.cursor_blink);
7950    init_Ires(screen.blink_on);
7951    init_Ires(screen.blink_off);
7952    screen->cursor_blink_res = screen->cursor_blink;
7953#endif
7954    init_Bres(screen.cursor_underline);
7955    /* resources allow for underline or block, not (yet) bar */
7956    InitCursorShape(screen, TScreenOf(request));
7957#if OPT_BLINK_CURS
7958    TRACE(("cursor_shape:%d blinks:%s\n",
7959	   screen->cursor_shape,
7960	   BtoS(screen->cursor_blink)));
7961#endif
7962#if OPT_BLINK_TEXT
7963    init_Ires(screen.blink_as_bold);
7964#endif
7965    init_Ires(screen.border);
7966    init_Bres(screen.jumpscroll);
7967    init_Bres(screen.fastscroll);
7968
7969    init_Bres(screen.old_fkeys);
7970    wnew->screen.old_fkeys0 = wnew->screen.old_fkeys;
7971    wnew->keyboard.type = screen->old_fkeys
7972	? keyboardIsLegacy
7973	: keyboardIsDefault;
7974
7975    init_Mres(screen.delete_is_del);
7976#ifdef ALLOWLOGGING
7977    init_Bres(misc.logInhibit);
7978    init_Bres(misc.log_on);
7979    init_Sres(screen.logfile);
7980#endif
7981    init_Bres(screen.bellIsUrgent);
7982    init_Bres(screen.bellOnReset);
7983    init_Bres(screen.marginbell);
7984    init_Bres(screen.multiscroll);
7985    init_Ires(screen.nmarginbell);
7986    init_Ires(screen.savelines);
7987    init_Ires(screen.scrollBarBorder);
7988    init_Ires(screen.scrolllines);
7989    init_Bres(screen.alternateScroll);
7990    init_Bres(screen.scrollttyoutput);
7991    init_Bres(screen.scrollkey);
7992
7993    init_Dres(screen.scale_height);
7994    if (screen->scale_height < 0.9)
7995	screen->scale_height = (float) 0.9;
7996    if (screen->scale_height > 1.5)
7997	screen->scale_height = (float) 1.5;
7998
7999    init_Bres(misc.autoWrap);
8000    init_Bres(misc.login_shell);
8001    init_Bres(misc.reverseWrap);
8002    init_Bres(misc.scrollbar);
8003    init_Sres(misc.geo_metry);
8004    init_Sres(misc.T_geometry);
8005
8006    init_Sres(screen.term_id);
8007    for (s = TScreenOf(request)->term_id; *s; s++) {
8008	if (!isalpha(CharOf(*s)))
8009	    break;
8010    }
8011    screen->terminal_id = atoi(s);
8012    if (screen->terminal_id < MIN_DECID)
8013	screen->terminal_id = MIN_DECID;
8014    if (screen->terminal_id > MAX_DECID)
8015	screen->terminal_id = MAX_DECID;
8016    TRACE(("term_id '%s' -> terminal_id %d\n",
8017	   screen->term_id,
8018	   screen->terminal_id));
8019
8020    screen->vtXX_level = (screen->terminal_id / 100);
8021
8022    init_Ires(screen.title_modes);
8023    wnew->screen.title_modes0 = wnew->screen.title_modes;
8024
8025    init_Bres(screen.visualbell);
8026    init_Bres(screen.flash_line);
8027    init_Ires(screen.visualBellDelay);
8028    init_Bres(screen.poponbell);
8029
8030    init_Bres(screen.eraseSavedLines0);
8031    screen->eraseSavedLines = screen->eraseSavedLines0;
8032
8033    init_Ires(misc.limit_resize);
8034
8035#if OPT_NUM_LOCK
8036    init_Bres(misc.real_NumLock);
8037    init_Bres(misc.alwaysUseMods);
8038#endif
8039
8040#if OPT_INPUT_METHOD
8041    init_Bres(misc.open_im);
8042    init_Ires(misc.retry_im);
8043    init_Sres(misc.f_x);
8044    init_Sres(misc.input_method);
8045    init_Sres(misc.preedit_type);
8046#endif
8047
8048#if OPT_SHIFT_FONTS
8049    init_Bres(misc.shift_fonts);
8050#endif
8051#if OPT_SUNPC_KBD
8052    init_Ires(misc.ctrl_fkeys);
8053#endif
8054#if OPT_TEK4014
8055    TEK4014_SHOWN(wnew) = False;	/* not a resource... */
8056    init_Bres(misc.tekInhibit);
8057    init_Bres(misc.tekSmall);
8058    init_Bres(misc.TekEmu);
8059#endif
8060#if OPT_TCAP_QUERY
8061    screen->tc_query_code = -1;
8062#endif
8063    wnew->misc.re_verse0 = request->misc.re_verse;
8064    init_Bres(misc.re_verse);
8065    init_Ires(screen.multiClickTime);
8066    init_Ires(screen.bellSuppressTime);
8067    init_Sres(screen.charClass);
8068
8069    init_Bres(screen.always_highlight);
8070    init_Bres(screen.brokenSelections);
8071    init_Bres(screen.cutNewline);
8072    init_Bres(screen.cutToBeginningOfLine);
8073    init_Bres(screen.highlight_selection);
8074    init_Bres(screen.show_wrap_marks);
8075    init_Bres(screen.i18nSelections);
8076    init_Bres(screen.keepClipboard);
8077    init_Bres(screen.keepSelection);
8078    init_Bres(screen.selectToClipboard);
8079    init_Bres(screen.trim_selection);
8080
8081    screen->pointer_cursor = TScreenOf(request)->pointer_cursor;
8082    init_Ires(screen.pointer_mode);
8083    wnew->screen.pointer_mode0 = wnew->screen.pointer_mode;
8084
8085    init_Sres(screen.answer_back);
8086
8087    wnew->SPS.printer_checked = False;
8088    init_Sres(SPS.printer_command);
8089    init_Bres(SPS.printer_autoclose);
8090    init_Bres(SPS.printer_extent);
8091    init_Bres(SPS.printer_formfeed);
8092    init_Bres(SPS.printer_newline);
8093    init_Ires(SPS.printer_controlmode);
8094#if OPT_PRINT_COLORS
8095    init_Ires(SPS.print_attributes);
8096#endif
8097
8098    init_Sres(screen.keyboard_dialect);
8099
8100    init_Bres(screen.input_eight_bits);
8101    init_Bres(screen.output_eight_bits);
8102    init_Bres(screen.control_eight_bits);
8103    init_Bres(screen.backarrow_key);
8104    init_Bres(screen.alt_is_not_meta);
8105    init_Bres(screen.alt_sends_esc);
8106    init_Bres(screen.meta_sends_esc);
8107
8108    init_Bres(screen.allowPasteControl0);
8109    init_Bres(screen.allowSendEvent0);
8110    init_Bres(screen.allowColorOp0);
8111    init_Bres(screen.allowFontOp0);
8112    init_Bres(screen.allowMouseOp0);
8113    init_Bres(screen.allowTcapOp0);
8114    init_Bres(screen.allowTitleOp0);
8115    init_Bres(screen.allowWindowOp0);
8116
8117#if OPT_SCROLL_LOCK
8118    init_Bres(screen.allowScrollLock0);
8119#endif
8120
8121    init_Sres(screen.disallowedColorOps);
8122
8123    set_flags_from_list(screen->disallow_color_ops,
8124			screen->disallowedColorOps,
8125			tblColorOps);
8126
8127    init_Sres(screen.disallowedFontOps);
8128
8129    set_flags_from_list(screen->disallow_font_ops,
8130			screen->disallowedFontOps,
8131			tblFontOps);
8132
8133    init_Sres(screen.disallowedMouseOps);
8134
8135    set_flags_from_list(screen->disallow_mouse_ops,
8136			screen->disallowedMouseOps,
8137			tblMouseOps);
8138
8139    init_Sres(screen.disallowedTcapOps);
8140
8141    set_flags_from_list(screen->disallow_tcap_ops,
8142			screen->disallowedTcapOps,
8143			tblTcapOps);
8144
8145    init_Sres(screen.disallowedWinOps);
8146
8147    set_flags_from_list(screen->disallow_win_ops,
8148			screen->disallowedWinOps,
8149			tblWindowOps);
8150
8151    init_Sres(screen.default_string);
8152    init_Sres(screen.eightbit_select_types);
8153#if OPT_WIDE_CHARS
8154    init_Sres(screen.utf8_select_types);
8155#endif
8156
8157    /* make a copy so that editres cannot change the resource after startup */
8158    screen->allowPasteControls = screen->allowPasteControl0;
8159    screen->allowSendEvents = screen->allowSendEvent0;
8160    screen->allowColorOps = screen->allowColorOp0;
8161    screen->allowFontOps = screen->allowFontOp0;
8162    screen->allowMouseOps = screen->allowMouseOp0;
8163    screen->allowTcapOps = screen->allowTcapOp0;
8164    screen->allowTitleOps = screen->allowTitleOp0;
8165    screen->allowWindowOps = screen->allowWindowOp0;
8166
8167#if OPT_SCROLL_LOCK
8168    screen->allowScrollLock = screen->allowScrollLock0;
8169#endif
8170
8171    init_Bres(screen.quiet_grab);
8172
8173#ifndef NO_ACTIVE_ICON
8174    init_Sres(screen.icon_fontname);
8175    getIconicFont(screen)->fs = XLoadQueryFont(screen->display,
8176					       screen->icon_fontname);
8177    TRACE(("iconFont '%s' %sloaded successfully\n",
8178	   screen->icon_fontname,
8179	   getIconicFont(screen)->fs ? "" : "NOT "));
8180    init_Sres(misc.active_icon_s);
8181    wnew->work.active_icon =
8182	(Boolean) extendedBoolean(wnew->misc.active_icon_s,
8183				  tblAIconOps, eiLAST);
8184    init_Ires(misc.icon_border_width);
8185    wnew->misc.icon_border_pixel = request->misc.icon_border_pixel;
8186#endif /* NO_ACTIVE_ICON */
8187
8188    init_Bres(misc.signalInhibit);
8189    init_Bres(misc.titeInhibit);
8190    init_Bres(misc.tiXtraScroll);
8191    init_Bres(misc.cdXtraScroll);
8192    init_Bres(misc.dynamicColors);
8193
8194#if OPT_DEC_CHRSET
8195    for (i = 0; i < NUM_CHRSET; i++) {
8196	screen->double_fonts[i].warn = fwResource;
8197    }
8198#endif
8199    for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) {
8200	init_Sres2(screen.MenuFontName, i);
8201    }
8202    for (i = 0; i < fMAX; i++) {
8203	screen->fnts[i].warn = fwResource;
8204#if OPT_WIDE_ATTRS
8205	screen->ifnts[i].warn = fwResource;
8206#endif
8207    }
8208#ifndef NO_ACTIVE_ICON
8209    screen->fnt_icon.warn = fwResource;
8210#endif
8211
8212    init_Ires(misc.fontWarnings);
8213
8214    initFontLists(wnew);
8215
8216#define DefaultFontNames screen->menu_font_names[fontMenu_default]
8217
8218    /*
8219     * Process Xft font resources first, since faceName may contain X11 fonts
8220     * that should override the "font" resource.
8221     */
8222#if OPT_RENDERFONT
8223    for (i = 0; i <= fontMenu_lastBuiltin; ++i) {
8224	init_Dres2(misc.face_size, i);
8225    }
8226
8227#define ALLOC_FONTLIST(name,which,field) \
8228    init_Sres(misc.default_xft.field);\
8229    allocFontList(wnew,\
8230		  name,\
8231		  &(wnew->work.fonts),\
8232		  which,\
8233		  wnew->misc.default_xft.field,\
8234		  True)
8235
8236    ALLOC_FONTLIST(XtNfaceName, fNorm, f_n);
8237
8238#if OPT_WIDE_CHARS
8239    ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w);
8240#endif
8241
8242#undef ALLOC_FONTLIST
8243
8244#endif
8245
8246    /*
8247     * Process X11 (XLFD) font specifications.
8248     */
8249#define ALLOC_FONTLIST(name,which,field) \
8250    init_Sres(misc.default_font.field);\
8251    allocFontList(wnew,\
8252		  name,\
8253		  &(wnew->work.fonts),\
8254		  which,\
8255		  wnew->misc.default_font.field,\
8256		  False)
8257
8258    ALLOC_FONTLIST(XtNfont, fNorm, f_n);
8259    ALLOC_FONTLIST(XtNboldFont, fBold, f_b);
8260
8261    DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew));
8262    DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew));
8263
8264#if OPT_WIDE_CHARS
8265    ALLOC_FONTLIST(XtNwideFont, fWide, f_w);
8266    ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb);
8267
8268    DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew));
8269    DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew));
8270#endif
8271
8272#undef ALLOC_FONTLIST
8273
8274    screen->EscapeFontName() = NULL;
8275    screen->SelectFontName() = NULL;
8276
8277    screen->menu_font_number = fontMenu_default;
8278    init_Sres(screen.initial_font);
8279    if (screen->initial_font != 0) {
8280	int result = xtermGetFont(screen->initial_font);
8281	if (result >= 0)
8282	    screen->menu_font_number = result;
8283    }
8284#if OPT_BROKEN_OSC
8285    init_Bres(screen.brokenLinuxOSC);
8286#endif
8287
8288#if OPT_BROKEN_ST
8289    init_Bres(screen.brokenStringTerm);
8290#endif
8291
8292#if OPT_C1_PRINT
8293    init_Bres(screen.c1_printable);
8294#endif
8295
8296#if OPT_CLIP_BOLD
8297    init_Bres(screen.use_clipping);
8298#endif
8299
8300#if OPT_DEC_CHRSET
8301    init_Bres(screen.font_doublesize);
8302    init_Ires(screen.cache_doublesize);
8303    if (screen->cache_doublesize > NUM_CHRSET)
8304	screen->cache_doublesize = NUM_CHRSET;
8305    if (screen->cache_doublesize == 0)
8306	screen->font_doublesize = False;
8307    TRACE(("Doublesize%s enabled, up to %d fonts\n",
8308	   screen->font_doublesize ? "" : " not",
8309	   screen->cache_doublesize));
8310#endif
8311
8312#if OPT_ISO_COLORS
8313    init_Ires(screen.veryBoldColors);
8314    init_Bres(screen.boldColors);
8315    init_Bres(screen.colorAttrMode);
8316    init_Bres(screen.colorBDMode);
8317    init_Bres(screen.colorBLMode);
8318    init_Bres(screen.colorMode);
8319    init_Bres(screen.colorULMode);
8320    init_Bres(screen.italicULMode);
8321    init_Bres(screen.colorRVMode);
8322
8323#if OPT_WIDE_ATTRS
8324    init_Bres(screen.colorITMode);
8325#endif
8326
8327#if OPT_COLOR_RES2
8328    TRACE(("...will fake resources for color%d to color%d\n",
8329	   MIN_ANSI_COLORS,
8330	   NUM_ANSI_COLORS - 1));
8331#endif
8332    for (i = 0, color_ok = False; i < MAXCOLORS; i++) {
8333
8334#if OPT_COLOR_RES2
8335	/*
8336	 * Xt has a hardcoded limit on the maximum number of resources that can
8337	 * be used in a widget.  If we configure both luit (which implies
8338	 * wide-characters) and 256-colors, it goes over that limit.  Most
8339	 * people would not need a resource-file with 256-colors; the default
8340	 * values in our table are sufficient.  In that case, fake the resource
8341	 * setting by copying the default value from the table.  The #define's
8342	 * can be overridden to make these true resources.
8343	 */
8344	if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) {
8345	    screen->Acolors[i].resource =
8346		x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr);
8347	    if (screen->Acolors[i].resource == 0)
8348		screen->Acolors[i].resource = XtDefaultForeground;
8349	} else
8350#endif /* OPT_COLOR_RES2 */
8351	{
8352	    screen->Acolors[i] = TScreenOf(request)->Acolors[i];
8353	    screen->Acolors[i].resource =
8354		x_strtrim(screen->Acolors[i].resource);
8355	}
8356
8357#if OPT_COLOR_RES
8358	TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource));
8359	screen->Acolors[i].mode = False;
8360	if (DftFg(Acolors[i])) {
8361	    screen->Acolors[i].value = T_COLOR(screen, TEXT_FG);
8362	    screen->Acolors[i].mode = True;
8363	} else if (DftBg(Acolors[i])) {
8364	    screen->Acolors[i].value = T_COLOR(screen, TEXT_BG);
8365	    screen->Acolors[i].mode = True;
8366	} else {
8367	    color_ok = True;
8368	}
8369#else
8370	TRACE(("Acolors[%d] = %#lx\n", i, TScreenOf(request)->Acolors[i]));
8371	if (screen->Acolors[i] != wnew->dft_foreground &&
8372	    screen->Acolors[i] != T_COLOR(screen, TEXT_FG) &&
8373	    screen->Acolors[i] != T_COLOR(screen, TEXT_BG))
8374	    color_ok = True;
8375#endif
8376    }
8377
8378    /*
8379     * Check if we're trying to use color in a monochrome screen.  Disable
8380     * color in that case, since that would make ANSI colors unusable.  A 4-bit
8381     * or 8-bit display is usable, so we do not have to check for anything more
8382     * specific.
8383     */
8384    if (color_ok) {
8385	if (getVisualDepth(wnew) <= 1) {
8386	    TRACE(("disabling color since screen is monochrome\n"));
8387	    color_ok = False;
8388	}
8389    }
8390
8391    /* If none of the colors are anything other than the foreground or
8392     * background, we'll assume this isn't color, no matter what the colorMode
8393     * resource says.  (There doesn't seem to be any good way to determine if
8394     * the resource lookup failed versus the user having misconfigured this).
8395     */
8396    if (!color_ok) {
8397	screen->colorMode = False;
8398	TRACE(("All colors are foreground or background: disable colorMode\n"));
8399    }
8400    wnew->sgr_foreground = -1;
8401    wnew->sgr_background = -1;
8402    wnew->sgr_extended = False;
8403#endif /* OPT_ISO_COLORS */
8404
8405    /*
8406     * Decode the resources that control the behavior on multiple mouse clicks.
8407     * A single click is always bound to normal character selection, but the
8408     * other flavors can be changed.
8409     */
8410    for (i = 0; i < NSELECTUNITS; ++i) {
8411	int ck = (i + 1);
8412	screen->maxClicks = ck;
8413	if (i == Select_CHAR)
8414	    screen->selectMap[i] = Select_CHAR;
8415	else if (TScreenOf(request)->onClick[i] != 0)
8416	    ParseOnClicks(wnew, request, (unsigned) i);
8417	else if (i <= Select_LINE)
8418	    screen->selectMap[i] = (SelectUnit) i;
8419	else
8420	    break;
8421	TRACE(("on%dClicks %s=%d\n", ck,
8422	       NonNull(TScreenOf(request)->onClick[i]),
8423	       screen->selectMap[i]));
8424	if (screen->selectMap[i] == NSELECTUNITS)
8425	    break;
8426    }
8427    TRACE(("maxClicks %d\n", screen->maxClicks));
8428
8429    init_Tres(MOUSE_FG);
8430    init_Tres(MOUSE_BG);
8431    init_Tres(TEXT_CURSOR);
8432#if OPT_HIGHLIGHT_COLOR
8433    init_Tres(HIGHLIGHT_BG);
8434    init_Tres(HIGHLIGHT_FG);
8435    init_Bres(screen.hilite_reverse);
8436    init_Mres(screen.hilite_color);
8437    if (screen->hilite_color == Maybe) {
8438	screen->hilite_color = False;
8439#if OPT_COLOR_RES
8440	/*
8441	 * If the highlight text/background are both set, and if they are
8442	 * not equal to either the text/background or background/text, then
8443	 * set the highlightColorMode automatically.
8444	 */
8445	if (!DftFg(Tcolors[HIGHLIGHT_BG])
8446	    && !DftBg(Tcolors[HIGHLIGHT_FG])
8447	    && !TxtFg(Tcolors[HIGHLIGHT_BG])
8448	    && !TxtBg(Tcolors[HIGHLIGHT_FG])
8449	    && !TxtBg(Tcolors[HIGHLIGHT_BG])
8450	    && !TxtFg(Tcolors[HIGHLIGHT_FG])) {
8451	    TRACE(("...setting hilite_color automatically\n"));
8452	    screen->hilite_color = True;
8453	}
8454#endif
8455    }
8456#endif
8457
8458#if OPT_TEK4014
8459    /*
8460     * The Tek4014 window has no separate resources for foreground, background
8461     * and cursor color.  Since xterm always creates the vt100 widget first, we
8462     * can set the Tektronix colors here.  That lets us use escape sequences to
8463     * set its dynamic colors and get consistent behavior whether or not the
8464     * window is displayed.
8465     */
8466    screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG];
8467    screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG];
8468    screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR];
8469#endif
8470
8471#ifdef SCROLLBAR_RIGHT
8472    init_Bres(misc.useRight);
8473#endif
8474
8475#if OPT_RENDERFONT
8476    init_Sres(misc.render_font_s);
8477    wnew->work.render_font =
8478	(Boolean) extendedBoolean(wnew->misc.render_font_s,
8479				  tblRenderFont, erLast);
8480    if (wnew->work.render_font == erDefault) {
8481	if (IsEmpty(CurrentXftFont(wnew))) {
8482	    free((void *) CurrentXftFont(wnew));
8483	    CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO);
8484	    TRACE(("will allow runtime switch to render_font using \"%s\"\n",
8485		   CurrentXftFont(wnew)));
8486	} else {
8487	    wnew->work.render_font = erTrue;
8488	    TRACE(("initially using TrueType font\n"));
8489	}
8490    }
8491    /* minor tweak to make debug traces consistent: */
8492    if (wnew->work.render_font) {
8493	if (IsEmpty(CurrentXftFont(wnew))) {
8494	    wnew->work.render_font = False;
8495	    TRACE(("reset render_font since there is no face_name\n"));
8496	}
8497    }
8498#endif
8499
8500#if OPT_WIDE_CHARS
8501    /* setup data for next call */
8502    request->screen.utf8_mode =
8503	extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast);
8504    request->screen.utf8_fonts =
8505	extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast);
8506
8507    /*
8508     * Make a copy in the input/request so that DefaultFontN() works for
8509     * the "CHECKFONT" option.
8510     */
8511    copyFontList(&(request->work.fonts.x11.list_n),
8512		 wnew->work.fonts.x11.list_n);
8513
8514    VTInitialize_locale(request);
8515    init_Bres(screen.normalized_c);
8516    init_Bres(screen.utf8_latin1);
8517    init_Bres(screen.utf8_title);
8518
8519#if OPT_LUIT_PROG
8520    init_Bres(misc.callfilter);
8521    init_Bres(misc.use_encoding);
8522    init_Sres(misc.locale_str);
8523    init_Sres(misc.localefilter);
8524#endif
8525
8526    init_Ires(screen.utf8_inparse);
8527    init_Ires(screen.utf8_mode);
8528    init_Ires(screen.utf8_fonts);
8529    init_Ires(screen.max_combining);
8530
8531    init_Ires(screen.utf8_always);	/* from utf8_mode, used in doparse */
8532
8533    if (screen->max_combining < 0) {
8534	screen->max_combining = 0;
8535    }
8536    if (screen->max_combining > 5) {
8537	screen->max_combining = 5;
8538    }
8539
8540    init_Bres(screen.vt100_graphics);
8541    init_Bres(screen.wide_chars);
8542    init_Bres(misc.mk_width);
8543    init_Bres(misc.cjk_width);
8544
8545    init_Ires(misc.mk_samplesize);
8546    init_Ires(misc.mk_samplepass);
8547
8548    if (wnew->misc.mk_samplesize > 0xffff)
8549	wnew->misc.mk_samplesize = 0xffff;
8550    if (wnew->misc.mk_samplesize < 0)
8551	wnew->misc.mk_samplesize = 0;
8552
8553    if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize)
8554	wnew->misc.mk_samplepass = wnew->misc.mk_samplesize;
8555    if (wnew->misc.mk_samplepass < 0)
8556	wnew->misc.mk_samplepass = 0;
8557
8558    if (TScreenOf(request)->utf8_mode) {
8559	TRACE(("setting wide_chars on\n"));
8560	screen->wide_chars = True;
8561    } else {
8562	TRACE(("setting utf8_mode to 0\n"));
8563	screen->utf8_mode = uFalse;
8564    }
8565    mk_wcwidth_init(screen->utf8_mode);
8566    TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode));
8567
8568#if OPT_MINI_LUIT
8569    if (TScreenOf(request)->latin9_mode) {
8570	screen->latin9_mode = True;
8571    }
8572    if (TScreenOf(request)->unicode_font) {
8573	screen->unicode_font = True;
8574    }
8575    TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode));
8576    TRACE(("initialized unicode_font to %d\n", screen->unicode_font));
8577#endif
8578
8579    decode_wcwidth(wnew);
8580    xtermSaveVTFonts(wnew);
8581#endif /* OPT_WIDE_CHARS */
8582
8583    init_Sres(screen.eight_bit_meta_s);
8584    wnew->screen.eight_bit_meta =
8585	extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, uLast);
8586    if (wnew->screen.eight_bit_meta == ebLocale) {
8587#if OPT_WIDE_CHARS
8588	if (xtermEnvUTF8()) {
8589	    wnew->screen.eight_bit_meta = ebFalse;
8590	    TRACE(("...eightBitMeta is false due to locale\n"));
8591	} else
8592#endif /* OPT_WIDE_CHARS */
8593	{
8594	    wnew->screen.eight_bit_meta = ebTrue;
8595	    TRACE(("...eightBitMeta is true due to locale\n"));
8596	}
8597    }
8598
8599    init_Bres(screen.always_bold_mode);
8600    init_Bres(screen.bold_mode);
8601    init_Bres(screen.underline);
8602
8603    wnew->cur_foreground = 0;
8604    wnew->cur_background = 0;
8605
8606    wnew->keyboard.flags = MODE_SRM;
8607
8608    if (screen->backarrow_key)
8609	wnew->keyboard.flags |= MODE_DECBKM;
8610    TRACE(("initialized DECBKM %s\n",
8611	   BtoS(wnew->keyboard.flags & MODE_DECBKM)));
8612
8613#if OPT_SIXEL_GRAPHICS
8614    init_Bres(screen.sixel_scrolling);
8615    if (screen->sixel_scrolling)
8616	wnew->keyboard.flags |= MODE_DECSDM;
8617    TRACE(("initialized DECSDM %s\n",
8618	   BtoS(wnew->keyboard.flags & MODE_DECSDM)));
8619#endif
8620
8621#if OPT_GRAPHICS
8622    init_Ires(screen.numcolorregisters);
8623    TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n",
8624	   screen->numcolorregisters));
8625
8626    init_Bres(screen.privatecolorregisters);	/* FIXME: should this be off unconditionally here? */
8627    TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n",
8628	   BtoS(screen->privatecolorregisters)));
8629#endif
8630
8631#if OPT_GRAPHICS
8632    {
8633	int native_w, native_h;
8634
8635	switch (screen->terminal_id) {
8636	case 125:
8637	    native_w = 768;
8638	    native_h = 460;
8639	    break;
8640	case 240:
8641	    native_w = 800;
8642	    native_h = 460;
8643	    break;
8644	case 241:
8645	    native_w = 800;
8646	    native_h = 460;
8647	    break;
8648	case 330:
8649	    native_w = 800;
8650	    native_h = 480;
8651	    break;
8652	case 340:
8653	    /* FALLTHRU */
8654	default:
8655	    native_w = 800;
8656	    native_h = 480;
8657	    break;
8658	case 382:
8659	    native_w = 960;
8660	    native_h = 750;
8661	    break;
8662	}
8663
8664# if OPT_REGIS_GRAPHICS
8665	init_Sres(screen.graphics_regis_default_font);
8666	TRACE(("default ReGIS font: %s\n",
8667	       screen->graphics_regis_default_font));
8668
8669	init_Sres(screen.graphics_regis_screensize);
8670	screen->graphics_regis_def_high = 1000;
8671	screen->graphics_regis_def_wide = 1000;
8672	if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) {
8673	    TRACE(("setting default ReGIS screensize based on terminal_id %d\n",
8674		   screen->terminal_id));
8675	    screen->graphics_regis_def_high = (Dimension) native_w;
8676	    screen->graphics_regis_def_wide = (Dimension) native_h;
8677	} else {
8678	    int conf_high;
8679	    int conf_wide;
8680	    char ignore;
8681
8682	    if (sscanf(screen->graphics_regis_screensize,
8683		       "%dx%d%c",
8684		       &conf_wide,
8685		       &conf_high,
8686		       &ignore) == 2) {
8687		if (conf_high > 0 && conf_wide > 0) {
8688		    screen->graphics_regis_def_high =
8689			(Dimension) conf_high;
8690		    screen->graphics_regis_def_wide =
8691			(Dimension) conf_wide;
8692		} else {
8693		    TRACE(("ignoring invalid regisScreenSize %s\n",
8694			   screen->graphics_regis_screensize));
8695		}
8696	    } else {
8697		TRACE(("ignoring invalid regisScreenSize %s\n",
8698		       screen->graphics_regis_screensize));
8699	    }
8700	}
8701	TRACE(("default ReGIS graphics screensize %dx%d\n",
8702	       (int) screen->graphics_regis_def_wide,
8703	       (int) screen->graphics_regis_def_high));
8704# endif
8705
8706	init_Sres(screen.graphics_max_size);
8707	screen->graphics_max_high = 1000;
8708	screen->graphics_max_wide = 1000;
8709	if (!x_strcasecmp(screen->graphics_max_size, "auto")) {
8710	    TRACE(("setting max graphics screensize based on terminal_id %d\n",
8711		   screen->terminal_id));
8712	    screen->graphics_max_high = (Dimension) native_w;
8713	    screen->graphics_max_wide = (Dimension) native_h;
8714	} else {
8715	    int conf_high;
8716	    int conf_wide;
8717	    char ignore;
8718
8719	    if (sscanf(screen->graphics_max_size,
8720		       "%dx%d%c",
8721		       &conf_wide,
8722		       &conf_high,
8723		       &ignore) == 2) {
8724		if (conf_high > 0 && conf_wide > 0) {
8725		    screen->graphics_max_high = (Dimension) conf_high;
8726		    screen->graphics_max_wide = (Dimension) conf_wide;
8727		} else {
8728		    TRACE(("ignoring invalid maxGraphicSize %s\n",
8729			   screen->graphics_max_size));
8730		}
8731	    } else {
8732		TRACE(("ignoring invalid maxGraphicSize %s\n",
8733		       screen->graphics_max_size));
8734	    }
8735	}
8736# if OPT_REGIS_GRAPHICS
8737	/* Make sure the max is large enough for the default ReGIS size. */
8738	if (screen->graphics_regis_def_high >
8739	    screen->graphics_max_high) {
8740	    screen->graphics_max_high =
8741		screen->graphics_regis_def_high;
8742	}
8743	if (screen->graphics_regis_def_wide >
8744	    screen->graphics_max_wide) {
8745	    screen->graphics_max_wide =
8746		screen->graphics_regis_def_wide;
8747	}
8748# endif
8749	TRACE(("max graphics screensize %dx%d\n",
8750	       (int) screen->graphics_max_wide,
8751	       (int) screen->graphics_max_high));
8752    }
8753#endif
8754
8755#if OPT_SIXEL_GRAPHICS
8756    init_Bres(screen.sixel_scrolls_right);
8757    TRACE(("initialized SIXEL_SCROLLS_RIGHT to resource default: %s\n",
8758	   BtoS(screen->sixel_scrolls_right)));
8759#endif
8760
8761    /* look for focus related events on the shell, because we need
8762     * to care about the shell's border being part of our focus.
8763     */
8764    TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent));
8765    XtAddEventHandler(my_parent, EnterWindowMask, False,
8766		      HandleEnterWindow, (Opaque) NULL);
8767    XtAddEventHandler(my_parent, LeaveWindowMask, False,
8768		      HandleLeaveWindow, (Opaque) NULL);
8769    XtAddEventHandler(my_parent, FocusChangeMask, False,
8770		      HandleFocusChange, (Opaque) NULL);
8771    XtAddEventHandler((Widget) wnew, 0L, True,
8772		      VTNonMaskableEvent, (Opaque) NULL);
8773    XtAddEventHandler((Widget) wnew, PropertyChangeMask, False,
8774		      HandleBellPropertyChange, (Opaque) NULL);
8775
8776#if HANDLE_STRUCT_NOTIFY
8777#if OPT_TOOLBAR
8778    wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar);
8779    init_Ires(VT100_TB_INFO(menu_height));
8780#else
8781    /* Flag icon name with "***"  on window output when iconified.
8782     * Put in a handler that will tell us when we get Map/Unmap events.
8783     */
8784    if (resource.zIconBeep)
8785#endif
8786	XtAddEventHandler(my_parent, StructureNotifyMask, False,
8787			  HandleStructNotify, (Opaque) 0);
8788#endif /* HANDLE_STRUCT_NOTIFY */
8789
8790    screen->bellInProgress = False;
8791
8792    set_character_class(screen->charClass);
8793#if OPT_REPORT_CCLASS
8794    if (resource.reportCClass)
8795	report_char_class(wnew);
8796#endif
8797
8798    /* create it, but don't realize it */
8799    ScrollBarOn(wnew, True);
8800
8801    /* make sure that the resize gravity acceptable */
8802    if (!GravityIsNorthWest(wnew) &&
8803	!GravityIsSouthWest(wnew)) {
8804	char value[80];
8805	String temp[2];
8806	Cardinal nparams = 1;
8807
8808	sprintf(value, "%d", wnew->misc.resizeGravity);
8809	temp[0] = value;
8810	temp[1] = 0;
8811	XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
8812			"unsupported resizeGravity resource value (%s)",
8813			temp, &nparams);
8814	wnew->misc.resizeGravity = SouthWestGravity;
8815    }
8816#ifndef NO_ACTIVE_ICON
8817    screen->whichVwin = &screen->fullVwin;
8818#endif /* NO_ACTIVE_ICON */
8819
8820    if (screen->savelines < 0)
8821	screen->savelines = 0;
8822
8823    init_Bres(screen.awaitInput);
8824
8825    wnew->flags = 0;
8826    if (!screen->jumpscroll)
8827	wnew->flags |= SMOOTHSCROLL;
8828    if (wnew->misc.reverseWrap)
8829	wnew->flags |= REVERSEWRAP;
8830    if (wnew->misc.autoWrap)
8831	wnew->flags |= WRAPAROUND;
8832    if (wnew->misc.re_verse != wnew->misc.re_verse0)
8833	wnew->flags |= REVERSE_VIDEO;
8834    if (screen->c132)
8835	wnew->flags |= IN132COLUMNS;
8836
8837    wnew->initflags = wnew->flags;
8838
8839#if OPT_MOD_FKEYS
8840    init_Ires(keyboard.modify_1st.allow_keys);
8841    init_Ires(keyboard.modify_1st.cursor_keys);
8842    init_Ires(keyboard.modify_1st.function_keys);
8843    init_Ires(keyboard.modify_1st.keypad_keys);
8844    init_Ires(keyboard.modify_1st.other_keys);
8845    init_Ires(keyboard.modify_1st.string_keys);
8846    init_Ires(keyboard.format_keys);
8847    wnew->keyboard.modify_now = wnew->keyboard.modify_1st;
8848#endif
8849
8850    init_Ires(misc.appcursorDefault);
8851    if (wnew->misc.appcursorDefault)
8852	wnew->keyboard.flags |= MODE_DECCKM;
8853
8854    init_Ires(misc.appkeypadDefault);
8855    if (wnew->misc.appkeypadDefault)
8856	wnew->keyboard.flags |= MODE_DECKPAM;
8857
8858    initLineData(wnew);
8859#if OPT_WIDE_CHARS
8860    freeFontList(&(request->work.fonts.x11.list_n));
8861#endif
8862    return;
8863}
8864
8865void
8866releaseCursorGCs(XtermWidget xw)
8867{
8868    TScreen *screen = TScreenOf(xw);
8869    VTwin *win = WhichVWin(screen);
8870    int n;
8871
8872    for_each_curs_gc(n) {
8873	freeCgs(xw, win, (CgsEnum) n);
8874    }
8875}
8876
8877void
8878releaseWindowGCs(XtermWidget xw, VTwin *win)
8879{
8880    int n;
8881
8882    for_each_text_gc(n) {
8883	freeCgs(xw, win, (CgsEnum) n);
8884    }
8885}
8886
8887#define TRACE_FREE_LEAK(name) \
8888	if (name) { \
8889	    TRACE(("freed " #name ": %p\n", (const void *) name)); \
8890	    free((void *) name); \
8891	    name = 0; \
8892	}
8893
8894#define FREE_LEAK(name) \
8895	if (name) { \
8896	    free((void *) name); \
8897	    name = 0; \
8898	}
8899
8900#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
8901static void
8902cleanupInputMethod(XtermWidget xw)
8903{
8904    TInput *input = lookupTInput(xw, (Widget) xw);
8905
8906    if (input && input->xim) {
8907	XCloseIM(input->xim);
8908	input->xim = 0;
8909	TRACE(("freed screen->xim\n"));
8910    }
8911}
8912#endif
8913
8914static void
8915VTDestroy(Widget w GCC_UNUSED)
8916{
8917#ifdef NO_LEAKS
8918    XtermWidget xw = (XtermWidget) w;
8919    TScreen *screen = TScreenOf(xw);
8920    Cardinal n, k;
8921
8922    StopBlinking(screen);
8923
8924    if (screen->scrollWidget) {
8925	XtUninstallTranslations(screen->scrollWidget);
8926	XtDestroyWidget(screen->scrollWidget);
8927    }
8928#if OPT_FIFO_LINES
8929    while (screen->saved_fifo > 0) {
8930	deleteScrollback(screen);
8931    }
8932#endif
8933    while (screen->save_title != 0) {
8934	SaveTitle *last = screen->save_title;
8935	screen->save_title = last->next;
8936	free(last->iconName);
8937	free(last->windowName);
8938	free(last);
8939    }
8940    TRACE_FREE_LEAK(xw->misc.active_icon_s);
8941#if OPT_ISO_COLORS
8942    TRACE_FREE_LEAK(screen->cmap_data);
8943    for (n = 0; n < MAXCOLORS; n++) {
8944	TRACE_FREE_LEAK(screen->Acolors[n].resource);
8945    }
8946#endif
8947#if OPT_COLOR_RES
8948    for (n = 0; n < NCOLORS; n++) {
8949	switch (n) {
8950#if OPT_TEK4014
8951	case TEK_BG:
8952	    /* FALLTHRU */
8953	case TEK_FG:
8954	    /* FALLTHRU */
8955	case TEK_CURSOR:
8956	    break;
8957#endif
8958	default:
8959	    TRACE_FREE_LEAK(screen->Tcolors[n].resource);
8960	    break;
8961	}
8962    }
8963#endif
8964    TRACE_FREE_LEAK(screen->save_ptr);
8965    TRACE_FREE_LEAK(screen->saveBuf_data);
8966    TRACE_FREE_LEAK(screen->saveBuf_index);
8967    for (n = 0; n < 2; ++n) {
8968	TRACE_FREE_LEAK(screen->editBuf_data[n]);
8969	TRACE_FREE_LEAK(screen->editBuf_index[n]);
8970    }
8971    TRACE_FREE_LEAK(screen->keyboard_dialect);
8972    TRACE_FREE_LEAK(screen->term_id);
8973#if OPT_WIDE_CHARS
8974#if OPT_LUIT_PROG
8975    TRACE_FREE_LEAK(xw->misc.locale_str);
8976    TRACE_FREE_LEAK(xw->misc.localefilter);
8977#endif
8978#endif
8979    TRACE_FREE_LEAK(xw->misc.T_geometry);
8980    TRACE_FREE_LEAK(xw->misc.geo_metry);
8981    TRACE_FREE_LEAK(xw->screen.term_id);
8982#if OPT_INPUT_METHOD
8983    cleanupInputMethod(xw);
8984    TRACE_FREE_LEAK(xw->misc.f_x);
8985    TRACE_FREE_LEAK(xw->misc.input_method);
8986    TRACE_FREE_LEAK(xw->misc.preedit_type);
8987#endif
8988    releaseCursorGCs(xw);
8989    releaseWindowGCs(xw, &(screen->fullVwin));
8990#ifndef NO_ACTIVE_ICON
8991    XFreeFont(screen->display, getIconicFont(screen)->fs);
8992    releaseWindowGCs(xw, &(screen->iconVwin));
8993#endif
8994    XtUninstallTranslations((Widget) xw);
8995#if OPT_TOOLBAR
8996    XtUninstallTranslations((Widget) XtParent(xw));
8997#endif
8998    XtUninstallTranslations((Widget) SHELL_OF(xw));
8999
9000    if (screen->hidden_cursor)
9001	XFreeCursor(screen->display, screen->hidden_cursor);
9002
9003    xtermCloseFonts(xw, screen->fnts);
9004#if OPT_WIDE_ATTRS
9005    xtermCloseFonts(xw, screen->ifnts);
9006#endif
9007    noleaks_cachedCgs(xw);
9008
9009    TRACE_FREE_LEAK(screen->selection_targets_8bit);
9010#if OPT_SELECT_REGEX
9011    for (n = 0; n < NSELECTUNITS; ++n) {
9012	if (screen->selectMap[n] == Select_REGEX) {
9013	    TRACE_FREE_LEAK(screen->selectExpr[n]);
9014	}
9015    }
9016#endif
9017
9018#if OPT_RENDERFONT
9019    for (n = 0; n < NMENUFONTS; ++n) {
9020	int e;
9021	for (e = 0; e < fMAX; ++e) {
9022	    xtermCloseXft(screen, getMyXftFont(xw, e, (int) n));
9023	}
9024    }
9025    if (screen->renderDraw)
9026	XftDrawDestroy(screen->renderDraw);
9027#endif
9028
9029    /* free things allocated via init_Sres or Init_Sres2 */
9030#ifndef NO_ACTIVE_ICON
9031    TRACE_FREE_LEAK(screen->icon_fontname);
9032#endif
9033#ifdef ALLOWLOGGING
9034    TRACE_FREE_LEAK(screen->logfile);
9035#endif
9036    TRACE_FREE_LEAK(screen->eight_bit_meta_s);
9037    TRACE_FREE_LEAK(screen->term_id);
9038    TRACE_FREE_LEAK(screen->charClass);
9039    TRACE_FREE_LEAK(screen->answer_back);
9040    TRACE_FREE_LEAK(screen->printer_state.printer_command);
9041    TRACE_FREE_LEAK(screen->keyboard_dialect);
9042    TRACE_FREE_LEAK(screen->disallowedColorOps);
9043    TRACE_FREE_LEAK(screen->disallowedFontOps);
9044    TRACE_FREE_LEAK(screen->disallowedMouseOps);
9045    TRACE_FREE_LEAK(screen->disallowedTcapOps);
9046    TRACE_FREE_LEAK(screen->disallowedWinOps);
9047    TRACE_FREE_LEAK(screen->default_string);
9048    TRACE_FREE_LEAK(screen->eightbit_select_types);
9049
9050#if OPT_WIDE_CHARS
9051    TRACE_FREE_LEAK(screen->utf8_select_types);
9052#endif
9053
9054#if 0
9055    for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) {
9056	TRACE_FREE_LEAK(screen->MenuFontName(n));
9057    }
9058#endif
9059
9060    TRACE_FREE_LEAK(screen->initial_font);
9061
9062#if OPT_LUIT_PROG
9063    TRACE_FREE_LEAK(xw->misc.locale_str);
9064    TRACE_FREE_LEAK(xw->misc.localefilter);
9065#endif
9066
9067#if OPT_RENDERFONT
9068    TRACE_FREE_LEAK(xw->misc.default_xft.f_n);
9069    TRACE_FREE_LEAK(xw->misc.default_xft.f_w);
9070    TRACE_FREE_LEAK(xw->misc.render_font_s);
9071#endif
9072
9073    TRACE_FREE_LEAK(xw->misc.default_font.f_n);
9074    TRACE_FREE_LEAK(xw->misc.default_font.f_b);
9075
9076#if OPT_WIDE_CHARS
9077    TRACE_FREE_LEAK(xw->misc.default_font.f_w);
9078    TRACE_FREE_LEAK(xw->misc.default_font.f_wb);
9079#endif
9080
9081    freeFontLists(&(xw->work.fonts.x11));
9082#if OPT_RENDERFONT
9083    freeFontLists(&(xw->work.fonts.xft));
9084#endif
9085
9086    xtermFontName(NULL);
9087#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS
9088    TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n);
9089    TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b);
9090#if OPT_WIDE_CHARS
9091    TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w);
9092    TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb);
9093#endif
9094    freeFontLists(&(screen->cacheVTFonts.fonts.x11));
9095    for (n = 0; n < NMENUFONTS; ++n) {
9096	for (k = 0; k < fMAX; ++k) {
9097	    if (screen->menu_font_names[n][k] !=
9098		screen->cacheVTFonts.menu_font_names[n][k]) {
9099		TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
9100		TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]);
9101	    } else {
9102		TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
9103	    }
9104	}
9105    }
9106#endif
9107
9108#if OPT_SELECT_REGEX
9109    for (n = 0; n < NSELECTUNITS; ++n) {
9110	FREE_LEAK(screen->selectExpr[n]);
9111    }
9112#endif
9113
9114    if (screen->selection_atoms)
9115	XtFree((void *) (screen->selection_atoms));
9116
9117    XtFree((void *) (screen->selection_data));
9118
9119    TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table);
9120    TRACE_FREE_LEAK(xw->keyboard.extra_translations);
9121    TRACE_FREE_LEAK(xw->keyboard.shell_translations);
9122    TRACE_FREE_LEAK(xw->keyboard.xterm_translations);
9123
9124    XtFree((void *) (xw->visInfo));
9125
9126#if OPT_WIDE_CHARS
9127    FreeTypedBuffer(XChar2b);
9128    FreeTypedBuffer(char);
9129#endif
9130#if OPT_RENDERFONT
9131#if OPT_RENDERWIDE
9132    FreeTypedBuffer(XftCharSpec);
9133#else
9134    FreeTypedBuffer(XftChar8);
9135#endif
9136#endif
9137
9138    TRACE_FREE_LEAK(myState.print_area);
9139    TRACE_FREE_LEAK(myState.string_area);
9140    memset(&myState, 0, sizeof(myState));
9141
9142#endif /* defined(NO_LEAKS) */
9143}
9144
9145#ifndef NO_ACTIVE_ICON
9146static void *
9147getProperty(Display *dpy,
9148	    Window w,
9149	    Atom req_type,
9150	    const char *prop_name)
9151{
9152    Atom property;
9153    Atom actual_return_type;
9154    int actual_format_return = 0;
9155    unsigned long nitems_return = 0;
9156    unsigned long bytes_after_return = 0;
9157    unsigned char *prop_return = 0;
9158    long long_length = 1024;
9159    size_t limit;
9160    char *result = 0;
9161
9162    TRACE(("getProperty %s(%s)\n", prop_name,
9163	   req_type ? TraceAtomName(dpy, req_type) : "?"));
9164    property = XInternAtom(dpy, prop_name, False);
9165
9166    if (!xtermGetWinProp(dpy,
9167			 w,
9168			 property,
9169			 0L,
9170			 long_length,
9171			 req_type,
9172			 &actual_return_type,
9173			 &actual_format_return,
9174			 &nitems_return,
9175			 &bytes_after_return,
9176			 &prop_return)) {
9177	TRACE((".. Cannot get %s property.\n", prop_name));
9178    } else if (prop_return != 0) {
9179
9180	if (nitems_return != 0 &&
9181	    actual_format_return != 0 &&
9182	    actual_return_type == req_type) {
9183	    /*
9184	     * Null-terminate the result to make string handling easier.
9185	     * The format==8 corresponds to strings, and the number of items
9186	     * is the number of characters.
9187	     */
9188	    if (actual_format_return == 8) {
9189		limit = nitems_return;
9190	    } else {
9191		/* manpage is misleading - X really uses 'long', not 32-bits */
9192		limit = sizeof(long) * nitems_return;
9193	    }
9194	    if ((result = malloc(limit + 1)) != 0) {
9195		memcpy(result, prop_return, limit);
9196		result[limit] = '\0';
9197	    }
9198	    TRACE(("... result %s\n", result ? ("ok") : "null"));
9199	}
9200	XFree(prop_return);
9201    } else {
9202	TRACE((".. no property returned\n"));
9203    }
9204    return (void *) result;
9205}
9206
9207/*
9208 * Active icons are supported by fvwm.  This feature is not supported by
9209 * metacity (gnome) or kwin (kde).  Both metacity and kwin support (in
9210 * incompatible ways, e.g., one uses the icon theme as a fallback for window
9211 * decorations but the other does not, etc, ...) an icon as part of the window
9212 * decoration (usually on the upper-left of the window).
9213 *
9214 * In either case, xterm's icon will only be shown in the window decorations if
9215 * xterm does not use the active icon feature.
9216 *
9217 * This function (tries to) determine the window manager's name, so that we can
9218 * provide a useful automatic default for active icons.  It is based on reading
9219 * wmctrl, which covers most of EWMH and ICCM.
9220 */
9221static char *
9222getWindowManagerName(XtermWidget xw)
9223{
9224    TScreen *screen = TScreenOf(xw);
9225    Display *dpy = screen->display;
9226    Window *sup_window = NULL;
9227    char *result = 0;
9228
9229    TRACE(("getWindowManagerName\n"));
9230#define getWinProp(type, name) \
9231    (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name)
9232    if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == 0) {
9233	sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK");
9234    }
9235
9236    /*
9237     * If we found the supporting window, get the property containing the
9238     * window manager's name.  EWMH defines _NET_WM_NAME, while ICCM defines
9239     * WM_CLASS.  There is no standard for the names stored there;
9240     * conventionally it is mixed case.  In practice, the former is more often
9241     * set; the latter is not given (or is a lowercased version of the former).
9242     */
9243    if (sup_window != 0) {
9244#define getStringProp(type,name) \
9245	(char *)getProperty(dpy, *sup_window, type, name)
9246	if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == 0
9247	    && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == 0
9248	    && (result = getStringProp(XA_STRING, "WM_CLASS")) == 0) {
9249	    TRACE(("... window manager does not tell its name\n"));
9250	}
9251	free(sup_window);
9252    } else {
9253	TRACE(("... Cannot get window manager info properties\n"));
9254    }
9255    if (result == 0)
9256	result = x_strdup("unknown");
9257    TRACE(("... window manager name is %s\n", result));
9258    return result;
9259}
9260#endif
9261
9262/*ARGSUSED*/
9263static void
9264VTRealize(Widget w,
9265	  XtValueMask * valuemask,
9266	  XSetWindowAttributes * values)
9267{
9268    XtermWidget xw = (XtermWidget) w;
9269    TScreen *screen = TScreenOf(xw);
9270
9271    const VTFontNames *myfont;
9272    struct Xinerama_geometry pos;
9273    int pr;
9274    Atom pid_atom;
9275    int i;
9276
9277    TRACE(("VTRealize {{\n"));
9278
9279#if OPT_TOOLBAR
9280    /*
9281     * Layout for the toolbar confuses the Shell widget.  Remind it that we
9282     * would like to be iconified if the corresponding resource was set.
9283     */
9284    if (XtIsRealized(toplevel)) {
9285	Boolean iconic = 0;
9286
9287	XtVaGetValues(toplevel,
9288		      XtNiconic, &iconic,
9289		      (XtPointer) 0);
9290
9291	if (iconic) {
9292	    XIconifyWindow(XtDisplay(toplevel),
9293			   XtWindow(toplevel),
9294			   DefaultScreen(XtDisplay(toplevel)));
9295	}
9296    }
9297#endif
9298
9299    TabReset(xw->tabs);
9300
9301    if (screen->menu_font_number == fontMenu_default) {
9302	myfont = defaultVTFontNames(xw);
9303    } else {
9304	myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number));
9305    }
9306    memset(screen->fnts, 0, sizeof(screen->fnts));
9307
9308    if (!xtermLoadFont(xw,
9309		       myfont,
9310		       False,
9311		       screen->menu_font_number)) {
9312	if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) {
9313	    char *use_font = x_strdup(DEFFONT);
9314	    xtermWarning("unable to open font \"%s\", trying \"%s\"....\n",
9315			 myfont->f_n, use_font);
9316	    (void) xtermLoadFont(xw,
9317				 xtermFontName(use_font),
9318				 False,
9319				 screen->menu_font_number);
9320	    screen->MenuFontName(screen->menu_font_number) = use_font;
9321	}
9322    }
9323
9324    /* really screwed if we couldn't open default font */
9325    if (!getNormalFont(screen, fNorm)->fs) {
9326	xtermWarning("unable to locate a suitable font\n");
9327	Exit(1);
9328    }
9329#if OPT_WIDE_CHARS
9330    if (screen->utf8_mode) {
9331	TRACE(("check if this is a wide font, if not try again\n"));
9332	if (xtermLoadWideFonts(xw, False)) {
9333	    SetVTFont(xw, screen->menu_font_number, True, NULL);
9334	    /* we will not be able to switch to ISO-8859-1 */
9335	    if (!screen->mergedVTFonts) {
9336		screen->utf8_fonts = uAlways;
9337		update_font_utf8_fonts();
9338	    }
9339	}
9340    }
9341#endif
9342
9343    /* making cursor */
9344    if (!screen->pointer_cursor) {
9345	screen->pointer_cursor =
9346	    make_colored_cursor(XC_xterm,
9347				T_COLOR(screen, MOUSE_FG),
9348				T_COLOR(screen, MOUSE_BG));
9349    } else {
9350	recolor_cursor(screen,
9351		       screen->pointer_cursor,
9352		       T_COLOR(screen, MOUSE_FG),
9353		       T_COLOR(screen, MOUSE_BG));
9354    }
9355
9356    /* set defaults */
9357    pos.x = 1;
9358    pos.y = 1;
9359    pos.w = 80;
9360    pos.h = 24;
9361
9362    TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry)));
9363    pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos);
9364    TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w));
9365
9366    set_max_col(screen, (int) (pos.w - 1));	/* units in character cells */
9367    set_max_row(screen, (int) (pos.h - 1));	/* units in character cells */
9368    xtermUpdateFontInfo(xw, False);
9369
9370    pos.w = screen->fullVwin.fullwidth;
9371    pos.h = screen->fullVwin.fullheight;
9372
9373    TRACE(("... border widget %d parent %d shell %d\n",
9374	   BorderWidth(xw),
9375	   BorderWidth(XtParent(xw)),
9376	   BorderWidth(SHELL_OF(xw))));
9377
9378    if ((pr & XValue) && (XNegative & pr)) {
9379	pos.x = (Position) (pos.x + (pos.scr_w
9380				     - (int) pos.w
9381				     - (BorderWidth(XtParent(xw)) * 2)));
9382    }
9383    if ((pr & YValue) && (YNegative & pr)) {
9384	pos.y = (Position) (pos.y + (pos.scr_h
9385				     - (int) pos.h
9386				     - (BorderWidth(XtParent(xw)) * 2)));
9387    }
9388    pos.x = (Position) (pos.x + pos.scr_x);
9389    pos.y = (Position) (pos.y + pos.scr_y);
9390
9391    /* set up size hints for window manager; min 1 char by 1 char */
9392    getXtermSizeHints(xw);
9393    xtermSizeHints(xw, (xw->misc.scrollbar
9394			? (screen->scrollWidget->core.width
9395			   + BorderWidth(screen->scrollWidget))
9396			: 0));
9397
9398    xw->hints.x = pos.x;
9399    xw->hints.y = pos.y;
9400#if OPT_MAXIMIZE
9401    /* assure single-increment resize for fullscreen */
9402    if (term->work.ewmh[0].mode) {
9403	xw->hints.width_inc = 1;
9404	xw->hints.height_inc = 1;
9405    }
9406#endif
9407    if ((XValue & pr) || (YValue & pr)) {
9408	xw->hints.flags |= USSize | USPosition;
9409	xw->hints.flags |= PWinGravity;
9410	switch (pr & (XNegative | YNegative)) {
9411	case 0:
9412	    xw->hints.win_gravity = NorthWestGravity;
9413	    break;
9414	case XNegative:
9415	    xw->hints.win_gravity = NorthEastGravity;
9416	    break;
9417	case YNegative:
9418	    xw->hints.win_gravity = SouthWestGravity;
9419	    break;
9420	default:
9421	    xw->hints.win_gravity = SouthEastGravity;
9422	    break;
9423	}
9424    } else {
9425	/* set a default size, but do *not* set position */
9426	xw->hints.flags |= PSize;
9427    }
9428    xw->hints.height = xw->hints.base_height
9429	+ xw->hints.height_inc * MaxRows(screen);
9430    xw->hints.width = xw->hints.base_width
9431	+ xw->hints.width_inc * MaxCols(screen);
9432
9433    if ((WidthValue & pr) || (HeightValue & pr))
9434	xw->hints.flags |= USSize;
9435    else
9436	xw->hints.flags |= PSize;
9437
9438    /*
9439     * Note that the size-hints are for the shell, while the resize-request
9440     * is for the vt100 widget.  They are not the same size.
9441     */
9442    (void) REQ_RESIZE((Widget) xw,
9443		      (Dimension) pos.w, (Dimension) pos.h,
9444		      &xw->core.width, &xw->core.height);
9445
9446    /* XXX This is bogus.  We are parsing geometries too late.  This
9447     * is information that the shell widget ought to have before we get
9448     * realized, so that it can do the right thing.
9449     */
9450    if (xw->hints.flags & USPosition)
9451	XMoveWindow(XtDisplay(xw), VShellWindow(xw),
9452		    xw->hints.x, xw->hints.y);
9453
9454    TRACE(("%s@%d -- ", __FILE__, __LINE__));
9455    TRACE_HINTS(&xw->hints);
9456    XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints);
9457    TRACE(("%s@%d -- ", __FILE__, __LINE__));
9458    TRACE_WM_HINTS(xw);
9459
9460    if ((pid_atom = XInternAtom(XtDisplay(xw), "_NET_WM_PID", False)) != None) {
9461	/* XChangeProperty format 32 really is "long" */
9462	unsigned long pid_l = (unsigned long) getpid();
9463	TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l));
9464	XChangeProperty(XtDisplay(xw), VShellWindow(xw),
9465			pid_atom, XA_CARDINAL, 32, PropModeReplace,
9466			(unsigned char *) &pid_l, 1);
9467    }
9468
9469    XFlush(XtDisplay(xw));	/* get it out to window manager */
9470
9471    /* use ForgetGravity instead of SouthWestGravity because translating
9472       the Expose events for ConfigureNotifys is too hard */
9473    values->bit_gravity = (GravityIsNorthWest(xw)
9474			   ? NorthWestGravity
9475			   : ForgetGravity);
9476    screen->fullVwin.window = XtWindow(xw) =
9477	XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)),
9478		      xw->core.x, xw->core.y,
9479		      xw->core.width, xw->core.height, BorderWidth(xw),
9480		      (int) xw->core.depth,
9481		      InputOutput, CopyFromParent,
9482		      *valuemask | CWBitGravity, values);
9483#if OPT_DOUBLE_BUFFER
9484    screen->fullVwin.drawable = screen->fullVwin.window;
9485
9486    {
9487	Window win = screen->fullVwin.window;
9488	Drawable d;
9489	int major, minor;
9490	if (!XdbeQueryExtension(XtDisplay(xw), &major, &minor)) {
9491	    fprintf(stderr, "XdbeQueryExtension returned zero!\n");
9492	    exit(3);
9493	}
9494	d = XdbeAllocateBackBufferName(XtDisplay(xw), win, XdbeCopied);
9495	if (d == None) {
9496	    fprintf(stderr, "Couldn't allocate a back buffer!\n");
9497	    exit(3);
9498	}
9499	screen->fullVwin.drawable = d;
9500	screen->needSwap = 1;
9501    }
9502#endif /* OPT_DOUBLE_BUFFER */
9503    screen->event_mask = values->event_mask;
9504
9505#ifndef NO_ACTIVE_ICON
9506    /*
9507     * Normally, the font-number for icon fonts does not correspond with any of
9508     * the menu-selectable fonts.  If we cannot load the font given for the
9509     * iconFont resource, try with font1 aka "Unreadable".
9510     */
9511    screen->icon_fontnum = -1;
9512    if (getIconicFont(screen)->fs == 0) {
9513	getIconicFont(screen)->fs =
9514	    XLoadQueryFont(screen->display,
9515			   screen->MenuFontName(fontMenu_font1));
9516	TRACE(("%susing font1 '%s' as iconFont\n",
9517	       (getIconicFont(screen)->fs
9518		? ""
9519		: "NOT "),
9520	       screen->MenuFontName(fontMenu_font1)));
9521    }
9522#if OPT_RENDERFONT
9523    /*
9524     * If we still have no result from iconFont resource (perhaps because fonts
9525     * are missing) but are using Xft, try to use that instead.  We prefer
9526     * bitmap fonts in any case, since scaled fonts are usually less readable,
9527     * particularly at small sizes.
9528     */
9529    if (UsingRenderFont(xw)
9530	&& getIconicFont(screen)->fs == 0) {
9531	screen->icon_fontnum = fontMenu_default;
9532	getIconicFont(screen)->fs = getNormalFont(screen, fNorm)->fs;	/* need for next-if */
9533	TRACE(("using TrueType font as iconFont\n"));
9534    }
9535#endif
9536    if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) {
9537	char *wm_name = getWindowManagerName(xw);
9538	if (x_strncasecmp(wm_name, "fvwm", 4) &&
9539	    x_strncasecmp(wm_name, "window maker", 12))
9540	    xw->work.active_icon = eiFalse;
9541	free(wm_name);
9542    }
9543    if (xw->work.active_icon && getIconicFont(screen)->fs) {
9544	int iconX = 0, iconY = 0;
9545	Widget shell = SHELL_OF(xw);
9546	VTwin *win = &(screen->iconVwin);
9547	int save_fontnum = screen->menu_font_number;
9548
9549	TRACE(("Initializing active-icon %d\n", screen->icon_fontnum));
9550	screen->menu_font_number = screen->icon_fontnum;
9551	XtVaGetValues(shell,
9552		      XtNiconX, &iconX,
9553		      XtNiconY, &iconY,
9554		      (XtPointer) 0);
9555	xtermComputeFontInfo(xw, &(screen->iconVwin),
9556			     getIconicFont(screen)->fs, 0);
9557	screen->menu_font_number = save_fontnum;
9558
9559	/* since only one client is permitted to select for Button
9560	 * events, we have to let the window manager get 'em...
9561	 */
9562	values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask);
9563	values->border_pixel = xw->misc.icon_border_pixel;
9564
9565	screen->iconVwin.window =
9566	    XCreateWindow(XtDisplay(xw),
9567			  RootWindowOfScreen(XtScreen(shell)),
9568			  iconX, iconY,
9569			  screen->iconVwin.fullwidth,
9570			  screen->iconVwin.fullheight,
9571			  xw->misc.icon_border_width,
9572			  (int) xw->core.depth,
9573			  InputOutput, CopyFromParent,
9574			  *valuemask | CWBitGravity | CWBorderPixel,
9575			  values);
9576#if OPT_DOUBLE_BUFFER
9577	screen->iconVwin.drawable = screen->iconVwin.window;
9578#endif
9579	XtVaSetValues(shell,
9580		      XtNiconWindow, screen->iconVwin.window,
9581		      (XtPointer) 0);
9582	XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w);
9583
9584	setCgsFont(xw, win, gcNorm, getIconicFont(screen));
9585	setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG));
9586	setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG));
9587
9588	copyCgs(xw, win, gcBold, gcNorm);
9589
9590	setCgsFont(xw, win, gcNormReverse, getIconicFont(screen));
9591	setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG));
9592	setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG));
9593
9594	copyCgs(xw, win, gcBoldReverse, gcNormReverse);
9595
9596#if OPT_TOOLBAR
9597	/*
9598	 * Toolbar is initialized before we get here.  Enable the menu item
9599	 * and set it properly.
9600	 */
9601	SetItemSensitivity(vtMenuEntries[vtMenu_activeicon].widget, True);
9602	update_activeicon();
9603#endif
9604    } else {
9605	TRACE(("Disabled active-icon\n"));
9606	xw->work.active_icon = eiFalse;
9607    }
9608#endif /* NO_ACTIVE_ICON */
9609
9610#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
9611    VTInitI18N(xw);
9612#endif
9613#if OPT_NUM_LOCK
9614    VTInitModifiers(xw);
9615#if OPT_EXTRA_PASTE
9616    if (xw->keyboard.extra_translations) {
9617	XtOverrideTranslations((Widget) xw,
9618			       XtParseTranslationTable(xw->keyboard.extra_translations));
9619    }
9620#endif
9621#endif
9622
9623    set_cursor_gcs(xw);
9624
9625    /* Reset variables used by ANSI emulation. */
9626
9627    resetCharsets(screen);
9628
9629    XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor);
9630
9631    set_cur_col(screen, 0);
9632    set_cur_row(screen, 0);
9633    set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1);
9634    set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1);
9635    reset_margins(screen);
9636
9637    memset(screen->sc, 0, sizeof(screen->sc));
9638
9639    /* Mark screen buffer as unallocated.  We wait until the run loop so
9640       that the child process does not fork and exec with all the dynamic
9641       memory it will never use.  If we were to do it here, the
9642       swap space for new process would be huge for huge savelines. */
9643#if OPT_TEK4014
9644    if (!tekWidget)		/* if not called after fork */
9645#endif
9646    {
9647	screen->visbuf = NULL;
9648	screen->saveBuf_index = NULL;
9649    }
9650
9651    ResetWrap(screen);
9652    screen->scrolls = screen->incopy = 0;
9653    xtermSetCursorBox(screen);
9654
9655    screen->savedlines = 0;
9656
9657    for (i = 0; i < 2; ++i) {
9658	screen->whichBuf = !screen->whichBuf;
9659	CursorSave(xw);
9660    }
9661
9662#ifndef NO_ACTIVE_ICON
9663    if (!xw->work.active_icon)
9664#endif
9665	xtermLoadIcon(xw);
9666
9667    /*
9668     * Do this last, since it may change the layout via a resize.
9669     */
9670    if (xw->misc.scrollbar) {
9671	screen->fullVwin.sb_info.width = 0;
9672	ScrollBarOn(xw, False);
9673    }
9674
9675    xtermSetWinSize(xw);
9676    TRACE(("}} VTRealize\n"));
9677}
9678
9679#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
9680
9681/* limit this feature to recent XFree86 since X11R6.x core dumps */
9682#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING)
9683#define USE_XIM_INSTANTIATE_CB
9684
9685static void
9686xim_instantiate_cb(Display *display,
9687		   XPointer client_data GCC_UNUSED,
9688		   XPointer call_data GCC_UNUSED)
9689{
9690    TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data));
9691
9692    if (display == XtDisplay(term)) {
9693	VTInitI18N(term);
9694    }
9695}
9696
9697static void
9698xim_destroy_cb(XIM im GCC_UNUSED,
9699	       XPointer client_data GCC_UNUSED,
9700	       XPointer call_data GCC_UNUSED)
9701{
9702    XtermWidget xw = term;
9703    TInput *input = lookupTInput(xw, (Widget) xw);
9704
9705    TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n",
9706	   (long) im, client_data, call_data));
9707    if (input)
9708	input->xic = NULL;
9709    XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
9710				   xim_instantiate_cb, NULL);
9711}
9712#endif /* X11R6+ */
9713
9714static Boolean
9715xim_create_fs(XtermWidget xw)
9716{
9717    XFontStruct **fonts;
9718    char **font_name_list;
9719    char **missing_charset_list;
9720    char *def_string;
9721    int missing_charset_count;
9722    unsigned i, j;
9723
9724    if (xw->work.xim_fs == 0) {
9725	xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
9726					 xw->misc.f_x,
9727					 &missing_charset_list,
9728					 &missing_charset_count,
9729					 &def_string);
9730	if (xw->work.xim_fs == NULL) {
9731	    xtermWarning("Preparation of font set "
9732			 "\"%s\" for XIM failed.\n", xw->misc.f_x);
9733	    xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
9734					     DEFXIMFONT,
9735					     &missing_charset_list,
9736					     &missing_charset_count,
9737					     &def_string);
9738	}
9739    }
9740    if (xw->work.xim_fs == NULL) {
9741	xtermWarning("Preparation of default font set "
9742		     "\"%s\" for XIM failed.\n", DEFXIMFONT);
9743	cleanupInputMethod(xw);
9744	xw->work.cannot_im = True;
9745    } else {
9746	(void) XExtentsOfFontSet(xw->work.xim_fs);
9747	j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list);
9748	for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) {
9749	    if (xw->work.xim_fs_ascent < (*fonts)->ascent)
9750		xw->work.xim_fs_ascent = (*fonts)->ascent;
9751	}
9752    }
9753    return (Boolean) !(xw->work.cannot_im);
9754}
9755
9756static void
9757xim_create_xic(XtermWidget xw, Widget theInput)
9758{
9759    Display *myDisplay = XtDisplay(theInput);
9760    Window myWindow = XtWindow(theInput);
9761    unsigned i, j;
9762    char *p = NULL, *s, *t, *ns, *end, buf[32];
9763    XIMStyles *xim_styles;
9764    XIMStyle input_style = 0;
9765    Bool found;
9766    static struct {
9767	const char *name;
9768	unsigned long code;
9769    } known_style[] = {
9770	{
9771	    "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing)
9772	},
9773	{
9774	    "OffTheSpot", (XIMPreeditArea | XIMStatusArea)
9775	},
9776	{
9777	    "Root", (XIMPreeditNothing | XIMStatusNothing)
9778	},
9779    };
9780    TInput *input = lookupTInput(xw, theInput);
9781
9782    if (xw->work.cannot_im) {
9783	return;
9784    }
9785
9786    if (input == 0) {
9787	for (i = 0; i < NINPUTWIDGETS; ++i) {
9788	    if (xw->work.inputs[i].w == 0) {
9789		input = xw->work.inputs + i;
9790		input->w = theInput;
9791		break;
9792	    }
9793	}
9794    }
9795
9796    if (input == 0) {
9797	xtermWarning("attempted to add too many input widgets\n");
9798	return;
9799    }
9800
9801    TRACE(("xim_real_init\n"));
9802
9803    if (IsEmpty(xw->misc.input_method)) {
9804	if ((p = XSetLocaleModifiers("")) != NULL && *p) {
9805	    input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
9806	}
9807    } else {
9808	s = xw->misc.input_method;
9809	i = 5 + (unsigned) strlen(s);
9810
9811	t = (char *) MyStackAlloc(i, buf);
9812	if (t == NULL) {
9813	    SysError(ERROR_VINIT);
9814	} else {
9815
9816	    for (ns = s; ns && *s;) {
9817		while (*s && isspace(CharOf(*s)))
9818		    s++;
9819		if (!*s)
9820		    break;
9821		if ((ns = end = strchr(s, ',')) == 0)
9822		    end = s + strlen(s);
9823		while ((end != s) && isspace(CharOf(end[-1])))
9824		    end--;
9825
9826		if (end != s) {
9827		    strcpy(t, "@im=");
9828		    strncat(t, s, (size_t) (end - s));
9829
9830		    if ((p = XSetLocaleModifiers(t)) != 0 && *p
9831			&& (input->xim = XOpenIM(myDisplay,
9832						 NULL,
9833						 NULL,
9834						 NULL)) != 0) {
9835			break;
9836		    }
9837
9838		}
9839		s = ns + 1;
9840	    }
9841	    MyStackFree(t, buf);
9842	}
9843    }
9844
9845    if (input->xim == NULL
9846	&& (p = XSetLocaleModifiers("@im=none")) != NULL
9847	&& *p) {
9848	input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
9849    }
9850
9851    if (!input->xim) {
9852	xtermWarning("Failed to open input method\n");
9853	return;
9854    }
9855    TRACE(("VTInitI18N opened input method:%s\n", NonNull(p)));
9856
9857    if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0)
9858	|| !xim_styles
9859	|| !xim_styles->count_styles) {
9860	xtermWarning("input method doesn't support any style\n");
9861	cleanupInputMethod(xw);
9862	xw->work.cannot_im = True;
9863	return;
9864    }
9865
9866    found = False;
9867    for (s = xw->misc.preedit_type; s && !found;) {
9868	while (*s && isspace(CharOf(*s)))
9869	    s++;
9870	if (!*s)
9871	    break;
9872	if ((ns = end = strchr(s, ',')) != 0)
9873	    ns++;
9874	else
9875	    end = s + strlen(s);
9876	while ((end != s) && isspace(CharOf(end[-1])))
9877	    end--;
9878
9879	if (end != s) {		/* just in case we have a spurious comma */
9880	    TRACE(("looking for style '%.*s'\n", (int) (end - s), s));
9881	    for (i = 0; i < XtNumber(known_style); i++) {
9882		if ((int) strlen(known_style[i].name) == (end - s)
9883		    && !strncmp(s, known_style[i].name, (size_t) (end - s))) {
9884		    input_style = known_style[i].code;
9885		    for (j = 0; j < xim_styles->count_styles; j++) {
9886			if (input_style == xim_styles->supported_styles[j]) {
9887			    found = True;
9888			    break;
9889			}
9890		    }
9891		    if (found)
9892			break;
9893		}
9894	    }
9895	}
9896
9897	s = ns;
9898    }
9899    XFree(xim_styles);
9900
9901    if (!found) {
9902	xtermWarning("input method doesn't support my preedit type (%s)\n",
9903		     xw->misc.preedit_type);
9904	cleanupInputMethod(xw);
9905	xw->work.cannot_im = True;
9906	return;
9907    }
9908
9909    /*
9910     * Check for styles we do not yet support.
9911     */
9912    TRACE(("input_style %#lx\n", input_style));
9913    if (input_style == (XIMPreeditArea | XIMStatusArea)) {
9914	xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n");
9915	cleanupInputMethod(xw);
9916	xw->work.cannot_im = True;
9917	return;
9918    }
9919
9920    /*
9921     * For XIMPreeditPosition (or OverTheSpot), XIM client has to
9922     * prepare a font.
9923     * The font has to be locale-dependent XFontSet, whereas
9924     * XTerm use Unicode font.  This leads a problem that the
9925     * same font cannot be used for XIM preedit.
9926     */
9927    if (input_style != (XIMPreeditNothing | XIMStatusNothing)) {
9928	XVaNestedList p_list;
9929	XPoint spot =
9930	{0, 0};
9931
9932	if (xim_create_fs(xw)) {
9933	    p_list = XVaCreateNestedList(0,
9934					 XNSpotLocation, &spot,
9935					 XNFontSet, xw->work.xim_fs,
9936					 (void *) 0);
9937	    input->xic = XCreateIC(input->xim,
9938				   XNInputStyle, input_style,
9939				   XNClientWindow, myWindow,
9940				   XNFocusWindow, myWindow,
9941				   XNPreeditAttributes, p_list,
9942				   (void *) 0);
9943	}
9944    } else {
9945	input->xic = XCreateIC(input->xim, XNInputStyle, input_style,
9946			       XNClientWindow, myWindow,
9947			       XNFocusWindow, myWindow,
9948			       (void *) 0);
9949    }
9950
9951    if (!input->xic) {
9952	xtermWarning("Failed to create input context\n");
9953	cleanupInputMethod(xw);
9954    }
9955#if defined(USE_XIM_INSTANTIATE_CB)
9956    else {
9957	XIMCallback destroy_cb;
9958
9959	destroy_cb.callback = xim_destroy_cb;
9960	destroy_cb.client_data = NULL;
9961	if (XSetIMValues(input->xim,
9962			 XNDestroyCallback,
9963			 &destroy_cb,
9964			 (void *) 0)) {
9965	    xtermWarning("Could not set destroy callback to IM\n");
9966	}
9967    }
9968#endif
9969
9970    return;
9971}
9972
9973static void
9974xim_real_init(XtermWidget xw)
9975{
9976    xim_create_xic(xw, (Widget) xw);
9977}
9978
9979static void
9980VTInitI18N(XtermWidget xw)
9981{
9982    if (xw->misc.open_im) {
9983	xim_real_init(xw);
9984
9985#if defined(USE_XIM_INSTANTIATE_CB)
9986	if (lookupTInput(xw, (Widget) xw) == NULL
9987	    && !xw->work.cannot_im
9988	    && xw->misc.retry_im-- > 0) {
9989	    sleep(3);
9990	    XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
9991					   xim_instantiate_cb, NULL);
9992	}
9993#endif
9994    }
9995}
9996
9997TInput *
9998lookupTInput(XtermWidget xw, Widget w)
9999{
10000    TInput *result = 0;
10001    unsigned n;
10002
10003    for (n = 0; n < NINPUTWIDGETS; ++n) {
10004	if (xw->work.inputs[n].w == w) {
10005	    result = xw->work.inputs + n;
10006	    break;
10007	}
10008    }
10009
10010    return result;
10011}
10012#endif /* OPT_I18N_SUPPORT && OPT_INPUT_METHOD */
10013
10014static void
10015set_cursor_outline_gc(XtermWidget xw,
10016		      Bool filled,
10017		      Pixel fg,
10018		      Pixel bg,
10019		      Pixel cc)
10020{
10021    TScreen *screen = TScreenOf(xw);
10022    VTwin *win = WhichVWin(screen);
10023    CgsEnum cgsId = gcVTcursOutline;
10024
10025    if (cc == bg)
10026	cc = fg;
10027
10028    if (filled) {
10029	setCgsFore(xw, win, cgsId, bg);
10030	setCgsBack(xw, win, cgsId, cc);
10031    } else {
10032	setCgsFore(xw, win, cgsId, cc);
10033	setCgsBack(xw, win, cgsId, bg);
10034    }
10035}
10036
10037static Boolean
10038VTSetValues(Widget cur,
10039	    Widget request GCC_UNUSED,
10040	    Widget wnew,
10041	    ArgList args GCC_UNUSED,
10042	    Cardinal *num_args GCC_UNUSED)
10043{
10044    XtermWidget curvt = (XtermWidget) cur;
10045    XtermWidget newvt = (XtermWidget) wnew;
10046    Boolean refresh_needed = False;
10047    Boolean fonts_redone = False;
10048
10049    if ((T_COLOR(TScreenOf(curvt), TEXT_BG) !=
10050	 T_COLOR(TScreenOf(newvt), TEXT_BG)) ||
10051	(T_COLOR(TScreenOf(curvt), TEXT_FG) !=
10052	 T_COLOR(TScreenOf(newvt), TEXT_FG)) ||
10053	(TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) !=
10054	 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) ||
10055	strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
10056	if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
10057	    TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt);
10058	}
10059	if (xtermLoadFont(newvt,
10060			  xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)),
10061			  True, TScreenOf(newvt)->menu_font_number)) {
10062	    /* resizing does the redisplay, so don't ask for it here */
10063	    refresh_needed = True;
10064	    fonts_redone = True;
10065	} else if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
10066	    TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt);
10067	}
10068    }
10069    if (!fonts_redone
10070	&& (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) !=
10071	    T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) {
10072	if (set_cursor_gcs(newvt))
10073	    refresh_needed = True;
10074    }
10075    if (curvt->misc.re_verse != newvt->misc.re_verse) {
10076	newvt->flags ^= REVERSE_VIDEO;
10077	ReverseVideo(newvt);
10078	/* ReverseVideo toggles */
10079	newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse);
10080	refresh_needed = True;
10081    }
10082    if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) !=
10083	 T_COLOR(TScreenOf(newvt), MOUSE_FG)) ||
10084	(T_COLOR(TScreenOf(curvt), MOUSE_BG) !=
10085	 T_COLOR(TScreenOf(newvt), MOUSE_BG))) {
10086	recolor_cursor(TScreenOf(newvt),
10087		       TScreenOf(newvt)->pointer_cursor,
10088		       T_COLOR(TScreenOf(newvt), MOUSE_FG),
10089		       T_COLOR(TScreenOf(newvt), MOUSE_BG));
10090	refresh_needed = True;
10091    }
10092    if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
10093	ToggleScrollBar(newvt);
10094    }
10095
10096    return refresh_needed;
10097}
10098
10099/*
10100 * Given a font-slot and information about selection/reverse, find the
10101 * corresponding cached-GC slot.
10102 */
10103static int
10104reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font)
10105{
10106    TScreen *screen = TScreenOf(xw);
10107    CgsEnum result = gcMAX;
10108
10109    if (ReverseOrHilite(screen, attr_flags, hilite)) {
10110	switch (font) {
10111	case fNorm:
10112	    result = gcNormReverse;
10113	    break;
10114	case fBold:
10115	    result = gcBoldReverse;
10116	    break;
10117#if OPT_WIDE_ATTRS || OPT_RENDERWIDE
10118	case fItal:
10119	    result = gcNormReverse;	/* FIXME */
10120	    break;
10121#endif
10122#if OPT_WIDE_CHARS
10123	case fWide:
10124	    result = gcWideReverse;
10125	    break;
10126	case fWBold:
10127	    result = gcWBoldReverse;
10128	    break;
10129	case fWItal:
10130	    result = gcWideReverse;	/* FIXME */
10131	    break;
10132#endif
10133	}
10134    } else {
10135	switch (font) {
10136	case fNorm:
10137	    result = gcNorm;
10138	    break;
10139	case fBold:
10140	    result = gcBold;
10141	    break;
10142#if OPT_WIDE_ATTRS || OPT_RENDERWIDE
10143	case fItal:
10144	    result = gcNorm;	/* FIXME */
10145	    break;
10146#endif
10147#if OPT_WIDE_CHARS
10148	case fWide:
10149	    result = gcWide;
10150	    break;
10151	case fWBold:
10152	    result = gcWBold;
10153	    break;
10154	case fWItal:
10155	    result = gcWide;	/* FIXME */
10156	    break;
10157#endif
10158	}
10159    }
10160    return result;
10161}
10162
10163#define setGC(code) set_at = __LINE__, currentCgs = code
10164
10165#define OutsideSelection(screen,srow,scol)  \
10166	 ((srow) > (screen)->endH.row || \
10167	  ((srow) == (screen)->endH.row && \
10168	   (scol) >= (screen)->endH.col) || \
10169	  (srow) < (screen)->startH.row || \
10170	  ((srow) == (screen)->startH.row && \
10171	   (scol) < (screen)->startH.col))
10172
10173/*
10174 * Shows cursor at new cursor position in screen.
10175 */
10176void
10177ShowCursor(void)
10178{
10179    XtermWidget xw = term;
10180    TScreen *screen = TScreenOf(xw);
10181    IChar base;
10182    unsigned flags;
10183    CellColor fg_bg = 0;
10184    GC currentGC;
10185    GC outlineGC;
10186    CgsEnum currentCgs = gcMAX;
10187    VTwin *currentWin = WhichVWin(screen);
10188    int set_at;
10189    Bool in_selection;
10190    Bool reversed;
10191    Bool filled;
10192    Pixel fg_pix;
10193    Pixel bg_pix;
10194    Pixel tmp;
10195#if OPT_HIGHLIGHT_COLOR
10196    Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG);
10197    Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG);
10198    Boolean use_selbg;
10199    Boolean use_selfg;
10200#endif
10201#if OPT_WIDE_CHARS
10202    int my_col = 0;
10203#endif
10204    int cursor_col;
10205    CLineData *ld = 0;
10206
10207    if (screen->cursor_state == BLINKED_OFF)
10208	return;
10209
10210    if (screen->eventMode != NORMAL)
10211	return;
10212
10213    if (INX2ROW(screen, screen->cur_row) > screen->max_row)
10214	return;
10215
10216    screen->cursorp.row = screen->cur_row;
10217    cursor_col = screen->cursorp.col = screen->cur_col;
10218    screen->cursor_moved = False;
10219
10220#ifndef NO_ACTIVE_ICON
10221    if (IsIcon(screen)) {
10222	screen->cursor_state = ON;
10223	return;
10224    }
10225#endif /* NO_ACTIVE_ICON */
10226
10227    ld = getLineData(screen, screen->cur_row);
10228
10229    base = ld->charData[cursor_col];
10230    flags = ld->attribs[cursor_col];
10231
10232    if_OPT_WIDE_CHARS(screen, {
10233	if (base == HIDDEN_CHAR && cursor_col > 0) {
10234	    /* if cursor points to non-initial part of wide character,
10235	     * back it up
10236	     */
10237	    --cursor_col;
10238	    base = ld->charData[cursor_col];
10239	}
10240	my_col = cursor_col;
10241	if (base == 0)
10242	    base = ' ';
10243	if (isWide((int) base))
10244	    my_col += 1;
10245    });
10246
10247    if (base == 0) {
10248	base = ' ';
10249    }
10250#if OPT_ISO_COLORS
10251#ifdef EXP_BOGUS_FG
10252    /*
10253     * If the cursor happens to be on blanks, and we have not set both
10254     * foreground and background color, do not treat it as a colored cell.
10255     */
10256    if (base == ' ') {
10257	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
10258	    TRACE(("ShowCursor - do not treat as a colored cell\n"));
10259	    flags &= ~(FG_COLOR | BG_COLOR);
10260	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
10261	    TRACE(("ShowCursor - should we treat as a colored cell?\n"));
10262	    if (!(xw->flags & FG_COLOR))
10263		if (CheckBogusForeground(screen, "ShowCursor"))
10264		    flags &= ~(FG_COLOR | BG_COLOR);
10265	}
10266    }
10267#else /* !EXP_BOGUS_FG */
10268    /*
10269     * If the cursor happens to be on blanks, and the foreground color is set
10270     * but not the background, do not treat it as a colored cell.
10271     */
10272    if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR
10273	&& base == ' ') {
10274	flags &= ~TERM_COLOR_FLAGS(xw);
10275    }
10276#endif
10277#endif
10278
10279    /*
10280     * Compare the current cell to the last set of colors used for the
10281     * cursor and update the GC's if needed.
10282     */
10283    if_OPT_ISO_COLORS(screen, {
10284	fg_bg = ld->color[cursor_col];
10285    });
10286
10287    fg_pix = getXtermForeground(xw, flags, (int) extract_fg(xw, fg_bg, flags));
10288    bg_pix = getXtermBackground(xw, flags, (int) extract_bg(xw, fg_bg, flags));
10289
10290    /*
10291     * If we happen to have the same foreground/background colors, choose
10292     * a workable foreground color from which we can obtain a visible cursor.
10293     */
10294    if (fg_pix == bg_pix) {
10295	long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG));
10296	long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG));
10297	if (bg_diff < 0)
10298	    bg_diff = -bg_diff;
10299	if (fg_diff < 0)
10300	    fg_diff = -fg_diff;
10301	if (bg_diff < fg_diff) {
10302	    fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG);
10303	} else {
10304	    fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG);
10305	}
10306    }
10307
10308    if (OutsideSelection(screen, screen->cur_row, screen->cur_col))
10309	in_selection = False;
10310    else
10311	in_selection = True;
10312
10313    reversed = ReverseOrHilite(screen, flags, in_selection);
10314
10315    /* This is like updatedXtermGC(), except that we have to worry about
10316     * whether the window has focus, since in that case we want just an
10317     * outline for the cursor.
10318     */
10319    filled = (screen->select || screen->always_highlight) && isCursorBlock(screen);
10320#if OPT_HIGHLIGHT_COLOR
10321    use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix);
10322    use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix);
10323#endif
10324    if (filled) {
10325	if (reversed) {		/* text is reverse video */
10326	    if (getCgsGC(xw, currentWin, gcVTcursNormal)) {
10327		setGC(gcVTcursNormal);
10328	    } else {
10329		if (flags & BOLDATTR(screen)) {
10330		    setGC(gcBold);
10331		} else {
10332		    setGC(gcNorm);
10333		}
10334	    }
10335	    EXCHANGE(fg_pix, bg_pix, tmp);
10336#if OPT_HIGHLIGHT_COLOR
10337	    if (screen->hilite_reverse) {
10338		if (use_selbg && !use_selfg)
10339		    fg_pix = bg_pix;
10340		if (use_selfg && !use_selbg)
10341		    bg_pix = fg_pix;
10342		if (use_selbg)
10343		    bg_pix = selbg_pix;
10344		if (use_selfg)
10345		    fg_pix = selfg_pix;
10346	    }
10347#endif
10348	} else {		/* normal video */
10349	    if (getCgsGC(xw, currentWin, gcVTcursReverse)) {
10350		setGC(gcVTcursReverse);
10351	    } else {
10352		if (flags & BOLDATTR(screen)) {
10353		    setGC(gcBoldReverse);
10354		} else {
10355		    setGC(gcNormReverse);
10356		}
10357	    }
10358	}
10359
10360#define CUR_XX T_COLOR(screen, TEXT_CURSOR)
10361#define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
10362#define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
10363
10364#define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground))
10365#define FIX_328 (CUR_XX == bg_pix)
10366#define FIX_330 (FIX_328 && reversed && in_selection)
10367
10368	if (FIX_330 || FIX_311) {
10369	    setCgsBack(xw, currentWin, currentCgs, fg_pix);
10370	}
10371	setCgsFore(xw, currentWin, currentCgs, bg_pix);
10372    } else {			/* not selected */
10373	if (reversed) {		/* text is reverse video */
10374	    EXCHANGE(fg_pix, bg_pix, tmp);
10375	    setGC(gcNormReverse);
10376	} else {		/* normal video */
10377	    setGC(gcNorm);
10378	}
10379#if OPT_HIGHLIGHT_COLOR
10380	if (screen->hilite_reverse) {
10381	    if (in_selection && !reversed) {
10382		/* EMPTY */
10383		/* really INVERSE ... */
10384		;
10385	    } else if (in_selection || reversed) {
10386		if (use_selbg) {
10387		    if (use_selfg) {
10388			bg_pix = fg_pix;
10389		    } else {
10390			fg_pix = bg_pix;
10391		    }
10392		}
10393		if (use_selbg) {
10394		    bg_pix = selbg_pix;
10395		}
10396		if (use_selfg) {
10397		    fg_pix = selfg_pix;
10398		}
10399	    }
10400	} else {
10401	    if (in_selection) {
10402		if (use_selbg) {
10403		    bg_pix = selbg_pix;
10404		}
10405		if (use_selfg) {
10406		    fg_pix = selfg_pix;
10407		}
10408	    }
10409	}
10410#endif
10411	setCgsFore(xw, currentWin, currentCgs, fg_pix);
10412	setCgsBack(xw, currentWin, currentCgs, bg_pix);
10413    }
10414
10415    if (screen->cursor_busy == 0
10416	&& (screen->cursor_state != ON || screen->cursor_GC != set_at)) {
10417	int x, y;
10418
10419	screen->cursor_GC = set_at;
10420	TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n",
10421	       screen->cur_row, screen->cur_col,
10422	       (filled ? "filled" : "outline"),
10423	       (isCursorBlock(screen) ? "box" :
10424		isCursorUnderline(screen) ? "underline" : "bar"),
10425	       set_at));
10426
10427	currentGC = getCgsGC(xw, currentWin, currentCgs);
10428	x = LineCursorX(screen, ld, cursor_col);
10429	y = CursorY(screen, screen->cur_row);
10430
10431	if (!isCursorBlock(screen)) {
10432	    /*
10433	     * Overriding the combination of filled, reversed, in_selection is
10434	     * too complicated since the underline or bar and the text-cell use
10435	     * different rules.  Just redraw the text-cell, and draw the
10436	     * underline or bar on top of it.
10437	     */
10438	    HideCursor();
10439
10440	    /*
10441	     * Our current-GC is likely to have been modified in HideCursor().
10442	     * Set up a new request.
10443	     */
10444	    if (filled) {
10445		if (FIX_330 || FIX_311) {
10446		    setCgsBack(xw, currentWin, currentCgs, fg_pix);
10447		}
10448		setCgsFore(xw, currentWin, currentCgs, bg_pix);
10449	    } else {
10450		setCgsFore(xw, currentWin, currentCgs, fg_pix);
10451		setCgsBack(xw, currentWin, currentCgs, bg_pix);
10452	    }
10453	}
10454
10455	/*
10456	 * Update the outline-gc, to keep the cursor color distinct from the
10457	 * background color.
10458	 */
10459	set_cursor_outline_gc(xw,
10460			      filled,
10461			      fg_pix,
10462			      bg_pix,
10463			      T_COLOR(screen, TEXT_CURSOR));
10464
10465	outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline);
10466	if (outlineGC == 0)
10467	    outlineGC = currentGC;
10468
10469	if (isCursorUnderline(screen)) {
10470
10471	    /*
10472	     * Finally, draw the underline.
10473	     */
10474	    screen->box->x = (short) x;
10475	    screen->box->y = (short) (y + FontHeight(screen) - 2);
10476	    XDrawLines(screen->display, VDrawable(screen), outlineGC,
10477		       screen->box, NBOX, CoordModePrevious);
10478	} else if (isCursorBar(screen)) {
10479
10480	    /*
10481	     * Or draw the bar.
10482	     */
10483	    screen->box->x = (short) x;
10484	    screen->box->y = (short) y;
10485	    XDrawLines(screen->display, VWindow(screen), outlineGC,
10486		       screen->box, NBOX, CoordModePrevious);
10487	} else {
10488#if OPT_WIDE_ATTRS
10489	    int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0);
10490	    int italics_off = ((xw->flags & ATR_ITALIC) != 0);
10491	    int fix_italics = (italics_on != italics_off);
10492	    int which_font = ((xw->flags & BOLD) ? fBold : fNorm);
10493
10494	    if_OPT_WIDE_CHARS(screen, {
10495		if (isWide((int) base)) {
10496		    which_font = ((xw->flags & BOLD) ? fWBold : fWide);
10497		}
10498	    });
10499
10500	    if (fix_italics && UseItalicFont(screen)) {
10501		xtermLoadItalics(xw);
10502		if (italics_on) {
10503		    setCgsFont(xw, currentWin, currentCgs,
10504			       getItalicFont(screen, which_font));
10505		} else {
10506		    setCgsFont(xw, currentWin, currentCgs,
10507			       getNormalFont(screen, which_font));
10508		}
10509	    }
10510	    currentGC = getCgsGC(xw, currentWin, currentCgs);
10511#endif /* OPT_WIDE_ATTRS */
10512
10513	    drawXtermText(xw,
10514			  flags & DRAWX_MASK,
10515			  0,
10516			  currentGC, x, y,
10517			  LineCharSet(screen, ld),
10518			  &base, 1, 0);
10519
10520#if OPT_WIDE_CHARS
10521	    if_OPT_WIDE_CHARS(screen, {
10522		size_t off;
10523		for_each_combData(off, ld) {
10524		    if (!(ld->combData[off][my_col]))
10525			break;
10526		    drawXtermText(xw,
10527				  (flags & DRAWX_MASK),
10528				  NOBACKGROUND,
10529				  currentGC, x, y,
10530				  LineCharSet(screen, ld),
10531				  ld->combData[off] + my_col,
10532				  1, isWide((int) base));
10533		}
10534	    });
10535#endif
10536
10537	    if (!filled) {
10538		screen->box->x = (short) x;
10539		screen->box->y = (short) y;
10540		XDrawLines(screen->display, VDrawable(screen), outlineGC,
10541			   screen->box, NBOX, CoordModePrevious);
10542	    }
10543#if OPT_WIDE_ATTRS
10544	    if (fix_italics && UseItalicFont(screen)) {
10545		if (italics_on) {
10546		    setCgsFont(xw, currentWin, currentCgs,
10547			       getNormalFont(screen, which_font));
10548		} else {
10549		    setCgsFont(xw, currentWin, currentCgs,
10550			       getItalicFont(screen, which_font));
10551		}
10552	    }
10553#endif
10554	}
10555    }
10556    screen->cursor_state = ON;
10557
10558    return;
10559}
10560
10561/*
10562 * hide cursor at previous cursor position in screen.
10563 */
10564void
10565HideCursor(void)
10566{
10567    XtermWidget xw = term;
10568    TScreen *screen = TScreenOf(xw);
10569    GC currentGC;
10570    int x, y;
10571    IChar base;
10572    unsigned flags;
10573    CellColor fg_bg = 0;
10574    Bool in_selection;
10575#if OPT_WIDE_CHARS
10576    int my_col = 0;
10577#endif
10578    int cursor_col;
10579    CLineData *ld = 0;
10580#if OPT_WIDE_ATTRS
10581    int which_Cgs = gcMAX;
10582    unsigned attr_flags;
10583    int which_font = fNorm;
10584#endif
10585
10586    if (screen->cursor_state == OFF)
10587	return;
10588    if (INX2ROW(screen, screen->cursorp.row) > screen->max_row)
10589	return;
10590
10591    cursor_col = screen->cursorp.col;
10592
10593#ifndef NO_ACTIVE_ICON
10594    if (IsIcon(screen)) {
10595	screen->cursor_state = OFF;
10596	return;
10597    }
10598#endif /* NO_ACTIVE_ICON */
10599
10600    ld = getLineData(screen, screen->cursorp.row);
10601
10602    base = ld->charData[cursor_col];
10603    flags = ld->attribs[cursor_col];
10604
10605    if_OPT_WIDE_CHARS(screen, {
10606	if (base == HIDDEN_CHAR && cursor_col > 0) {
10607	    /* if cursor points to non-initial part of wide character,
10608	     * back it up
10609	     */
10610	    --cursor_col;
10611	    base = ld->charData[cursor_col];
10612	}
10613	my_col = cursor_col;
10614	if (base == 0)
10615	    base = ' ';
10616	if (isWide((int) base))
10617	    my_col += 1;
10618    });
10619
10620    if (base == 0) {
10621	base = ' ';
10622    }
10623#ifdef EXP_BOGUS_FG
10624    /*
10625     * If the cursor happens to be on blanks, and we have not set both
10626     * foreground and background color, do not treat it as a colored cell.
10627     */
10628#if OPT_ISO_COLORS
10629    if (base == ' ') {
10630	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
10631	    TRACE(("HideCursor - do not treat as a colored cell\n"));
10632	    flags &= ~(FG_COLOR | BG_COLOR);
10633	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
10634	    TRACE(("HideCursor - should we treat as a colored cell?\n"));
10635	    if (!(xw->flags & FG_COLOR))
10636		if (CheckBogusForeground(screen, "HideCursor"))
10637		    flags &= ~(FG_COLOR | BG_COLOR);
10638	}
10639    }
10640#endif
10641#endif
10642#if OPT_ISO_COLORS
10643    fg_bg = 0;
10644#endif
10645
10646    /*
10647     * Compare the current cell to the last set of colors used for the
10648     * cursor and update the GC's if needed.
10649     */
10650    if_OPT_ISO_COLORS(screen, {
10651	fg_bg = ld->color[cursor_col];
10652    });
10653
10654    if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col))
10655	in_selection = False;
10656    else
10657	in_selection = True;
10658
10659#if OPT_WIDE_ATTRS
10660    attr_flags = ld->attribs[cursor_col];
10661    if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) {
10662	which_font = ((attr_flags & BOLD) ? fBold : fNorm);
10663
10664	if_OPT_WIDE_CHARS(screen, {
10665	    if (isWide((int) base)) {
10666		which_font = ((attr_flags & BOLD) ? fWBold : fWide);
10667	    }
10668	});
10669
10670	which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font);
10671	if (which_Cgs != gcMAX) {
10672	    setCgsFont(xw, WhichVWin(screen),
10673		       (CgsEnum) which_Cgs,
10674		       (((attr_flags & ATR_ITALIC) && UseItalicFont(screen))
10675			? getItalicFont(screen, which_font)
10676			: getNormalFont(screen, which_font)));
10677	}
10678    }
10679#endif
10680
10681    currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection);
10682
10683    TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n",
10684	   screen->cursorp.row, screen->cursorp.col));
10685
10686    x = LineCursorX(screen, ld, cursor_col);
10687    y = CursorY(screen, screen->cursorp.row);
10688
10689    drawXtermText(xw,
10690		  flags & DRAWX_MASK,
10691		  0,
10692		  currentGC, x, y,
10693		  LineCharSet(screen, ld),
10694		  &base, 1, 0);
10695
10696#if OPT_WIDE_CHARS
10697    if_OPT_WIDE_CHARS(screen, {
10698	size_t off;
10699	for_each_combData(off, ld) {
10700	    if (!(ld->combData[off][my_col]))
10701		break;
10702	    drawXtermText(xw,
10703			  (flags & DRAWX_MASK),
10704			  NOBACKGROUND,
10705			  currentGC, x, y,
10706			  LineCharSet(screen, ld),
10707			  ld->combData[off] + my_col,
10708			  1, isWide((int) base));
10709	}
10710    });
10711#endif
10712    screen->cursor_state = OFF;
10713
10714#if OPT_WIDE_ATTRS
10715    if (which_Cgs != gcMAX) {
10716	setCgsFont(xw, WhichVWin(screen),
10717		   (CgsEnum) which_Cgs,
10718		   (((xw->flags & ATR_ITALIC) && UseItalicFont(screen))
10719		    ? getItalicFont(screen, which_font)
10720		    : getNormalFont(screen, which_font)));
10721    }
10722#endif
10723    resetXtermGC(xw, flags, in_selection);
10724
10725    refresh_displayed_graphics(xw,
10726			       screen->cursorp.col,
10727			       screen->cursorp.row,
10728			       1, 1);
10729
10730    return;
10731}
10732
10733#if OPT_BLINK_CURS || OPT_BLINK_TEXT
10734static void
10735StartBlinking(TScreen *screen)
10736{
10737    if (screen->blink_timer == 0) {
10738	unsigned long interval = (unsigned long) ((screen->cursor_state == ON)
10739						  ? screen->blink_on
10740						  : screen->blink_off);
10741	if (interval == 0)	/* wow! */
10742	    interval = 1;	/* let's humor him anyway */
10743	screen->blink_timer = XtAppAddTimeOut(app_con,
10744					      interval,
10745					      HandleBlinking,
10746					      screen);
10747    }
10748}
10749
10750static void
10751StopBlinking(TScreen *screen)
10752{
10753    if (screen->blink_timer) {
10754	XtRemoveTimeOut(screen->blink_timer);
10755	screen->blink_timer = 0;
10756	reallyStopBlinking(screen);
10757    } else {
10758	screen->blink_timer = 0;
10759    }
10760}
10761
10762#if OPT_BLINK_TEXT
10763Bool
10764LineHasBlinking(TScreen *screen, CLineData *ld)
10765{
10766    Bool result = False;
10767    if (ld != 0) {
10768	int col;
10769
10770	for (col = 0; col < MaxCols(screen); ++col) {
10771	    if (ld->attribs[col] & BLINK) {
10772		result = True;
10773		break;
10774	    }
10775	}
10776    }
10777    return result;
10778}
10779#endif
10780
10781/*
10782 * Blink the cursor by alternately showing/hiding cursor.  We leave the timer
10783 * running all the time (even though that's a little inefficient) to make the
10784 * logic simple.
10785 */
10786static void
10787HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED)
10788{
10789    TScreen *screen = (TScreen *) closure;
10790    Bool resume = False;
10791
10792    screen->blink_timer = 0;
10793    screen->blink_state = !screen->blink_state;
10794
10795#if OPT_BLINK_CURS
10796    if (DoStartBlinking(screen)) {
10797	if (screen->cursor_state == ON) {
10798	    if (screen->select || screen->always_highlight) {
10799		HideCursor();
10800		if (screen->cursor_state == OFF)
10801		    screen->cursor_state = BLINKED_OFF;
10802	    }
10803	} else if (screen->cursor_state == BLINKED_OFF) {
10804	    screen->cursor_state = OFF;
10805	    ShowCursor();
10806	    if (screen->cursor_state == OFF)
10807		screen->cursor_state = BLINKED_OFF;
10808	}
10809	resume = True;
10810    }
10811#endif
10812
10813#if OPT_BLINK_TEXT
10814    /*
10815     * Inspect the lines on the current screen to see if any have the BLINK flag
10816     * associated with them.  Prune off any that have had the corresponding
10817     * cells reset.  If any are left, repaint those lines with ScrnRefresh().
10818     */
10819    if (!(screen->blink_as_bold)) {
10820	int row;
10821	int first_row = screen->max_row;
10822	int last_row = -1;
10823
10824	for (row = screen->max_row; row >= 0; row--) {
10825	    LineData *ld = getLineData(screen, ROW2INX(screen, row));
10826
10827	    if (ld != 0 && LineTstBlinked(ld)) {
10828		if (LineHasBlinking(screen, ld)) {
10829		    resume = True;
10830		    if (row > last_row)
10831			last_row = row;
10832		    if (row < first_row)
10833			first_row = row;
10834		} else {
10835		    LineClrBlinked(ld);
10836		}
10837	    }
10838	}
10839	/*
10840	 * FIXME: this could be a little more efficient, e.g,. by limiting the
10841	 * columns which are updated.
10842	 */
10843	if (first_row <= last_row) {
10844	    ScrnRefresh(term,
10845			first_row,
10846			0,
10847			last_row + 1 - first_row,
10848			MaxCols(screen),
10849			True);
10850	}
10851    }
10852#endif
10853
10854    /*
10855     * If either the cursor or text is blinking, restart the timer.
10856     */
10857    if (resume)
10858	StartBlinking(screen);
10859}
10860#endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */
10861
10862void
10863RestartBlinking(TScreen *screen GCC_UNUSED)
10864{
10865#if OPT_BLINK_CURS || OPT_BLINK_TEXT
10866    if (screen->blink_timer == 0) {
10867	Bool resume = False;
10868
10869#if OPT_BLINK_CURS
10870	if (DoStartBlinking(screen)) {
10871	    resume = True;
10872	}
10873#endif
10874#if OPT_BLINK_TEXT
10875	if (!resume) {
10876	    int row;
10877
10878	    for (row = screen->max_row; row >= 0; row--) {
10879		CLineData *ld = getLineData(screen, ROW2INX(screen, row));
10880
10881		if (ld != 0 && LineTstBlinked(ld)) {
10882		    if (LineHasBlinking(screen, ld)) {
10883			resume = True;
10884			break;
10885		    }
10886		}
10887	    }
10888	}
10889#endif
10890	if (resume)
10891	    StartBlinking(screen);
10892    }
10893#endif
10894}
10895
10896/*
10897 * Implement soft or hard (full) reset of the VTxxx emulation.  There are a
10898 * couple of differences from real DEC VTxxx terminals (to avoid breaking
10899 * applications which have come to rely on xterm doing this):
10900 *
10901 *	+ autowrap mode should be reset (instead it's reset to the resource
10902 *	  default).
10903 *	+ the popup menu offers a choice of resetting the savedLines, or not.
10904 *	  (but the control sequence does this anyway).
10905 */
10906static void
10907ReallyReset(XtermWidget xw, Bool full, Bool saved)
10908{
10909    TScreen *screen = TScreenOf(xw);
10910
10911    if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) {
10912	Bell(xw, XkbBI_MinorError, 0);
10913	return;
10914    }
10915
10916    if (saved) {
10917	screen->savedlines = 0;
10918	ScrollBarDrawThumb(screen->scrollWidget);
10919    }
10920
10921    /* make cursor visible */
10922    screen->cursor_set = ON;
10923    InitCursorShape(screen, screen);
10924#if OPT_BLINK_CURS
10925    TRACE(("cursor_shape:%d blinks:%s\n",
10926	   screen->cursor_shape,
10927	   BtoS(screen->cursor_blink)));
10928#endif
10929
10930    /* reset scrolling region */
10931    reset_margins(screen);
10932
10933    bitclr(&xw->flags, ORIGIN);
10934
10935    if_OPT_ISO_COLORS(screen, {
10936	static char empty[1];
10937	reset_SGR_Colors(xw);
10938	if (ResetAnsiColorRequest(xw, empty, 0))
10939	    xtermRepaint(xw);
10940    });
10941
10942    /* Reset character-sets to initial state */
10943    resetCharsets(screen);
10944
10945#if OPT_MOD_FKEYS
10946    /* Reset modifier-resources to initial state */
10947    xw->keyboard.modify_now = xw->keyboard.modify_1st;
10948#endif
10949
10950    /* Reset DECSCA */
10951    bitclr(&xw->flags, PROTECTED);
10952    screen->protected_mode = OFF_PROTECT;
10953
10954    reset_displayed_graphics(screen);
10955
10956    if (full) {			/* RIS */
10957	if (screen->bellOnReset)
10958	    Bell(xw, XkbBI_TerminalBell, 0);
10959
10960	/* reset the mouse mode */
10961	screen->send_mouse_pos = MOUSE_OFF;
10962	screen->send_focus_pos = OFF;
10963	screen->extend_coords = 0;
10964	screen->waitingForTrackInfo = False;
10965	screen->eventMode = NORMAL;
10966
10967	xtermShowPointer(xw, True);
10968
10969	TabReset(xw->tabs);
10970	xw->keyboard.flags = MODE_SRM;
10971
10972	guard_keyboard_type = False;
10973	screen->old_fkeys = screen->old_fkeys0;
10974	decode_keyboard_type(xw, &resource);
10975	update_keyboard_type();
10976
10977#if OPT_INITIAL_ERASE
10978	if (xw->keyboard.reset_DECBKM == 1)
10979	    xw->keyboard.flags |= MODE_DECBKM;
10980	else if (xw->keyboard.reset_DECBKM == 2)
10981#endif
10982	    if (TScreenOf(xw)->backarrow_key)
10983		xw->keyboard.flags |= MODE_DECBKM;
10984	TRACE(("full reset DECBKM %s\n",
10985	       BtoS(xw->keyboard.flags & MODE_DECBKM)));
10986
10987#if OPT_SCROLL_LOCK
10988	xtermClearLEDs(screen);
10989#endif
10990	screen->title_modes = screen->title_modes0;
10991	screen->pointer_mode = screen->pointer_mode0;
10992#if OPT_SIXEL_GRAPHICS
10993	if (TScreenOf(xw)->sixel_scrolling)
10994	    xw->keyboard.flags |= MODE_DECSDM;
10995	TRACE(("full reset DECSDM to %s (resource default is %s)\n",
10996	       BtoS(xw->keyboard.flags & MODE_DECSDM),
10997	       BtoS(TScreenOf(xw)->sixel_scrolling)));
10998#endif
10999
11000#if OPT_GRAPHICS
11001	screen->privatecolorregisters = TScreenOf(xw)->privatecolorregisters;
11002	TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n",
11003	       BtoS(screen->privatecolorregisters),
11004	       BtoS(TScreenOf(xw)->privatecolorregisters)));
11005#endif
11006
11007#if OPT_SIXEL_GRAPHICS
11008	screen->sixel_scrolls_right = TScreenOf(xw)->sixel_scrolls_right;
11009	TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n",
11010	       BtoS(screen->sixel_scrolls_right),
11011	       BtoS(TScreenOf(xw)->sixel_scrolls_right)));
11012#endif
11013
11014	update_appcursor();
11015	update_appkeypad();
11016	update_decbkm();
11017	update_decsdm();
11018	show_8bit_control(False);
11019	reset_decudk(xw);
11020
11021	FromAlternate(xw);
11022	ClearScreen(xw);
11023	screen->cursor_state = OFF;
11024	if (xw->flags & REVERSE_VIDEO)
11025	    ReverseVideo(xw);
11026
11027	xw->flags = xw->initflags;
11028	update_reversevideo();
11029	update_autowrap();
11030	update_reversewrap();
11031	update_autolinefeed();
11032
11033	screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL));
11034	update_jumpscroll();
11035
11036#if OPT_DEC_RECTOPS
11037	screen->cur_decsace = 0;
11038#endif
11039#if OPT_READLINE
11040	screen->click1_moves = OFF;
11041	screen->paste_moves = OFF;
11042	screen->dclick3_deletes = OFF;
11043	screen->paste_brackets = OFF;
11044	screen->paste_quotes = OFF;
11045	screen->paste_literal_nl = OFF;
11046#endif /* OPT_READLINE */
11047
11048	if (screen->c132 && (xw->flags & IN132COLUMNS)) {
11049	    Dimension reqWidth = (Dimension) (80 * FontWidth(screen)
11050					      + 2 * screen->border
11051					      + ScrollbarWidth(screen));
11052	    Dimension reqHeight = (Dimension) (FontHeight(screen)
11053					       * MaxRows(screen)
11054					       + 2 * screen->border);
11055	    Dimension replyWidth;
11056	    Dimension replyHeight;
11057
11058	    TRACE(("Making resize-request to restore 80-columns %dx%d\n",
11059		   reqHeight, reqWidth));
11060	    REQ_RESIZE((Widget) xw,
11061		       reqWidth,
11062		       reqHeight,
11063		       &replyWidth, &replyHeight);
11064	    repairSizeHints();
11065	    XSync(screen->display, False);	/* synchronize */
11066	    if (xtermAppPending())
11067		xevents();
11068	}
11069
11070	CursorSet(screen, 0, 0, xw->flags);
11071	CursorSave(xw);
11072    } else {			/* DECSTR */
11073	/*
11074	 * There's a tiny difference, to accommodate usage of xterm.
11075	 * We reset autowrap to the resource values rather than turning
11076	 * it off.
11077	 */
11078	UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM));
11079	bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP);
11080	bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE);
11081	if_OPT_ISO_COLORS(screen, {
11082	    reset_SGR_Colors(xw);
11083	});
11084	update_appcursor();
11085	update_autowrap();
11086	update_reversewrap();
11087
11088	CursorSave(xw);
11089	screen->sc[screen->whichBuf].row =
11090	    screen->sc[screen->whichBuf].col = 0;
11091    }
11092}
11093
11094void
11095VTReset(XtermWidget xw, Bool full, Bool saved)
11096{
11097    ReallyReset(xw, full, saved);
11098    longjmp(vtjmpbuf, 1);	/* force ground state in parser */
11099}
11100
11101typedef enum {
11102    ccLO,
11103    ccDASH,
11104    ccHI,
11105    ccCOLON,
11106    ccID,
11107    ccCOMMA
11108} CCLASS;
11109
11110/*
11111 * set_character_class - takes a string of the form
11112 *
11113 *   low[-high][:id][,low[-high][:id][...]]
11114 *
11115 * and sets the indicated ranges to the indicated values.
11116 */
11117static int
11118set_character_class(char *s)
11119{
11120#define FMT "%s in range string \"%s\" (position %d)\n"
11121
11122    TRACE(("set_character_class(%s) {{\n", NonNull(s)));
11123    if (IsEmpty(s)) {
11124	return -1;
11125    } else {
11126	CCLASS state = ccLO;
11127	int arg[3];
11128	int i;
11129	int len = (int) strlen(s);
11130
11131	arg[0] =
11132	    arg[1] =
11133	    arg[2] = -1;
11134
11135	for (i = 0; i < len; ++i) {
11136	    int ch = CharOf(s[i]);
11137	    char *t = 0;
11138	    long value = 0;
11139
11140	    if (isspace(ch))
11141		continue;
11142
11143	    switch (state) {
11144	    case ccLO:
11145	    case ccHI:
11146	    case ccID:
11147		if (!isdigit(ch)) {
11148		    xtermWarning(FMT, "missing number", s, i);
11149		    return (-1);
11150		}
11151		value = strtol(s + i, &t, 0);
11152		i = (int) (t - s - 1);
11153		break;
11154	    case ccDASH:
11155	    case ccCOLON:
11156	    case ccCOMMA:
11157		break;
11158	    }
11159
11160	    switch (state) {
11161	    case ccLO:
11162		arg[0] =
11163		    arg[1] = (int) value;
11164		arg[2] = -1;
11165		state = ccDASH;
11166		break;
11167
11168	    case ccDASH:
11169		if (ch == '-') {
11170		    state = ccHI;
11171		} else {
11172		    goto parse_class;
11173		}
11174		break;
11175
11176	    case ccHI:
11177		arg[1] = (int) value;
11178		state = ccCOLON;
11179		break;
11180
11181	      parse_class:
11182	    case ccCOLON:
11183		if (ch == ':') {
11184		    state = ccID;
11185		} else if (ch == ',') {
11186		    goto apply_class;
11187		} else {
11188		    xtermWarning(FMT, "unexpected character", s, i);
11189		    return (-1);
11190		}
11191		break;
11192
11193	    case ccID:
11194		arg[2] = (int) value;
11195		state = ccCOMMA;
11196		break;
11197
11198	      apply_class:
11199	    case ccCOMMA:
11200		if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
11201		    xtermWarning(FMT, "bad range", s, i);
11202		    return -1;
11203		}
11204		state = ccLO;
11205		break;
11206	    }
11207	}
11208	if (state >= ccDASH) {
11209	    if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
11210		xtermWarning(FMT, "bad range", s, i);
11211		return -1;
11212	    }
11213	}
11214    }
11215
11216    TRACE(("}} set_character_class\n"));
11217    return (0);
11218#undef FMT
11219}
11220
11221void
11222getKeymapResources(Widget w,
11223		   const char *mapName,
11224		   const char *mapClass,
11225		   const char *type,
11226		   void *result,
11227		   size_t size)
11228{
11229    XtResource key_resources[1];
11230    key_resources[0].resource_name = XtNtranslations;
11231    key_resources[0].resource_class = XtCTranslations;
11232    key_resources[0].resource_type = (char *) type;
11233    key_resources[0].resource_size = (Cardinal) size;
11234    key_resources[0].resource_offset = 0;
11235    key_resources[0].default_type = key_resources[0].resource_type;
11236    key_resources[0].default_addr = 0;
11237    XtGetSubresources(w, (XtPointer) result, mapName, mapClass,
11238		      key_resources, (Cardinal) 1, NULL, (Cardinal) 0);
11239}
11240
11241/* ARGSUSED */
11242static void
11243HandleKeymapChange(Widget w,
11244		   XEvent *event GCC_UNUSED,
11245		   String *params,
11246		   Cardinal *param_count)
11247{
11248    static XtTranslations keymap, original;
11249
11250    TRACE(("HandleKeymapChange(%#lx, %s)\n",
11251	   (unsigned long) w,
11252	   (*param_count
11253	    ? params[0]
11254	    : "missing")));
11255
11256    if (*param_count != 1)
11257	return;
11258
11259    if (original == NULL) {
11260	TRACE(("...saving original keymap-translations\n"));
11261	original = w->core.tm.translations;
11262    }
11263
11264    if (strcmp(params[0], "None") == 0) {
11265	TRACE(("...restoring original keymap-translations\n"));
11266	XtOverrideTranslations(w, original);
11267    } else {
11268	char mapName[1000];
11269	char mapClass[1000];
11270	char *pmapName;
11271	char *pmapClass;
11272	size_t len;
11273
11274	len = strlen(params[0]) + 7;
11275
11276	pmapName = (char *) MyStackAlloc(len, mapName);
11277	pmapClass = (char *) MyStackAlloc(len, mapClass);
11278	if (pmapName == NULL
11279	    || pmapClass == NULL) {
11280	    SysError(ERROR_KMMALLOC1);
11281	} else {
11282
11283	    (void) sprintf(pmapName, "%sKeymap", params[0]);
11284	    (void) strcpy(pmapClass, pmapName);
11285	    if (islower(CharOf(pmapClass[0])))
11286		pmapClass[0] = x_toupper(pmapClass[0]);
11287	    getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable,
11288			       &keymap, sizeof(keymap));
11289	    if (keymap != NULL) {
11290		TRACE(("...applying keymap \"%s\"\n", pmapName));
11291		XtOverrideTranslations(w, keymap);
11292	    } else {
11293		TRACE(("...found no match for keymap \"%s\"\n", pmapName));
11294	    }
11295
11296	    MyStackFree(pmapName, mapName);
11297	    MyStackFree(pmapClass, mapClass);
11298	}
11299    }
11300}
11301
11302/* ARGSUSED */
11303static void
11304HandleBell(Widget w GCC_UNUSED,
11305	   XEvent *event GCC_UNUSED,
11306	   String *params,	/* [0] = volume */
11307	   Cardinal *param_count)	/* 0 or 1 */
11308{
11309    int percent = (*param_count) ? atoi(params[0]) : 0;
11310
11311    Bell(term, XkbBI_TerminalBell, percent);
11312}
11313
11314/* ARGSUSED */
11315static void
11316HandleVisualBell(Widget w GCC_UNUSED,
11317		 XEvent *event GCC_UNUSED,
11318		 String *params GCC_UNUSED,
11319		 Cardinal *param_count GCC_UNUSED)
11320{
11321    VisualBell();
11322}
11323
11324/* ARGSUSED */
11325static void
11326HandleIgnore(Widget w,
11327	     XEvent *event,
11328	     String *params GCC_UNUSED,
11329	     Cardinal *param_count GCC_UNUSED)
11330{
11331    XtermWidget xw;
11332
11333    TRACE(("Handle ignore for %p %s\n",
11334	   (void *) w, visibleEventType(event->type)));
11335    if ((xw = getXtermWidget(w)) != 0) {
11336	/* do nothing, but check for funny escape sequences */
11337	(void) SendMousePosition(xw, event);
11338    }
11339}
11340
11341/* ARGSUSED */
11342static void
11343DoSetSelectedFont(Widget w,
11344		  XtPointer client_data GCC_UNUSED,
11345		  Atom *selection GCC_UNUSED,
11346		  Atom *type,
11347		  XtPointer value,
11348		  unsigned long *length,
11349		  int *format)
11350{
11351    XtermWidget xw = getXtermWidget(w);
11352
11353    if (xw == 0) {
11354	xtermWarning("unexpected widget in DoSetSelectedFont\n");
11355    } else if (*type != XA_STRING || *format != 8) {
11356	Bell(xw, XkbBI_MinorError, 0);
11357    } else {
11358	Boolean failed = False;
11359	int oldFont = TScreenOf(xw)->menu_font_number;
11360	char *save = TScreenOf(xw)->SelectFontName();
11361	char *val;
11362	char *test = 0;
11363	unsigned len = (unsigned) *length;
11364	unsigned tst;
11365
11366	/*
11367	 * Some versions of X deliver null-terminated selections, some do not.
11368	 */
11369	for (tst = 0; tst < len; ++tst) {
11370	    if (((char *) value)[tst] == '\0') {
11371		len = tst;
11372		break;
11373	    }
11374	}
11375
11376	if (len > 0 && (val = TypeMallocN(char, len + 1)) != 0) {
11377	    char *used;
11378
11379	    memcpy(val, value, (size_t) len);
11380	    val[len] = '\0';
11381	    used = x_strtrim(val);
11382	    TRACE(("DoSetSelectedFont(%s)\n", used));
11383	    /* Do some sanity checking to avoid sending a long selection
11384	       back to the server in an OpenFont that is unlikely to succeed.
11385	       XLFD allows up to 255 characters and no control characters;
11386	       we are a little more liberal here. */
11387	    if (len < 1000
11388		&& used != 0
11389		&& !strchr(used, '\n')
11390		&& (test = x_strdup(used)) != 0) {
11391		TScreenOf(xw)->SelectFontName() = test;
11392		if (!xtermLoadFont(term,
11393				   xtermFontName(used),
11394				   True,
11395				   fontMenu_fontsel)) {
11396		    failed = True;
11397		    free(test);
11398		    TScreenOf(xw)->SelectFontName() = save;
11399		}
11400	    } else {
11401		failed = True;
11402	    }
11403	    if (failed) {
11404		(void) xtermLoadFont(term,
11405				     xtermFontName(TScreenOf(xw)->MenuFontName(oldFont)),
11406				     True,
11407				     oldFont);
11408		Bell(xw, XkbBI_MinorError, 0);
11409	    }
11410	    free(used);
11411	    free(val);
11412	}
11413    }
11414}
11415
11416void
11417FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe)
11418{
11419    TScreen *screen = TScreenOf(xw);
11420    static AtomPtr *atoms;
11421    static unsigned int atomCount = 0;
11422    AtomPtr *pAtom;
11423    unsigned a;
11424    Atom target;
11425
11426    if (!atom_name)
11427	atom_name = ((screen->mappedSelect && atomCount)
11428		     ? screen->mappedSelect[0]
11429		     : "PRIMARY");
11430    TRACE(("FindFontSelection(%s)\n", atom_name));
11431
11432    for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
11433	if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) {
11434	    TRACE(("...found atom %d:%s\n", a + 1, atom_name));
11435	    break;
11436	}
11437    }
11438    if (!a) {
11439	atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1);
11440	*(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name);
11441	++atomCount;
11442	TRACE(("...added atom %d:%s\n", atomCount, atom_name));
11443    }
11444
11445    target = XmuInternAtom(XtDisplay(xw), *pAtom);
11446    if (justprobe) {
11447	screen->SelectFontName() =
11448	    XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : 0;
11449	TRACE(("...selected fontname '%s'\n",
11450	       NonNull(screen->SelectFontName())));
11451    } else {
11452	XtGetSelectionValue((Widget) xw, target, XA_STRING,
11453			    DoSetSelectedFont, NULL,
11454			    XtLastTimestampProcessed(XtDisplay(xw)));
11455    }
11456    return;
11457}
11458
11459Bool
11460set_cursor_gcs(XtermWidget xw)
11461{
11462    TScreen *screen = TScreenOf(xw);
11463    VTwin *win = WhichVWin(screen);
11464
11465    Pixel cc = T_COLOR(screen, TEXT_CURSOR);
11466    Pixel fg = T_COLOR(screen, TEXT_FG);
11467    Pixel bg = T_COLOR(screen, TEXT_BG);
11468    Bool changed = False;
11469
11470    /*
11471     * Let's see, there are three things that have "color":
11472     *
11473     *     background
11474     *     text
11475     *     cursorblock
11476     *
11477     * And, there are four situations when drawing a cursor, if we decide
11478     * that we like have a solid block of cursor color with the letter
11479     * that it is highlighting shown in the background color to make it
11480     * stand out:
11481     *
11482     *     selected window, normal video - background on cursor
11483     *     selected window, reverse video - foreground on cursor
11484     *     unselected window, normal video - foreground on background
11485     *     unselected window, reverse video - background on foreground
11486     *
11487     * Since the last two are really just normalGC and reverseGC, we only
11488     * need two new GC's.  Under monochrome, we get the same effect as
11489     * above by setting cursor color to foreground.
11490     */
11491
11492    TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg));
11493    if (win != 0 && (cc != bg)) {
11494	/* set the fonts to the current one */
11495	setCgsFont(xw, win, gcVTcursNormal, 0);
11496	setCgsFont(xw, win, gcVTcursFilled, 0);
11497	setCgsFont(xw, win, gcVTcursReverse, 0);
11498	setCgsFont(xw, win, gcVTcursOutline, 0);
11499
11500	/* we have a colored cursor */
11501	setCgsFore(xw, win, gcVTcursNormal, fg);
11502	setCgsBack(xw, win, gcVTcursNormal, cc);
11503
11504	setCgsFore(xw, win, gcVTcursFilled, cc);
11505	setCgsBack(xw, win, gcVTcursFilled, fg);
11506
11507	if (screen->always_highlight) {
11508	    /* both GC's use the same color */
11509	    setCgsFore(xw, win, gcVTcursReverse, bg);
11510	    setCgsBack(xw, win, gcVTcursReverse, cc);
11511	} else {
11512	    setCgsFore(xw, win, gcVTcursReverse, bg);
11513	    setCgsBack(xw, win, gcVTcursReverse, cc);
11514	}
11515	set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc);
11516	changed = True;
11517    }
11518
11519    if (changed) {
11520	TRACE(("...set_cursor_gcs - done\n"));
11521    }
11522    return changed;
11523}
11524
11525/*
11526 * Build up the default translations string, allowing the user to suppress
11527 * some of the features.
11528 */
11529void
11530VTInitTranslations(void)
11531{
11532    /* *INDENT-OFF* */
11533    static struct {
11534	Boolean wanted;
11535	const char *name;
11536	const char *value;
11537    } table[] = {
11538	{
11539	    False,
11540	    "default",
11541"\
11542          Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
11543           Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
11544         Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\
11545         Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\
11546"
11547	},
11548#if OPT_MAXIMIZE
11549	{
11550	    False,
11551	    "fullscreen",
11552"\
11553                 Alt <Key>Return:fullscreen() \n\
11554"
11555	},
11556#endif
11557#if OPT_SCROLL_LOCK
11558	{
11559	    False,
11560	    "scroll-lock",
11561"\
11562        <KeyRelease> Scroll_Lock:scroll-lock() \n\
11563"
11564	},
11565#endif
11566#if OPT_SHIFT_FONTS
11567	{
11568	    False,
11569	    "shift-fonts",
11570"\
11571    Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\
11572    Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\
11573    Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\
11574"
11575	},
11576#endif
11577	/* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */
11578	{
11579	    False,
11580	    "default",
11581"\
11582                ~Meta <KeyPress>:insert-seven-bit() \n\
11583                 Meta <KeyPress>:insert-eight-bit() \n\
11584                !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
11585           !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
11586 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\
11587     ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
11588                ~Meta <Btn1Down>:select-start() \n\
11589              ~Meta <Btn1Motion>:select-extend() \n\
11590                !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
11591           !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
11592 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\
11593     ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
11594          ~Ctrl ~Meta <Btn2Down>:ignore() \n\
11595                 Meta <Btn2Down>:clear-saved-lines() \n\
11596            ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\
11597                !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
11598           !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
11599 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\
11600     ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
11601          ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
11602              ~Meta <Btn3Motion>:select-extend() \n\
11603"
11604	},
11605	{
11606	    False,
11607	    "wheel-mouse",
11608"\
11609                 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
11610            Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
11611  Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
11612       @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
11613                      <Btn4Down>:scroll-back(5,line,m)     \n\
11614                 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
11615            Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
11616  Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
11617       @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
11618                      <Btn5Down>:scroll-forw(5,line,m)     \n\
11619"
11620	},
11621	{
11622	    False,
11623	    "default",
11624"\
11625                         <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\
11626                       <BtnDown>:ignore() \
11627"
11628	}
11629    };
11630    /* *INDENT-ON* */
11631
11632    char *result = 0;
11633
11634    int pass;
11635    Cardinal item;
11636
11637    TRACE(("VTInitTranslations\n"));
11638    for (item = 0; item < XtNumber(table); ++item) {
11639	table[item].wanted = True;
11640    }
11641#if OPT_MAXIMIZE
11642    /*
11643     * As a special case, allow for disabling the alt-enter translation if
11644     * the resource settings prevent fullscreen from being used.  We would
11645     * do the same for scroll-lock and shift-fonts if they were application
11646     * resources too, rather than in the widget.
11647     */
11648    if (resource.fullscreen == esNever) {
11649	for (item = 0; item < XtNumber(table); ++item) {
11650	    if (!strcmp(table[item].name, "fullscreen")) {
11651		table[item].wanted = False;
11652		TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
11653	    }
11654	}
11655    }
11656#endif
11657    if (!IsEmpty(resource.omitTranslation)) {
11658	char *value;
11659	const char *source = resource.omitTranslation;
11660
11661	while (*source != '\0' && (value = ParseList(&source)) != 0) {
11662	    size_t len = strlen(value);
11663
11664	    TRACE(("parsed:%s\n", value));
11665	    for (item = 0; item < XtNumber(table); ++item) {
11666		if (strlen(table[item].name) >= len
11667		    && x_strncasecmp(table[item].name,
11668				     value,
11669				     (unsigned) len) == 0) {
11670		    table[item].wanted = False;
11671		    TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
11672		    break;
11673		}
11674	    }
11675	    free(value);
11676	}
11677    }
11678
11679    for (pass = 0; pass < 2; ++pass) {
11680	size_t needed = 0;
11681	for (item = 0; item < XtNumber(table); ++item) {
11682	    if (table[item].wanted) {
11683		if (pass) {
11684		    strcat(result, table[item].value);
11685		} else {
11686		    needed += strlen(table[item].value) + 1;
11687		}
11688	    }
11689	}
11690	if (!pass) {
11691	    result = XtMalloc((Cardinal) needed);
11692	    *result = '\0';
11693	}
11694    }
11695
11696    TRACE(("result:\n%s\n", result));
11697
11698    defaultTranslations = result;
11699    xtermClassRec.core_class.tm_table = result;
11700}
11701
11702#ifdef NO_LEAKS
11703void
11704noleaks_charproc(void)
11705{
11706    if (v_buffer != 0)
11707	free(v_buffer);
11708}
11709#endif
11710