charproc.c revision 956cc18d
1/* $XTermId: charproc.c,v 1.972 2009/09/10 09:03:49 tom Exp $ */
2
3/*
4
5Copyright 1999-2008,2009 by Thomas E. Dickey
6
7                        All Rights Reserved
8
9Permission is hereby granted, free of charge, to any person obtaining a
10copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice shall be included
18in all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
24CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28Except as contained in this notice, the name(s) of the above copyright
29holders shall not be used in advertising or otherwise to promote the
30sale, use or other dealings in this Software without prior written
31authorization.
32
33Copyright 1988  The Open Group
34
35Permission to use, copy, modify, distribute, and sell this software and its
36documentation for any purpose is hereby granted without fee, provided that
37the above copyright notice appear in all copies and that both that
38copyright notice and this permission notice appear in supporting
39documentation.
40
41The above copyright notice and this permission notice shall be included in
42all copies or substantial portions of the Software.
43
44THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
47OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
48AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50
51Except as contained in this notice, the name of The Open Group shall not be
52used in advertising or otherwise to promote the sale, use or other dealings
53in 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_NEXTAW)
98#include <X11/neXtaw/XawImP.h>
99#elif defined(HAVE_LIB_XAWPLUS)
100#include <X11/XawPlus/XawImP.h>
101#endif
102
103#endif
104
105#if OPT_WIDE_CHARS
106#include <wcwidth.h>
107#include <precompose.h>
108#ifdef HAVE_LANGINFO_CODESET
109#include <langinfo.h>
110#endif
111#endif
112
113#if OPT_INPUT_METHOD
114#include <X11/Xlocale.h>
115#endif
116
117#include <stdio.h>
118#include <ctype.h>
119
120#if defined(HAVE_SCHED_YIELD)
121#include <sched.h>
122#endif
123
124#include <VTparse.h>
125#include <data.h>
126#include <error.h>
127#include <menu.h>
128#include <main.h>
129#include <fontutils.h>
130#include <xcharmouse.h>
131#include <charclass.h>
132#include <xstrings.h>
133
134static IChar doinput(void);
135static int set_character_class(char *s);
136static void FromAlternate(XtermWidget /* xw */ );
137static void RequestResize(XtermWidget termw, int rows, int cols, Bool text);
138static void SwitchBufs(XtermWidget xw);
139static void ToAlternate(XtermWidget /* xw */ );
140static void ansi_modes(XtermWidget termw,
141		       void (*func) (unsigned *p, unsigned mask));
142static void bitclr(unsigned *p, unsigned mask);
143static void bitcpy(unsigned *p, unsigned q, unsigned mask);
144static void bitset(unsigned *p, unsigned mask);
145static void dpmodes(XtermWidget termw, void (*func) (unsigned *p, unsigned mask));
146static void restoremodes(XtermWidget termw);
147static void savemodes(XtermWidget termw);
148static void window_ops(XtermWidget termw);
149
150#define DoStartBlinking(s) ((s)->cursor_blink ^ (s)->cursor_blink_esc)
151
152#if OPT_BLINK_CURS || OPT_BLINK_TEXT
153static void HandleBlinking(XtPointer closure, XtIntervalId * id);
154static void StartBlinking(TScreen * screen);
155static void StopBlinking(TScreen * screen);
156#else
157#define StartBlinking(screen)	/* nothing */
158#define StopBlinking(screen)	/* nothing */
159#endif
160
161#if OPT_INPUT_METHOD
162static void PreeditPosition(TScreen * screen);
163#endif
164
165#define	DEFAULT		-1
166#define BELLSUPPRESSMSEC 200
167
168static int nparam;
169static ANSI reply;
170static int param[NPARAM];
171
172static jmp_buf vtjmpbuf;
173
174/* event handlers */
175static void HandleBell PROTO_XT_ACTIONS_ARGS;
176static void HandleIgnore PROTO_XT_ACTIONS_ARGS;
177static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS;
178static void HandleVisualBell PROTO_XT_ACTIONS_ARGS;
179#if HANDLE_STRUCT_NOTIFY
180static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS;
181#endif
182
183/*
184 * NOTE: VTInitialize zeros out the entire ".screen" component of the
185 * XtermWidget, so make sure to add an assignment statement in VTInitialize()
186 * for each new ".screen" field added to this resource list.
187 */
188
189/* Defaults */
190#if OPT_ISO_COLORS
191
192/*
193 * If we default to colorMode enabled, compile-in defaults for the ANSI colors.
194 */
195#if DFT_COLORMODE
196#define DFT_COLOR(name) name
197#else
198#define DFT_COLOR(name) XtDefaultForeground
199#endif
200#endif
201
202static char *_Font_Selected_ = "yes";	/* string is arbitrary */
203
204static char defaultTranslations[] =
205"\
206          Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
207           Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
208         Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\
209         Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\
210"
211#if OPT_SHIFT_FONTS
212"\
213    Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\
214    Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\
215    Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\
216"
217#endif
218"\
219                ~Meta <KeyPress>:insert-seven-bit() \n\
220                 Meta <KeyPress>:insert-eight-bit() \n\
221                !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
222           !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
223 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\
224     ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
225                ~Meta <Btn1Down>:select-start() \n\
226              ~Meta <Btn1Motion>:select-extend() \n\
227                !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
228           !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
229 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\
230     ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
231          ~Ctrl ~Meta <Btn2Down>:ignore() \n\
232                 Meta <Btn2Down>:clear-saved-lines() \n\
233            ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\
234                !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
235           !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
236 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\
237     ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
238          ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
239              ~Meta <Btn3Motion>:select-extend() \n\
240                 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
241            Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
242  Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
243       @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
244                      <Btn4Down>:scroll-back(5,line,m)     \n\
245                 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
246            Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
247  Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
248       @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
249                      <Btn5Down>:scroll-forw(5,line,m)     \n\
250                         <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\
251                       <BtnDown>:ignore() \
252";				/* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */
253/* *INDENT-OFF* */
254static XtActionsRec actionsList[] = {
255    { "allow-send-events",	HandleAllowSends },
256    { "bell",			HandleBell },
257    { "clear-saved-lines",	HandleClearSavedLines },
258    { "create-menu",		HandleCreateMenu },
259    { "delete-is-del",		HandleDeleteIsDEL },
260    { "dired-button",		DiredButton },
261    { "hard-reset",		HandleHardReset },
262    { "ignore",			HandleIgnore },
263    { "insert",			HandleKeyPressed },  /* alias for insert-seven-bit */
264    { "insert-eight-bit",	HandleEightBitKeyPressed },
265    { "insert-selection",	HandleInsertSelection },
266    { "insert-seven-bit",	HandleKeyPressed },
267    { "interpret",		HandleInterpret },
268    { "keymap",			HandleKeymapChange },
269    { "popup-menu",		HandlePopupMenu },
270    { "print",			HandlePrintScreen },
271    { "print-everything",	HandlePrintEverything },
272    { "print-redir",		HandlePrintControlMode },
273    { "quit",			HandleQuit },
274    { "redraw",			HandleRedraw },
275    { "scroll-back",		HandleScrollBack },
276    { "scroll-forw",		HandleScrollForward },
277    { "secure",			HandleSecure },
278    { "select-cursor-end",	HandleKeyboardSelectEnd },
279    { "select-cursor-extend",   HandleKeyboardSelectExtend },
280    { "select-cursor-start",	HandleKeyboardSelectStart },
281    { "select-end",		HandleSelectEnd },
282    { "select-extend",		HandleSelectExtend },
283    { "select-set",		HandleSelectSet },
284    { "select-start",		HandleSelectStart },
285    { "send-signal",		HandleSendSignal },
286    { "set-8-bit-control",	Handle8BitControl },
287    { "set-allow132",		HandleAllow132 },
288    { "set-altscreen",		HandleAltScreen },
289    { "set-appcursor",		HandleAppCursor },
290    { "set-appkeypad",		HandleAppKeypad },
291    { "set-autolinefeed",	HandleAutoLineFeed },
292    { "set-autowrap",		HandleAutoWrap },
293    { "set-backarrow",		HandleBackarrow },
294    { "set-bellIsUrgent",	HandleBellIsUrgent },
295    { "set-cursesemul",		HandleCursesEmul },
296    { "set-jumpscroll",		HandleJumpscroll },
297    { "set-keep-selection",	HandleKeepSelection },
298    { "set-marginbell",		HandleMarginBell },
299    { "set-old-function-keys",	HandleOldFunctionKeys },
300    { "set-pop-on-bell",	HandleSetPopOnBell },
301    { "set-reverse-video",	HandleReverseVideo },
302    { "set-reversewrap",	HandleReverseWrap },
303    { "set-scroll-on-key",	HandleScrollKey },
304    { "set-scroll-on-tty-output", HandleScrollTtyOutput },
305    { "set-scrollbar",		HandleScrollbar },
306    { "set-select",		HandleSetSelect },
307    { "set-sun-keyboard",	HandleSunKeyboard },
308    { "set-titeInhibit",	HandleTiteInhibit },
309    { "set-visual-bell",	HandleSetVisualBell },
310    { "set-vt-font",		HandleSetFont },
311    { "soft-reset",		HandleSoftReset },
312    { "start-cursor-extend",	HandleKeyboardStartExtend },
313    { "start-extend",		HandleStartExtend },
314    { "string",			HandleStringEvent },
315    { "vi-button",		ViButton },
316    { "visual-bell",		HandleVisualBell },
317#ifdef ALLOWLOGGING
318    { "set-logging",		HandleLogging },
319#endif
320#if OPT_ALLOW_XXX_OPS
321    { "allow-font-ops",		HandleAllowFontOps },
322    { "allow-tcap-ops",		HandleAllowTcapOps },
323    { "allow-title-ops",	HandleAllowTitleOps },
324    { "allow-window-ops",	HandleAllowWindowOps },
325#endif
326#if OPT_BLINK_CURS
327    { "set-cursorblink",	HandleCursorBlink },
328#endif
329#if OPT_BOX_CHARS
330    { "set-font-linedrawing",	HandleFontBoxChars },
331#endif
332#if OPT_DABBREV
333    { "dabbrev-expand",		HandleDabbrevExpand },
334#endif
335#if OPT_DEC_CHRSET
336    { "set-font-doublesize",	HandleFontDoublesize },
337#endif
338#if OPT_DEC_SOFTFONT
339    { "set-font-loading",	HandleFontLoading },
340#endif
341#if OPT_EXEC_XTERM
342    { "spawn-new-terminal",	HandleSpawnTerminal },
343#endif
344#if OPT_HP_FUNC_KEYS
345    { "set-hp-function-keys",	HandleHpFunctionKeys },
346#endif
347#if OPT_LOAD_VTFONTS
348    { "load-vt-fonts",		HandleLoadVTFonts },
349#endif
350#if OPT_MAXIMIZE
351    { "deiconify",		HandleDeIconify },
352    { "iconify",		HandleIconify },
353    { "maximize",		HandleMaximize },
354    { "restore",		HandleRestoreSize },
355#endif
356#if OPT_NUM_LOCK
357    { "alt-sends-escape",	HandleAltEsc },
358    { "meta-sends-escape",	HandleMetaEsc },
359    { "set-num-lock",		HandleNumLock },
360#endif
361#if OPT_READLINE
362    { "readline-button",	ReadLineButton },
363#endif
364#if OPT_RENDERFONT
365    { "set-render-font",	HandleRenderFont },
366#endif
367#if OPT_SCO_FUNC_KEYS
368    { "set-sco-function-keys",	HandleScoFunctionKeys },
369#endif
370#if OPT_SHIFT_FONTS
371    { "larger-vt-font",		HandleLargerFont },
372    { "smaller-vt-font",	HandleSmallerFont },
373#endif
374#if OPT_SUN_FUNC_KEYS
375    { "set-sun-function-keys",	HandleSunFunctionKeys },
376#endif
377#if OPT_TEK4014
378    { "set-terminal-type",	HandleSetTerminalType },
379    { "set-visibility",		HandleVisibility },
380    { "set-tek-text",		HandleSetTekText },
381    { "tek-page",		HandleTekPage },
382    { "tek-reset",		HandleTekReset },
383    { "tek-copy",		HandleTekCopy },
384#endif
385#if OPT_TOOLBAR
386    { "set-toolbar",		HandleToolbar },
387#endif
388#if OPT_WIDE_CHARS
389    { "set-utf8-mode",		HandleUTF8Mode },
390    { "set-utf8-title",		HandleUTF8Title },
391#endif
392};
393/* *INDENT-ON* */
394
395static XtResource resources[] =
396{
397    Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False),
398    Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT),
399    Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP),
400    Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE),
401    Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW),
402    Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False),
403    Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, False),
404    Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False),
405    Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False),
406    Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False),
407    Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False),
408    Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True),
409    Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False),
410    Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False),
411    Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, True),
412    Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False),
413    Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True),
414    Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True),
415    Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False),
416    Bres(XtNc132, XtCC132, screen.c132, False),
417    Bres(XtNcurses, XtCCurses, screen.curses, False),
418    Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True),
419    Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine,
420	 screen.cutToBeginningOfLine, True),
421    Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL),
422    Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True),
423    Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False),
424    Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True),
425    Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True),
426    Bres(XtNhighlightSelection, XtCHighlightSelection,
427	 screen.highlight_selection, False),
428    Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False),
429    Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True),
430    Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False),
431    Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True),
432    Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True),
433    Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False),
434    Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False),
435    Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, False),
436    Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False),
437    Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False),
438    Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False),
439    Bres(XtNprinterAutoClose, XtCPrinterAutoClose, screen.printer_autoclose, False),
440    Bres(XtNprinterExtent, XtCPrinterExtent, screen.printer_extent, False),
441    Bres(XtNprinterFormFeed, XtCPrinterFormFeed, screen.printer_formfeed, False),
442    Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False),
443    Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False),
444    Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False),
445    Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False),
446    Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False),
447    Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True),
448    Bres(XtNselectToClipboard, XtCSelectToClipboard,
449	 screen.selectToClipboard, False),
450    Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False),
451    Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False),
452    Bres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll, False),
453    Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False),
454    Bres(XtNunderLine, XtCUnderLine, screen.underline, True),
455    Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False),
456
457    Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC),
458    Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource),
459    Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER),
460    Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1),
461    Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME),
462    Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL),
463    Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE),
464    Ires(XtNprinterControlMode, XtCPrinterControlMode,
465	 screen.printer_controlmode, 0),
466    Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100),
467    Ires(XtNsaveLines, XtCSaveLines, screen.savelines, SAVELINES),
468    Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1),
469    Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, SCROLLLINES),
470
471    Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL),
472    Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL),
473    Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL),
474    Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL),
475    Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL),
476    Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL),
477    Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL),
478
479    Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""),
480    Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT),
481    Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL),
482    Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID),
483    Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"),
484    Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes,
485	 screen.eightbit_select_types, NULL),
486    Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT),
487    Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL),
488    Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT),
489    Sres(XtNprinterCommand, XtCPrinterCommand, screen.printer_command, ""),
490    Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL),
491
492    Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground),
493    Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground),
494    Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground),
495    Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground),
496    Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground),
497
498    {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
499     XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
500     XtRImmediate, (XtPointer) SouthWestGravity},
501
502    {XtNpointerShape, XtCCursor, XtRCursor, sizeof(Cursor),
503     XtOffsetOf(XtermWidgetRec, screen.pointer_cursor),
504     XtRString, (XtPointer) "xterm"},
505
506#ifdef ALLOWLOGGING
507    Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False),
508    Bres(XtNlogging, XtCLogging, misc.log_on, False),
509    Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL),
510#endif
511
512#ifndef NO_ACTIVE_ICON
513    Bres("activeIcon", "ActiveIcon", misc.active_icon, False),
514    Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2),
515    Fres("iconFont", "IconFont", screen.fnt_icon.fs, XtDefaultFont),
516    Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground),
517#endif				/* NO_ACTIVE_ICON */
518
519#if OPT_BLINK_CURS
520    Bres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink, False),
521#endif
522    Bres(XtNcursorUnderline, XtCCursorUnderline, screen.cursor_underline, False),
523
524#if OPT_BLINK_TEXT
525    Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD),
526#endif
527
528#if OPT_BLINK_CURS || OPT_BLINK_TEXT
529    Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600),
530    Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300),
531#endif
532
533#if OPT_BOX_CHARS
534    Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False),
535    Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False),
536#endif
537
538#if OPT_BROKEN_OSC
539    Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True),
540#endif
541
542#if OPT_BROKEN_ST
543    Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, True),
544#endif
545
546#if OPT_C1_PRINT
547    Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False),
548#endif
549
550#if OPT_CLIP_BOLD
551    Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True),
552#endif
553
554#if OPT_DEC_CHRSET
555    Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True),
556    Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET),
557#endif
558
559#if OPT_HIGHLIGHT_COLOR
560    Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground),
561    Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground),
562    Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True),
563    Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe),
564#endif				/* OPT_HIGHLIGHT_COLOR */
565
566#if OPT_INPUT_METHOD
567    Bres(XtNopenIm, XtCOpenIm, misc.open_im, True),
568    Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL),
569    Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type,
570	 "OverTheSpot,Root"),
571    Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3),
572#endif
573
574#if OPT_ISO_COLORS
575    Bres(XtNboldColors, XtCColorMode, screen.boldColors, True),
576    Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0),
577    Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE),
578
579    Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False),
580    Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False),
581    Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False),
582    Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False),
583    Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False),
584    Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False),
585
586    COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")),
587    COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")),
588    COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")),
589    COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")),
590    COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)),
591    COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")),
592    COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")),
593    COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")),
594    COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")),
595    COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")),
596    COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")),
597    COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")),
598    COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)),
599    COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")),
600    COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")),
601    COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")),
602    COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)),
603    COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)),
604    COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)),
605    COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)),
606
607    CLICK_RES("2", screen.onClick[1], "word"),
608    CLICK_RES("3", screen.onClick[2], "line"),
609    CLICK_RES("4", screen.onClick[3], 0),
610    CLICK_RES("5", screen.onClick[4], 0),
611
612#if !OPT_COLOR_RES2
613#if OPT_256_COLORS
614# include <256colres.h>
615#elif OPT_88_COLORS
616# include <88colres.h>
617#endif
618#endif				/* !OPT_COLOR_RES2 */
619
620#endif				/* OPT_ISO_COLORS */
621
622#if OPT_MOD_FKEYS
623    Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys,
624	 keyboard.modify_1st.cursor_keys, 2),
625    Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys,
626	 keyboard.modify_1st.function_keys, 2),
627    Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys,
628	 keyboard.modify_1st.keypad_keys, 0),
629    Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys,
630	 keyboard.modify_1st.other_keys, 0),
631    Ires(XtNmodifyStringKeys, XtCModifyStringKeys,
632	 keyboard.modify_1st.string_keys, 0),
633    Ires(XtNformatOtherKeys, XtCFormatOtherKeys,
634	 keyboard.format_keys, 0),
635#endif
636
637#if OPT_NUM_LOCK
638    Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False),
639    Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True),
640#endif
641
642#if OPT_PRINT_COLORS
643    Ires(XtNprintAttributes, XtCPrintAttributes, screen.print_attributes, 1),
644#endif
645
646#if OPT_SHIFT_FONTS
647    Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True),
648#endif
649
650#if OPT_SUNPC_KBD
651    Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10),
652#endif
653
654#if OPT_TEK4014
655    Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False),
656    Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False),
657    Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False),
658#endif
659
660#if OPT_TOOLBAR
661    Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0),
662    Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25),
663#endif
664
665#if OPT_WIDE_CHARS
666    Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False),
667    Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False),
668    Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False),
669    Bres(XtNutf8Title, XtCUtf8Title, screen.utf8_title, False),
670    Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True),
671    Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False),
672    Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2),
673    Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 256),
674    Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 1024),
675    Ires(XtNutf8, XtCUtf8, screen.utf8_mode, uDefault),
676    Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT),
677    Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT),
678    Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL),
679#endif
680
681#if OPT_LUIT_PROG
682    Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"),
683    Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER),
684#endif
685
686#if OPT_INPUT_METHOD
687    Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT),
688#endif
689
690#if OPT_XMC_GLITCH
691    Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False),
692    Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True),
693    Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1),
694    Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0),
695#endif
696
697#ifdef SCROLLBAR_RIGHT
698    Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False),
699#endif
700
701#if OPT_RENDERFONT
702#define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0")
703    RES_FACESIZE(1),
704    RES_FACESIZE(2),
705    RES_FACESIZE(3),
706    RES_FACESIZE(4),
707    RES_FACESIZE(5),
708    RES_FACESIZE(6),
709    Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE),
710    Sres(XtNfaceName, XtCFaceName, misc.face_name, DEFFACENAME),
711    Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.face_wide_name, DEFFACENAME),
712    Bres(XtNrenderFont, XtCRenderFont, misc.render_font, True),
713#endif
714};
715
716static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg,
717			   ArgList args, Cardinal *num_args);
718static void VTClassInit(void);
719static void VTDestroy(Widget w);
720static void VTExpose(Widget w, XEvent * event, Region region);
721static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args,
722			 Cardinal *num_args);
723static void VTRealize(Widget w, XtValueMask * valuemask,
724		      XSetWindowAttributes * values);
725static void VTResize(Widget w);
726
727#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
728static void VTInitI18N(XtermWidget);
729#endif
730
731#ifdef VMS
732globaldef {
733    "xtermclassrec"
734} noshare
735
736#else
737static
738#endif				/* VMS */
739WidgetClassRec xtermClassRec =
740{
741    {
742/* core_class fields */
743	(WidgetClass) & widgetClassRec,		/* superclass     */
744	"VT100",		/* class_name                   */
745	sizeof(XtermWidgetRec),	/* widget_size                  */
746	VTClassInit,		/* class_initialize             */
747	NULL,			/* class_part_initialize        */
748	False,			/* class_inited                 */
749	VTInitialize,		/* initialize                   */
750	NULL,			/* initialize_hook              */
751	VTRealize,		/* realize                      */
752	actionsList,		/* actions                      */
753	XtNumber(actionsList),	/* num_actions                  */
754	resources,		/* resources                    */
755	XtNumber(resources),	/* num_resources                */
756	NULLQUARK,		/* xrm_class                    */
757	True,			/* compress_motion              */
758	False,			/* compress_exposure            */
759	True,			/* compress_enterleave          */
760	False,			/* visible_interest             */
761	VTDestroy,		/* destroy                      */
762	VTResize,		/* resize                       */
763	VTExpose,		/* expose                       */
764	VTSetValues,		/* set_values                   */
765	NULL,			/* set_values_hook              */
766	XtInheritSetValuesAlmost,	/* set_values_almost    */
767	NULL,			/* get_values_hook              */
768	NULL,			/* accept_focus                 */
769	XtVersion,		/* version                      */
770	NULL,			/* callback_offsets             */
771	defaultTranslations,	/* tm_table                     */
772	XtInheritQueryGeometry,	/* query_geometry               */
773	XtInheritDisplayAccelerator,	/* display_accelerator  */
774	NULL			/* extension                    */
775    }
776};
777
778#ifdef VMS
779globaldef {
780    "xtermwidgetclass"
781}
782noshare
783#endif /* VMS */
784WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec;
785
786/*
787 * Add input-actions for widgets that are overlooked (scrollbar and toolbar):
788 *
789 *	a) Sometimes the scrollbar passes through translations, sometimes it
790 *	   doesn't.  We add the KeyPress translations here, just to be sure.
791 *	b) In the normal (non-toolbar) configuration, the xterm widget covers
792 *	   almost all of the window.  With a toolbar, there's a relatively
793 *	   large area that the user would expect to enter keystrokes since the
794 *	   program can get the focus.
795 */
796void
797xtermAddInput(Widget w)
798{
799    /* *INDENT-OFF* */
800    XtActionsRec input_actions[] = {
801	{ "insert",		    HandleKeyPressed }, /* alias */
802	{ "insert-eight-bit",	    HandleEightBitKeyPressed },
803	{ "insert-seven-bit",	    HandleKeyPressed },
804	{ "secure",		    HandleSecure },
805	{ "string",		    HandleStringEvent },
806	{ "scroll-back",	    HandleScrollBack },
807	{ "scroll-forw",	    HandleScrollForward },
808	{ "select-cursor-end",	    HandleKeyboardSelectEnd },
809	{ "select-cursor-extend",   HandleKeyboardSelectExtend },
810	{ "select-cursor-start",    HandleKeyboardSelectStart },
811	{ "insert-selection",	    HandleInsertSelection },
812	{ "select-start",	    HandleSelectStart },
813	{ "select-extend",	    HandleSelectExtend },
814	{ "start-extend",	    HandleStartExtend },
815	{ "select-end",		    HandleSelectEnd },
816	{ "clear-saved-lines",	    HandleClearSavedLines },
817	{ "popup-menu",		    HandlePopupMenu },
818	{ "bell",		    HandleBell },
819	{ "ignore",		    HandleIgnore },
820#if OPT_DABBREV
821	{ "dabbrev-expand",	    HandleDabbrevExpand },
822#endif
823#if OPT_SHIFT_FONTS
824	{ "larger-vt-font",	    HandleLargerFont },
825	{ "smaller-vt-font",	    HandleSmallerFont },
826#endif
827    };
828    /* *INDENT-ON* */
829
830    TRACE_TRANS("BEFORE", w);
831    XtAppAddActions(app_con, input_actions, XtNumber(input_actions));
832    XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations));
833    TRACE_TRANS("AFTER:", w);
834
835#if OPT_EXTRA_PASTE
836    if (term && term->keyboard.extra_translations)
837	XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations));
838#endif
839}
840
841#if OPT_ISO_COLORS
842#ifdef EXP_BOGUS_FG
843static Bool
844CheckBogusForeground(TScreen * screen, const char *tag)
845{
846    int row = -1, col = -1, pass;
847    Bool isClear = True;
848
849    (void) tag;
850    for (pass = 0; pass < 2; ++pass) {
851	row = screen->cur_row;
852	for (; isClear && (row <= screen->max_row); ++row) {
853	    LineData *ld = getLineData(screen, row)->;
854	    Char *attribs = ld->attribs;
855
856	    col = (row == screen->cur_row) ? screen->cur_col : 0;
857	    for (; isClear && (col <= screen->max_col); ++col) {
858		unsigned flags = attribs[col];
859		if (pass) {
860		    flags &= ~FG_COLOR;
861		    attribs[col] = (Char) flags;
862		} else if ((flags & BG_COLOR)) {
863		    isClear = False;
864		} else if ((flags & FG_COLOR)) {
865		    unsigned ch = ld->charData[col];
866		    isClear = ((ch == ' ') || (ch == 0));
867		} else {
868		    isClear = False;
869		}
870	    }
871	}
872    }
873    TRACE(("%s checked %d,%d to %d,%d %s pass %d\n",
874	   tag, screen->cur_row, screen->cur_col,
875	   row, col,
876	   isClear && pass ? "cleared" : "unchanged",
877	   pass));
878
879    return isClear;
880}
881#endif
882
883/*
884 * The terminal's foreground and background colors are set via two mechanisms:
885 *	text (cur_foreground, cur_background values that are passed down to
886 *		XDrawImageString and XDrawString)
887 *	area (X11 graphics context used in XClearArea and XFillRectangle)
888 */
889void
890SGR_Foreground(XtermWidget xw, int color)
891{
892    TScreen *screen = &xw->screen;
893    Pixel fg;
894
895    if (color >= 0) {
896	xw->flags |= FG_COLOR;
897    } else {
898	xw->flags &= ~FG_COLOR;
899    }
900    fg = getXtermForeground(xw, xw->flags, color);
901    xw->cur_foreground = color;
902
903    setCgsFore(xw, WhichVWin(screen), gcNorm, fg);
904    setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg);
905
906    setCgsFore(xw, WhichVWin(screen), gcBold, fg);
907    setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg);
908
909#ifdef EXP_BOGUS_FG
910    /*
911     * If we've just turned off the foreground color, check for blank cells
912     * which have no background color, but do have foreground color.  This
913     * could happen due to setting the foreground color just before scrolling.
914     *
915     * Those cells look uncolored, but will confuse ShowCursor(), which looks
916     * for the colors in the current cell, and will see the foreground color.
917     * In that case, remove the foreground color from the blank cells.
918     */
919    if (color < 0) {
920	CheckBogusForeground(screen, "SGR_Foreground");
921    }
922#endif
923}
924
925void
926SGR_Background(XtermWidget xw, int color)
927{
928    TScreen *screen = &xw->screen;
929    Pixel bg;
930
931    /*
932     * An indexing operation may have set screen->scroll_amt, which would
933     * normally result in calling FlushScroll() in WriteText().  However,
934     * if we're changing the background color now, then the new value
935     * should not apply to the pending blank lines.
936     */
937    if (screen->scroll_amt && (color != xw->cur_background))
938	FlushScroll(xw);
939
940    if (color >= 0) {
941	xw->flags |= BG_COLOR;
942    } else {
943	xw->flags &= ~BG_COLOR;
944    }
945    bg = getXtermBackground(xw, xw->flags, color);
946    xw->cur_background = color;
947
948    setCgsBack(xw, WhichVWin(screen), gcNorm, bg);
949    setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg);
950
951    setCgsBack(xw, WhichVWin(screen), gcBold, bg);
952    setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg);
953}
954
955/* Invoked after updating bold/underline flags, computes the extended color
956 * index to use for foreground.  (See also 'extract_fg()').
957 */
958static void
959setExtendedFG(XtermWidget xw)
960{
961    int fg = xw->sgr_foreground;
962
963    if (xw->screen.colorAttrMode
964	|| (fg < 0)) {
965	if (xw->screen.colorULMode && (xw->flags & UNDERLINE))
966	    fg = COLOR_UL;
967	if (xw->screen.colorBDMode && (xw->flags & BOLD))
968	    fg = COLOR_BD;
969	if (xw->screen.colorBLMode && (xw->flags & BLINK))
970	    fg = COLOR_BL;
971    }
972
973    /* This implements the IBM PC-style convention of 8-colors, with one
974     * bit for bold, thus mapping the 0-7 codes to 8-15.  It won't make
975     * much sense for 16-color applications, but we keep it to retain
976     * compatiblity with ANSI-color applications.
977     */
978#if OPT_PC_COLORS		/* XXXJTL should be settable at runtime (resource or OSC?) */
979    if (xw->screen.boldColors
980	&& (!xw->sgr_extended)
981	&& (fg >= 0)
982	&& (fg < 8)
983	&& (xw->flags & BOLD))
984	fg |= 8;
985#endif
986
987    SGR_Foreground(xw, fg);
988}
989
990/* Invoked after updating inverse flag, computes the extended color
991 * index to use for background.  (See also 'extract_bg()').
992 */
993static void
994setExtendedBG(XtermWidget xw)
995{
996    int bg = xw->sgr_background;
997
998    if (xw->screen.colorAttrMode
999	|| (bg < 0)) {
1000	if (xw->screen.colorRVMode && (xw->flags & INVERSE))
1001	    bg = COLOR_RV;
1002    }
1003
1004    SGR_Background(xw, bg);
1005}
1006
1007static void
1008reset_SGR_Foreground(XtermWidget xw)
1009{
1010    xw->sgr_foreground = -1;
1011    xw->sgr_extended = False;
1012    setExtendedFG(xw);
1013}
1014
1015static void
1016reset_SGR_Background(XtermWidget xw)
1017{
1018    xw->sgr_background = -1;
1019    setExtendedBG(xw);
1020}
1021
1022static void
1023reset_SGR_Colors(XtermWidget xw)
1024{
1025    reset_SGR_Foreground(xw);
1026    reset_SGR_Background(xw);
1027}
1028#endif /* OPT_ISO_COLORS */
1029
1030void
1031resetCharsets(TScreen * screen)
1032{
1033    TRACE(("resetCharsets\n"));
1034
1035    screen->gsets[0] = 'B';	/* ASCII_G              */
1036    screen->gsets[1] = 'B';	/* ASCII_G              */
1037    screen->gsets[2] = 'B';	/* ASCII_G              */
1038    screen->gsets[3] = 'B';	/* ASCII_G              */
1039
1040    screen->curgl = 0;		/* G0 => GL.            */
1041    screen->curgr = 2;		/* G2 => GR.            */
1042    screen->curss = 0;		/* No single shift.     */
1043
1044#if OPT_VT52_MODE
1045    if (screen->vtXX_level == 0)
1046	screen->gsets[1] = '0';	/* Graphics             */
1047#endif
1048}
1049
1050/*
1051 * VT300 and up support three ANSI conformance levels, defined according to
1052 * the dpANSI X3.134.1 standard.  DEC's manuals equate levels 1 and 2, and
1053 * are unclear.  This code is written based on the manuals.
1054 */
1055static void
1056set_ansi_conformance(TScreen * screen, int level)
1057{
1058    TRACE(("set_ansi_conformance(%d) terminal_id %d, ansi_level %d\n",
1059	   level,
1060	   screen->terminal_id,
1061	   screen->ansi_level));
1062    if (screen->vtXX_level >= 3) {
1063	switch (screen->ansi_level = level) {
1064	case 1:
1065	    /* FALLTHRU */
1066	case 2:
1067	    screen->gsets[0] = 'B';	/* G0 is ASCII */
1068	    screen->gsets[1] = 'B';	/* G1 is ISO Latin-1 (FIXME) */
1069	    screen->curgl = 0;
1070	    screen->curgr = 1;
1071	    break;
1072	case 3:
1073	    screen->gsets[0] = 'B';	/* G0 is ASCII */
1074	    screen->curgl = 0;
1075	    break;
1076	}
1077    }
1078}
1079
1080/*
1081 * Set scrolling margins.  VTxxx terminals require that the top/bottom are
1082 * different, so we have at least two lines in the scrolling region.
1083 */
1084void
1085set_tb_margins(TScreen * screen, int top, int bottom)
1086{
1087    TRACE(("set_tb_margins %d..%d, prior %d..%d\n",
1088	   top, bottom,
1089	   screen->top_marg,
1090	   screen->bot_marg));
1091    if (bottom > top) {
1092	screen->top_marg = top;
1093	screen->bot_marg = bottom;
1094    }
1095    if (screen->top_marg > screen->max_row)
1096	screen->top_marg = screen->max_row;
1097    if (screen->bot_marg > screen->max_row)
1098	screen->bot_marg = screen->max_row;
1099}
1100
1101void
1102set_max_col(TScreen * screen, int cols)
1103{
1104    TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col));
1105    if (cols < 0)
1106	cols = 0;
1107    screen->max_col = cols;
1108}
1109
1110void
1111set_max_row(TScreen * screen, int rows)
1112{
1113    TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row));
1114    if (rows < 0)
1115	rows = 0;
1116    screen->max_row = rows;
1117}
1118
1119#if OPT_MOD_FKEYS
1120static void
1121set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled)
1122{
1123#define SET_MOD_FKEYS(field) \
1124    xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \
1125				     ? xw->keyboard.modify_1st.field \
1126				     : what; \
1127    TRACE(("set modify_now.%s to %d\n", #field, \
1128	   xw->keyboard.modify_now.field));
1129
1130    switch (which) {
1131    case 1:
1132	SET_MOD_FKEYS(cursor_keys);
1133	break;
1134    case 2:
1135	SET_MOD_FKEYS(function_keys);
1136	break;
1137    case 3:
1138	SET_MOD_FKEYS(keypad_keys);
1139	break;
1140    case 4:
1141	SET_MOD_FKEYS(other_keys);
1142	break;
1143    case 5:
1144	SET_MOD_FKEYS(string_keys);
1145	break;
1146    }
1147}
1148#endif /* OPT_MOD_FKEYS */
1149
1150#if OPT_TRACE
1151#define WHICH_TABLE(name) if (table == name) result = #name
1152static char *
1153which_table(Const PARSE_T * table)
1154{
1155    char *result = "?";
1156    /* *INDENT-OFF* */
1157    WHICH_TABLE (ansi_table);
1158    else WHICH_TABLE (cigtable);
1159    else WHICH_TABLE (csi2_table);
1160    else WHICH_TABLE (csi_ex_table);
1161    else WHICH_TABLE (csi_quo_table);
1162    else WHICH_TABLE (csi_table);
1163    else WHICH_TABLE (dec2_table);
1164    else WHICH_TABLE (dec3_table);
1165    else WHICH_TABLE (dec_table);
1166    else WHICH_TABLE (eigtable);
1167    else WHICH_TABLE (esc_sp_table);
1168    else WHICH_TABLE (esc_table);
1169    else WHICH_TABLE (scrtable);
1170    else WHICH_TABLE (scs96table);
1171    else WHICH_TABLE (scstable);
1172    else WHICH_TABLE (sos_table);
1173#if OPT_DEC_LOCATOR
1174    else WHICH_TABLE (csi_tick_table);
1175#endif
1176#if OPT_DEC_RECTOPS
1177    else WHICH_TABLE (csi_dollar_table);
1178    else WHICH_TABLE (csi_star_table);
1179#endif
1180#if OPT_WIDE_CHARS
1181    else WHICH_TABLE (esc_pct_table);
1182#endif
1183#if OPT_VT52_MODE
1184    else WHICH_TABLE (vt52_table);
1185    else WHICH_TABLE (vt52_esc_table);
1186    else WHICH_TABLE (vt52_ignore_table);
1187#endif
1188    /* *INDENT-ON* */
1189
1190    return result;
1191}
1192#endif
1193
1194	/* allocate larger buffer if needed/possible */
1195#define SafeAlloc(type, area, used, size) \
1196		type *new_string = area; \
1197		unsigned new_length = size; \
1198		if (new_length == 0) { \
1199		    new_length = 256; \
1200		    new_string = TypeMallocN(type, new_length); \
1201		} else if (used+1 >= new_length) { \
1202		    new_length = size * 2; \
1203		    new_string = TypeMallocN(type, new_length); \
1204		    if (new_string != 0 \
1205		     && area != 0 \
1206		     && used != 0) \
1207			memcpy(new_string, area, used * sizeof(type)); \
1208		}
1209
1210#define WriteNow() {						\
1211	    unsigned single = 0;				\
1212								\
1213	    if (screen->curss) {				\
1214		dotext(xw,					\
1215		       screen->gsets[(int) (screen->curss)],	\
1216		       sp->print_area,				\
1217		       (Cardinal) 1);				\
1218		screen->curss = 0;				\
1219		single++;					\
1220	    }							\
1221	    if (sp->print_used > single) {			\
1222		dotext(xw,					\
1223		       screen->gsets[(int) (screen->curgl)],	\
1224		       sp->print_area + single,			\
1225		       (Cardinal) (sp->print_used - single));	\
1226	    }							\
1227	    sp->print_used = 0;					\
1228	}							\
1229
1230struct ParseState {
1231#if OPT_VT52_MODE
1232    Bool vt52_cup;
1233#endif
1234    Const PARSE_T *groundtable;
1235    Const PARSE_T *parsestate;
1236    int scstype;
1237    int scssize;
1238    Bool private_function;	/* distinguish private-mode from standard */
1239    int string_mode;		/* nonzero iff we're processing a string */
1240    int lastchar;		/* positive iff we had a graphic character */
1241    int nextstate;
1242#if OPT_WIDE_CHARS
1243    int last_was_wide;
1244#endif
1245    /* Buffer for processing printable text */
1246    IChar *print_area;
1247    size_t print_size;
1248    size_t print_used;
1249    /* Buffer for processing strings (e.g., OSC ... ST) */
1250    Char *string_area;
1251    size_t string_size;
1252    size_t string_used;
1253};
1254
1255static struct ParseState myState;
1256
1257static void
1258init_groundtable(TScreen * screen, struct ParseState *sp)
1259{
1260    (void) screen;
1261
1262#if OPT_VT52_MODE
1263    if (!(screen->vtXX_level)) {
1264	sp->groundtable = vt52_table;
1265    } else if (screen->terminal_id >= 100)
1266#endif
1267    {
1268	sp->groundtable = ansi_table;
1269    }
1270}
1271
1272static void
1273select_charset(struct ParseState *sp, int type, int size)
1274{
1275    TRACE(("select_charset %#x %d\n", type, size));
1276    sp->scstype = type;
1277    sp->scssize = size;
1278    if (size == 94) {
1279	sp->parsestate = scstable;
1280    } else {
1281	sp->parsestate = scs96table;
1282    }
1283}
1284
1285static Boolean
1286doparsing(XtermWidget xw, unsigned c, struct ParseState *sp)
1287{
1288    TScreen *screen = &xw->screen;
1289    int row;
1290    int col;
1291    int top;
1292    int bot;
1293    int count;
1294    int laststate;
1295    int thischar = -1;
1296    XTermRect myRect;
1297
1298    do {
1299#if OPT_WIDE_CHARS
1300	int this_is_wide = 0;
1301
1302	/*
1303	 * Handle zero-width combining characters.  Make it faster by noting
1304	 * that according to the Unicode charts, the majority of Western
1305	 * character sets do not use this feature.  There are some unassigned
1306	 * codes at 0x242, but no zero-width characters until past 0x300.
1307	 */
1308	if (c >= 0x300 && screen->wide_chars
1309	    && my_wcwidth((int) c) == 0
1310	    && !isWideControl(c)) {
1311	    int prev, precomposed;
1312
1313	    WriteNow();
1314
1315	    prev = (int) XTERM_CELL(screen->last_written_row,
1316				    screen->last_written_col);
1317	    precomposed = do_precomposition(prev, (int) c);
1318	    TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n",
1319		   prev, my_wcwidth(prev),
1320		   (int) c, my_wcwidth((int) c),
1321		   precomposed, my_wcwidth(precomposed)));
1322
1323	    /* substitute combined character with precomposed character
1324	     * only if it does not change the width of the base character
1325	     */
1326	    if (precomposed != -1 && my_wcwidth(precomposed) == my_wcwidth(prev)) {
1327		putXtermCell(screen,
1328			     screen->last_written_row,
1329			     screen->last_written_col, precomposed);
1330	    } else {
1331		addXtermCombining(screen,
1332				  screen->last_written_row,
1333				  screen->last_written_col, c);
1334	    }
1335
1336	    if (!screen->scroll_amt)
1337		ScrnUpdate(xw,
1338			   screen->last_written_row,
1339			   screen->last_written_col, 1, 1, 1);
1340	    continue;
1341	}
1342#endif
1343
1344	/* Intercept characters for printer controller mode */
1345	if (screen->printer_controlmode == 2) {
1346	    if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0)
1347		continue;
1348	}
1349
1350	/*
1351	 * VT52 is a little ugly in the one place it has a parameterized
1352	 * control sequence, since the parameter falls after the character
1353	 * that denotes the type of sequence.
1354	 */
1355#if OPT_VT52_MODE
1356	if (sp->vt52_cup) {
1357	    if (nparam < NPARAM)
1358		param[nparam++] = (int) (c & 0x7f) - 32;
1359	    if (nparam < 2)
1360		continue;
1361	    sp->vt52_cup = False;
1362	    if ((row = param[0]) < 0)
1363		row = 0;
1364	    if ((col = param[1]) < 0)
1365		col = 0;
1366	    CursorSet(screen, row, col, xw->flags);
1367	    sp->parsestate = vt52_table;
1368	    param[0] = 0;
1369	    param[1] = 0;
1370	    continue;
1371	}
1372#endif
1373
1374	laststate = sp->nextstate;
1375	if (c == ANSI_DEL
1376	    && sp->parsestate == sp->groundtable
1377	    && sp->scssize == 96
1378	    && sp->scstype != 0) {
1379	    /*
1380	     * Handle special case of shifts for 96-character sets by checking
1381	     * if we have a DEL.  The other special case for SPACE will always
1382	     * be printable.
1383	     */
1384	    sp->nextstate = CASE_PRINT;
1385	} else
1386#if OPT_WIDE_CHARS
1387	if (c > 255) {
1388	    /*
1389	     * The parsing tables all have 256 entries.  If we're supporting
1390	     * wide characters, we handle them by treating them the same as
1391	     * printing characters.
1392	     */
1393	    if (sp->parsestate == sp->groundtable) {
1394		sp->nextstate = CASE_PRINT;
1395	    } else if (sp->parsestate == sos_table) {
1396		c &= 0xffff;
1397		if (c > 255) {
1398		    TRACE(("Found code > 255 while in SOS state: %04X\n", c));
1399		    c = '?';
1400		}
1401	    } else {
1402		sp->nextstate = CASE_GROUND_STATE;
1403	    }
1404	} else
1405#endif
1406	    sp->nextstate = sp->parsestate[E2A(c)];
1407
1408#if OPT_BROKEN_OSC
1409	/*
1410	 * Linux console palette escape sequences start with an OSC, but do
1411	 * not terminate correctly.  Some scripts do not check before writing
1412	 * them, making xterm appear to hang (it's awaiting a valid string
1413	 * terminator).  Just ignore these if we see them - there's no point
1414	 * in emulating bad code.
1415	 */
1416	if (screen->brokenLinuxOSC
1417	    && sp->parsestate == sos_table) {
1418	    if (sp->string_used) {
1419		switch (sp->string_area[0]) {
1420		case 'P':
1421		    if (sp->string_used <= 7)
1422			break;
1423		    /* FALLTHRU */
1424		case 'R':
1425		    sp->parsestate = sp->groundtable;
1426		    sp->nextstate = sp->parsestate[E2A(c)];
1427		    TRACE(("Reset to ground state (brokenLinuxOSC)\n"));
1428		    break;
1429		}
1430	    }
1431	}
1432#endif
1433
1434#if OPT_BROKEN_ST
1435	/*
1436	 * Before patch #171, carriage control embedded within an OSC string
1437	 * would terminate it.  Some (buggy, of course) applications rely on
1438	 * this behavior.  Accommodate them by allowing one to compile xterm
1439	 * and emulate the old behavior.
1440	 */
1441	if (screen->brokenStringTerm
1442	    && sp->parsestate == sos_table
1443	    && c < 32) {
1444	    switch (c) {
1445	    case 5:		/* FALLTHRU */
1446	    case 8:		/* FALLTHRU */
1447	    case 9:		/* FALLTHRU */
1448	    case 10:		/* FALLTHRU */
1449	    case 11:		/* FALLTHRU */
1450	    case 12:		/* FALLTHRU */
1451	    case 13:		/* FALLTHRU */
1452	    case 14:		/* FALLTHRU */
1453	    case 15:		/* FALLTHRU */
1454	    case 24:
1455		sp->parsestate = sp->groundtable;
1456		sp->nextstate = sp->parsestate[E2A(c)];
1457		TRACE(("Reset to ground state (brokenStringTerm)\n"));
1458		break;
1459	    }
1460	}
1461#endif
1462
1463#if OPT_C1_PRINT
1464	/*
1465	 * This is not completely foolproof, but will allow an application
1466	 * with values in the C1 range to use them as printable characters,
1467	 * provided that they are not intermixed with an escape sequence.
1468	 */
1469	if (screen->c1_printable
1470	    && (c >= 128 && c < 160)) {
1471	    sp->nextstate = (sp->parsestate == esc_table
1472			     ? CASE_ESC_IGNORE
1473			     : sp->parsestate[E2A(160)]);
1474	}
1475#endif
1476
1477#if OPT_WIDE_CHARS
1478	/*
1479	 * If we have a C1 code and the c1_printable flag is not set, simply
1480	 * ignore it when it was translated from UTF-8.  That is because the
1481	 * value could not have been present as-is in the UTF-8.
1482	 *
1483	 * To see that CASE_IGNORE is a consistent value, note that it is
1484	 * always used for NUL and other uninteresting C0 controls.
1485	 */
1486#if OPT_C1_PRINT
1487	if (!screen->c1_printable)
1488#endif
1489	    if (screen->wide_chars
1490		&& (c >= 128 && c < 160)) {
1491		sp->nextstate = CASE_IGNORE;
1492	    }
1493
1494	/*
1495	 * If this character is a different width than the last one, put the
1496	 * previous text into the buffer and draw it now.
1497	 */
1498	this_is_wide = isWide((int) c);
1499	if (this_is_wide != sp->last_was_wide) {
1500	    WriteNow();
1501	}
1502#endif
1503
1504	/*
1505	 * Accumulate string for printable text.  This may be 8/16-bit
1506	 * characters.
1507	 */
1508	if (sp->nextstate == CASE_PRINT) {
1509	    SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size);
1510	    if (new_string == 0) {
1511		fprintf(stderr,
1512			"Cannot allocate %u bytes for printable text\n",
1513			new_length);
1514		continue;
1515	    }
1516#if OPT_VT52_MODE
1517	    /*
1518	     * Strip output text to 7-bits for VT52.  We should do this for
1519	     * VT100 also (which is a 7-bit device), but xterm has been
1520	     * doing this for so long we shouldn't change this behavior.
1521	     */
1522	    if (screen->vtXX_level < 1)
1523		c &= 0x7f;
1524#endif
1525	    sp->print_area = new_string;
1526	    sp->print_size = new_length;
1527	    sp->print_area[sp->print_used++] = (IChar) c;
1528	    sp->lastchar = thischar = (int) c;
1529#if OPT_WIDE_CHARS
1530	    sp->last_was_wide = this_is_wide;
1531#endif
1532	    if (morePtyData(screen, VTbuffer)) {
1533		continue;
1534	    }
1535	}
1536
1537	if (sp->nextstate == CASE_PRINT
1538	    || (laststate == CASE_PRINT && sp->print_used)) {
1539	    WriteNow();
1540	}
1541
1542	/*
1543	 * Accumulate string for APC, DCS, PM, OSC, SOS controls
1544	 * This should always be 8-bit characters.
1545	 */
1546	if (sp->parsestate == sos_table) {
1547	    SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size);
1548	    if (new_string == 0) {
1549		fprintf(stderr,
1550			"Cannot allocate %u bytes for string mode %d\n",
1551			new_length, sp->string_mode);
1552		continue;
1553	    }
1554#if OPT_WIDE_CHARS
1555	    /*
1556	     * We cannot display codes above 255, but let's try to
1557	     * accommodate the application a little by not aborting the
1558	     * string.
1559	     */
1560	    if ((c & 0xffff) > 255) {
1561		sp->nextstate = CASE_PRINT;
1562		c = '?';
1563	    }
1564#endif
1565	    sp->string_area = new_string;
1566	    sp->string_size = new_length;
1567	    sp->string_area[(sp->string_used)++] = CharOf(c);
1568	} else if (sp->parsestate != esc_table) {
1569	    /* if we were accumulating, we're not any more */
1570	    sp->string_mode = 0;
1571	    sp->string_used = 0;
1572	}
1573
1574	TRACE(("parse %04X -> %d %s\n", c, sp->nextstate, which_table(sp->parsestate)));
1575
1576	switch (sp->nextstate) {
1577	case CASE_PRINT:
1578	    TRACE(("CASE_PRINT - printable characters\n"));
1579	    break;
1580
1581	case CASE_GROUND_STATE:
1582	    TRACE(("CASE_GROUND_STATE - exit ignore mode\n"));
1583	    sp->parsestate = sp->groundtable;
1584	    break;
1585
1586	case CASE_IGNORE:
1587	    TRACE(("CASE_IGNORE - Ignore character %02X\n", c));
1588	    break;
1589
1590	case CASE_ENQ:
1591	    TRACE(("CASE_ENQ - answerback\n"));
1592	    for (count = 0; screen->answer_back[count] != 0; count++)
1593		unparseputc(xw, screen->answer_back[count]);
1594	    unparse_end(xw);
1595	    break;
1596
1597	case CASE_BELL:
1598	    TRACE(("CASE_BELL - bell\n"));
1599	    if (sp->string_mode == ANSI_OSC) {
1600		if (sp->string_used)
1601		    sp->string_area[--(sp->string_used)] = '\0';
1602		do_osc(xw, sp->string_area, sp->string_used, (int) c);
1603		sp->parsestate = sp->groundtable;
1604	    } else {
1605		/* bell */
1606		Bell(XkbBI_TerminalBell, 0);
1607	    }
1608	    break;
1609
1610	case CASE_BS:
1611	    TRACE(("CASE_BS - backspace\n"));
1612	    CursorBack(xw, 1);
1613	    break;
1614
1615	case CASE_CR:
1616	    /* CR */
1617	    CarriageReturn(screen);
1618	    break;
1619
1620	case CASE_ESC:
1621	    if_OPT_VT52_MODE(screen, {
1622		sp->parsestate = vt52_esc_table;
1623		break;
1624	    });
1625	    sp->parsestate = esc_table;
1626	    break;
1627
1628#if OPT_VT52_MODE
1629	case CASE_VT52_CUP:
1630	    TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n"));
1631	    sp->vt52_cup = True;
1632	    nparam = 0;
1633	    break;
1634
1635	case CASE_VT52_IGNORE:
1636	    TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n"));
1637	    sp->parsestate = vt52_ignore_table;
1638	    break;
1639#endif
1640
1641	case CASE_VMOT:
1642	    /*
1643	     * form feed, line feed, vertical tab
1644	     */
1645	    xtermAutoPrint(xw, c);
1646	    xtermIndex(xw, 1);
1647	    if (xw->flags & LINEFEED)
1648		CarriageReturn(screen);
1649	    else
1650		do_xevents();
1651	    break;
1652
1653	case CASE_CBT:
1654	    /* cursor backward tabulation */
1655	    if ((count = param[0]) == DEFAULT)
1656		count = 1;
1657	    while ((count-- > 0)
1658		   && (TabToPrevStop(xw))) ;
1659	    sp->parsestate = sp->groundtable;
1660	    break;
1661
1662	case CASE_CHT:
1663	    /* cursor forward tabulation */
1664	    if ((count = param[0]) == DEFAULT)
1665		count = 1;
1666	    while ((count-- > 0)
1667		   && (TabToNextStop(xw))) ;
1668	    sp->parsestate = sp->groundtable;
1669	    break;
1670
1671	case CASE_TAB:
1672	    /* tab */
1673	    TabToNextStop(xw);
1674	    break;
1675
1676	case CASE_SI:
1677	    screen->curgl = 0;
1678	    if_OPT_VT52_MODE(screen, {
1679		sp->parsestate = sp->groundtable;
1680	    });
1681	    break;
1682
1683	case CASE_SO:
1684	    screen->curgl = 1;
1685	    if_OPT_VT52_MODE(screen, {
1686		sp->parsestate = sp->groundtable;
1687	    });
1688	    break;
1689
1690	case CASE_DECDHL:
1691	    xterm_DECDHL(xw, c == '3');
1692	    sp->parsestate = sp->groundtable;
1693	    break;
1694
1695	case CASE_DECSWL:
1696	    xterm_DECSWL(xw);
1697	    sp->parsestate = sp->groundtable;
1698	    break;
1699
1700	case CASE_DECDWL:
1701	    xterm_DECDWL(xw);
1702	    sp->parsestate = sp->groundtable;
1703	    break;
1704
1705	case CASE_SCR_STATE:
1706	    /* enter scr state */
1707	    sp->parsestate = scrtable;
1708	    break;
1709
1710	case CASE_SCS0_STATE:
1711	    /* enter scs state 0 */
1712	    select_charset(sp, 0, 94);
1713	    break;
1714
1715	case CASE_SCS1_STATE:
1716	    /* enter scs state 1 */
1717	    select_charset(sp, 1, 94);
1718	    break;
1719
1720	case CASE_SCS2_STATE:
1721	    /* enter scs state 2 */
1722	    select_charset(sp, 2, 94);
1723	    break;
1724
1725	case CASE_SCS3_STATE:
1726	    /* enter scs state 3 */
1727	    select_charset(sp, 3, 94);
1728	    break;
1729
1730	case CASE_SCS1A_STATE:
1731	    /* enter scs state 1 */
1732	    select_charset(sp, 1, 96);
1733	    break;
1734
1735	case CASE_SCS2A_STATE:
1736	    /* enter scs state 2 */
1737	    select_charset(sp, 2, 96);
1738	    break;
1739
1740	case CASE_SCS3A_STATE:
1741	    /* enter scs state 3 */
1742	    select_charset(sp, 3, 96);
1743	    break;
1744
1745	case CASE_ESC_IGNORE:
1746	    /* unknown escape sequence */
1747	    sp->parsestate = eigtable;
1748	    break;
1749
1750	case CASE_ESC_DIGIT:
1751	    /* digit in csi or dec mode */
1752	    if ((row = param[nparam - 1]) == DEFAULT)
1753		row = 0;
1754	    param[nparam - 1] = (10 * row) + ((int) c - '0');
1755	    if (param[nparam - 1] > 65535)
1756		param[nparam - 1] = 65535;
1757	    if (sp->parsestate == csi_table)
1758		sp->parsestate = csi2_table;
1759	    break;
1760
1761	case CASE_ESC_SEMI:
1762	    /* semicolon in csi or dec mode */
1763	    if (nparam < NPARAM)
1764		param[nparam++] = DEFAULT;
1765	    if (sp->parsestate == csi_table)
1766		sp->parsestate = csi2_table;
1767	    break;
1768
1769	case CASE_DEC_STATE:
1770	    /* enter dec mode */
1771	    sp->parsestate = dec_table;
1772	    break;
1773
1774	case CASE_DEC2_STATE:
1775	    /* enter dec2 mode */
1776	    sp->parsestate = dec2_table;
1777	    break;
1778
1779	case CASE_DEC3_STATE:
1780	    /* enter dec3 mode */
1781	    sp->parsestate = dec3_table;
1782	    break;
1783
1784	case CASE_ICH:
1785	    TRACE(("CASE_ICH - insert char\n"));
1786	    if ((row = param[0]) < 1)
1787		row = 1;
1788	    InsertChar(xw, (unsigned) row);
1789	    sp->parsestate = sp->groundtable;
1790	    break;
1791
1792	case CASE_CUU:
1793	    TRACE(("CASE_CUU - cursor up\n"));
1794	    if ((row = param[0]) < 1)
1795		row = 1;
1796	    CursorUp(screen, row);
1797	    sp->parsestate = sp->groundtable;
1798	    break;
1799
1800	case CASE_CUD:
1801	    TRACE(("CASE_CUD - cursor down\n"));
1802	    if ((row = param[0]) < 1)
1803		row = 1;
1804	    CursorDown(screen, row);
1805	    sp->parsestate = sp->groundtable;
1806	    break;
1807
1808	case CASE_CUF:
1809	    TRACE(("CASE_CUF - cursor forward\n"));
1810	    if ((col = param[0]) < 1)
1811		col = 1;
1812	    CursorForward(screen, col);
1813	    sp->parsestate = sp->groundtable;
1814	    break;
1815
1816	case CASE_CUB:
1817	    TRACE(("CASE_CUB - cursor backward\n"));
1818	    if ((col = param[0]) < 1)
1819		col = 1;
1820	    CursorBack(xw, col);
1821	    sp->parsestate = sp->groundtable;
1822	    break;
1823
1824	case CASE_CUP:
1825	    TRACE(("CASE_CUP - cursor position\n"));
1826	    if_OPT_XMC_GLITCH(screen, {
1827		Jump_XMC(xw);
1828	    });
1829	    if ((row = param[0]) < 1)
1830		row = 1;
1831	    if (nparam < 2 || (col = param[1]) < 1)
1832		col = 1;
1833	    CursorSet(screen, row - 1, col - 1, xw->flags);
1834	    sp->parsestate = sp->groundtable;
1835	    break;
1836
1837	case CASE_VPA:
1838	    TRACE(("CASE_VPA - vertical position\n"));
1839	    if ((row = param[0]) < 1)
1840		row = 1;
1841	    CursorSet(screen, row - 1, screen->cur_col, xw->flags);
1842	    sp->parsestate = sp->groundtable;
1843	    break;
1844
1845	case CASE_HPA:
1846	    TRACE(("CASE_HPA - horizontal position\n"));
1847	    if ((col = param[0]) < 1)
1848		col = 1;
1849	    CursorSet(screen, screen->cur_row, col - 1, xw->flags);
1850	    sp->parsestate = sp->groundtable;
1851	    break;
1852
1853	case CASE_HP_BUGGY_LL:
1854	    TRACE(("CASE_HP_BUGGY_LL\n"));
1855	    /* Some HP-UX applications have the bug that they
1856	       assume ESC F goes to the lower left corner of
1857	       the screen, regardless of what terminfo says. */
1858	    if (screen->hp_ll_bc)
1859		CursorSet(screen, screen->max_row, 0, xw->flags);
1860	    sp->parsestate = sp->groundtable;
1861	    break;
1862
1863	case CASE_ED:
1864	    TRACE(("CASE_ED - erase display\n"));
1865	    do_erase_display(xw, param[0], OFF_PROTECT);
1866	    sp->parsestate = sp->groundtable;
1867	    break;
1868
1869	case CASE_EL:
1870	    TRACE(("CASE_EL - erase line\n"));
1871	    do_erase_line(xw, param[0], OFF_PROTECT);
1872	    sp->parsestate = sp->groundtable;
1873	    break;
1874
1875	case CASE_ECH:
1876	    TRACE(("CASE_ECH - erase char\n"));
1877	    /* ECH */
1878	    ClearRight(xw, param[0] < 1 ? 1 : param[0]);
1879	    sp->parsestate = sp->groundtable;
1880	    break;
1881
1882	case CASE_IL:
1883	    TRACE(("CASE_IL - insert line\n"));
1884	    if ((row = param[0]) < 1)
1885		row = 1;
1886	    InsertLine(xw, row);
1887	    sp->parsestate = sp->groundtable;
1888	    break;
1889
1890	case CASE_DL:
1891	    TRACE(("CASE_DL - delete line\n"));
1892	    if ((row = param[0]) < 1)
1893		row = 1;
1894	    DeleteLine(xw, row);
1895	    sp->parsestate = sp->groundtable;
1896	    break;
1897
1898	case CASE_DCH:
1899	    TRACE(("CASE_DCH - delete char\n"));
1900	    if ((row = param[0]) < 1)
1901		row = 1;
1902	    DeleteChar(xw, (unsigned) row);
1903	    sp->parsestate = sp->groundtable;
1904	    break;
1905
1906	case CASE_TRACK_MOUSE:
1907	    /*
1908	     * A single parameter other than zero is always scroll-down.
1909	     * A zero-parameter is used to reset the mouse mode, and is
1910	     * not useful for scrolling anyway.
1911	     */
1912	    if (nparam > 1 || param[0] == 0) {
1913		CELL start;
1914
1915		TRACE(("CASE_TRACK_MOUSE\n"));
1916		/* Track mouse as long as in window and between
1917		 * specified rows
1918		 */
1919		start.row = param[2] - 1;
1920		start.col = param[1] - 1;
1921		TrackMouse(xw,
1922			   param[0],
1923			   &start,
1924			   param[3] - 1, param[4] - 2);
1925	    } else {
1926		TRACE(("CASE_SD - scroll down\n"));
1927		/* SD */
1928		if ((count = param[0]) < 1)
1929		    count = 1;
1930		RevScroll(xw, count);
1931		do_xevents();
1932	    }
1933	    sp->parsestate = sp->groundtable;
1934	    break;
1935
1936	case CASE_DECID:
1937	    TRACE(("CASE_DECID\n"));
1938	    if_OPT_VT52_MODE(screen, {
1939		unparseputc(xw, ANSI_ESC);
1940		unparseputc(xw, '/');
1941		unparseputc(xw, 'Z');
1942		unparse_end(xw);
1943		sp->parsestate = sp->groundtable;
1944		break;
1945	    });
1946	    param[0] = DEFAULT;	/* Default ID parameter */
1947	    /* FALLTHRU */
1948	case CASE_DA1:
1949	    TRACE(("CASE_DA1\n"));
1950	    if (param[0] <= 0) {	/* less than means DEFAULT */
1951		count = 0;
1952		reply.a_type = ANSI_CSI;
1953		reply.a_pintro = '?';
1954
1955		/* The first param corresponds to the highest
1956		 * operating level (i.e., service level) of the
1957		 * emulation.  A DEC terminal can be setup to
1958		 * respond with a different DA response, but
1959		 * there's no control sequence that modifies this.
1960		 * We set it via a resource.
1961		 */
1962		if (screen->terminal_id < 200) {
1963		    switch (screen->terminal_id) {
1964		    case 102:
1965			reply.a_param[count++] = 6;	/* VT102 */
1966			break;
1967		    case 101:
1968			reply.a_param[count++] = 1;	/* VT101 */
1969			reply.a_param[count++] = 0;	/* no options */
1970			break;
1971		    default:	/* VT100 */
1972			reply.a_param[count++] = 1;	/* VT100 */
1973			reply.a_param[count++] = 2;	/* AVO */
1974			break;
1975		    }
1976		} else {
1977		    reply.a_param[count++] = (ParmType) (60
1978							 + screen->terminal_id
1979							 / 100);
1980		    reply.a_param[count++] = 1;		/* 132-columns */
1981		    reply.a_param[count++] = 2;		/* printer */
1982		    reply.a_param[count++] = 6;		/* selective-erase */
1983#if OPT_SUNPC_KBD
1984		    if (xw->keyboard.type == keyboardIsVT220)
1985#endif
1986			reply.a_param[count++] = 8;	/* user-defined-keys */
1987		    reply.a_param[count++] = 9;		/* national replacement charsets */
1988		    reply.a_param[count++] = 15;	/* technical characters */
1989		    if_OPT_ISO_COLORS(screen, {
1990			reply.a_param[count++] = 22;	/* ANSI color, VT525 */
1991		    });
1992#if OPT_DEC_LOCATOR
1993		    reply.a_param[count++] = 29;	/* ANSI text locator */
1994#endif
1995		}
1996		reply.a_nparam = (ParmType) count;
1997		reply.a_inters = 0;
1998		reply.a_final = 'c';
1999		unparseseq(xw, &reply);
2000	    }
2001	    sp->parsestate = sp->groundtable;
2002	    break;
2003
2004	case CASE_DA2:
2005	    TRACE(("CASE_DA2\n"));
2006	    if (param[0] <= 0) {	/* less than means DEFAULT */
2007		count = 0;
2008		reply.a_type = ANSI_CSI;
2009		reply.a_pintro = '>';
2010
2011		if (screen->terminal_id >= 200)
2012		    reply.a_param[count++] = 1;		/* VT220 */
2013		else
2014		    reply.a_param[count++] = 0;		/* VT100 (nonstandard) */
2015		reply.a_param[count++] = XTERM_PATCH;	/* Version */
2016		reply.a_param[count++] = 0;	/* options (none) */
2017		reply.a_nparam = (ParmType) count;
2018		reply.a_inters = 0;
2019		reply.a_final = 'c';
2020		unparseseq(xw, &reply);
2021	    }
2022	    sp->parsestate = sp->groundtable;
2023	    break;
2024
2025	case CASE_DECRPTUI:
2026	    TRACE(("CASE_DECRPTUI\n"));
2027	    if ((screen->terminal_id >= 400)
2028		&& (param[0] <= 0)) {	/* less than means DEFAULT */
2029		unparseputc1(xw, ANSI_DCS);
2030		unparseputc(xw, '!');
2031		unparseputc(xw, '|');
2032		unparseputc(xw, '0');
2033		unparseputc1(xw, ANSI_ST);
2034		unparse_end(xw);
2035	    }
2036	    sp->parsestate = sp->groundtable;
2037	    break;
2038
2039	case CASE_TBC:
2040	    TRACE(("CASE_TBC - tab clear\n"));
2041	    if ((row = param[0]) <= 0)	/* less than means default */
2042		TabClear(xw->tabs, screen->cur_col);
2043	    else if (row == 3)
2044		TabZonk(xw->tabs);
2045	    sp->parsestate = sp->groundtable;
2046	    break;
2047
2048	case CASE_SET:
2049	    TRACE(("CASE_SET - set mode\n"));
2050	    ansi_modes(xw, bitset);
2051	    sp->parsestate = sp->groundtable;
2052	    break;
2053
2054	case CASE_RST:
2055	    TRACE(("CASE_RST - reset mode\n"));
2056	    ansi_modes(xw, bitclr);
2057	    sp->parsestate = sp->groundtable;
2058	    break;
2059
2060	case CASE_SGR:
2061	    for (row = 0; row < nparam; ++row) {
2062		if_OPT_XMC_GLITCH(screen, {
2063		    Mark_XMC(xw, param[row]);
2064		});
2065		TRACE(("CASE_SGR %d\n", param[row]));
2066		switch (param[row]) {
2067		case DEFAULT:
2068		case 0:
2069		    xw->flags &=
2070			~(INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE);
2071		    if_OPT_ISO_COLORS(screen, {
2072			reset_SGR_Colors(xw);
2073		    });
2074		    break;
2075		case 1:	/* Bold                 */
2076		    xw->flags |= BOLD;
2077		    if_OPT_ISO_COLORS(screen, {
2078			setExtendedFG(xw);
2079		    });
2080		    break;
2081		case 5:	/* Blink                */
2082		    xw->flags |= BLINK;
2083		    StartBlinking(screen);
2084		    if_OPT_ISO_COLORS(screen, {
2085			setExtendedFG(xw);
2086		    });
2087		    break;
2088		case 4:	/* Underscore           */
2089		    xw->flags |= UNDERLINE;
2090		    if_OPT_ISO_COLORS(screen, {
2091			setExtendedFG(xw);
2092		    });
2093		    break;
2094		case 7:
2095		    xw->flags |= INVERSE;
2096		    if_OPT_ISO_COLORS(screen, {
2097			setExtendedBG(xw);
2098		    });
2099		    break;
2100		case 8:
2101		    xw->flags |= INVISIBLE;
2102		    break;
2103		case 22:	/* reset 'bold' */
2104		    xw->flags &= ~BOLD;
2105		    if_OPT_ISO_COLORS(screen, {
2106			setExtendedFG(xw);
2107		    });
2108		    break;
2109		case 24:
2110		    xw->flags &= ~UNDERLINE;
2111		    if_OPT_ISO_COLORS(screen, {
2112			setExtendedFG(xw);
2113		    });
2114		    break;
2115		case 25:	/* reset 'blink' */
2116		    xw->flags &= ~BLINK;
2117		    if_OPT_ISO_COLORS(screen, {
2118			setExtendedFG(xw);
2119		    });
2120		    break;
2121		case 27:
2122		    xw->flags &= ~INVERSE;
2123		    if_OPT_ISO_COLORS(screen, {
2124			setExtendedBG(xw);
2125		    });
2126		    break;
2127		case 28:
2128		    xw->flags &= ~INVISIBLE;
2129		    break;
2130		case 30:
2131		case 31:
2132		case 32:
2133		case 33:
2134		case 34:
2135		case 35:
2136		case 36:
2137		case 37:
2138		    if_OPT_ISO_COLORS(screen, {
2139			xw->sgr_foreground = (param[row] - 30);
2140			xw->sgr_extended = False;
2141			setExtendedFG(xw);
2142		    });
2143		    break;
2144		case 38:
2145		    /* This is more complicated than I'd
2146		       like, but it should properly eat all
2147		       the parameters for unsupported modes
2148		     */
2149		    if_OPT_ISO_COLORS(screen, {
2150			row++;
2151			if (row < nparam) {
2152			    switch (param[row]) {
2153			    case 5:
2154				row++;
2155				if (row < nparam &&
2156				    param[row] < NUM_ANSI_COLORS) {
2157				    xw->sgr_foreground = param[row];
2158				    xw->sgr_extended = True;
2159				    setExtendedFG(xw);
2160				}
2161				break;
2162			    default:
2163				row += 7;
2164				break;
2165			    }
2166			}
2167		    });
2168		    break;
2169		case 39:
2170		    if_OPT_ISO_COLORS(screen, {
2171			reset_SGR_Foreground(xw);
2172		    });
2173		    break;
2174		case 40:
2175		case 41:
2176		case 42:
2177		case 43:
2178		case 44:
2179		case 45:
2180		case 46:
2181		case 47:
2182		    if_OPT_ISO_COLORS(screen, {
2183			xw->sgr_background = (param[row] - 40);
2184			setExtendedBG(xw);
2185		    });
2186		    break;
2187		case 48:
2188		    if_OPT_ISO_COLORS(screen, {
2189			row++;
2190			if (row < nparam) {
2191			    switch (param[row]) {
2192			    case 5:
2193				row++;
2194				if (row < nparam &&
2195				    param[row] < NUM_ANSI_COLORS) {
2196				    xw->sgr_background = param[row];
2197				    setExtendedBG(xw);
2198				}
2199				break;
2200			    default:
2201				row += 7;
2202				break;
2203			    }
2204			}
2205		    });
2206		    break;
2207		case 49:
2208		    if_OPT_ISO_COLORS(screen, {
2209			reset_SGR_Background(xw);
2210		    });
2211		    break;
2212		case 90:
2213		case 91:
2214		case 92:
2215		case 93:
2216		case 94:
2217		case 95:
2218		case 96:
2219		case 97:
2220		    if_OPT_AIX_COLORS(screen, {
2221			xw->sgr_foreground = (param[row] - 90 + 8);
2222			xw->sgr_extended = False;
2223			setExtendedFG(xw);
2224		    });
2225		    break;
2226		case 100:
2227#if !OPT_AIX_COLORS
2228		    if_OPT_ISO_COLORS(screen, {
2229			reset_SGR_Foreground(xw);
2230			reset_SGR_Background(xw);
2231		    });
2232		    break;
2233#endif
2234		case 101:
2235		case 102:
2236		case 103:
2237		case 104:
2238		case 105:
2239		case 106:
2240		case 107:
2241		    if_OPT_AIX_COLORS(screen, {
2242			xw->sgr_background = (param[row] - 100 + 8);
2243			setExtendedBG(xw);
2244		    });
2245		    break;
2246		}
2247	    }
2248	    sp->parsestate = sp->groundtable;
2249	    break;
2250
2251	    /* DSR (except for the '?') is a superset of CPR */
2252	case CASE_DSR:
2253	    sp->private_function = True;
2254
2255	    /* FALLTHRU */
2256	case CASE_CPR:
2257	    TRACE(("CASE_CPR - cursor position\n"));
2258	    count = 0;
2259	    reply.a_type = ANSI_CSI;
2260	    reply.a_pintro = CharOf(sp->private_function ? '?' : 0);
2261	    reply.a_inters = 0;
2262	    reply.a_final = 'n';
2263
2264	    switch (param[0]) {
2265	    case 5:
2266		/* operating status */
2267		reply.a_param[count++] = 0;	/* (no malfunction ;-) */
2268		break;
2269	    case 6:
2270		/* CPR */
2271		/* DECXCPR (with page=0) */
2272		reply.a_param[count++] = (ParmType) (screen->cur_row + 1);
2273		reply.a_param[count++] = (ParmType) (screen->cur_col + 1);
2274		reply.a_final = 'R';
2275		break;
2276	    case 15:
2277		/* printer status */
2278		if (screen->terminal_id >= 200) {	/* VT220 */
2279		    reply.a_param[count++] = 13;	/* implement printer */
2280		}
2281		break;
2282	    case 25:
2283		/* UDK status */
2284		if (screen->terminal_id >= 200) {	/* VT220 */
2285		    reply.a_param[count++] = 20;	/* UDK always unlocked */
2286		}
2287		break;
2288	    case 26:
2289		/* keyboard status */
2290		if (screen->terminal_id >= 200) {	/* VT220 */
2291		    reply.a_param[count++] = 27;
2292		    reply.a_param[count++] = 1;		/* North American */
2293		    if (screen->terminal_id >= 400) {
2294			reply.a_param[count++] = 0;	/* ready */
2295			reply.a_param[count++] = 0;	/* LK201 */
2296		    }
2297		}
2298		break;
2299	    case 53:
2300		/* Locator status */
2301		if (screen->terminal_id >= 200) {	/* VT220 */
2302#if OPT_DEC_LOCATOR
2303		    reply.a_param[count++] = 50;	/* locator ready */
2304#else
2305		    reply.a_param[count++] = 53;	/* no locator */
2306#endif
2307		}
2308		break;
2309	    default:
2310		break;
2311	    }
2312
2313	    if ((reply.a_nparam = (ParmType) count) != 0)
2314		unparseseq(xw, &reply);
2315
2316	    sp->parsestate = sp->groundtable;
2317	    sp->private_function = False;
2318	    break;
2319
2320	case CASE_MC:
2321	    TRACE(("CASE_MC - media control\n"));
2322	    xtermMediaControl(xw, param[0], False);
2323	    sp->parsestate = sp->groundtable;
2324	    break;
2325
2326	case CASE_DEC_MC:
2327	    TRACE(("CASE_DEC_MC - DEC media control\n"));
2328	    xtermMediaControl(xw, param[0], True);
2329	    sp->parsestate = sp->groundtable;
2330	    break;
2331
2332	case CASE_HP_MEM_LOCK:
2333	case CASE_HP_MEM_UNLOCK:
2334	    TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK)
2335			    ? "CASE_HP_MEM_LOCK"
2336			    : "CASE_HP_MEM_UNLOCK")));
2337	    if (screen->scroll_amt)
2338		FlushScroll(xw);
2339	    if (sp->parsestate[c] == CASE_HP_MEM_LOCK)
2340		set_tb_margins(screen, screen->cur_row, screen->bot_marg);
2341	    else
2342		set_tb_margins(screen, 0, screen->bot_marg);
2343	    sp->parsestate = sp->groundtable;
2344	    break;
2345
2346	case CASE_DECSTBM:
2347	    TRACE(("CASE_DECSTBM - set scrolling region\n"));
2348	    if ((top = param[0]) < 1)
2349		top = 1;
2350	    if (nparam < 2 || (bot = param[1]) == DEFAULT
2351		|| bot > MaxRows(screen)
2352		|| bot == 0)
2353		bot = MaxRows(screen);
2354	    if (bot > top) {
2355		if (screen->scroll_amt)
2356		    FlushScroll(xw);
2357		set_tb_margins(screen, top - 1, bot - 1);
2358		CursorSet(screen, 0, 0, xw->flags);
2359	    }
2360	    sp->parsestate = sp->groundtable;
2361	    break;
2362
2363	case CASE_DECREQTPARM:
2364	    TRACE(("CASE_DECREQTPARM\n"));
2365	    if (screen->terminal_id < 200) {	/* VT102 */
2366		if ((row = param[0]) == DEFAULT)
2367		    row = 0;
2368		if (row == 0 || row == 1) {
2369		    reply.a_type = ANSI_CSI;
2370		    reply.a_pintro = 0;
2371		    reply.a_nparam = 7;
2372		    reply.a_param[0] = (ParmType) (row + 2);
2373		    reply.a_param[1] = 1;	/* no parity */
2374		    reply.a_param[2] = 1;	/* eight bits */
2375		    reply.a_param[3] = 128;	/* transmit 38.4k baud */
2376		    reply.a_param[4] = 128;	/* receive 38.4k baud */
2377		    reply.a_param[5] = 1;	/* clock multiplier ? */
2378		    reply.a_param[6] = 0;	/* STP flags ? */
2379		    reply.a_inters = 0;
2380		    reply.a_final = 'x';
2381		    unparseseq(xw, &reply);
2382		}
2383	    }
2384	    sp->parsestate = sp->groundtable;
2385	    break;
2386
2387	case CASE_DECSET:
2388	    /* DECSET */
2389#if OPT_VT52_MODE
2390	    if (screen->vtXX_level != 0)
2391#endif
2392		dpmodes(xw, bitset);
2393	    sp->parsestate = sp->groundtable;
2394#if OPT_TEK4014
2395	    if (TEK4014_ACTIVE(xw))
2396		return False;
2397#endif
2398	    break;
2399
2400	case CASE_DECRST:
2401	    /* DECRST */
2402	    dpmodes(xw, bitclr);
2403	    init_groundtable(screen, sp);
2404	    sp->parsestate = sp->groundtable;
2405	    break;
2406
2407	case CASE_DECALN:
2408	    TRACE(("CASE_DECALN - alignment test\n"));
2409	    if (screen->cursor_state)
2410		HideCursor();
2411	    set_tb_margins(screen, 0, screen->max_row);
2412	    CursorSet(screen, 0, 0, xw->flags);
2413	    xtermParseRect(xw, 0, 0, &myRect);
2414	    ScrnFillRectangle(xw, &myRect, 'E', 0, False);
2415	    sp->parsestate = sp->groundtable;
2416	    break;
2417
2418	case CASE_GSETS:
2419	    TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
2420	    if (screen->vtXX_level != 0)
2421		screen->gsets[sp->scstype] = CharOf(c);
2422	    sp->parsestate = sp->groundtable;
2423	    break;
2424
2425	case CASE_DECSC:
2426	    TRACE(("CASE_DECSC - save cursor\n"));
2427	    CursorSave(xw);
2428	    sp->parsestate = sp->groundtable;
2429	    break;
2430
2431	case CASE_DECRC:
2432	    TRACE(("CASE_DECRC - restore cursor\n"));
2433	    CursorRestore(xw);
2434	    if_OPT_ISO_COLORS(screen, {
2435		setExtendedFG(xw);
2436	    });
2437	    sp->parsestate = sp->groundtable;
2438	    break;
2439
2440	case CASE_DECKPAM:
2441	    TRACE(("CASE_DECKPAM\n"));
2442	    xw->keyboard.flags |= MODE_DECKPAM;
2443	    update_appkeypad();
2444	    sp->parsestate = sp->groundtable;
2445	    break;
2446
2447	case CASE_DECKPNM:
2448	    TRACE(("CASE_DECKPNM\n"));
2449	    xw->keyboard.flags &= ~MODE_DECKPAM;
2450	    update_appkeypad();
2451	    sp->parsestate = sp->groundtable;
2452	    break;
2453
2454	case CASE_CSI_QUOTE_STATE:
2455	    sp->parsestate = csi_quo_table;
2456	    break;
2457
2458#if OPT_VT52_MODE
2459	case CASE_VT52_FINISH:
2460	    TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n",
2461		   screen->terminal_id,
2462		   screen->vtXX_level));
2463	    if (screen->terminal_id >= 100
2464		&& screen->vtXX_level == 0) {
2465		sp->groundtable =
2466		    sp->parsestate = ansi_table;
2467		screen->vtXX_level = screen->vt52_save_level;
2468		screen->curgl = screen->vt52_save_curgl;
2469		screen->curgr = screen->vt52_save_curgr;
2470		screen->curss = screen->vt52_save_curss;
2471		memmove(screen->gsets, screen->vt52_save_gsets, sizeof(screen->gsets));
2472	    }
2473	    break;
2474#endif
2475
2476	case CASE_ANSI_LEVEL_1:
2477	    TRACE(("CASE_ANSI_LEVEL_1\n"));
2478	    set_ansi_conformance(screen, 1);
2479	    sp->parsestate = sp->groundtable;
2480	    break;
2481
2482	case CASE_ANSI_LEVEL_2:
2483	    TRACE(("CASE_ANSI_LEVEL_2\n"));
2484	    set_ansi_conformance(screen, 2);
2485	    sp->parsestate = sp->groundtable;
2486	    break;
2487
2488	case CASE_ANSI_LEVEL_3:
2489	    TRACE(("CASE_ANSI_LEVEL_3\n"));
2490	    set_ansi_conformance(screen, 3);
2491	    sp->parsestate = sp->groundtable;
2492	    break;
2493
2494	case CASE_DECSCL:
2495	    TRACE(("CASE_DECSCL(%d,%d)\n", param[0], param[1]));
2496	    if (param[0] >= 61 && param[0] <= 65) {
2497		/*
2498		 * VT300, VT420, VT520 manuals claim that DECSCL does a hard
2499		 * reset (RIS).  VT220 manual states that it is a soft reset.
2500		 * Perhaps both are right (unlikely).  Kermit says it's soft.
2501		 */
2502		VTReset(xw, False, False);
2503		screen->vtXX_level = param[0] - 60;
2504		if (param[0] > 61) {
2505		    if (param[1] == 1)
2506			show_8bit_control(False);
2507		    else if (param[1] == 0 || param[1] == 2)
2508			show_8bit_control(True);
2509		}
2510	    }
2511	    sp->parsestate = sp->groundtable;
2512	    break;
2513
2514	case CASE_DECSCA:
2515	    TRACE(("CASE_DECSCA\n"));
2516	    screen->protected_mode = DEC_PROTECT;
2517	    if (param[0] <= 0 || param[0] == 2)
2518		xw->flags &= ~PROTECTED;
2519	    else if (param[0] == 1)
2520		xw->flags |= PROTECTED;
2521	    sp->parsestate = sp->groundtable;
2522	    break;
2523
2524	case CASE_DECSED:
2525	    TRACE(("CASE_DECSED\n"));
2526	    do_erase_display(xw, param[0], DEC_PROTECT);
2527	    sp->parsestate = sp->groundtable;
2528	    break;
2529
2530	case CASE_DECSEL:
2531	    TRACE(("CASE_DECSEL\n"));
2532	    do_erase_line(xw, param[0], DEC_PROTECT);
2533	    sp->parsestate = sp->groundtable;
2534	    break;
2535
2536	case CASE_ST:
2537	    TRACE(("CASE_ST: End of String (%d bytes)\n", sp->string_used));
2538	    sp->parsestate = sp->groundtable;
2539	    if (!sp->string_used)
2540		break;
2541	    sp->string_area[--(sp->string_used)] = '\0';
2542	    switch (sp->string_mode) {
2543	    case ANSI_APC:
2544		/* ignored */
2545		break;
2546	    case ANSI_DCS:
2547		do_dcs(xw, sp->string_area, sp->string_used);
2548		break;
2549	    case ANSI_OSC:
2550		do_osc(xw, sp->string_area, sp->string_used, ANSI_ST);
2551		break;
2552	    case ANSI_PM:
2553		/* ignored */
2554		break;
2555	    case ANSI_SOS:
2556		/* ignored */
2557		break;
2558	    }
2559	    break;
2560
2561	case CASE_SOS:
2562	    TRACE(("CASE_SOS: Start of String\n"));
2563	    sp->string_mode = ANSI_SOS;
2564	    sp->parsestate = sos_table;
2565	    break;
2566
2567	case CASE_PM:
2568	    TRACE(("CASE_PM: Privacy Message\n"));
2569	    sp->string_mode = ANSI_PM;
2570	    sp->parsestate = sos_table;
2571	    break;
2572
2573	case CASE_DCS:
2574	    TRACE(("CASE_DCS: Device Control String\n"));
2575	    sp->string_mode = ANSI_DCS;
2576	    sp->parsestate = sos_table;
2577	    break;
2578
2579	case CASE_APC:
2580	    TRACE(("CASE_APC: Application Program Command\n"));
2581	    sp->string_mode = ANSI_APC;
2582	    sp->parsestate = sos_table;
2583	    break;
2584
2585	case CASE_SPA:
2586	    TRACE(("CASE_SPA - start protected area\n"));
2587	    screen->protected_mode = ISO_PROTECT;
2588	    xw->flags |= PROTECTED;
2589	    sp->parsestate = sp->groundtable;
2590	    break;
2591
2592	case CASE_EPA:
2593	    TRACE(("CASE_EPA - end protected area\n"));
2594	    xw->flags &= ~PROTECTED;
2595	    sp->parsestate = sp->groundtable;
2596	    break;
2597
2598	case CASE_SU:
2599	    TRACE(("CASE_SU - scroll up\n"));
2600	    if ((count = param[0]) < 1)
2601		count = 1;
2602	    xtermScroll(xw, count);
2603	    sp->parsestate = sp->groundtable;
2604	    break;
2605
2606	case CASE_IND:
2607	    TRACE(("CASE_IND - index\n"));
2608	    xtermIndex(xw, 1);
2609	    do_xevents();
2610	    sp->parsestate = sp->groundtable;
2611	    break;
2612
2613	case CASE_CPL:
2614	    TRACE(("CASE_CPL - cursor prev line\n"));
2615	    CursorPrevLine(screen, param[0]);
2616	    sp->parsestate = sp->groundtable;
2617	    break;
2618
2619	case CASE_CNL:
2620	    TRACE(("CASE_CNL - cursor next line\n"));
2621	    CursorNextLine(screen, param[0]);
2622	    sp->parsestate = sp->groundtable;
2623	    break;
2624
2625	case CASE_NEL:
2626	    TRACE(("CASE_NEL\n"));
2627	    xtermIndex(xw, 1);
2628	    CarriageReturn(screen);
2629	    sp->parsestate = sp->groundtable;
2630	    break;
2631
2632	case CASE_HTS:
2633	    TRACE(("CASE_HTS - horizontal tab set\n"));
2634	    TabSet(xw->tabs, screen->cur_col);
2635	    sp->parsestate = sp->groundtable;
2636	    break;
2637
2638	case CASE_RI:
2639	    TRACE(("CASE_RI - reverse index\n"));
2640	    RevIndex(xw, 1);
2641	    sp->parsestate = sp->groundtable;
2642	    break;
2643
2644	case CASE_SS2:
2645	    TRACE(("CASE_SS2\n"));
2646	    screen->curss = 2;
2647	    sp->parsestate = sp->groundtable;
2648	    break;
2649
2650	case CASE_SS3:
2651	    TRACE(("CASE_SS3\n"));
2652	    screen->curss = 3;
2653	    sp->parsestate = sp->groundtable;
2654	    break;
2655
2656	case CASE_CSI_STATE:
2657	    /* enter csi state */
2658	    nparam = 1;
2659	    param[0] = DEFAULT;
2660	    sp->parsestate = csi_table;
2661	    break;
2662
2663	case CASE_ESC_SP_STATE:
2664	    /* esc space */
2665	    sp->parsestate = esc_sp_table;
2666	    break;
2667
2668	case CASE_CSI_EX_STATE:
2669	    /* csi exclamation */
2670	    sp->parsestate = csi_ex_table;
2671	    break;
2672
2673#if OPT_DEC_LOCATOR
2674	case CASE_CSI_TICK_STATE:
2675	    /* csi tick (') */
2676	    sp->parsestate = csi_tick_table;
2677	    break;
2678
2679	case CASE_DECEFR:
2680	    TRACE(("CASE_DECEFR - Enable Filter Rectangle\n"));
2681	    if (screen->send_mouse_pos == DEC_LOCATOR) {
2682		MotionOff(screen, xw);
2683		if ((screen->loc_filter_top = param[0]) < 1)
2684		    screen->loc_filter_top = LOC_FILTER_POS;
2685		if (nparam < 2 || (screen->loc_filter_left = param[1]) < 1)
2686		    screen->loc_filter_left = LOC_FILTER_POS;
2687		if (nparam < 3 || (screen->loc_filter_bottom = param[2]) < 1)
2688		    screen->loc_filter_bottom = LOC_FILTER_POS;
2689		if (nparam < 4 || (screen->loc_filter_right = param[3]) < 1)
2690		    screen->loc_filter_right = LOC_FILTER_POS;
2691		InitLocatorFilter(xw);
2692	    }
2693	    sp->parsestate = sp->groundtable;
2694	    break;
2695
2696	case CASE_DECELR:
2697	    MotionOff(screen, xw);
2698	    if (param[0] <= 0 || param[0] > 2) {
2699		screen->send_mouse_pos = MOUSE_OFF;
2700		TRACE(("DECELR - Disable Locator Reports\n"));
2701	    } else {
2702		TRACE(("DECELR - Enable Locator Reports\n"));
2703		screen->send_mouse_pos = DEC_LOCATOR;
2704		xtermShowPointer(xw, True);
2705		if (param[0] == 2) {
2706		    screen->locator_reset = True;
2707		} else {
2708		    screen->locator_reset = False;
2709		}
2710		if (nparam < 2 || param[1] != 1) {
2711		    screen->locator_pixels = False;
2712		} else {
2713		    screen->locator_pixels = True;
2714		}
2715		screen->loc_filter = False;
2716	    }
2717	    sp->parsestate = sp->groundtable;
2718	    break;
2719
2720	case CASE_DECSLE:
2721	    TRACE(("DECSLE - Select Locator Events\n"));
2722	    for (count = 0; count < nparam; ++count) {
2723		switch (param[count]) {
2724		case DEFAULT:
2725		case 0:
2726		    MotionOff(screen, xw);
2727		    screen->loc_filter = False;
2728		    screen->locator_events = 0;
2729		    break;
2730		case 1:
2731		    screen->locator_events |= LOC_BTNS_DN;
2732		    break;
2733		case 2:
2734		    screen->locator_events &= ~LOC_BTNS_DN;
2735		    break;
2736		case 3:
2737		    screen->locator_events |= LOC_BTNS_UP;
2738		    break;
2739		case 4:
2740		    screen->locator_events &= ~LOC_BTNS_UP;
2741		    break;
2742		}
2743	    }
2744	    sp->parsestate = sp->groundtable;
2745	    break;
2746
2747	case CASE_DECRQLP:
2748	    TRACE(("DECRQLP - Request Locator Position\n"));
2749	    if (param[0] < 2) {
2750		/* Issue DECLRP Locator Position Report */
2751		GetLocatorPosition(xw);
2752	    }
2753	    sp->parsestate = sp->groundtable;
2754	    break;
2755#endif /* OPT_DEC_LOCATOR */
2756
2757#if OPT_DEC_RECTOPS
2758	case CASE_CSI_DOLLAR_STATE:
2759	    /* csi dollar ($) */
2760	    if (screen->vtXX_level >= 4)
2761		sp->parsestate = csi_dollar_table;
2762	    else
2763		sp->parsestate = eigtable;
2764	    break;
2765
2766	case CASE_CSI_STAR_STATE:
2767	    /* csi dollar (*) */
2768	    if (screen->vtXX_level >= 4)
2769		sp->parsestate = csi_star_table;
2770	    else
2771		sp->parsestate = eigtable;
2772	    break;
2773
2774	case CASE_DECCRA:
2775	    TRACE(("CASE_DECCRA - Copy rectangular area\n"));
2776	    xtermParseRect(xw, nparam, param, &myRect);
2777	    ScrnCopyRectangle(xw, &myRect, nparam - 5, param + 5);
2778	    sp->parsestate = sp->groundtable;
2779	    break;
2780
2781	case CASE_DECERA:
2782	    TRACE(("CASE_DECERA - Erase rectangular area\n"));
2783	    xtermParseRect(xw, nparam, param, &myRect);
2784	    ScrnFillRectangle(xw, &myRect, ' ', 0, True);
2785	    sp->parsestate = sp->groundtable;
2786	    break;
2787
2788	case CASE_DECFRA:
2789	    TRACE(("CASE_DECFRA - Fill rectangular area\n"));
2790	    if (nparam > 0
2791		&& ((param[0] >= 32 && param[0] <= 126)
2792		    || (param[0] >= 160 && param[0] <= 255))) {
2793		xtermParseRect(xw, nparam - 1, param + 1, &myRect);
2794		ScrnFillRectangle(xw, &myRect, param[0], xw->flags, True);
2795	    }
2796	    sp->parsestate = sp->groundtable;
2797	    break;
2798
2799	case CASE_DECSERA:
2800	    TRACE(("CASE_DECSERA - Selective erase rectangular area\n"));
2801	    xtermParseRect(xw, nparam > 4 ? 4 : nparam, param, &myRect);
2802	    ScrnWipeRectangle(xw, &myRect);
2803	    sp->parsestate = sp->groundtable;
2804	    break;
2805
2806	case CASE_DECSACE:
2807	    TRACE(("CASE_DECSACE - Select attribute change extent\n"));
2808	    screen->cur_decsace = param[0];
2809	    sp->parsestate = sp->groundtable;
2810	    break;
2811
2812	case CASE_DECCARA:
2813	    TRACE(("CASE_DECCARA - Change attributes in rectangular area\n"));
2814	    xtermParseRect(xw, nparam > 4 ? 4 : nparam, param, &myRect);
2815	    ScrnMarkRectangle(xw, &myRect, False, nparam - 4, param + 4);
2816	    sp->parsestate = sp->groundtable;
2817	    break;
2818
2819	case CASE_DECRARA:
2820	    TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n"));
2821	    xtermParseRect(xw, nparam > 4 ? 4 : nparam, param, &myRect);
2822	    ScrnMarkRectangle(xw, &myRect, True, nparam - 4, param + 4);
2823	    sp->parsestate = sp->groundtable;
2824	    break;
2825#else
2826	case CASE_CSI_DOLLAR_STATE:
2827	    /* csi dollar ($) */
2828	    sp->parsestate = eigtable;
2829	    break;
2830
2831	case CASE_CSI_STAR_STATE:
2832	    /* csi dollar (*) */
2833	    sp->parsestate = eigtable;
2834	    break;
2835#endif /* OPT_DEC_RECTOPS */
2836
2837	case CASE_S7C1T:
2838	    TRACE(("CASE_S7C1T\n"));
2839	    show_8bit_control(False);
2840	    sp->parsestate = sp->groundtable;
2841	    break;
2842
2843	case CASE_S8C1T:
2844	    TRACE(("CASE_S8C1T\n"));
2845#if OPT_VT52_MODE
2846	    if (screen->vtXX_level <= 1)
2847		break;
2848#endif
2849	    show_8bit_control(True);
2850	    sp->parsestate = sp->groundtable;
2851	    break;
2852
2853	case CASE_OSC:
2854	    TRACE(("CASE_OSC: Operating System Command\n"));
2855	    sp->parsestate = sos_table;
2856	    sp->string_mode = ANSI_OSC;
2857	    break;
2858
2859	case CASE_RIS:
2860	    TRACE(("CASE_RIS\n"));
2861	    VTReset(xw, True, True);
2862	    sp->parsestate = sp->groundtable;
2863	    break;
2864
2865	case CASE_DECSTR:
2866	    TRACE(("CASE_DECSTR\n"));
2867	    VTReset(xw, False, False);
2868	    sp->parsestate = sp->groundtable;
2869	    break;
2870
2871	case CASE_REP:
2872	    TRACE(("CASE_REP\n"));
2873	    if (sp->lastchar >= 0 &&
2874		sp->lastchar < 256 &&
2875		sp->groundtable[E2A(sp->lastchar)] == CASE_PRINT) {
2876		IChar repeated[2];
2877		count = (param[0] < 1) ? 1 : param[0];
2878		repeated[0] = (IChar) sp->lastchar;
2879		while (count-- > 0) {
2880		    dotext(xw,
2881			   screen->gsets[(int) (screen->curgl)],
2882			   repeated, 1);
2883		}
2884	    }
2885	    sp->parsestate = sp->groundtable;
2886	    break;
2887
2888	case CASE_LS2:
2889	    TRACE(("CASE_LS2\n"));
2890	    screen->curgl = 2;
2891	    sp->parsestate = sp->groundtable;
2892	    break;
2893
2894	case CASE_LS3:
2895	    TRACE(("CASE_LS3\n"));
2896	    screen->curgl = 3;
2897	    sp->parsestate = sp->groundtable;
2898	    break;
2899
2900	case CASE_LS3R:
2901	    TRACE(("CASE_LS3R\n"));
2902	    screen->curgr = 3;
2903	    sp->parsestate = sp->groundtable;
2904	    break;
2905
2906	case CASE_LS2R:
2907	    TRACE(("CASE_LS2R\n"));
2908	    screen->curgr = 2;
2909	    sp->parsestate = sp->groundtable;
2910	    break;
2911
2912	case CASE_LS1R:
2913	    TRACE(("CASE_LS1R\n"));
2914	    screen->curgr = 1;
2915	    sp->parsestate = sp->groundtable;
2916	    break;
2917
2918	case CASE_XTERM_SAVE:
2919	    savemodes(xw);
2920	    sp->parsestate = sp->groundtable;
2921	    break;
2922
2923	case CASE_XTERM_RESTORE:
2924	    restoremodes(xw);
2925	    sp->parsestate = sp->groundtable;
2926	    break;
2927
2928	case CASE_XTERM_WINOPS:
2929	    TRACE(("CASE_XTERM_WINOPS\n"));
2930	    if (AllowWindowOps(xw))
2931		window_ops(xw);
2932	    sp->parsestate = sp->groundtable;
2933	    break;
2934#if OPT_WIDE_CHARS
2935	case CASE_ESC_PERCENT:
2936	    sp->parsestate = esc_pct_table;
2937	    break;
2938
2939	case CASE_UTF8:
2940	    /* If we did not set UTF-8 mode from resource or the
2941	     * command-line, allow it to be enabled/disabled by
2942	     * control sequence.
2943	     */
2944	    if (!screen->wide_chars) {
2945		WriteNow();
2946		ChangeToWide(xw);
2947	    }
2948	    if (screen->wide_chars
2949		&& screen->utf8_mode != uAlways) {
2950		switchPtyData(screen, c == 'G');
2951		TRACE(("UTF8 mode %s\n",
2952		       BtoS(screen->utf8_mode)));
2953	    } else {
2954		TRACE(("UTF8 mode NOT turned %s (%s)\n",
2955		       BtoS(c == 'G'),
2956		       (screen->utf8_mode == uAlways)
2957		       ? "UTF-8 mode set from command-line"
2958		       : "wideChars resource was not set"));
2959	    }
2960	    sp->parsestate = sp->groundtable;
2961	    break;
2962#endif
2963#if OPT_MOD_FKEYS
2964	case CASE_SET_MOD_FKEYS:
2965	    TRACE(("CASE_SET_MOD_FKEYS\n"));
2966	    if (nparam >= 1) {
2967		set_mod_fkeys(xw, param[0], nparam > 1 ? param[1] : DEFAULT, True);
2968	    } else {
2969		for (row = 1; row <= 5; ++row)
2970		    set_mod_fkeys(xw, row, DEFAULT, True);
2971	    }
2972	    break;
2973	case CASE_SET_MOD_FKEYS0:
2974	    TRACE(("CASE_SET_MOD_FKEYS0\n"));
2975	    if (nparam >= 1 && param[0] != DEFAULT) {
2976		set_mod_fkeys(xw, param[0], -1, False);
2977	    } else {
2978		xw->keyboard.modify_now.function_keys = -1;
2979	    }
2980	    break;
2981#endif
2982	case CASE_HIDE_POINTER:
2983	    TRACE(("CASE_HIDE_POINTER\n"));
2984	    if (nparam >= 1 && param[0] != DEFAULT) {
2985		screen->pointer_mode = param[0];
2986	    } else {
2987		screen->pointer_mode = DEF_POINTER_MODE;
2988	    }
2989	    break;
2990
2991	case CASE_CSI_IGNORE:
2992	    sp->parsestate = cigtable;
2993	    break;
2994	}
2995	if (sp->parsestate == sp->groundtable)
2996	    sp->lastchar = thischar;
2997    } while (0);
2998
2999#if OPT_WIDE_CHARS
3000    screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse)
3001				      && (sp->parsestate != sos_table));
3002#endif
3003
3004    return True;
3005}
3006
3007static void
3008VTparse(XtermWidget xw)
3009{
3010    TScreen *screen;
3011
3012    /* We longjmp back to this point in VTReset() */
3013    (void) setjmp(vtjmpbuf);
3014    screen = &xw->screen;
3015    memset(&myState, 0, sizeof(myState));
3016    myState.scssize = 94;	/* number of printable/nonspace ASCII */
3017    myState.lastchar = -1;	/* not a legal IChar */
3018    myState.nextstate = -1;	/* not a legal state */
3019
3020    init_groundtable(screen, &myState);
3021    myState.parsestate = myState.groundtable;
3022
3023    do {
3024    } while (doparsing(xw, doinput(), &myState));
3025}
3026
3027static Char *v_buffer;		/* pointer to physical buffer */
3028static Char *v_bufstr = NULL;	/* beginning of area to write */
3029static Char *v_bufptr;		/* end of area to write */
3030static Char *v_bufend;		/* end of physical buffer */
3031
3032/* Write data to the pty as typed by the user, pasted with the mouse,
3033   or generated by us in response to a query ESC sequence. */
3034
3035int
3036v_write(int f, Char * data, unsigned len)
3037{
3038    int riten;
3039    unsigned c = len;
3040
3041    if (v_bufstr == NULL && len > 0) {
3042	v_buffer = (Char *) XtMalloc((Cardinal) len);
3043	v_bufstr = v_buffer;
3044	v_bufptr = v_buffer;
3045	v_bufend = v_buffer + len;
3046    }
3047#ifdef DEBUG
3048    if (debug) {
3049	fprintf(stderr, "v_write called with %d bytes (%d left over)",
3050		len, v_bufptr - v_bufstr);
3051	if (len > 1 && len < 10)
3052	    fprintf(stderr, " \"%.*s\"", len, (char *) data);
3053	fprintf(stderr, "\n");
3054    }
3055#endif
3056
3057#ifdef VMS
3058    if ((1 << f) != pty_mask)
3059	return (tt_write((char *) data, len));
3060#else /* VMS */
3061    if (!FD_ISSET(f, &pty_mask))
3062	return (write(f, (char *) data, len));
3063#endif /* VMS */
3064
3065    /*
3066     * Append to the block we already have.
3067     * Always doing this simplifies the code, and
3068     * isn't too bad, either.  If this is a short
3069     * block, it isn't too expensive, and if this is
3070     * a long block, we won't be able to write it all
3071     * anyway.
3072     */
3073
3074    if (len > 0) {
3075#if OPT_DABBREV
3076	term->screen.dabbrev_working = False;	/* break dabbrev sequence */
3077#endif
3078	if (v_bufend < v_bufptr + len) {	/* we've run out of room */
3079	    if (v_bufstr != v_buffer) {
3080		/* there is unused space, move everything down */
3081		/* possibly overlapping memmove here */
3082#ifdef DEBUG
3083		if (debug)
3084		    fprintf(stderr, "moving data down %d\n",
3085			    v_bufstr - v_buffer);
3086#endif
3087		memmove(v_buffer, v_bufstr, (unsigned) (v_bufptr - v_bufstr));
3088		v_bufptr -= v_bufstr - v_buffer;
3089		v_bufstr = v_buffer;
3090	    }
3091	    if (v_bufend < v_bufptr + len) {
3092		/* still won't fit: get more space */
3093		/* Don't use XtRealloc because an error is not fatal. */
3094		unsigned size = (unsigned) (v_bufptr - v_buffer);
3095		v_buffer = TypeRealloc(Char, size + len, v_buffer);
3096		if (v_buffer) {
3097#ifdef DEBUG
3098		    if (debug)
3099			fprintf(stderr, "expanded buffer to %d\n",
3100				size + len);
3101#endif
3102		    v_bufstr = v_buffer;
3103		    v_bufptr = v_buffer + size;
3104		    v_bufend = v_bufptr + len;
3105		} else {
3106		    /* no memory: ignore entire write request */
3107		    fprintf(stderr, "%s: cannot allocate buffer space\n",
3108			    xterm_name);
3109		    v_buffer = v_bufstr;	/* restore clobbered pointer */
3110		    c = 0;
3111		}
3112	    }
3113	}
3114	if (v_bufend >= v_bufptr + len) {
3115	    /* new stuff will fit */
3116	    memmove(v_bufptr, data, len);
3117	    v_bufptr += len;
3118	}
3119    }
3120
3121    /*
3122     * Write out as much of the buffer as we can.
3123     * Be careful not to overflow the pty's input silo.
3124     * We are conservative here and only write
3125     * a small amount at a time.
3126     *
3127     * If we can't push all the data into the pty yet, we expect write
3128     * to return a non-negative number less than the length requested
3129     * (if some data written) or -1 and set errno to EAGAIN,
3130     * EWOULDBLOCK, or EINTR (if no data written).
3131     *
3132     * (Not all systems do this, sigh, so the code is actually
3133     * a little more forgiving.)
3134     */
3135
3136#define MAX_PTY_WRITE 128	/* 1/2 POSIX minimum MAX_INPUT */
3137
3138    if (v_bufptr > v_bufstr) {
3139#ifdef VMS
3140	riten = tt_write(v_bufstr,
3141			 ((v_bufptr - v_bufstr <= VMS_TERM_BUFFER_SIZE)
3142			  ? v_bufptr - v_bufstr
3143			  : VMS_TERM_BUFFER_SIZE));
3144	if (riten == 0)
3145	    return (riten);
3146#else /* VMS */
3147	riten = write(f, v_bufstr,
3148		      (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE)
3149				? v_bufptr - v_bufstr
3150				: MAX_PTY_WRITE));
3151	if (riten < 0)
3152#endif /* VMS */
3153	{
3154#ifdef DEBUG
3155	    if (debug)
3156		perror("write");
3157#endif
3158	    riten = 0;
3159	}
3160#ifdef DEBUG
3161	if (debug)
3162	    fprintf(stderr, "write called with %d, wrote %d\n",
3163		    v_bufptr - v_bufstr <= MAX_PTY_WRITE ?
3164		    v_bufptr - v_bufstr : MAX_PTY_WRITE,
3165		    riten);
3166#endif
3167	v_bufstr += riten;
3168	if (v_bufstr >= v_bufptr)	/* we wrote it all */
3169	    v_bufstr = v_bufptr = v_buffer;
3170    }
3171
3172    /*
3173     * If we have lots of unused memory allocated, return it
3174     */
3175    if (v_bufend - v_bufptr > 1024) {	/* arbitrary hysteresis */
3176	/* save pointers across realloc */
3177	int start = v_bufstr - v_buffer;
3178	int size = v_bufptr - v_buffer;
3179	unsigned allocsize = (unsigned) (size ? size : 1);
3180
3181	v_buffer = TypeRealloc(Char, allocsize, v_buffer);
3182	if (v_buffer) {
3183	    v_bufstr = v_buffer + start;
3184	    v_bufptr = v_buffer + size;
3185	    v_bufend = v_buffer + allocsize;
3186#ifdef DEBUG
3187	    if (debug)
3188		fprintf(stderr, "shrunk buffer to %d\n", allocsize);
3189#endif
3190	} else {
3191	    /* should we print a warning if couldn't return memory? */
3192	    v_buffer = v_bufstr - start;	/* restore clobbered pointer */
3193	}
3194    }
3195    return ((int) c);
3196}
3197
3198#ifdef VMS
3199#define	ptymask()	(v_bufptr > v_bufstr ? pty_mask : 0)
3200
3201static void
3202in_put(XtermWidget xw)
3203{
3204    static PtySelect select_mask;
3205    static PtySelect write_mask;
3206    int update = VTbuffer->update;
3207    int size;
3208
3209    int status;
3210    Dimension replyWidth, replyHeight;
3211    XtGeometryResult stat;
3212
3213    TScreen *screen = &xw->screen;
3214    char *cp;
3215    int i;
3216
3217    select_mask = pty_mask;	/* force initial read */
3218    for (;;) {
3219
3220	/* if the terminal changed size, resize the widget */
3221	if (tt_changed) {
3222	    tt_changed = False;
3223
3224	    stat = REQ_RESIZE((Widget) xw,
3225			      ((Dimension) FontWidth(screen)
3226			       * (tt_width)
3227			       + 2 * screen->border
3228			       + screen->fullVwin.sb_info.width),
3229			      ((Dimension) FontHeight(screen)
3230			       * (tt_length)
3231			       + 2 * screen->border),
3232			      &replyWidth, &replyHeight);
3233
3234	    if (stat == XtGeometryYes || stat == XtGeometryDone) {
3235		xw->core.width = replyWidth;
3236		xw->core.height = replyHeight;
3237
3238		ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
3239	    }
3240	    repairSizeHints();
3241	}
3242
3243	if (screen->eventMode == NORMAL
3244	    && readPtyData(screen, &select_mask, VTbuffer)) {
3245	    if (screen->scrollWidget
3246		&& screen->scrollttyoutput
3247		&& screen->topline < 0)
3248		/* Scroll to bottom */
3249		WindowScroll(xw, 0);
3250	    break;
3251	}
3252	if (screen->scroll_amt)
3253	    FlushScroll(xw);
3254	if (screen->cursor_set && CursorMoved(screen)) {
3255	    if (screen->cursor_state)
3256		HideCursor();
3257	    ShowCursor();
3258#if OPT_INPUT_METHOD
3259	    PreeditPosition(screen);
3260#endif
3261	} else if (screen->cursor_set != screen->cursor_state) {
3262	    if (screen->cursor_set)
3263		ShowCursor();
3264	    else
3265		HideCursor();
3266	}
3267
3268	if (QLength(screen->display)) {
3269	    select_mask = X_mask;
3270	} else {
3271	    write_mask = ptymask();
3272	    XFlush(screen->display);
3273	    select_mask = Select_mask;
3274	    if (screen->eventMode != NORMAL)
3275		select_mask = X_mask;
3276	}
3277	if (write_mask & ptymask()) {
3278	    v_write(screen->respond, 0, 0);	/* flush buffer */
3279	}
3280
3281	if (select_mask & X_mask) {
3282	    xevents();
3283	    if (VTbuffer->update != update)
3284		break;
3285	}
3286    }
3287}
3288#else /* VMS */
3289
3290static void
3291in_put(XtermWidget xw)
3292{
3293    static PtySelect select_mask;
3294    static PtySelect write_mask;
3295
3296    TScreen *screen = &xw->screen;
3297    int i, time_select;
3298    int size;
3299    int update = VTbuffer->update;
3300
3301    static struct timeval select_timeout;
3302
3303#if OPT_BLINK_CURS
3304    /*
3305     * Compute the timeout for the blinking cursor to be much smaller than
3306     * the "on" or "off" interval.
3307     */
3308    int tick = ((screen->blink_on < screen->blink_off)
3309		? screen->blink_on
3310		: screen->blink_off);
3311    tick *= (1000 / 8);		/* 1000 for msec/usec, 8 for "much" smaller */
3312    if (tick < 1)
3313	tick = 1;
3314#endif
3315
3316    for (;;) {
3317	if (screen->eventMode == NORMAL
3318	    && (size = readPtyData(screen, &select_mask, VTbuffer)) != 0) {
3319	    if (screen->scrollWidget
3320		&& screen->scrollttyoutput
3321		&& screen->topline < 0)
3322		WindowScroll(xw, 0);	/* Scroll to bottom */
3323	    /* stop speed reading at some point to look for X stuff */
3324	    TRACE(("VTbuffer uses %d/%d\n",
3325		   VTbuffer->last - VTbuffer->buffer,
3326		   BUF_SIZE));
3327	    if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) {
3328		FD_CLR(screen->respond, &select_mask);
3329		break;
3330	    }
3331#if defined(HAVE_SCHED_YIELD)
3332	    /*
3333	     * If we've read a full (small/fragment) buffer, let the operating
3334	     * system have a turn, and we'll resume reading until we've either
3335	     * read only a fragment of the buffer, or we've filled the large
3336	     * buffer (see above).  Doing this helps keep up with large bursts
3337	     * of output.
3338	     */
3339	    if (size == FRG_SIZE) {
3340		select_timeout.tv_sec = 0;
3341		i = Select(max_plus1, &select_mask, &write_mask, 0,
3342			   &select_timeout);
3343		if (i > 0) {
3344		    sched_yield();
3345		} else
3346		    break;
3347	    } else {
3348		break;
3349	    }
3350#else
3351	    (void) size;	/* unused in this branch */
3352	    break;
3353#endif
3354	}
3355	/* update the screen */
3356	if (screen->scroll_amt)
3357	    FlushScroll(xw);
3358	if (screen->cursor_set && CursorMoved(screen)) {
3359	    if (screen->cursor_state)
3360		HideCursor();
3361	    ShowCursor();
3362#if OPT_INPUT_METHOD
3363	    PreeditPosition(screen);
3364#endif
3365	} else if (screen->cursor_set != screen->cursor_state) {
3366	    if (screen->cursor_set)
3367		ShowCursor();
3368	    else
3369		HideCursor();
3370	}
3371
3372	XFlush(screen->display);	/* always flush writes before waiting */
3373
3374	/* Update the masks and, unless X events are already in the queue,
3375	   wait for I/O to be possible. */
3376	XFD_COPYSET(&Select_mask, &select_mask);
3377	/* in selection mode xterm does not read pty */
3378	if (screen->eventMode != NORMAL)
3379	    FD_CLR(screen->respond, &select_mask);
3380
3381	if (v_bufptr > v_bufstr) {
3382	    XFD_COPYSET(&pty_mask, &write_mask);
3383	} else
3384	    FD_ZERO(&write_mask);
3385	select_timeout.tv_sec = 0;
3386	time_select = 0;
3387
3388	/*
3389	 * if there's either an XEvent or an XtTimeout pending, just take
3390	 * a quick peek, i.e. timeout from the select() immediately.  If
3391	 * there's nothing pending, let select() block a little while, but
3392	 * for a shorter interval than the arrow-style scrollbar timeout.
3393	 * The blocking is optional, because it tends to increase the load
3394	 * on the host.
3395	 */
3396	if (XtAppPending(app_con)) {
3397	    select_timeout.tv_usec = 0;
3398	    time_select = 1;
3399	} else if (screen->awaitInput) {
3400	    select_timeout.tv_usec = 50000;
3401	    time_select = 1;
3402#if OPT_BLINK_CURS
3403	} else if ((screen->blink_timer != 0 &&
3404		    ((screen->select & FOCUS) || screen->always_highlight)) ||
3405		   (screen->cursor_state == BLINKED_OFF)) {
3406	    select_timeout.tv_usec = tick;
3407	    while (select_timeout.tv_usec > 1000000) {
3408		select_timeout.tv_usec -= 1000000;
3409		select_timeout.tv_sec++;
3410	    }
3411	    time_select = 1;
3412#endif
3413#if OPT_SESSION_MGT
3414	} else if (resource.sessionMgt) {
3415	    if (ice_fd >= 0)
3416		FD_SET(ice_fd, &select_mask);
3417#endif
3418	}
3419	if (need_cleanup)
3420	    Cleanup(0);
3421	i = Select(max_plus1, &select_mask, &write_mask, 0,
3422		   (time_select ? &select_timeout : 0));
3423	if (i < 0) {
3424	    if (errno != EINTR)
3425		SysError(ERROR_SELECT);
3426	    continue;
3427	}
3428
3429	/* if there is room to write more data to the pty, go write more */
3430	if (FD_ISSET(screen->respond, &write_mask)) {
3431	    v_write(screen->respond, (Char *) 0, 0);	/* flush buffer */
3432	}
3433
3434	/* if there are X events already in our queue, it
3435	   counts as being readable */
3436	if (XtAppPending(app_con) ||
3437	    FD_ISSET(ConnectionNumber(screen->display), &select_mask)) {
3438	    xevents();
3439	    if (VTbuffer->update != update)	/* HandleInterpret */
3440		break;
3441	}
3442
3443    }
3444}
3445#endif /* VMS */
3446
3447static IChar
3448doinput(void)
3449{
3450    TScreen *screen = TScreenOf(term);
3451
3452    while (!morePtyData(screen, VTbuffer))
3453	in_put(term);
3454    return nextPtyData(screen, VTbuffer);
3455}
3456
3457#if OPT_INPUT_METHOD
3458/*
3459 *  For OverTheSpot, client has to inform the position for XIM preedit.
3460 */
3461static void
3462PreeditPosition(TScreen * screen)
3463{
3464    LineData *ld;
3465    XPoint spot;
3466    XVaNestedList list;
3467
3468    if (screen->xic
3469	&& (ld = getLineData(screen, screen->cur_row)) != 0) {
3470	spot.x = (short) LineCursorX(screen, ld, screen->cur_col);
3471	spot.y = (short) (CursorY(screen, screen->cur_row) + screen->fs_ascent);
3472	list = XVaCreateNestedList(0,
3473				   XNSpotLocation, &spot,
3474				   XNForeground, T_COLOR(screen, TEXT_FG),
3475				   XNBackground, T_COLOR(screen, TEXT_BG),
3476				   NULL);
3477	XSetICValues(screen->xic, XNPreeditAttributes, list, NULL);
3478	XFree(list);
3479    }
3480}
3481#endif
3482
3483static void
3484WrapLine(XtermWidget xw)
3485{
3486    TScreen *screen = &(xw->screen);
3487    LineData *ld = getLineData(screen, screen->cur_row);
3488
3489    if (ld != 0) {
3490	/* mark that we had to wrap this line */
3491	LineSetFlag(ld, LINEWRAPPED);
3492	xtermAutoPrint(xw, '\n');
3493	xtermIndex(xw, 1);
3494	set_cur_col(screen, 0);
3495    }
3496}
3497
3498/*
3499 * process a string of characters according to the character set indicated
3500 * by charset.  worry about end of line conditions (wraparound if selected).
3501 */
3502void
3503dotext(XtermWidget xw,
3504       int charset,
3505       IChar * buf,		/* start of characters to process */
3506       Cardinal len)		/* end */
3507{
3508    TScreen *screen = &(xw->screen);
3509#if OPT_WIDE_CHARS
3510    Cardinal chars_chomped = 1;
3511    int next_col = screen->cur_col;
3512#else
3513    int next_col, last_col, this_col;	/* must be signed */
3514#endif
3515    Cardinal offset;
3516
3517#if OPT_WIDE_CHARS
3518    /* don't translate if we use UTF-8, and are not handling legacy support
3519     * for line-drawing characters.
3520     */
3521    if ((screen->utf8_mode == uFalse)
3522	|| (screen->vt100_graphics))
3523#endif
3524	if (!xtermCharSetOut(xw, buf, buf + len, charset))
3525	    return;
3526
3527    if_OPT_XMC_GLITCH(screen, {
3528	Cardinal n;
3529	if (charset != '?') {
3530	    for (n = 0; n < len; n++) {
3531		if (buf[n] == XMC_GLITCH)
3532		    buf[n] = XMC_GLITCH + 1;
3533	    }
3534	}
3535    });
3536
3537#if OPT_WIDE_CHARS
3538    for (offset = 0;
3539	 offset < len && (chars_chomped > 0 || screen->do_wrap);
3540	 offset += chars_chomped) {
3541	int width_available = MaxCols(screen) - screen->cur_col;
3542	int width_here = 0;
3543	Boolean need_wrap = False;
3544	int last_chomp = 0;
3545	chars_chomped = 0;
3546
3547	if (screen->do_wrap) {
3548	    screen->do_wrap = False;
3549	    if ((xw->flags & WRAPAROUND)) {
3550		WrapLine(xw);
3551		width_available = MaxCols(screen) - screen->cur_col;
3552		next_col = screen->cur_col;
3553	    }
3554	}
3555
3556	while (width_here <= width_available && chars_chomped < (len - offset)) {
3557	    if (!screen->utf8_mode
3558		|| (screen->vt100_graphics && charset == '0'))
3559		last_chomp = 1;
3560	    else
3561		last_chomp = my_wcwidth((int) buf[chars_chomped + offset]);
3562	    width_here += last_chomp;
3563	    chars_chomped++;
3564	}
3565
3566	if (width_here > width_available) {
3567	    if (last_chomp > MaxCols(screen))
3568		break;		/* give up - it is too big */
3569	    chars_chomped--;
3570	    width_here -= last_chomp;
3571	    if (chars_chomped > 0) {
3572		need_wrap = True;
3573	    }
3574	} else if (width_here == width_available) {
3575	    need_wrap = True;
3576	} else if (chars_chomped != (len - offset)) {
3577	    need_wrap = True;
3578	}
3579
3580	/*
3581	 * Split the wide characters back into separate arrays of 8-bit
3582	 * characters so we can use the existing interface.
3583	 *
3584	 * FIXME:  If we rewrote this interface, it would involve
3585	 * rewriting all of the memory-management for the screen
3586	 * buffers (perhaps this is simpler).
3587	 */
3588	if (chars_chomped != 0 && next_col <= screen->max_col) {
3589	    WriteText(xw, buf + offset, chars_chomped);
3590	}
3591	next_col += width_here;
3592	screen->do_wrap = need_wrap;
3593    }
3594#else /* ! OPT_WIDE_CHARS */
3595
3596    for (offset = 0; offset < len; offset += this_col) {
3597#if OPT_DEC_CHRSET
3598	LineData *ld = getLineData(screen, screen->cur_row);
3599#endif
3600
3601	last_col = LineMaxCol(screen, ld);
3602	this_col = last_col - screen->cur_col + 1;
3603	if (this_col <= 1) {
3604	    if (screen->do_wrap) {
3605		screen->do_wrap = False;
3606		if ((xw->flags & WRAPAROUND)) {
3607		    WrapLine(xw);
3608		}
3609	    }
3610	    this_col = 1;
3611	}
3612	if (offset + this_col > len) {
3613	    this_col = len - offset;
3614	}
3615	next_col = screen->cur_col + this_col;
3616
3617	WriteText(xw, buf + offset, (unsigned) this_col);
3618
3619	/*
3620	 * The call to WriteText updates screen->cur_col.
3621	 * If screen->cur_col is less than next_col, we must have
3622	 * hit the right margin - so set the do_wrap flag.
3623	 */
3624	screen->do_wrap = (screen->cur_col < next_col);
3625    }
3626
3627#endif /* OPT_WIDE_CHARS */
3628}
3629
3630#if OPT_WIDE_CHARS
3631unsigned
3632visual_width(IChar * str, Cardinal len)
3633{
3634    /* returns the visual width of a string (doublewide characters count
3635       as 2, normalwide characters count as 1) */
3636    unsigned my_len = 0;
3637    while (len) {
3638	int ch = (int) *str++;
3639	if (isWide(ch))
3640	    my_len += 2;
3641	else
3642	    my_len++;
3643	len--;
3644    }
3645    return my_len;
3646}
3647#endif
3648
3649#if HANDLE_STRUCT_NOTIFY
3650/* Flag icon name with "***"  on window output when iconified.
3651 */
3652static void
3653HandleStructNotify(Widget w GCC_UNUSED,
3654		   XtPointer closure GCC_UNUSED,
3655		   XEvent * event,
3656		   Boolean * cont GCC_UNUSED)
3657{
3658    static char *icon_name;
3659    static Arg args[] =
3660    {
3661	{XtNiconName, (XtArgVal) & icon_name}
3662    };
3663    XtermWidget xw = term;
3664    TScreen *screen = TScreenOf(xw);
3665
3666    switch (event->type) {
3667    case MapNotify:
3668	TRACE(("HandleStructNotify(MapNotify)\n"));
3669#if OPT_ZICONBEEP
3670	if (screen->zIconBeep_flagged) {
3671	    screen->zIconBeep_flagged = False;
3672	    icon_name = NULL;
3673	    XtGetValues(toplevel, args, XtNumber(args));
3674	    if (icon_name != NULL) {
3675		char *buf = CastMallocN(char, strlen(icon_name));
3676		if (buf == NULL) {
3677		    screen->zIconBeep_flagged = True;
3678		    return;
3679		}
3680		strcpy(buf, icon_name + 4);
3681		ChangeIconName(xw, buf);
3682		free(buf);
3683	    }
3684	}
3685#endif /* OPT_ZICONBEEP */
3686	mapstate = !IsUnmapped;
3687	break;
3688    case UnmapNotify:
3689	TRACE(("HandleStructNotify(UnmapNotify)\n"));
3690	mapstate = IsUnmapped;
3691	break;
3692    case ConfigureNotify:
3693	if (event->xconfigure.window == XtWindow(toplevel)) {
3694	    int height, width;
3695
3696	    height = event->xconfigure.height;
3697	    width = event->xconfigure.width;
3698	    TRACE(("HandleStructNotify(ConfigureNotify) %d,%d %dx%d\n",
3699		   event->xconfigure.y, event->xconfigure.x,
3700		   event->xconfigure.height, event->xconfigure.width));
3701
3702#if OPT_TOOLBAR
3703	    /*
3704	     * The notification is for the top-level widget, but we care about
3705	     * vt100 (ignore the tek4014 window).
3706	     */
3707	    if (xw->screen.Vshow) {
3708		VTwin *Vwin = WhichVWin(&(xw->screen));
3709		TbInfo *info = &(Vwin->tb_info);
3710		TbInfo save = *info;
3711
3712		if (info->menu_bar) {
3713		    XtVaGetValues(info->menu_bar,
3714				  XtNheight, &info->menu_height,
3715				  XtNborderWidth, &info->menu_border,
3716				  (XtPointer) 0);
3717
3718		    if (save.menu_height != info->menu_height
3719			|| save.menu_border != info->menu_border) {
3720
3721			TRACE(("...menu_height %d\n", info->menu_height));
3722			TRACE(("...menu_border %d\n", info->menu_border));
3723			TRACE(("...had height  %d, border %d\n",
3724			       save.menu_height,
3725			       save.menu_border));
3726
3727			/*
3728			 * FIXME:  Window manager still may be using the old
3729			 * values.  Try to fool it.
3730			 */
3731			REQ_RESIZE((Widget) xw,
3732				   screen->fullVwin.fullwidth,
3733				   (Dimension) (info->menu_height
3734						- save.menu_height
3735						+ screen->fullVwin.fullheight),
3736				   NULL, NULL);
3737			repairSizeHints();
3738		    }
3739		}
3740	    }
3741#else
3742	    if (height != xw->hints.height || width != xw->hints.width)
3743		RequestResize(xw, height, width, False);
3744#endif /* OPT_TOOLBAR */
3745	}
3746	break;
3747    case ReparentNotify:
3748	TRACE(("HandleStructNotify(ReparentNotify)\n"));
3749	break;
3750    default:
3751	TRACE(("HandleStructNotify(event %s)\n",
3752	       visibleEventType(event->type)));
3753	break;
3754    }
3755}
3756#endif /* HANDLE_STRUCT_NOTIFY */
3757
3758#if OPT_BLINK_CURS
3759static void
3760SetCursorBlink(TScreen * screen, Bool enable)
3761{
3762    screen->cursor_blink = (Boolean) enable;
3763    if (DoStartBlinking(screen)) {
3764	StartBlinking(screen);
3765    } else {
3766#if !OPT_BLINK_TEXT
3767	StopBlinking(screen);
3768#endif
3769    }
3770    update_cursorblink();
3771}
3772
3773void
3774ToggleCursorBlink(TScreen * screen)
3775{
3776    SetCursorBlink(screen, (Bool) (!(screen->cursor_blink)));
3777}
3778#endif
3779
3780/*
3781 * process ANSI modes set, reset
3782 */
3783static void
3784ansi_modes(XtermWidget xw,
3785	   void (*func) (unsigned *p, unsigned mask))
3786{
3787    int i;
3788
3789    for (i = 0; i < nparam; ++i) {
3790	switch (param[i]) {
3791	case 2:		/* KAM (if set, keyboard locked */
3792	    (*func) (&xw->keyboard.flags, MODE_KAM);
3793	    break;
3794
3795	case 4:		/* IRM                          */
3796	    (*func) (&xw->flags, INSERT);
3797	    break;
3798
3799	case 12:		/* SRM (if set, local echo      */
3800	    (*func) (&xw->keyboard.flags, MODE_SRM);
3801	    break;
3802
3803	case 20:		/* LNM                          */
3804	    (*func) (&xw->flags, LINEFEED);
3805	    update_autolinefeed();
3806	    break;
3807	}
3808    }
3809}
3810
3811#define IsSM() (func == bitset)
3812
3813#define set_bool_mode(flag) \
3814	flag = (Boolean) IsSM()
3815
3816static void
3817really_set_mousemode(XtermWidget xw,
3818		     Bool enabled,
3819		     XtermMouseModes mode)
3820{
3821    xw->screen.send_mouse_pos = enabled ? mode : MOUSE_OFF;
3822    if (xw->screen.send_mouse_pos != MOUSE_OFF)
3823	xtermShowPointer(xw, True);
3824}
3825
3826#define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode)
3827
3828#if OPT_READLINE
3829#define set_mouseflag(f)		\
3830	(IsSM()				\
3831	 ? SCREEN_FLAG_set(screen, f)	\
3832	 : SCREEN_FLAG_unset(screen, f))
3833#endif
3834
3835/*
3836 * process DEC private modes set, reset
3837 */
3838static void
3839dpmodes(XtermWidget xw,
3840	void (*func) (unsigned *p, unsigned mask))
3841{
3842    TScreen *screen = &xw->screen;
3843    int i, j;
3844    unsigned myflags;
3845
3846    for (i = 0; i < nparam; ++i) {
3847	TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", param[i]));
3848	switch (param[i]) {
3849	case 1:		/* DECCKM                       */
3850	    (*func) (&xw->keyboard.flags, MODE_DECCKM);
3851	    update_appcursor();
3852	    break;
3853	case 2:		/* DECANM - ANSI/VT52 mode      */
3854	    if (IsSM()) {	/* ANSI (VT100) */
3855		/*
3856		 * Setting DECANM should have no effect, since this function
3857		 * cannot be reached from vt52 mode.
3858		 */
3859		;
3860	    }
3861#if OPT_VT52_MODE
3862	    else if (screen->terminal_id >= 100) {	/* VT52 */
3863		TRACE(("DECANM terminal_id %d, vtXX_level %d\n",
3864		       screen->terminal_id,
3865		       screen->vtXX_level));
3866		screen->vt52_save_level = screen->vtXX_level;
3867		screen->vtXX_level = 0;
3868		screen->vt52_save_curgl = screen->curgl;
3869		screen->vt52_save_curgr = screen->curgr;
3870		screen->vt52_save_curss = screen->curss;
3871		memmove(screen->vt52_save_gsets, screen->gsets, sizeof(screen->gsets));
3872		resetCharsets(screen);
3873		nparam = 0;	/* ignore the remaining params, if any */
3874	    }
3875#endif
3876	    break;
3877	case 3:		/* DECCOLM                      */
3878	    if (screen->c132) {
3879		ClearScreen(xw);
3880		CursorSet(screen, 0, 0, xw->flags);
3881		if ((j = IsSM()? 132 : 80) !=
3882		    ((xw->flags & IN132COLUMNS) ? 132 : 80) ||
3883		    j != MaxCols(screen))
3884		    RequestResize(xw, -1, j, True);
3885		(*func) (&xw->flags, IN132COLUMNS);
3886	    }
3887	    break;
3888	case 4:		/* DECSCLM (slow scroll)        */
3889	    if (IsSM()) {
3890		screen->jumpscroll = 0;
3891		if (screen->scroll_amt)
3892		    FlushScroll(xw);
3893	    } else
3894		screen->jumpscroll = 1;
3895	    (*func) (&xw->flags, SMOOTHSCROLL);
3896	    update_jumpscroll();
3897	    break;
3898	case 5:		/* DECSCNM                      */
3899	    myflags = xw->flags;
3900	    (*func) (&xw->flags, REVERSE_VIDEO);
3901	    if ((xw->flags ^ myflags) & REVERSE_VIDEO)
3902		ReverseVideo(xw);
3903	    /* update_reversevideo done in RevVid */
3904	    break;
3905
3906	case 6:		/* DECOM                        */
3907	    (*func) (&xw->flags, ORIGIN);
3908	    CursorSet(screen, 0, 0, xw->flags);
3909	    break;
3910
3911	case 7:		/* DECAWM                       */
3912	    (*func) (&xw->flags, WRAPAROUND);
3913	    update_autowrap();
3914	    break;
3915	case 8:		/* DECARM                       */
3916	    /* ignore autorepeat
3917	     * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only
3918	     * for the whole display - not limited to a given window.
3919	     */
3920	    break;
3921	case SET_X10_MOUSE:	/* MIT bogus sequence           */
3922	    MotionOff(screen, xw);
3923	    set_mousemode(X10_MOUSE);
3924	    break;
3925#if OPT_TOOLBAR
3926	case 10:		/* rxvt */
3927	    ShowToolbar(IsSM());
3928	    break;
3929#endif
3930#if OPT_BLINK_CURS
3931	case 12:		/* att610: Start/stop blinking cursor */
3932	    if (screen->cursor_blink_res) {
3933		set_bool_mode(screen->cursor_blink_esc);
3934		SetCursorBlink(screen, screen->cursor_blink);
3935	    }
3936	    break;
3937#endif
3938	case 18:		/* DECPFF: print form feed */
3939	    set_bool_mode(screen->printer_formfeed);
3940	    break;
3941	case 19:		/* DECPEX: print extent */
3942	    set_bool_mode(screen->printer_extent);
3943	    break;
3944	case 25:		/* DECTCEM: Show/hide cursor (VT200) */
3945	    set_bool_mode(screen->cursor_set);
3946	    break;
3947	case 30:		/* rxvt */
3948	    if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF))
3949		ToggleScrollBar(xw);
3950	    break;
3951#if OPT_SHIFT_FONTS
3952	case 35:		/* rxvt */
3953	    set_bool_mode(xw->misc.shift_fonts);
3954	    break;
3955#endif
3956	case 38:		/* DECTEK                       */
3957#if OPT_TEK4014
3958	    if (IsSM() && !(screen->inhibit & I_TEK)) {
3959		FlushLog(screen);
3960		TEK4014_ACTIVE(xw) = True;
3961	    }
3962#endif
3963	    break;
3964	case 40:		/* 132 column mode              */
3965	    set_bool_mode(screen->c132);
3966	    update_allow132();
3967	    break;
3968	case 41:		/* curses hack                  */
3969	    set_bool_mode(screen->curses);
3970	    update_cursesemul();
3971	    break;
3972	case 42:		/* DECNRCM national charset (VT220) */
3973	    (*func) (&xw->flags, NATIONAL);
3974	    break;
3975	case 44:		/* margin bell                  */
3976	    set_bool_mode(screen->marginbell);
3977	    if (!screen->marginbell)
3978		screen->bellarmed = -1;
3979	    update_marginbell();
3980	    break;
3981	case 45:		/* reverse wraparound   */
3982	    (*func) (&xw->flags, REVERSEWRAP);
3983	    update_reversewrap();
3984	    break;
3985#ifdef ALLOWLOGGING
3986	case 46:		/* logging              */
3987#ifdef ALLOWLOGFILEONOFF
3988	    /*
3989	     * if this feature is enabled, logging may be
3990	     * enabled and disabled via escape sequences.
3991	     */
3992	    if (IsSM())
3993		StartLog(screen);
3994	    else
3995		CloseLog(screen);
3996#else
3997	    Bell(XkbBI_Info, 0);
3998	    Bell(XkbBI_Info, 0);
3999#endif /* ALLOWLOGFILEONOFF */
4000	    break;
4001#endif
4002	case 1049:		/* alternate buffer & cursor */
4003	    if (!xw->misc.titeInhibit) {
4004		if (IsSM()) {
4005		    CursorSave(xw);
4006		    ToAlternate(xw);
4007		    ClearScreen(xw);
4008		} else {
4009		    FromAlternate(xw);
4010		    CursorRestore(xw);
4011		}
4012	    } else if (xw->misc.tiXtraScroll) {
4013		if (IsSM()) {
4014		    xtermScroll(xw, screen->max_row);
4015		}
4016	    }
4017	    break;
4018	case 1047:
4019	    /* FALLTHRU */
4020	case 47:		/* alternate buffer */
4021	    if (!xw->misc.titeInhibit) {
4022		if (IsSM()) {
4023		    ToAlternate(xw);
4024		} else {
4025		    if (screen->whichBuf
4026			&& (param[i] == 1047))
4027			ClearScreen(xw);
4028		    FromAlternate(xw);
4029		}
4030	    } else if (xw->misc.tiXtraScroll) {
4031		if (IsSM()) {
4032		    xtermScroll(xw, screen->max_row);
4033		}
4034	    }
4035	    break;
4036	case 66:		/* DECNKM */
4037	    (*func) (&xw->keyboard.flags, MODE_DECKPAM);
4038	    update_appkeypad();
4039	    break;
4040	case 67:		/* DECBKM */
4041	    /* back-arrow mapped to backspace or delete(D) */
4042	    (*func) (&xw->keyboard.flags, MODE_DECBKM);
4043	    TRACE(("DECSET DECBKM %s\n",
4044		   BtoS(xw->keyboard.flags & MODE_DECBKM)));
4045	    update_decbkm();
4046	    break;
4047	case SET_VT200_MOUSE:	/* xterm bogus sequence         */
4048	    MotionOff(screen, xw);
4049	    set_mousemode(VT200_MOUSE);
4050	    break;
4051	case SET_VT200_HIGHLIGHT_MOUSE:	/* xterm sequence w/hilite tracking */
4052	    MotionOff(screen, xw);
4053	    set_mousemode(VT200_HIGHLIGHT_MOUSE);
4054	    break;
4055	case SET_BTN_EVENT_MOUSE:
4056	    MotionOff(screen, xw);
4057	    set_mousemode(BTN_EVENT_MOUSE);
4058	    break;
4059	case SET_ANY_EVENT_MOUSE:
4060	    set_mousemode(ANY_EVENT_MOUSE);
4061	    if (screen->send_mouse_pos == MOUSE_OFF) {
4062		MotionOff(screen, xw);
4063	    } else {
4064		MotionOn(screen, xw);
4065	    }
4066	    break;
4067#if OPT_FOCUS_EVENT
4068	case SET_FOCUS_EVENT_MOUSE:
4069	    set_bool_mode(screen->send_focus_pos);
4070	    break;
4071#endif
4072	case 1010:		/* rxvt */
4073	    set_bool_mode(screen->scrollttyoutput);
4074	    update_scrollttyoutput();
4075	    break;
4076	case 1011:		/* rxvt */
4077	    set_bool_mode(screen->scrollkey);
4078	    update_scrollkey();
4079	    break;
4080	case 1034:
4081	    set_bool_mode(xw->screen.input_eight_bits);
4082	    update_alt_esc();
4083	    break;
4084#if OPT_NUM_LOCK
4085	case 1035:
4086	    set_bool_mode(xw->misc.real_NumLock);
4087	    update_num_lock();
4088	    break;
4089	case 1036:
4090	    set_bool_mode(screen->meta_sends_esc);
4091	    update_meta_esc();
4092	    break;
4093#endif
4094	case 1037:
4095	    set_bool_mode(screen->delete_is_del);
4096	    update_delete_del();
4097	    break;
4098#if OPT_NUM_LOCK
4099	case 1039:
4100	    set_bool_mode(screen->alt_sends_esc);
4101	    update_alt_esc();
4102	    break;
4103#endif
4104	case 1040:
4105	    set_bool_mode(screen->keepSelection);
4106	    update_keepSelection();
4107	    break;
4108	case 1041:
4109	    set_bool_mode(screen->selectToClipboard);
4110	    update_selectToClipboard();
4111	    break;
4112	case 1042:
4113	    set_bool_mode(screen->bellIsUrgent);
4114	    update_bellIsUrgent();
4115	    break;
4116	case 1043:
4117	    set_bool_mode(screen->poponbell);
4118	    update_poponbell();
4119	    break;
4120	case 1048:
4121	    if (!xw->misc.titeInhibit) {
4122		if (IsSM())
4123		    CursorSave(xw);
4124		else
4125		    CursorRestore(xw);
4126	    }
4127	    break;
4128#if OPT_TCAP_FKEYS
4129	case 1050:
4130	    set_keyboard_type(xw, keyboardIsTermcap, IsSM());
4131	    break;
4132#endif
4133#if OPT_SUN_FUNC_KEYS
4134	case 1051:
4135	    set_keyboard_type(xw, keyboardIsSun, IsSM());
4136	    break;
4137#endif
4138#if OPT_HP_FUNC_KEYS
4139	case 1052:
4140	    set_keyboard_type(xw, keyboardIsHP, IsSM());
4141	    break;
4142#endif
4143#if OPT_SCO_FUNC_KEYS
4144	case 1053:
4145	    set_keyboard_type(xw, keyboardIsSCO, IsSM());
4146	    break;
4147#endif
4148	case 1060:
4149	    set_keyboard_type(xw, keyboardIsLegacy, IsSM());
4150	    break;
4151#if OPT_SUNPC_KBD
4152	case 1061:
4153	    set_keyboard_type(xw, keyboardIsVT220, IsSM());
4154	    break;
4155#endif
4156#if OPT_READLINE
4157	case SET_BUTTON1_MOVE_POINT:
4158	    set_mouseflag(click1_moves);
4159	    break;
4160	case SET_BUTTON2_MOVE_POINT:
4161	    set_mouseflag(paste_moves);
4162	    break;
4163	case SET_DBUTTON3_DELETE:
4164	    set_mouseflag(dclick3_deletes);
4165	    break;
4166	case SET_PASTE_IN_BRACKET:
4167	    set_mouseflag(paste_brackets);
4168	    break;
4169	case SET_PASTE_QUOTE:
4170	    set_mouseflag(paste_quotes);
4171	    break;
4172	case SET_PASTE_LITERAL_NL:
4173	    set_mouseflag(paste_literal_nl);
4174	    break;
4175#endif /* OPT_READLINE */
4176	}
4177    }
4178}
4179
4180/*
4181 * process xterm private modes save
4182 */
4183static void
4184savemodes(XtermWidget xw)
4185{
4186    TScreen *screen = &xw->screen;
4187    int i;
4188
4189    for (i = 0; i < nparam; i++) {
4190	TRACE(("savemodes %d\n", param[i]));
4191	switch (param[i]) {
4192	case 1:		/* DECCKM                       */
4193	    DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM);
4194	    break;
4195	case 3:		/* DECCOLM                      */
4196	    if (screen->c132)
4197		DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS);
4198	    break;
4199	case 4:		/* DECSCLM (slow scroll)        */
4200	    DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL);
4201	    break;
4202	case 5:		/* DECSCNM                      */
4203	    DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO);
4204	    break;
4205	case 6:		/* DECOM                        */
4206	    DoSM(DP_DECOM, xw->flags & ORIGIN);
4207	    break;
4208	case 7:		/* DECAWM                       */
4209	    DoSM(DP_DECAWM, xw->flags & WRAPAROUND);
4210	    break;
4211	case 8:		/* DECARM                       */
4212	    /* ignore autorepeat */
4213	    break;
4214	case SET_X10_MOUSE:	/* mouse bogus sequence */
4215	    DoSM(DP_X_X10MSE, screen->send_mouse_pos);
4216	    break;
4217#if OPT_TOOLBAR
4218	case 10:		/* rxvt */
4219	    DoSM(DP_TOOLBAR, resource.toolBar);
4220	    break;
4221#endif
4222#if OPT_BLINK_CURS
4223	case 12:		/* att610: Start/stop blinking cursor */
4224	    if (screen->cursor_blink_res) {
4225		DoSM(DP_CRS_BLINK, screen->cursor_blink_esc);
4226	    }
4227	    break;
4228#endif
4229	case 18:		/* DECPFF: print form feed */
4230	    DoSM(DP_PRN_FORMFEED, screen->printer_formfeed);
4231	    break;
4232	case 19:		/* DECPEX: print extent */
4233	    DoSM(DP_PRN_EXTENT, screen->printer_extent);
4234	    break;
4235	case 25:		/* DECTCEM: Show/hide cursor (VT200) */
4236	    DoSM(DP_CRS_VISIBLE, screen->cursor_set);
4237	    break;
4238	case 40:		/* 132 column mode              */
4239	    DoSM(DP_X_DECCOLM, screen->c132);
4240	    break;
4241	case 41:		/* curses hack                  */
4242	    DoSM(DP_X_MORE, screen->curses);
4243	    break;
4244	case 42:		/* DECNRCM national charset (VT220) */
4245	    /* do nothing */
4246	    break;
4247	case 44:		/* margin bell                  */
4248	    DoSM(DP_X_MARGIN, screen->marginbell);
4249	    break;
4250	case 45:		/* reverse wraparound   */
4251	    DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP);
4252	    break;
4253#ifdef ALLOWLOGGING
4254	case 46:		/* logging              */
4255	    DoSM(DP_X_LOGGING, screen->logging);
4256	    break;
4257#endif
4258	case 1047:		/* alternate buffer             */
4259	    /* FALLTHRU */
4260	case 47:		/* alternate buffer             */
4261	    DoSM(DP_X_ALTSCRN, screen->whichBuf);
4262	    break;
4263	case SET_VT200_MOUSE:	/* mouse bogus sequence         */
4264	case SET_VT200_HIGHLIGHT_MOUSE:
4265	case SET_BTN_EVENT_MOUSE:
4266	case SET_ANY_EVENT_MOUSE:
4267	    DoSM(DP_X_MOUSE, screen->send_mouse_pos);
4268	    break;
4269#if OPT_FOCUS_EVENT
4270	case SET_FOCUS_EVENT_MOUSE:
4271	    DoSM(DP_X_FOCUS, screen->send_focus_pos);
4272	    break;
4273#endif
4274	case 1048:
4275	    if (!xw->misc.titeInhibit) {
4276		CursorSave(xw);
4277	    }
4278	    break;
4279#if OPT_READLINE
4280	case SET_BUTTON1_MOVE_POINT:
4281	    SCREEN_FLAG_save(screen, click1_moves);
4282	    break;
4283	case SET_BUTTON2_MOVE_POINT:
4284	    SCREEN_FLAG_save(screen, paste_moves);
4285	    break;
4286	case SET_DBUTTON3_DELETE:
4287	    SCREEN_FLAG_save(screen, dclick3_deletes);
4288	    break;
4289	case SET_PASTE_IN_BRACKET:
4290	    SCREEN_FLAG_save(screen, paste_brackets);
4291	    break;
4292	case SET_PASTE_QUOTE:
4293	    SCREEN_FLAG_save(screen, paste_quotes);
4294	    break;
4295	case SET_PASTE_LITERAL_NL:
4296	    SCREEN_FLAG_save(screen, paste_literal_nl);
4297	    break;
4298#endif /* OPT_READLINE */
4299	}
4300    }
4301}
4302
4303/*
4304 * process xterm private modes restore
4305 */
4306static void
4307restoremodes(XtermWidget xw)
4308{
4309    TScreen *screen = &xw->screen;
4310    int i, j;
4311
4312    for (i = 0; i < nparam; i++) {
4313	TRACE(("restoremodes %d\n", param[i]));
4314	switch (param[i]) {
4315	case 1:		/* DECCKM                       */
4316	    bitcpy(&xw->keyboard.flags,
4317		   screen->save_modes[DP_DECCKM], MODE_DECCKM);
4318	    update_appcursor();
4319	    break;
4320	case 3:		/* DECCOLM                      */
4321	    if (screen->c132) {
4322		ClearScreen(xw);
4323		CursorSet(screen, 0, 0, xw->flags);
4324		if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS)
4325		     ? 132 : 80) != ((xw->flags & IN132COLUMNS)
4326				     ? 132 : 80) || j != MaxCols(screen))
4327		    RequestResize(xw, -1, j, True);
4328		bitcpy(&xw->flags,
4329		       screen->save_modes[DP_DECCOLM],
4330		       IN132COLUMNS);
4331	    }
4332	    break;
4333	case 4:		/* DECSCLM (slow scroll)        */
4334	    if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) {
4335		screen->jumpscroll = 0;
4336		if (screen->scroll_amt)
4337		    FlushScroll(xw);
4338	    } else
4339		screen->jumpscroll = 1;
4340	    bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL);
4341	    update_jumpscroll();
4342	    break;
4343	case 5:		/* DECSCNM                      */
4344	    if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) {
4345		bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO);
4346		ReverseVideo(xw);
4347		/* update_reversevideo done in RevVid */
4348	    }
4349	    break;
4350	case 6:		/* DECOM                        */
4351	    bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN);
4352	    CursorSet(screen, 0, 0, xw->flags);
4353	    break;
4354
4355	case 7:		/* DECAWM                       */
4356	    bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND);
4357	    update_autowrap();
4358	    break;
4359	case 8:		/* DECARM                       */
4360	    /* ignore autorepeat */
4361	    break;
4362	case SET_X10_MOUSE:	/* MIT bogus sequence           */
4363	    DoRM0(DP_X_X10MSE, screen->send_mouse_pos);
4364	    break;
4365#if OPT_TOOLBAR
4366	case 10:		/* rxvt */
4367	    DoRM(DP_TOOLBAR, resource.toolBar);
4368	    ShowToolbar(resource.toolBar);
4369	    break;
4370#endif
4371#if OPT_BLINK_CURS
4372	case 12:		/* att610: Start/stop blinking cursor */
4373	    if (screen->cursor_blink_res) {
4374		DoRM(DP_CRS_BLINK, screen->cursor_blink_esc);
4375		SetCursorBlink(screen, screen->cursor_blink);
4376	    }
4377	    break;
4378#endif
4379	case 18:		/* DECPFF: print form feed */
4380	    DoRM(DP_PRN_FORMFEED, screen->printer_formfeed);
4381	    break;
4382	case 19:		/* DECPEX: print extent */
4383	    DoRM(DP_PRN_EXTENT, screen->printer_extent);
4384	    break;
4385	case 25:		/* DECTCEM: Show/hide cursor (VT200) */
4386	    DoRM(DP_CRS_VISIBLE, screen->cursor_set);
4387	    break;
4388	case 40:		/* 132 column mode              */
4389	    DoRM(DP_X_DECCOLM, screen->c132);
4390	    update_allow132();
4391	    break;
4392	case 41:		/* curses hack                  */
4393	    DoRM(DP_X_MORE, screen->curses);
4394	    update_cursesemul();
4395	    break;
4396	case 44:		/* margin bell                  */
4397	    if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0)
4398		screen->bellarmed = -1;
4399	    update_marginbell();
4400	    break;
4401	case 45:		/* reverse wraparound   */
4402	    bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP);
4403	    update_reversewrap();
4404	    break;
4405#ifdef ALLOWLOGGING
4406	case 46:		/* logging              */
4407#ifdef ALLOWLOGFILEONOFF
4408	    if (screen->save_modes[DP_X_LOGGING])
4409		StartLog(screen);
4410	    else
4411		CloseLog(screen);
4412#endif /* ALLOWLOGFILEONOFF */
4413	    /* update_logging done by StartLog and CloseLog */
4414	    break;
4415#endif
4416	case 1047:		/* alternate buffer */
4417	    /* FALLTHRU */
4418	case 47:		/* alternate buffer */
4419	    if (!xw->misc.titeInhibit) {
4420		if (screen->save_modes[DP_X_ALTSCRN])
4421		    ToAlternate(xw);
4422		else
4423		    FromAlternate(xw);
4424		/* update_altscreen done by ToAlt and FromAlt */
4425	    } else if (xw->misc.tiXtraScroll) {
4426		if (screen->save_modes[DP_X_ALTSCRN]) {
4427		    xtermScroll(xw, screen->max_row);
4428		}
4429	    }
4430	    break;
4431	case SET_VT200_MOUSE:	/* mouse bogus sequence         */
4432	case SET_VT200_HIGHLIGHT_MOUSE:
4433	case SET_BTN_EVENT_MOUSE:
4434	case SET_ANY_EVENT_MOUSE:
4435	    DoRM0(DP_X_MOUSE, screen->send_mouse_pos);
4436	    break;
4437#if OPT_FOCUS_EVENT
4438	case SET_FOCUS_EVENT_MOUSE:
4439	    DoRM(DP_X_FOCUS, screen->send_focus_pos);
4440	    break;
4441#endif
4442	case 1048:
4443	    if (!xw->misc.titeInhibit) {
4444		CursorRestore(xw);
4445	    }
4446	    break;
4447#if OPT_READLINE
4448	case SET_BUTTON1_MOVE_POINT:
4449	    SCREEN_FLAG_restore(screen, click1_moves);
4450	    break;
4451	case SET_BUTTON2_MOVE_POINT:
4452	    SCREEN_FLAG_restore(screen, paste_moves);
4453	    break;
4454	case SET_DBUTTON3_DELETE:
4455	    SCREEN_FLAG_restore(screen, dclick3_deletes);
4456	    break;
4457	case SET_PASTE_IN_BRACKET:
4458	    SCREEN_FLAG_restore(screen, paste_brackets);
4459	    break;
4460	case SET_PASTE_QUOTE:
4461	    SCREEN_FLAG_restore(screen, paste_quotes);
4462	    break;
4463	case SET_PASTE_LITERAL_NL:
4464	    SCREEN_FLAG_restore(screen, paste_literal_nl);
4465	    break;
4466#endif /* OPT_READLINE */
4467	}
4468    }
4469}
4470
4471/*
4472 * Report window label (icon or title) in dtterm protocol
4473 * ESC ] code label ESC backslash
4474 */
4475static void
4476report_win_label(XtermWidget xw,
4477		 int code,
4478		 XTextProperty * text,
4479		 Status ok)
4480{
4481    char **list;
4482    int length = 0;
4483
4484    reply.a_type = ANSI_ESC;
4485    unparseputc(xw, ANSI_ESC);
4486    unparseputc(xw, ']');
4487    unparseputc(xw, code);
4488
4489    if (ok) {
4490	if (XTextPropertyToStringList(text, &list, &length)) {
4491	    int n, c;
4492	    for (n = 0; n < length; n++) {
4493		char *s = list[n];
4494		while ((c = *s++) != '\0')
4495		    unparseputc(xw, c);
4496	    }
4497	    XFreeStringList(list);
4498	}
4499	if (text->value != 0)
4500	    XFree(text->value);
4501    }
4502
4503    unparseputc(xw, ANSI_ESC);
4504    unparseputc(xw, '\\');	/* should be ST */
4505    unparse_end(xw);
4506}
4507
4508/*
4509 * Window operations (from CDE dtterm description, as well as extensions).
4510 * See also "allowWindowOps" resource.
4511 */
4512static void
4513window_ops(XtermWidget xw)
4514{
4515    TScreen *screen = &xw->screen;
4516    XWindowChanges values;
4517    XWindowAttributes win_attrs;
4518    XTextProperty text;
4519    unsigned value_mask;
4520#if OPT_MAXIMIZE
4521    unsigned root_width;
4522    unsigned root_height;
4523#endif
4524
4525    TRACE(("window_ops %d\n", param[0]));
4526    switch (param[0]) {
4527    case 1:			/* Restore (de-iconify) window */
4528	TRACE(("...de-iconify window\n"));
4529	XMapWindow(screen->display,
4530		   VShellWindow);
4531	break;
4532
4533    case 2:			/* Minimize (iconify) window */
4534	TRACE(("...iconify window\n"));
4535	XIconifyWindow(screen->display,
4536		       VShellWindow,
4537		       DefaultScreen(screen->display));
4538	break;
4539
4540    case 3:			/* Move the window to the given position */
4541	TRACE(("...move window to %d,%d\n", param[1], param[2]));
4542	values.x = param[1];
4543	values.y = param[2];
4544	value_mask = (CWX | CWY);
4545	XReconfigureWMWindow(screen->display,
4546			     VShellWindow,
4547			     DefaultScreen(screen->display),
4548			     value_mask,
4549			     &values);
4550	break;
4551
4552    case 4:			/* Resize the window to given size in pixels */
4553	RequestResize(xw, param[1], param[2], False);
4554	break;
4555
4556    case 5:			/* Raise the window to the front of the stack */
4557	TRACE(("...raise window\n"));
4558	XRaiseWindow(screen->display, VShellWindow);
4559	break;
4560
4561    case 6:			/* Lower the window to the bottom of the stack */
4562	TRACE(("...lower window\n"));
4563	XLowerWindow(screen->display, VShellWindow);
4564	break;
4565
4566    case 7:			/* Refresh the window */
4567	TRACE(("...redraw window\n"));
4568	Redraw();
4569	break;
4570
4571    case 8:			/* Resize the text-area, in characters */
4572	RequestResize(xw, param[1], param[2], True);
4573	break;
4574
4575#if OPT_MAXIMIZE
4576    case 9:			/* Maximize or restore */
4577	RequestMaximize(xw, param[1]);
4578	break;
4579#endif
4580
4581    case 11:			/* Report the window's state */
4582	TRACE(("...get window attributes\n"));
4583	XGetWindowAttributes(screen->display,
4584			     VWindow(screen),
4585			     &win_attrs);
4586	reply.a_type = ANSI_CSI;
4587	reply.a_pintro = 0;
4588	reply.a_nparam = 1;
4589	reply.a_param[0] = (ParmType) ((win_attrs.map_state == IsViewable)
4590				       ? 1
4591				       : 2);
4592	reply.a_inters = 0;
4593	reply.a_final = 't';
4594	unparseseq(xw, &reply);
4595	break;
4596
4597    case 13:			/* Report the window's position */
4598	TRACE(("...get window position\n"));
4599	XGetWindowAttributes(screen->display,
4600			     WMFrameWindow(xw),
4601			     &win_attrs);
4602	reply.a_type = ANSI_CSI;
4603	reply.a_pintro = 0;
4604	reply.a_nparam = 3;
4605	reply.a_param[0] = 3;
4606	reply.a_param[1] = (ParmType) win_attrs.x;
4607	reply.a_param[2] = (ParmType) win_attrs.y;
4608	reply.a_inters = 0;
4609	reply.a_final = 't';
4610	unparseseq(xw, &reply);
4611	break;
4612
4613    case 14:			/* Report the window's size in pixels */
4614	TRACE(("...get window size in pixels\n"));
4615	XGetWindowAttributes(screen->display,
4616			     VWindow(screen),
4617			     &win_attrs);
4618	reply.a_type = ANSI_CSI;
4619	reply.a_pintro = 0;
4620	reply.a_nparam = 3;
4621	reply.a_param[0] = 4;
4622	/*FIXME: find if dtterm uses
4623	 *    win_attrs.height or Height
4624	 *      win_attrs.width  or Width
4625	 */
4626	reply.a_param[1] = (ParmType) Height(screen);
4627	reply.a_param[2] = (ParmType) Width(screen);
4628	reply.a_inters = 0;
4629	reply.a_final = 't';
4630	unparseseq(xw, &reply);
4631	break;
4632
4633    case 18:			/* Report the text's size in characters */
4634	TRACE(("...get window size in characters\n"));
4635	reply.a_type = ANSI_CSI;
4636	reply.a_pintro = 0;
4637	reply.a_nparam = 3;
4638	reply.a_param[0] = 8;
4639	reply.a_param[1] = (ParmType) MaxRows(screen);
4640	reply.a_param[2] = (ParmType) MaxCols(screen);
4641	reply.a_inters = 0;
4642	reply.a_final = 't';
4643	unparseseq(xw, &reply);
4644	break;
4645
4646#if OPT_MAXIMIZE
4647    case 19:			/* Report the screen's size, in characters */
4648	if (!QueryMaximize(xw, &root_height, &root_width)) {
4649	    root_height = 0;
4650	    root_width = 0;
4651	}
4652	reply.a_type = ANSI_CSI;
4653	reply.a_pintro = 0;
4654	reply.a_nparam = 3;
4655	reply.a_param[0] = 9;
4656	reply.a_param[1] = (ParmType) (root_height / FontHeight(screen));
4657	reply.a_param[2] = (ParmType) (root_width / FontWidth(screen));
4658	reply.a_inters = 0;
4659	reply.a_final = 't';
4660	unparseseq(xw, &reply);
4661	break;
4662#endif
4663
4664    case 20:			/* Report the icon's label */
4665	report_win_label(xw, 'L', &text,
4666			 XGetWMIconName(screen->display, VShellWindow, &text));
4667	break;
4668
4669    case 21:			/* Report the window's title */
4670	report_win_label(xw, 'l', &text,
4671			 XGetWMName(screen->display, VShellWindow, &text));
4672	break;
4673
4674    default:			/* DECSLPP (24, 25, 36, 48, 72, 144) */
4675	if (param[0] >= 24)
4676	    RequestResize(xw, param[0], -1, True);
4677	break;
4678    }
4679}
4680
4681/*
4682 * set a bit in a word given a pointer to the word and a mask.
4683 */
4684static void
4685bitset(unsigned *p, unsigned mask)
4686{
4687    *p |= mask;
4688}
4689
4690/*
4691 * clear a bit in a word given a pointer to the word and a mask.
4692 */
4693static void
4694bitclr(unsigned *p, unsigned mask)
4695{
4696    *p &= ~mask;
4697}
4698
4699/*
4700 * Copy bits from one word to another, given a mask
4701 */
4702static void
4703bitcpy(unsigned *p, unsigned q, unsigned mask)
4704{
4705    bitclr(p, mask);
4706    bitset(p, q & mask);
4707}
4708
4709void
4710unparseputc1(XtermWidget xw, int c)
4711{
4712    if (c >= 0x80 && c <= 0x9F) {
4713	if (!xw->screen.control_eight_bits) {
4714	    unparseputc(xw, A2E(ANSI_ESC));
4715	    c = A2E(c - 0x40);
4716	}
4717    }
4718    unparseputc(xw, c);
4719}
4720
4721void
4722unparseseq(XtermWidget xw, ANSI * ap)
4723{
4724    int c;
4725    int i;
4726    int inters;
4727
4728    unparseputc1(xw, c = ap->a_type);
4729    if (c == ANSI_ESC
4730	|| c == ANSI_DCS
4731	|| c == ANSI_CSI
4732	|| c == ANSI_OSC
4733	|| c == ANSI_PM
4734	|| c == ANSI_APC
4735	|| c == ANSI_SS3) {
4736	if (ap->a_pintro != 0)
4737	    unparseputc(xw, ap->a_pintro);
4738	for (i = 0; i < ap->a_nparam; ++i) {
4739	    if (i != 0)
4740		unparseputc(xw, ';');
4741	    unparseputn(xw, (unsigned int) ap->a_param[i]);
4742	}
4743	if ((inters = ap->a_inters) != 0) {
4744	    for (i = 3; i >= 0; --i) {
4745		c = CharOf(inters >> (8 * i));
4746		if (c != 0)
4747		    unparseputc(xw, c);
4748	    }
4749	}
4750	unparseputc(xw, (char) ap->a_final);
4751    }
4752    unparse_end(xw);
4753}
4754
4755void
4756unparseputn(XtermWidget xw, unsigned int n)
4757{
4758    unsigned int q;
4759
4760    q = n / 10;
4761    if (q != 0)
4762	unparseputn(xw, q);
4763    unparseputc(xw, (char) ('0' + (n % 10)));
4764}
4765
4766void
4767unparseputs(XtermWidget xw, char *s)
4768{
4769    while (*s)
4770	unparseputc(xw, *s++);
4771}
4772
4773void
4774unparseputc(XtermWidget xw, int c)
4775{
4776    IChar *buf = xw->screen.unparse_bfr;
4777    unsigned len;
4778
4779    if ((xw->screen.unparse_len + 2) >= sizeof(xw->screen.unparse_bfr))
4780	unparse_end(xw);
4781
4782    len = xw->screen.unparse_len;
4783
4784#if OPT_TCAP_QUERY
4785    /*
4786     * If we're returning a termcap string, it has to be translated since
4787     * a DCS must not contain any characters except for the normal 7-bit
4788     * printable ASCII (counting tab, carriage return, etc).  For now,
4789     * just use hexadecimal for the whole thing.
4790     */
4791    if (xw->screen.tc_query_code >= 0) {
4792	char tmp[3];
4793	sprintf(tmp, "%02X", c & 0xFF);
4794	buf[len++] = CharOf(tmp[0]);
4795	buf[len++] = CharOf(tmp[1]);
4796    } else
4797#endif
4798    if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) {
4799	buf[len++] = '\n';
4800    }
4801
4802    xw->screen.unparse_len = len;
4803
4804    /* If send/receive mode is reset, we echo characters locally */
4805    if ((xw->keyboard.flags & MODE_SRM) == 0) {
4806	(void) doparsing(xw, (unsigned) c, &myState);
4807    }
4808}
4809
4810void
4811unparse_end(XtermWidget xw)
4812{
4813    if (xw->screen.unparse_len) {
4814#ifdef VMS
4815	tt_write(xw->screen.unparse_bfr, xw->screen.unparse_len);
4816#else /* VMS */
4817	writePtyData(xw->screen.respond, xw->screen.unparse_bfr, xw->screen.unparse_len);
4818#endif /* VMS */
4819	xw->screen.unparse_len = 0;
4820    }
4821}
4822
4823void
4824ToggleAlternate(XtermWidget xw)
4825{
4826    if (xw->screen.whichBuf)
4827	FromAlternate(xw);
4828    else
4829	ToAlternate(xw);
4830}
4831
4832static void
4833ToAlternate(XtermWidget xw)
4834{
4835    TScreen *screen = &(xw->screen);
4836
4837    if (screen->whichBuf == 0) {
4838	TRACE(("ToAlternate\n"));
4839	if (!screen->editBuf_index[1])
4840	    screen->editBuf_index[1] = allocScrnBuf(xw,
4841						    (unsigned) MaxRows(screen),
4842						    (unsigned) MaxCols(screen),
4843						    &screen->editBuf_data[1]);
4844	SwitchBufs(xw);
4845	screen->whichBuf = 1;
4846#if OPT_SAVE_LINES
4847	screen->visbuf = screen->editBuf_index[screen->whichBuf];
4848#endif
4849	update_altscreen();
4850    }
4851}
4852
4853static void
4854FromAlternate(XtermWidget xw)
4855{
4856    TScreen *screen = &(xw->screen);
4857
4858    if (screen->whichBuf != 0) {
4859	TRACE(("FromAlternate\n"));
4860	if (screen->scroll_amt)
4861	    FlushScroll(xw);
4862	screen->whichBuf = 0;
4863	SwitchBufs(xw);
4864#if OPT_SAVE_LINES
4865	screen->visbuf = screen->editBuf_index[screen->whichBuf];
4866#endif
4867	update_altscreen();
4868    }
4869}
4870
4871static void
4872SwitchBufs(XtermWidget xw)
4873{
4874    TScreen *screen = &(xw->screen);
4875    int rows, top;
4876
4877    if (screen->cursor_state)
4878	HideCursor();
4879
4880    rows = MaxRows(screen);
4881    SwitchBufPtrs(screen);
4882
4883    if ((top = INX2ROW(screen, 0)) < rows) {
4884	if (screen->scroll_amt)
4885	    FlushScroll(xw);
4886	XClearArea(screen->display,
4887		   VWindow(screen),
4888		   (int) OriginX(screen),
4889		   (int) top * FontHeight(screen) + screen->border,
4890		   (unsigned) Width(screen),
4891		   (unsigned) ((rows - top) * FontHeight(screen)),
4892		   False);
4893    }
4894    ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False);
4895}
4896
4897Bool
4898CheckBufPtrs(TScreen * screen)
4899{
4900    return (screen->visbuf != 0
4901#if OPT_SAVE_LINES
4902	    && screen->editBuf_index[0] != 0
4903#endif
4904	    && screen->editBuf_index[1] != 0);
4905}
4906
4907/*
4908 * Swap buffer line pointers between alternate and regular screens.
4909 */
4910void
4911SwitchBufPtrs(TScreen * screen)
4912{
4913    if (CheckBufPtrs(screen)) {
4914#if OPT_SAVE_LINES
4915	screen->visbuf = screen->editBuf_index[screen->whichBuf];
4916#else
4917	size_t len = ScrnPointers(screen, (unsigned) MaxRows(screen));
4918
4919	memcpy(screen->save_ptr, screen->visbuf, len);
4920	memcpy(screen->visbuf, screen->editBuf_index[1], len);
4921	memcpy(screen->editBuf_index[1], screen->save_ptr, len);
4922#endif
4923    }
4924}
4925
4926void
4927VTRun(XtermWidget xw)
4928{
4929    TScreen *screen = TScreenOf(xw);
4930
4931    TRACE(("VTRun ...\n"));
4932
4933    if (!screen->Vshow) {
4934	set_vt_visibility(True);
4935    }
4936    update_vttekmode();
4937    update_vtshow();
4938    update_tekshow();
4939    set_vthide_sensitivity();
4940
4941    ScrnAllocBuf(xw);
4942
4943    screen->cursor_state = OFF;
4944    screen->cursor_set = ON;
4945#if OPT_BLINK_CURS
4946    if (DoStartBlinking(screen))
4947	StartBlinking(screen);
4948#endif
4949
4950#if OPT_TEK4014
4951    if (Tpushb > Tpushback) {
4952	fillPtyData(screen, VTbuffer, (char *) Tpushback, Tpushb - Tpushback);
4953	Tpushb = Tpushback;
4954    }
4955#endif
4956    screen->is_running = True;
4957    if (!setjmp(VTend))
4958	VTparse(xw);
4959    StopBlinking(screen);
4960    HideCursor();
4961    screen->cursor_set = OFF;
4962    TRACE(("... VTRun\n"));
4963}
4964
4965/*ARGSUSED*/
4966static void
4967VTExpose(Widget w GCC_UNUSED,
4968	 XEvent * event,
4969	 Region region GCC_UNUSED)
4970{
4971#ifdef DEBUG
4972    if (debug)
4973	fputs("Expose\n", stderr);
4974#endif /* DEBUG */
4975    if (event->type == Expose)
4976	HandleExposure(term, event);
4977}
4978
4979static void
4980VTGraphicsOrNoExpose(XEvent * event)
4981{
4982    TScreen *screen = TScreenOf(term);
4983    if (screen->incopy <= 0) {
4984	screen->incopy = 1;
4985	if (screen->scrolls > 0)
4986	    screen->scrolls--;
4987    }
4988    if (event->type == GraphicsExpose)
4989	if (HandleExposure(term, event))
4990	    screen->cursor_state = OFF;
4991    if ((event->type == NoExpose)
4992	|| ((XGraphicsExposeEvent *) event)->count == 0) {
4993	if (screen->incopy <= 0 && screen->scrolls > 0)
4994	    screen->scrolls--;
4995	if (screen->scrolls)
4996	    screen->incopy = -1;
4997	else
4998	    screen->incopy = 0;
4999    }
5000}
5001
5002/*ARGSUSED*/
5003static void
5004VTNonMaskableEvent(Widget w GCC_UNUSED,
5005		   XtPointer closure GCC_UNUSED,
5006		   XEvent * event,
5007		   Boolean * cont GCC_UNUSED)
5008{
5009    switch (event->type) {
5010    case GraphicsExpose:
5011    case NoExpose:
5012	VTGraphicsOrNoExpose(event);
5013	break;
5014    }
5015}
5016
5017static void
5018VTResize(Widget w)
5019{
5020    if (XtIsRealized(w)) {
5021	XtermWidget xw = (XtermWidget) w;
5022	ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags);
5023    }
5024}
5025
5026#define okDimension(src,dst) ((src <= 32767) \
5027			  && ((dst = (Dimension) src) == src))
5028
5029static void
5030RequestResize(XtermWidget xw, int rows, int cols, Bool text)
5031{
5032    TScreen *screen = &xw->screen;
5033    unsigned long value;
5034    Dimension replyWidth, replyHeight;
5035    Dimension askedWidth, askedHeight;
5036    XtGeometryResult status;
5037    XWindowAttributes attrs;
5038
5039    TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text));
5040
5041    if ((askedWidth = (Dimension) cols) < cols
5042	|| (askedHeight = (Dimension) rows) < rows)
5043	return;
5044
5045    if (askedHeight == 0
5046	|| askedWidth == 0
5047	|| xw->misc.limit_resize > 0) {
5048	XGetWindowAttributes(XtDisplay(xw),
5049			     RootWindowOfScreen(XtScreen(xw)), &attrs);
5050    }
5051
5052    if (text) {
5053	if ((value = (unsigned long) rows) != 0) {
5054	    if (rows < 0)
5055		value = (unsigned long) MaxRows(screen);
5056	    value *= (unsigned long) FontHeight(screen);
5057	    value += (unsigned long) (2 * screen->border);
5058	    if (!okDimension(value, askedHeight))
5059		return;
5060	}
5061
5062	if ((value = (unsigned long) cols) != 0) {
5063	    if (cols < 0)
5064		value = (unsigned long) MaxCols(screen);
5065	    value *= (unsigned long) FontWidth(screen);
5066	    value += (unsigned long) ((2 * screen->border)
5067				      + ScrollbarWidth(screen));
5068	    if (!okDimension(value, askedWidth))
5069		return;
5070	}
5071
5072    } else {
5073	if (rows < 0)
5074	    askedHeight = FullHeight(screen);
5075	if (cols < 0)
5076	    askedWidth = FullWidth(screen);
5077    }
5078
5079    if (rows == 0)
5080	askedHeight = (Dimension) attrs.height;
5081    if (cols == 0)
5082	askedWidth = (Dimension) attrs.width;
5083
5084    if (xw->misc.limit_resize > 0) {
5085	Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height);
5086	Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width);
5087	if (high < attrs.height)
5088	    high = (Dimension) attrs.height;
5089	if (askedHeight > high)
5090	    askedHeight = high;
5091	if (wide < attrs.width)
5092	    wide = (Dimension) attrs.width;
5093	if (askedWidth > wide)
5094	    askedWidth = wide;
5095    }
5096#ifndef nothack
5097    getXtermSizeHints(xw);
5098#endif
5099
5100    TRACE(("...requesting resize %dx%d\n", askedHeight, askedWidth));
5101    status = REQ_RESIZE((Widget) xw,
5102			askedWidth, askedHeight,
5103			&replyWidth, &replyHeight);
5104
5105    if (status == XtGeometryYes ||
5106	status == XtGeometryDone) {
5107	ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
5108    }
5109#ifndef nothack
5110    /*
5111     * XtMakeResizeRequest() has the undesirable side-effect of clearing
5112     * the window manager's hints, even on a failed request.  This would
5113     * presumably be fixed if the shell did its own work.
5114     */
5115    if (xw->hints.flags
5116	&& replyHeight
5117	&& replyWidth) {
5118	xw->hints.height = replyHeight;
5119	xw->hints.width = replyWidth;
5120
5121	TRACE(("%s@%d -- ", __FILE__, __LINE__));
5122	TRACE_HINTS(&xw->hints);
5123	XSetWMNormalHints(screen->display, VShellWindow, &xw->hints);
5124	TRACE(("%s@%d -- ", __FILE__, __LINE__));
5125	TRACE_WM_HINTS(xw);
5126    }
5127#endif
5128
5129    XSync(screen->display, False);	/* synchronize */
5130    if (XtAppPending(app_con))
5131	xevents();
5132
5133    TRACE(("...RequestResize done\n"));
5134}
5135
5136static String xterm_trans =
5137"<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
5138     <MappingNotify>: KeyboardMapping()\n";
5139
5140int
5141VTInit(XtermWidget xw)
5142{
5143    Widget vtparent = SHELL_OF(xw);
5144
5145    TRACE(("VTInit {{\n"));
5146
5147    XtRealizeWidget(vtparent);
5148    XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
5149    (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent),
5150			   &wm_delete_window, 1);
5151    TRACE_TRANS("shell", vtparent);
5152    TRACE_TRANS("vt100", (Widget) (xw));
5153
5154    ScrnAllocBuf(xw);
5155
5156    TRACE(("...}} VTInit\n"));
5157    return (1);
5158}
5159
5160static void
5161VTClassInit(void)
5162{
5163    XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
5164		   (XtConvertArgList) NULL, (Cardinal) 0);
5165}
5166
5167/*
5168 * The whole wnew->screen struct is zeroed in VTInitialize.  Use these macros
5169 * where applicable for copying the pieces from the request widget into the
5170 * new widget.  We do not have to use them for wnew->misc, but the associated
5171 * traces are very useful for debugging.
5172 */
5173#if OPT_TRACE
5174#define init_Bres(name) \
5175	TRACE(("init " #name " = %s\n", \
5176		BtoS(wnew->name = request->name)))
5177#define init_Dres2(name,i) \
5178	TRACE(("init " #name "[%d] = %f\n", i, \
5179		wnew->name[i] = request->name[i]))
5180#define init_Ires(name) \
5181	TRACE(("init " #name " = %d\n", \
5182		wnew->name = request->name))
5183#define init_Sres(name) \
5184	TRACE(("init " #name " = \"%s\"\n", \
5185		(wnew->name = x_strtrim(request->name)) != NULL \
5186			? wnew->name : "<null>"))
5187#define init_Sres2(name,i) \
5188	TRACE(("init " #name "[%d] = \"%s\"\n", i, \
5189		(wnew->name(i) = x_strtrim(request->name(i))) != NULL \
5190			? wnew->name(i) : "<null>"))
5191#define init_Tres(offset) \
5192	TRACE(("init screen.Tcolors[" #offset "] = %#lx\n", \
5193		fill_Tres(wnew, request, offset)))
5194#else
5195#define init_Bres(name)    wnew->name = request->name
5196#define init_Dres2(name,i) wnew->name[i] = request->name[i]
5197#define init_Ires(name)    wnew->name = request->name
5198#define init_Sres(name)    wnew->name = x_strtrim(request->name)
5199#define init_Sres2(name,i) wnew->name(i) = x_strtrim(request->name(i))
5200#define init_Tres(offset)  fill_Tres(wnew, request, offset)
5201#endif
5202
5203#if OPT_COLOR_RES
5204/*
5205 * Override the use of XtDefaultForeground/XtDefaultBackground to make some
5206 * colors, such as cursor color, use the actual foreground/background value
5207 * if there is no explicit resource value used.
5208 */
5209static Pixel
5210fill_Tres(XtermWidget target, XtermWidget source, int offset)
5211{
5212    char *name;
5213    ScrnColors temp;
5214
5215    target->screen.Tcolors[offset] = source->screen.Tcolors[offset];
5216    target->screen.Tcolors[offset].mode = False;
5217
5218    if ((name = x_strtrim(target->screen.Tcolors[offset].resource)) != 0)
5219	target->screen.Tcolors[offset].resource = name;
5220
5221    if (name == 0) {
5222	target->screen.Tcolors[offset].value = target->dft_foreground;
5223    } else if (isDefaultForeground(name)) {
5224	target->screen.Tcolors[offset].value =
5225	    ((offset == TEXT_FG || offset == TEXT_BG)
5226	     ? target->dft_foreground
5227	     : target->screen.Tcolors[TEXT_FG].value);
5228    } else if (isDefaultBackground(name)) {
5229	target->screen.Tcolors[offset].value =
5230	    ((offset == TEXT_FG || offset == TEXT_BG)
5231	     ? target->dft_background
5232	     : target->screen.Tcolors[TEXT_BG].value);
5233    } else {
5234	memset(&temp, 0, sizeof(temp));
5235	if (AllocateTermColor(target, &temp, offset, name)) {
5236	    if (COLOR_DEFINED(&(temp), offset))
5237		free(temp.names[offset]);
5238	    target->screen.Tcolors[offset].value = temp.colors[offset];
5239	}
5240    }
5241    return target->screen.Tcolors[offset].value;
5242}
5243#else
5244#define fill_Tres(target, source, offset) \
5245	target->screen.Tcolors[offset] = source->screen.Tcolors[offset]
5246#endif
5247
5248#if OPT_WIDE_CHARS
5249static void
5250VTInitialize_locale(XtermWidget request)
5251{
5252    Bool is_utf8 = xtermEnvUTF8();
5253
5254    TRACE(("VTInitialize_locale\n"));
5255    TRACE(("... request screen.utf8_mode = %d\n", request->screen.utf8_mode));
5256
5257    if (request->screen.utf8_mode < 0)
5258	request->screen.utf8_mode = uFalse;
5259
5260    if (request->screen.utf8_mode > 3)
5261	request->screen.utf8_mode = uDefault;
5262
5263    request->screen.latin9_mode = 0;
5264    request->screen.unicode_font = 0;
5265#if OPT_LUIT_PROG
5266    request->misc.callfilter = 0;
5267    request->misc.use_encoding = 0;
5268
5269    TRACE(("... setup for luit:\n"));
5270    TRACE(("... request misc.locale_str = \"%s\"\n", request->misc.locale_str));
5271
5272    if (request->screen.utf8_mode == uFalse) {
5273	TRACE(("... command-line +u8 overrides\n"));
5274    } else
5275#if OPT_MINI_LUIT
5276    if (x_strcasecmp(request->misc.locale_str, "CHECKFONT") == 0) {
5277	int fl = (request->misc.default_font.f_n
5278		  ? (int) strlen(request->misc.default_font.f_n)
5279		  : 0);
5280	if (fl > 11
5281	    && x_strcasecmp(request->misc.default_font.f_n + fl - 11,
5282			    "-ISO10646-1") == 0) {
5283	    request->screen.unicode_font = 1;
5284	    /* unicode font, use True */
5285#ifdef HAVE_LANGINFO_CODESET
5286	    if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968")
5287		|| !strcmp(xtermEnvEncoding(), "ISO-8859-1")) {
5288		if (request->screen.utf8_mode == uDefault)
5289		    request->screen.utf8_mode = uFalse;
5290	    } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) {
5291		if (request->screen.utf8_mode == uDefault)
5292		    request->screen.utf8_mode = uFalse;
5293		request->screen.latin9_mode = 1;
5294	    } else {
5295		request->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
5296		request->screen.utf8_mode = uAlways;
5297	    }
5298#else
5299	    request->misc.callfilter = is_utf8 ? 0 : 1;
5300	    request->screen.utf8_mode = uAlways;
5301#endif
5302	} else {
5303	    /* other encoding, use False */
5304	    if (request->screen.utf8_mode == uDefault) {
5305		request->screen.utf8_mode = is_utf8 ? uAlways : uFalse;
5306	    }
5307	}
5308    } else
5309#endif /* OPT_MINI_LUIT */
5310	if (x_strcasecmp(request->misc.locale_str, "TRUE") == 0 ||
5311	    x_strcasecmp(request->misc.locale_str, "ON") == 0 ||
5312	    x_strcasecmp(request->misc.locale_str, "YES") == 0 ||
5313	    x_strcasecmp(request->misc.locale_str, "AUTO") == 0 ||
5314	    strcmp(request->misc.locale_str, "1") == 0) {
5315	/* when true ... fully obeying LC_CTYPE locale */
5316	request->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
5317	request->screen.utf8_mode = uAlways;
5318    } else if (x_strcasecmp(request->misc.locale_str, "FALSE") == 0 ||
5319	       x_strcasecmp(request->misc.locale_str, "OFF") == 0 ||
5320	       x_strcasecmp(request->misc.locale_str, "NO") == 0 ||
5321	       strcmp(request->misc.locale_str, "0") == 0) {
5322	/* when false ... original value of utf8_mode is effective */
5323	if (request->screen.utf8_mode == uDefault) {
5324	    request->screen.utf8_mode = is_utf8 ? uAlways : uFalse;
5325	}
5326    } else if (x_strcasecmp(request->misc.locale_str, "MEDIUM") == 0 ||
5327	       x_strcasecmp(request->misc.locale_str, "SEMIAUTO") == 0) {
5328	/* when medium ... obeying locale only for UTF-8 and Asian */
5329	if (is_utf8) {
5330	    request->screen.utf8_mode = uAlways;
5331	} else if (
5332#ifdef MB_CUR_MAX
5333		      MB_CUR_MAX > 1 ||
5334#else
5335		      !strncmp(xtermEnvLocale(), "ja", 2) ||
5336		      !strncmp(xtermEnvLocale(), "ko", 2) ||
5337		      !strncmp(xtermEnvLocale(), "zh", 2) ||
5338#endif
5339		      !strncmp(xtermEnvLocale(), "th", 2) ||
5340		      !strncmp(xtermEnvLocale(), "vi", 2)) {
5341	    request->misc.callfilter = 1;
5342	    request->screen.utf8_mode = uAlways;
5343	} else {
5344	    request->screen.utf8_mode = uFalse;
5345	}
5346    } else if (x_strcasecmp(request->misc.locale_str, "UTF-8") == 0 ||
5347	       x_strcasecmp(request->misc.locale_str, "UTF8") == 0) {
5348	/* when UTF-8 ... UTF-8 mode */
5349	request->screen.utf8_mode = uAlways;
5350    } else {
5351	/* other words are regarded as encoding name passed to luit */
5352	request->misc.callfilter = 1;
5353	request->screen.utf8_mode = uAlways;
5354	request->misc.use_encoding = 1;
5355    }
5356    TRACE(("... updated misc.callfilter = %s\n", BtoS(request->misc.callfilter)));
5357    TRACE(("... updated misc.use_encoding = %s\n", BtoS(request->misc.use_encoding)));
5358#else
5359    if (request->screen.utf8_mode == uDefault) {
5360	request->screen.utf8_mode = is_utf8 ? uAlways : uFalse;
5361    }
5362#endif /* OPT_LUIT_PROG */
5363
5364    request->screen.utf8_inparse = (Boolean) (request->screen.utf8_mode != uFalse);
5365
5366    TRACE(("... updated screen.utf8_mode = %d\n", request->screen.utf8_mode));
5367    TRACE(("...VTInitialize_locale done\n"));
5368}
5369#endif
5370
5371static void
5372ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item)
5373{
5374    /* *INDENT-OFF* */
5375    static struct {
5376	const String	name;
5377	SelectUnit	code;
5378    } table[] = {
5379    	{ "char",	Select_CHAR },
5380    	{ "word",	Select_WORD },
5381    	{ "line",	Select_LINE },
5382    	{ "group",	Select_GROUP },
5383    	{ "page",	Select_PAGE },
5384    	{ "all",	Select_ALL },
5385#if OPT_SELECT_REGEX
5386    	{ "regex",	Select_REGEX },
5387#endif
5388    };
5389    /* *INDENT-ON* */
5390
5391    String res = wreq->screen.onClick[item];
5392    String next = x_skip_nonblanks(res);
5393    Cardinal n;
5394
5395    wnew->screen.selectMap[item] = NSELECTUNITS;
5396    for (n = 0; n < XtNumber(table); ++n) {
5397	if (!x_strncasecmp(table[n].name, res, (unsigned) (next - res))) {
5398	    wnew->screen.selectMap[item] = table[n].code;
5399#if OPT_SELECT_REGEX
5400	    if (table[n].code == Select_REGEX) {
5401		wnew->screen.selectExpr[item] = x_strtrim(next);
5402		TRACE(("Parsed regex \"%s\"\n", wnew->screen.selectExpr[item]));
5403	    }
5404#endif
5405	    break;
5406	}
5407    }
5408}
5409
5410/* ARGSUSED */
5411static void
5412VTInitialize(Widget wrequest,
5413	     Widget new_arg,
5414	     ArgList args GCC_UNUSED,
5415	     Cardinal *num_args GCC_UNUSED)
5416{
5417#define Kolor(name) wnew->screen.name.resource
5418#define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name))
5419#define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name))
5420#define DftFg(name) isDefaultForeground(Kolor(name))
5421#define DftBg(name) isDefaultBackground(Kolor(name))
5422
5423    XtermWidget request = (XtermWidget) wrequest;
5424    XtermWidget wnew = (XtermWidget) new_arg;
5425    Widget my_parent = SHELL_OF(wnew);
5426    int i;
5427    char *s;
5428
5429#if OPT_ISO_COLORS
5430    Bool color_ok;
5431#endif
5432
5433#if OPT_COLOR_RES2 && (MAXCOLORS > MIN_ANSI_COLORS)
5434    static XtResource fake_resources[] =
5435    {
5436#if OPT_256_COLORS
5437# include <256colres.h>
5438#elif OPT_88_COLORS
5439# include <88colres.h>
5440#endif
5441    };
5442#endif /* OPT_COLOR_RES2 */
5443
5444    TRACE(("VTInitialize\n"));
5445
5446    /* Zero out the entire "screen" component of "wnew" widget, then do
5447     * field-by-field assignment of "screen" fields that are named in the
5448     * resource list.
5449     */
5450    memset(&wnew->screen, 0, sizeof(wnew->screen));
5451
5452    /* DESCO Sys#67660
5453     * Zero out the entire "keyboard" component of "wnew" widget.
5454     */
5455    memset(&wnew->keyboard, 0, sizeof(wnew->keyboard));
5456
5457    /* dummy values so that we don't try to Realize the parent shell with height
5458     * or width of 0, which is illegal in X.  The real size is computed in the
5459     * xtermWidget's Realize proc, but the shell's Realize proc is called first,
5460     * and must see a valid size.
5461     */
5462    wnew->core.height = wnew->core.width = 1;
5463
5464    /*
5465     * The definition of -rv now is that it changes the definition of
5466     * XtDefaultForeground and XtDefaultBackground.  So, we no longer
5467     * need to do anything special.
5468     */
5469    wnew->screen.display = wnew->core.screen->display;
5470
5471    /*
5472     * We use the default foreground/background colors to compare/check if a
5473     * color-resource has been set.
5474     */
5475#define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy))
5476#define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy))
5477
5478    if (request->misc.re_verse) {
5479	wnew->dft_foreground = MyWhitePixel(wnew->screen.display);
5480	wnew->dft_background = MyBlackPixel(wnew->screen.display);
5481    } else {
5482	wnew->dft_foreground = MyBlackPixel(wnew->screen.display);
5483	wnew->dft_background = MyWhitePixel(wnew->screen.display);
5484    }
5485    init_Tres(TEXT_FG);
5486    init_Tres(TEXT_BG);
5487
5488    TRACE(("Color resource initialization:\n"));
5489    TRACE(("   Default foreground %#lx\n", wnew->dft_foreground));
5490    TRACE(("   Default background %#lx\n", wnew->dft_background));
5491    TRACE(("   Screen foreground  %#lx\n", T_COLOR(&(wnew->screen), TEXT_FG)));
5492    TRACE(("   Screen background  %#lx\n", T_COLOR(&(wnew->screen), TEXT_BG)));
5493
5494    wnew->screen.mouse_button = -1;
5495    wnew->screen.mouse_row = -1;
5496    wnew->screen.mouse_col = -1;
5497
5498#if OPT_BOX_CHARS
5499    init_Bres(screen.force_box_chars);
5500    init_Bres(screen.force_all_chars);
5501#endif
5502    init_Bres(screen.free_bold_box);
5503
5504    init_Bres(screen.c132);
5505    init_Bres(screen.curses);
5506    init_Bres(screen.hp_ll_bc);
5507#if OPT_XMC_GLITCH
5508    init_Ires(screen.xmc_glitch);
5509    init_Ires(screen.xmc_attributes);
5510    init_Bres(screen.xmc_inline);
5511    init_Bres(screen.move_sgr_ok);
5512#endif
5513#if OPT_BLINK_CURS
5514    init_Bres(screen.cursor_blink);
5515    init_Ires(screen.blink_on);
5516    init_Ires(screen.blink_off);
5517    wnew->screen.cursor_blink_res = wnew->screen.cursor_blink;
5518#endif
5519    init_Bres(screen.cursor_underline);
5520#if OPT_BLINK_TEXT
5521    init_Ires(screen.blink_as_bold);
5522#endif
5523    init_Ires(screen.border);
5524    init_Bres(screen.jumpscroll);
5525    init_Bres(screen.fastscroll);
5526    init_Bres(screen.old_fkeys);
5527    init_Bres(screen.delete_is_del);
5528    wnew->keyboard.type = wnew->screen.old_fkeys
5529	? keyboardIsLegacy
5530	: keyboardIsDefault;
5531#ifdef ALLOWLOGGING
5532    init_Sres(screen.logfile);
5533#endif
5534    init_Bres(screen.bellIsUrgent);
5535    init_Bres(screen.bellOnReset);
5536    init_Bres(screen.marginbell);
5537    init_Bres(screen.multiscroll);
5538    init_Ires(screen.nmarginbell);
5539    init_Ires(screen.savelines);
5540    init_Ires(screen.scrollBarBorder);
5541    init_Ires(screen.scrolllines);
5542    init_Bres(screen.scrollttyoutput);
5543    init_Bres(screen.scrollkey);
5544
5545    init_Sres(screen.term_id);
5546    for (s = request->screen.term_id; *s; s++) {
5547	if (!isalpha(CharOf(*s)))
5548	    break;
5549    }
5550    wnew->screen.terminal_id = atoi(s);
5551    if (wnew->screen.terminal_id < MIN_DECID)
5552	wnew->screen.terminal_id = MIN_DECID;
5553    if (wnew->screen.terminal_id > MAX_DECID)
5554	wnew->screen.terminal_id = MAX_DECID;
5555    TRACE(("term_id '%s' -> terminal_id %d\n",
5556	   wnew->screen.term_id,
5557	   wnew->screen.terminal_id));
5558
5559    wnew->screen.vtXX_level = (wnew->screen.terminal_id / 100);
5560    init_Bres(screen.visualbell);
5561    init_Ires(screen.visualBellDelay);
5562    init_Bres(screen.poponbell);
5563    init_Ires(misc.limit_resize);
5564#if OPT_NUM_LOCK
5565    init_Bres(misc.real_NumLock);
5566    init_Bres(misc.alwaysUseMods);
5567    wnew->misc.num_lock = 0;
5568    wnew->misc.alt_mods = 0;
5569    wnew->misc.meta_mods = 0;
5570    wnew->misc.other_mods = 0;
5571#endif
5572#if OPT_SHIFT_FONTS
5573    init_Bres(misc.shift_fonts);
5574#endif
5575#if OPT_SUNPC_KBD
5576    init_Ires(misc.ctrl_fkeys);
5577#endif
5578#if OPT_TEK4014
5579    TEK4014_SHOWN(wnew) = False;	/* not a resource... */
5580    init_Bres(misc.tekInhibit);
5581    init_Bres(misc.tekSmall);
5582    init_Bres(misc.TekEmu);
5583#endif
5584#if OPT_TCAP_QUERY
5585    wnew->screen.tc_query_code = -1;
5586#endif
5587    wnew->misc.re_verse0 = request->misc.re_verse;
5588    init_Bres(misc.re_verse);
5589    init_Ires(screen.multiClickTime);
5590    init_Ires(screen.bellSuppressTime);
5591    init_Sres(screen.charClass);
5592
5593    init_Bres(screen.always_highlight);
5594    init_Bres(screen.brokenSelections);
5595    init_Bres(screen.cutNewline);
5596    init_Bres(screen.cutToBeginningOfLine);
5597    init_Bres(screen.highlight_selection);
5598    init_Bres(screen.i18nSelections);
5599    init_Bres(screen.keepSelection);
5600    init_Bres(screen.selectToClipboard);
5601    init_Bres(screen.trim_selection);
5602
5603    wnew->screen.pointer_cursor = request->screen.pointer_cursor;
5604    init_Ires(screen.pointer_mode);
5605
5606    init_Sres(screen.answer_back);
5607
5608    init_Sres(screen.printer_command);
5609    init_Bres(screen.printer_autoclose);
5610    init_Bres(screen.printer_extent);
5611    init_Bres(screen.printer_formfeed);
5612    init_Ires(screen.printer_controlmode);
5613#if OPT_PRINT_COLORS
5614    init_Ires(screen.print_attributes);
5615#endif
5616
5617    init_Sres(screen.keyboard_dialect);
5618
5619    init_Bres(screen.input_eight_bits);
5620    init_Bres(screen.output_eight_bits);
5621    init_Bres(screen.control_eight_bits);
5622    init_Bres(screen.backarrow_key);
5623    init_Bres(screen.alt_is_not_meta);
5624    init_Bres(screen.alt_sends_esc);
5625    init_Bres(screen.meta_sends_esc);
5626
5627    init_Bres(screen.allowSendEvent0);
5628    init_Bres(screen.allowFontOp0);
5629    init_Bres(screen.allowTcapOp0);
5630    init_Bres(screen.allowTitleOp0);
5631    init_Bres(screen.allowWindowOp0);
5632
5633    init_Sres(screen.default_string);
5634    init_Sres(screen.eightbit_select_types);
5635#if OPT_WIDE_CHARS
5636    init_Sres(screen.utf8_select_types);
5637#endif
5638
5639    /* make a copy so that editres cannot change the resource after startup */
5640    wnew->screen.allowSendEvents = wnew->screen.allowSendEvent0;
5641    wnew->screen.allowFontOps = wnew->screen.allowFontOp0;
5642    wnew->screen.allowTcapOps = wnew->screen.allowTcapOp0;
5643    wnew->screen.allowTitleOps = wnew->screen.allowTitleOp0;
5644    wnew->screen.allowWindowOps = wnew->screen.allowWindowOp0;
5645
5646    init_Bres(screen.quiet_grab);
5647
5648#ifndef NO_ACTIVE_ICON
5649    wnew->screen.fnt_icon.fs = request->screen.fnt_icon.fs;
5650    init_Bres(misc.active_icon);
5651    init_Ires(misc.icon_border_width);
5652    wnew->misc.icon_border_pixel = request->misc.icon_border_pixel;
5653#endif /* NO_ACTIVE_ICON */
5654    init_Bres(misc.titeInhibit);
5655    init_Bres(misc.tiXtraScroll);
5656    init_Bres(misc.dynamicColors);
5657    for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) {
5658	init_Sres2(screen.MenuFontName, i);
5659    }
5660    init_Ires(misc.fontWarnings);
5661#define DefaultFontNames wnew->screen.menu_font_names[fontMenu_default]
5662    DefaultFontNames[fNorm] = wnew->misc.default_font.f_n;
5663    DefaultFontNames[fBold] = wnew->misc.default_font.f_b;
5664#if OPT_WIDE_CHARS
5665    DefaultFontNames[fWide] = wnew->misc.default_font.f_w;
5666    DefaultFontNames[fWBold] = wnew->misc.default_font.f_wb;
5667#endif
5668    wnew->screen.MenuFontName(fontMenu_fontescape) = NULL;
5669    wnew->screen.MenuFontName(fontMenu_fontsel) = NULL;
5670
5671    wnew->screen.menu_font_number = fontMenu_default;
5672    init_Sres(screen.initial_font);
5673    if (wnew->screen.initial_font != 0) {
5674	int result = xtermGetFont(wnew->screen.initial_font);
5675	if (result >= 0)
5676	    wnew->screen.menu_font_number = result;
5677    }
5678#if OPT_BROKEN_OSC
5679    init_Bres(screen.brokenLinuxOSC);
5680#endif
5681
5682#if OPT_BROKEN_ST
5683    init_Bres(screen.brokenStringTerm);
5684#endif
5685
5686#if OPT_C1_PRINT
5687    init_Bres(screen.c1_printable);
5688#endif
5689
5690#if OPT_CLIP_BOLD
5691    init_Bres(screen.use_clipping);
5692#endif
5693
5694#if OPT_DEC_CHRSET
5695    init_Bres(screen.font_doublesize);
5696    init_Ires(screen.cache_doublesize);
5697    if (wnew->screen.cache_doublesize > NUM_CHRSET)
5698	wnew->screen.cache_doublesize = NUM_CHRSET;
5699    if (wnew->screen.cache_doublesize == 0)
5700	wnew->screen.font_doublesize = False;
5701    TRACE(("Doublesize%s enabled, up to %d fonts\n",
5702	   wnew->screen.font_doublesize ? "" : " not",
5703	   wnew->screen.cache_doublesize));
5704#endif
5705
5706#if OPT_ISO_COLORS
5707    init_Ires(screen.veryBoldColors);
5708    init_Bres(screen.boldColors);
5709    init_Bres(screen.colorAttrMode);
5710    init_Bres(screen.colorBDMode);
5711    init_Bres(screen.colorBLMode);
5712    init_Bres(screen.colorMode);
5713    init_Bres(screen.colorULMode);
5714    init_Bres(screen.italicULMode);
5715    init_Bres(screen.colorRVMode);
5716
5717    for (i = 0, color_ok = False; i < MAXCOLORS; i++) {
5718
5719#if OPT_COLOR_RES2 && (MAXCOLORS > MIN_ANSI_COLORS)
5720	/*
5721	 * Xt has a hardcoded limit on the maximum number of resources that can
5722	 * be used in a widget.  If we configure both luit (which implies
5723	 * wide-characters) and 256-colors, it goes over that limit.  Most
5724	 * people would not need a resource-file with 256-colors; the default
5725	 * values in our table are sufficient.  In that case, fake the resource
5726	 * setting by copying the default value from the table.  The #define's
5727	 * can be overridden to make these true resources.
5728	 */
5729	if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) {
5730	    wnew->screen.Acolors[i].resource
5731		= ((char *) fake_resources[i - MIN_ANSI_COLORS].default_addr);
5732	    if (wnew->screen.Acolors[i].resource == 0)
5733		wnew->screen.Acolors[i].resource = XtDefaultForeground;
5734	} else
5735#endif /* OPT_COLOR_RES2 */
5736	    wnew->screen.Acolors[i] = request->screen.Acolors[i];
5737
5738#if OPT_COLOR_RES
5739	TRACE(("Acolors[%d] = %s\n", i, wnew->screen.Acolors[i].resource));
5740	wnew->screen.Acolors[i].mode = False;
5741	if (DftFg(Acolors[i])) {
5742	    wnew->screen.Acolors[i].value = T_COLOR(&(wnew->screen), TEXT_FG);
5743	    wnew->screen.Acolors[i].mode = True;
5744	} else if (DftBg(Acolors[i])) {
5745	    wnew->screen.Acolors[i].value = T_COLOR(&(wnew->screen), TEXT_BG);
5746	    wnew->screen.Acolors[i].mode = True;
5747	} else {
5748	    color_ok = True;
5749	}
5750#else
5751	TRACE(("Acolors[%d] = %#lx\n", i, request->screen.Acolors[i]));
5752	if (wnew->screen.Acolors[i] != wnew->dft_foreground &&
5753	    wnew->screen.Acolors[i] != T_COLOR(&(wnew->screen), TEXT_FG) &&
5754	    wnew->screen.Acolors[i] != T_COLOR(&(wnew->screen), TEXT_BG))
5755	    color_ok = True;
5756#endif
5757    }
5758
5759    /*
5760     * Check if we're trying to use color in a monochrome screen.  Disable
5761     * color in that case, since that would make ANSI colors unusable.  A 4-bit
5762     * or 8-bit display is usable, so we do not have to check for anything more
5763     * specific.
5764     */
5765    if (color_ok) {
5766	Display *display = wnew->screen.display;
5767	XVisualInfo myTemplate, *visInfoPtr;
5768	int numFound;
5769
5770	myTemplate.visualid = XVisualIDFromVisual(DefaultVisual(display,
5771								XDefaultScreen(display)));
5772	visInfoPtr = XGetVisualInfo(display, (long) VisualIDMask,
5773				    &myTemplate, &numFound);
5774	if (visInfoPtr == 0
5775	    || numFound == 0
5776	    || visInfoPtr->depth <= 1) {
5777	    TRACE(("disabling color since screen is monochrome\n"));
5778	    color_ok = False;
5779	} else {
5780	    XFree(visInfoPtr);
5781	}
5782    }
5783
5784    /* If none of the colors are anything other than the foreground or
5785     * background, we'll assume this isn't color, no matter what the colorMode
5786     * resource says.  (There doesn't seem to be any good way to determine if
5787     * the resource lookup failed versus the user having misconfigured this).
5788     */
5789    if (!color_ok) {
5790	wnew->screen.colorMode = False;
5791	TRACE(("All colors are foreground or background: disable colorMode\n"));
5792    }
5793    wnew->sgr_foreground = -1;
5794    wnew->sgr_background = -1;
5795    wnew->sgr_extended = False;
5796#endif /* OPT_ISO_COLORS */
5797
5798    /*
5799     * Decode the resources that control the behavior on multiple mouse clicks.
5800     * A single click is always bound to normal character selection, but the
5801     * other flavors can be changed.
5802     */
5803    for (i = 0; i < NSELECTUNITS; ++i) {
5804	int ck = (i + 1);
5805	wnew->screen.maxClicks = ck;
5806	if (i == Select_CHAR)
5807	    wnew->screen.selectMap[i] = Select_CHAR;
5808	else if (request->screen.onClick[i] != 0)
5809	    ParseOnClicks(wnew, request, (unsigned) i);
5810	else if (i <= Select_LINE)
5811	    wnew->screen.selectMap[i] = (SelectUnit) i;
5812	else
5813	    break;
5814	TRACE(("on%dClicks %s=%d\n", ck,
5815	       NonNull(request->screen.onClick[i]),
5816	       wnew->screen.selectMap[i]));
5817	if (wnew->screen.selectMap[i] == NSELECTUNITS)
5818	    break;
5819    }
5820    TRACE(("maxClicks %d\n", wnew->screen.maxClicks));
5821
5822    init_Tres(MOUSE_FG);
5823    init_Tres(MOUSE_BG);
5824    init_Tres(TEXT_CURSOR);
5825#if OPT_HIGHLIGHT_COLOR
5826    init_Tres(HIGHLIGHT_BG);
5827    init_Tres(HIGHLIGHT_FG);
5828    init_Bres(screen.hilite_reverse);
5829    init_Bres(screen.hilite_color);
5830    if (wnew->screen.hilite_color == Maybe) {
5831	wnew->screen.hilite_color = False;
5832#if OPT_COLOR_RES
5833	/*
5834	 * If the highlight text/background are both set, and if they are
5835	 * not equal to either the text/background or background/text, then
5836	 * set the highlightColorMode automatically.
5837	 */
5838	if (!DftFg(Tcolors[HIGHLIGHT_BG])
5839	    && !DftBg(Tcolors[HIGHLIGHT_FG])
5840	    && !TxtFg(Tcolors[HIGHLIGHT_BG])
5841	    && !TxtBg(Tcolors[HIGHLIGHT_FG])
5842	    && !TxtBg(Tcolors[HIGHLIGHT_BG])
5843	    && !TxtFg(Tcolors[HIGHLIGHT_FG])) {
5844	    TRACE(("...setting hilite_color automatically\n"));
5845	    wnew->screen.hilite_color = True;
5846	}
5847#endif
5848    }
5849#endif
5850
5851#if OPT_TEK4014
5852    /*
5853     * The Tek4014 window has no separate resources for foreground, background
5854     * and cursor color.  Since xterm always creates the vt100 widget first, we
5855     * can set the Tektronix colors here.  That lets us use escape sequences to
5856     * set its dynamic colors and get consistent behavior whether or not the
5857     * window is displayed.
5858     */
5859    T_COLOR(&(wnew->screen), TEK_BG) = T_COLOR(&(wnew->screen), TEXT_BG);
5860    T_COLOR(&(wnew->screen), TEK_FG) = T_COLOR(&(wnew->screen), TEXT_FG);
5861    T_COLOR(&(wnew->screen), TEK_CURSOR) = T_COLOR(&(wnew->screen), TEXT_CURSOR);
5862#endif
5863
5864#if OPT_WIDE_CHARS
5865    VTInitialize_locale(request);
5866    init_Bres(screen.utf8_latin1);
5867    init_Bres(screen.utf8_title);
5868
5869#if OPT_LUIT_PROG
5870    init_Bres(misc.callfilter);
5871    init_Bres(misc.use_encoding);
5872    init_Sres(misc.locale_str);
5873    init_Sres(misc.localefilter);
5874#endif
5875
5876#if OPT_RENDERFONT
5877    for (i = 0; i <= fontMenu_lastBuiltin; ++i) {
5878	init_Dres2(misc.face_size, i);
5879    }
5880    init_Sres(misc.face_name);
5881    init_Sres(misc.face_wide_name);
5882    init_Bres(misc.render_font);
5883    /* minor tweak to make debug traces consistent: */
5884    if (wnew->misc.render_font) {
5885	if (wnew->misc.face_name == 0) {
5886	    wnew->misc.render_font = False;
5887	    TRACE(("reset render_font since there is no face_name\n"));
5888	}
5889    }
5890#endif
5891
5892    init_Ires(screen.utf8_inparse);
5893    init_Ires(screen.utf8_mode);
5894    init_Ires(screen.max_combining);
5895
5896    if (wnew->screen.max_combining < 0) {
5897	wnew->screen.max_combining = 0;
5898    }
5899    if (wnew->screen.max_combining > 5) {
5900	wnew->screen.max_combining = 5;
5901    }
5902
5903    init_Bres(screen.vt100_graphics);
5904    init_Bres(screen.wide_chars);
5905    init_Bres(misc.mk_width);
5906    init_Bres(misc.cjk_width);
5907
5908    init_Ires(misc.mk_samplesize);
5909    init_Ires(misc.mk_samplepass);
5910
5911    if (wnew->misc.mk_samplesize > 0xffff)
5912	wnew->misc.mk_samplesize = 0xffff;
5913    if (wnew->misc.mk_samplesize < 0)
5914	wnew->misc.mk_samplesize = 0;
5915
5916    if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize)
5917	wnew->misc.mk_samplepass = wnew->misc.mk_samplesize;
5918    if (wnew->misc.mk_samplepass < 0)
5919	wnew->misc.mk_samplepass = 0;
5920
5921    if (request->screen.utf8_mode) {
5922	TRACE(("setting wide_chars on\n"));
5923	wnew->screen.wide_chars = True;
5924    } else {
5925	TRACE(("setting utf8_mode to 0\n"));
5926	wnew->screen.utf8_mode = uFalse;
5927    }
5928    TRACE(("initialized UTF-8 mode to %d\n", wnew->screen.utf8_mode));
5929
5930#if OPT_MINI_LUIT
5931    if (request->screen.latin9_mode) {
5932	wnew->screen.latin9_mode = True;
5933    }
5934    if (request->screen.unicode_font) {
5935	wnew->screen.unicode_font = True;
5936    }
5937    TRACE(("initialized Latin9 mode to %d\n", wnew->screen.latin9_mode));
5938    TRACE(("initialized unicode_font to %d\n", wnew->screen.unicode_font));
5939#endif
5940
5941    decode_wcwidth((wnew->misc.cjk_width ? 2 : 0)
5942		   + (wnew->misc.mk_width ? 1 : 0)
5943		   + 1,
5944		   wnew->misc.mk_samplesize,
5945		   wnew->misc.mk_samplepass);
5946#endif /* OPT_WIDE_CHARS */
5947
5948    init_Bres(screen.always_bold_mode);
5949    init_Bres(screen.bold_mode);
5950    init_Bres(screen.underline);
5951
5952    wnew->cur_foreground = 0;
5953    wnew->cur_background = 0;
5954
5955    wnew->keyboard.flags = MODE_SRM;
5956    if (wnew->screen.backarrow_key)
5957	wnew->keyboard.flags |= MODE_DECBKM;
5958    TRACE(("initialized DECBKM %s\n",
5959	   BtoS(wnew->keyboard.flags & MODE_DECBKM)));
5960
5961    /* look for focus related events on the shell, because we need
5962     * to care about the shell's border being part of our focus.
5963     */
5964    XtAddEventHandler(my_parent, EnterWindowMask, False,
5965		      HandleEnterWindow, (Opaque) NULL);
5966    XtAddEventHandler(my_parent, LeaveWindowMask, False,
5967		      HandleLeaveWindow, (Opaque) NULL);
5968    XtAddEventHandler(my_parent, FocusChangeMask, False,
5969		      HandleFocusChange, (Opaque) NULL);
5970    XtAddEventHandler((Widget) wnew, 0L, True,
5971		      VTNonMaskableEvent, (Opaque) NULL);
5972    XtAddEventHandler((Widget) wnew, PropertyChangeMask, False,
5973		      HandleBellPropertyChange, (Opaque) NULL);
5974
5975#if HANDLE_STRUCT_NOTIFY
5976#if OPT_TOOLBAR
5977    wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar);
5978    init_Ires(VT100_TB_INFO(menu_height));
5979#else
5980    /* Flag icon name with "***"  on window output when iconified.
5981     * Put in a handler that will tell us when we get Map/Unmap events.
5982     */
5983    if (resource.zIconBeep)
5984#endif
5985	XtAddEventHandler(my_parent, StructureNotifyMask, False,
5986			  HandleStructNotify, (Opaque) 0);
5987#endif /* HANDLE_STRUCT_NOTIFY */
5988
5989    wnew->screen.bellInProgress = False;
5990
5991    set_character_class(wnew->screen.charClass);
5992
5993    /* create it, but don't realize it */
5994    ScrollBarOn(wnew, True);
5995
5996    /* make sure that the resize gravity acceptable */
5997    if (!GravityIsNorthWest(wnew) &&
5998	!GravityIsSouthWest(wnew)) {
5999	char value[80];
6000	char *temp[2];
6001	Cardinal nparams = 1;
6002
6003	sprintf(temp[0] = value, "%d", wnew->misc.resizeGravity);
6004	temp[1] = 0;
6005	XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
6006			"unsupported resizeGravity resource value (%s)",
6007			temp, &nparams);
6008	wnew->misc.resizeGravity = SouthWestGravity;
6009    }
6010#ifndef NO_ACTIVE_ICON
6011    wnew->screen.whichVwin = &wnew->screen.fullVwin;
6012#endif /* NO_ACTIVE_ICON */
6013
6014    if (wnew->screen.savelines < 0)
6015	wnew->screen.savelines = 0;
6016
6017    init_Bres(screen.awaitInput);
6018
6019    wnew->flags = 0;
6020    if (!wnew->screen.jumpscroll)
6021	wnew->flags |= SMOOTHSCROLL;
6022    if (wnew->misc.reverseWrap)
6023	wnew->flags |= REVERSEWRAP;
6024    if (wnew->misc.autoWrap)
6025	wnew->flags |= WRAPAROUND;
6026    if (wnew->misc.re_verse != wnew->misc.re_verse0)
6027	wnew->flags |= REVERSE_VIDEO;
6028    if (wnew->screen.c132)
6029	wnew->flags |= IN132COLUMNS;
6030
6031    wnew->initflags = wnew->flags;
6032
6033#if OPT_MOD_FKEYS
6034    init_Ires(keyboard.modify_1st.cursor_keys);
6035    init_Ires(keyboard.modify_1st.function_keys);
6036    init_Ires(keyboard.modify_1st.keypad_keys);
6037    init_Ires(keyboard.modify_1st.other_keys);
6038    init_Ires(keyboard.modify_1st.string_keys);
6039    init_Ires(keyboard.format_keys);
6040    wnew->keyboard.modify_now = wnew->keyboard.modify_1st;
6041#endif
6042
6043    init_Ires(misc.appcursorDefault);
6044    if (wnew->misc.appcursorDefault)
6045	wnew->keyboard.flags |= MODE_DECCKM;
6046
6047    init_Ires(misc.appkeypadDefault);
6048    if (wnew->misc.appkeypadDefault)
6049	wnew->keyboard.flags |= MODE_DECKPAM;
6050
6051    initLineData(wnew);
6052    return;
6053}
6054
6055void
6056releaseCursorGCs(XtermWidget xw)
6057{
6058    TScreen *screen = &xw->screen;
6059    VTwin *win = WhichVWin(screen);
6060    int n;
6061
6062    for_each_curs_gc(n) {
6063	freeCgs(xw, win, (CgsEnum) n);
6064    }
6065}
6066
6067void
6068releaseWindowGCs(XtermWidget xw, VTwin * win)
6069{
6070    int n;
6071
6072    for_each_text_gc(n) {
6073	freeCgs(xw, win, (CgsEnum) n);
6074    }
6075}
6076
6077#define TRACE_FREE_LEAK(name) \
6078	if (name) { \
6079	    free(name); \
6080	    name = 0; \
6081	    TRACE(("freed " #name "\n")); \
6082	}
6083
6084#define FREE_LEAK(name) \
6085	if (name) { \
6086	    free(name); \
6087	    name = 0; \
6088	}
6089
6090#ifdef NO_LEAKS
6091#if OPT_RENDERFONT
6092static void
6093xtermCloseXft(TScreen * screen, XTermXftFonts * pub)
6094{
6095    if (pub->font != 0) {
6096	XftFontClose(screen->display, pub->font);
6097	pub->font = 0;
6098    }
6099}
6100#endif
6101#endif
6102
6103#if OPT_INPUT_METHOD
6104static void
6105cleanupInputMethod(TScreen * screen)
6106{
6107    if (screen->xim) {
6108	XCloseIM(screen->xim);
6109	screen->xim = 0;
6110	TRACE(("freed screen->xim\n"));
6111    }
6112}
6113#endif
6114
6115static void
6116VTDestroy(Widget w GCC_UNUSED)
6117{
6118#ifdef NO_LEAKS
6119    XtermWidget xw = (XtermWidget) w;
6120    TScreen *screen = &xw->screen;
6121    Cardinal n;
6122
6123    StopBlinking(screen);
6124
6125    if (screen->scrollWidget) {
6126	XtUninstallTranslations(screen->scrollWidget);
6127	XtDestroyWidget(screen->scrollWidget);
6128    }
6129#if OPT_FIFO_LINES
6130    while (screen->saved_fifo-- > 0) {
6131	deleteScrollback(screen, 0);
6132    }
6133#endif
6134    TRACE_FREE_LEAK(screen->save_ptr);
6135    TRACE_FREE_LEAK(screen->saveBuf_data);
6136    TRACE_FREE_LEAK(screen->saveBuf_index);
6137    for (n = 0; n < 2; ++n) {
6138	TRACE_FREE_LEAK(screen->editBuf_data[n]);
6139	TRACE_FREE_LEAK(screen->editBuf_index[n]);
6140    }
6141    TRACE_FREE_LEAK(screen->keyboard_dialect);
6142    TRACE_FREE_LEAK(screen->term_id);
6143#if OPT_WIDE_CHARS
6144#if OPT_LUIT_PROG
6145    TRACE_FREE_LEAK(xw->misc.locale_str);
6146    TRACE_FREE_LEAK(xw->misc.localefilter);
6147#endif
6148#endif
6149#if OPT_INPUT_METHOD
6150    cleanupInputMethod(screen);
6151#endif
6152    releaseCursorGCs(xw);
6153    releaseWindowGCs(xw, &(screen->fullVwin));
6154#ifndef NO_ACTIVE_ICON
6155    releaseWindowGCs(xw, &(screen->iconVwin));
6156#endif
6157    XtUninstallTranslations((Widget) xw);
6158#if OPT_TOOLBAR
6159    XtUninstallTranslations((Widget) XtParent(xw));
6160#endif
6161    XtUninstallTranslations((Widget) SHELL_OF(xw));
6162
6163    if (screen->hidden_cursor)
6164	XFreeCursor(screen->display, screen->hidden_cursor);
6165
6166    xtermCloseFonts(xw, screen->fnts);
6167    noleaks_cachedCgs(xw);
6168
6169#if OPT_RENDERFONT
6170    for (n = 0; n < NMENUFONTS; ++n) {
6171	xtermCloseXft(screen, &(screen->renderFontNorm[n]));
6172	xtermCloseXft(screen, &(screen->renderFontBold[n]));
6173	xtermCloseXft(screen, &(screen->renderFontItal[n]));
6174#if OPT_RENDERWIDE
6175	xtermCloseXft(screen, &(screen->renderWideNorm[n]));
6176	xtermCloseXft(screen, &(screen->renderWideBold[n]));
6177	xtermCloseXft(screen, &(screen->renderWideItal[n]));
6178#endif
6179    }
6180#endif
6181
6182#if 0				/* some strings may be owned by X libraries */
6183    for (n = 0; n <= fontMenu_lastBuiltin; ++n) {
6184	int k;
6185	for (k = 0; k < fMAX; ++k) {
6186	    char *s = screen->menu_font_names[n][k];
6187	    if (s != 0)
6188		free(s);
6189	}
6190    }
6191#endif
6192
6193#if OPT_COLOR_RES
6194    /* free local copies of resource strings */
6195    for (n = 0; n < NCOLORS; ++n) {
6196	FREE_LEAK(screen->Tcolors[n].resource);
6197    }
6198#endif
6199#if OPT_SELECT_REGEX
6200    for (n = 0; n < NSELECTUNITS; ++n) {
6201	FREE_LEAK(screen->selectExpr[n]);
6202    }
6203#endif
6204
6205    if (screen->selection_atoms)
6206	XtFree((char *) (screen->selection_atoms));
6207
6208    XtFree((char *) (screen->selection_data));
6209
6210    TRACE_FREE_LEAK(xw->keyboard.extra_translations);
6211    TRACE_FREE_LEAK(xw->keyboard.shell_translations);
6212    TRACE_FREE_LEAK(xw->keyboard.xterm_translations);
6213
6214#if OPT_WIDE_CHARS
6215    FreeTypedBuffer(XChar2b);
6216    FreeTypedBuffer(char);
6217#endif
6218#if OPT_RENDERFONT
6219#if OPT_RENDERWIDE
6220    FreeTypedBuffer(XftCharSpec);
6221#else
6222    FreeTypedBuffer(XftChar8);
6223#endif
6224#endif
6225
6226    TRACE_FREE_LEAK(myState.print_area);
6227    TRACE_FREE_LEAK(myState.string_area);
6228    memset(&myState, 0, sizeof(myState));
6229
6230#endif /* defined(NO_LEAKS) */
6231}
6232
6233/*ARGSUSED*/
6234static void
6235VTRealize(Widget w,
6236	  XtValueMask * valuemask,
6237	  XSetWindowAttributes * values)
6238{
6239    XtermWidget xw = (XtermWidget) w;
6240    TScreen *screen = &xw->screen;
6241
6242    const VTFontNames *myfont;
6243    unsigned width, height;
6244    int xpos, ypos, pr;
6245    Atom pid_atom;
6246    int i;
6247
6248    TRACE(("VTRealize\n"));
6249
6250    TabReset(xw->tabs);
6251
6252    if (screen->menu_font_number == fontMenu_default) {
6253	myfont = &(xw->misc.default_font);
6254    } else {
6255	myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number));
6256    }
6257    memset(screen->fnts, 0, sizeof(screen->fnts));
6258
6259    if (!xtermLoadFont(xw,
6260		       myfont,
6261		       False,
6262		       screen->menu_font_number)) {
6263	if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) {
6264	    fprintf(stderr,
6265		    "%s:  unable to open font \"%s\", trying \"%s\"....\n",
6266		    xterm_name, myfont->f_n, DEFFONT);
6267	    (void) xtermLoadFont(xw,
6268				 xtermFontName(DEFFONT),
6269				 False,
6270				 screen->menu_font_number);
6271	    screen->MenuFontName(screen->menu_font_number) = DEFFONT;
6272	}
6273    }
6274
6275    /* really screwed if we couldn't open default font */
6276    if (!screen->fnts[fNorm].fs) {
6277	fprintf(stderr, "%s:  unable to locate a suitable font\n",
6278		xterm_name);
6279	Exit(1);
6280    }
6281#if OPT_WIDE_CHARS
6282    if (xw->screen.utf8_mode) {
6283	TRACE(("check if this is a wide font, if not try again\n"));
6284	if (xtermLoadWideFonts(xw, False))
6285	    SetVTFont(xw, screen->menu_font_number, True, NULL);
6286    }
6287#endif
6288
6289    /* making cursor */
6290    if (!screen->pointer_cursor) {
6291	screen->pointer_cursor =
6292	    make_colored_cursor(XC_xterm,
6293				T_COLOR(screen, MOUSE_FG),
6294				T_COLOR(screen, MOUSE_BG));
6295    } else {
6296	recolor_cursor(screen,
6297		       screen->pointer_cursor,
6298		       T_COLOR(screen, MOUSE_FG),
6299		       T_COLOR(screen, MOUSE_BG));
6300    }
6301
6302    /* set defaults */
6303    xpos = 1;
6304    ypos = 1;
6305    width = 80;
6306    height = 24;
6307
6308    TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry)));
6309    pr = XParseGeometry(xw->misc.geo_metry, &xpos, &ypos,
6310			&width, &height);
6311    TRACE(("... position %d,%d size %dx%d\n", ypos, xpos, height, width));
6312
6313    set_max_col(screen, (int) (width - 1));	/* units in character cells */
6314    set_max_row(screen, (int) (height - 1));	/* units in character cells */
6315    xtermUpdateFontInfo(xw, False);
6316
6317    width = screen->fullVwin.fullwidth;
6318    height = screen->fullVwin.fullheight;
6319
6320    TRACE(("... border widget %d parent %d shell %d\n",
6321	   BorderWidth(xw),
6322	   BorderWidth(XtParent(xw)),
6323	   BorderWidth(SHELL_OF(xw))));
6324
6325    if ((pr & XValue) && (XNegative & pr)) {
6326	xpos += (DisplayWidth(screen->display, DefaultScreen(screen->display))
6327		 - (int) width
6328		 - (BorderWidth(XtParent(xw)) * 2));
6329    }
6330    if ((pr & YValue) && (YNegative & pr)) {
6331	ypos += (DisplayHeight(screen->display, DefaultScreen(screen->display))
6332		 - (int) height
6333		 - (BorderWidth(XtParent(xw)) * 2));
6334    }
6335
6336    /* set up size hints for window manager; min 1 char by 1 char */
6337    getXtermSizeHints(xw);
6338    xtermSizeHints(xw, (xw->misc.scrollbar
6339			? (screen->scrollWidget->core.width
6340			   + BorderWidth(screen->scrollWidget))
6341			: 0));
6342
6343    xw->hints.x = xpos;
6344    xw->hints.y = ypos;
6345    if ((XValue & pr) || (YValue & pr)) {
6346	xw->hints.flags |= USSize | USPosition;
6347	xw->hints.flags |= PWinGravity;
6348	switch (pr & (XNegative | YNegative)) {
6349	case 0:
6350	    xw->hints.win_gravity = NorthWestGravity;
6351	    break;
6352	case XNegative:
6353	    xw->hints.win_gravity = NorthEastGravity;
6354	    break;
6355	case YNegative:
6356	    xw->hints.win_gravity = SouthWestGravity;
6357	    break;
6358	default:
6359	    xw->hints.win_gravity = SouthEastGravity;
6360	    break;
6361	}
6362    } else {
6363	/* set a default size, but do *not* set position */
6364	xw->hints.flags |= PSize;
6365    }
6366    xw->hints.height = xw->hints.base_height
6367	+ xw->hints.height_inc * MaxRows(screen);
6368    xw->hints.width = xw->hints.base_width
6369	+ xw->hints.width_inc * MaxCols(screen);
6370
6371    if ((WidthValue & pr) || (HeightValue & pr))
6372	xw->hints.flags |= USSize;
6373    else
6374	xw->hints.flags |= PSize;
6375
6376    /*
6377     * Note that the size-hints are for the shell, while the resize-request
6378     * is for the vt100 widget.  They are not the same size.
6379     */
6380    (void) REQ_RESIZE((Widget) xw,
6381		      (Dimension) width, (Dimension) height,
6382		      &xw->core.width, &xw->core.height);
6383
6384    /* XXX This is bogus.  We are parsing geometries too late.  This
6385     * is information that the shell widget ought to have before we get
6386     * realized, so that it can do the right thing.
6387     */
6388    if (xw->hints.flags & USPosition)
6389	XMoveWindow(XtDisplay(xw), XtWindow(SHELL_OF(xw)),
6390		    xw->hints.x, xw->hints.y);
6391
6392    TRACE(("%s@%d -- ", __FILE__, __LINE__));
6393    TRACE_HINTS(&xw->hints);
6394    XSetWMNormalHints(XtDisplay(xw), XtWindow(SHELL_OF(xw)), &xw->hints);
6395    TRACE(("%s@%d -- ", __FILE__, __LINE__));
6396    TRACE_WM_HINTS(xw);
6397
6398    if ((pid_atom = XInternAtom(XtDisplay(xw), "_NET_WM_PID", False)) != None) {
6399	/* XChangeProperty format 32 really is "long" */
6400	unsigned long pid_l = (unsigned long) getpid();
6401	TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l));
6402	XChangeProperty(XtDisplay(xw), VShellWindow,
6403			pid_atom, XA_CARDINAL, 32, PropModeReplace,
6404			(unsigned char *) &pid_l, 1);
6405    }
6406
6407    XFlush(XtDisplay(xw));	/* get it out to window manager */
6408
6409    /* use ForgetGravity instead of SouthWestGravity because translating
6410       the Expose events for ConfigureNotifys is too hard */
6411    values->bit_gravity = (GravityIsNorthWest(xw)
6412			   ? NorthWestGravity
6413			   : ForgetGravity);
6414    xw->screen.fullVwin.window = XtWindow(xw) =
6415	XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)),
6416		      xw->core.x, xw->core.y,
6417		      xw->core.width, xw->core.height, BorderWidth(xw),
6418		      (int) xw->core.depth,
6419		      InputOutput, CopyFromParent,
6420		      *valuemask | CWBitGravity, values);
6421    screen->event_mask = values->event_mask;
6422
6423#ifndef NO_ACTIVE_ICON
6424    if (xw->misc.active_icon && screen->fnt_icon.fs) {
6425	int iconX = 0, iconY = 0;
6426	Widget shell = SHELL_OF(xw);
6427	VTwin *win = &(screen->iconVwin);
6428
6429	TRACE(("Initializing active-icon\n"));
6430	XtVaGetValues(shell, XtNiconX, &iconX, XtNiconY, &iconY, (XtPointer) 0);
6431	xtermComputeFontInfo(xw, &(screen->iconVwin), screen->fnt_icon.fs, 0);
6432
6433	/* since only one client is permitted to select for Button
6434	 * events, we have to let the window manager get 'em...
6435	 */
6436	values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask);
6437	values->border_pixel = xw->misc.icon_border_pixel;
6438
6439	screen->iconVwin.window =
6440	    XCreateWindow(XtDisplay(xw),
6441			  RootWindowOfScreen(XtScreen(shell)),
6442			  iconX, iconY,
6443			  screen->iconVwin.fullwidth,
6444			  screen->iconVwin.fullheight,
6445			  xw->misc.icon_border_width,
6446			  (int) xw->core.depth,
6447			  InputOutput, CopyFromParent,
6448			  *valuemask | CWBitGravity | CWBorderPixel,
6449			  values);
6450	XtVaSetValues(shell,
6451		      XtNiconWindow, screen->iconVwin.window,
6452		      (XtPointer) 0);
6453	XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w);
6454
6455	setCgsFont(xw, win, gcNorm, &(screen->fnt_icon));
6456	setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG));
6457	setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG));
6458
6459	copyCgs(xw, win, gcBold, gcNorm);
6460
6461	setCgsFont(xw, win, gcNormReverse, &(screen->fnt_icon));
6462	setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG));
6463	setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG));
6464
6465	copyCgs(xw, win, gcBoldReverse, gcNormReverse);
6466
6467#if OPT_TOOLBAR
6468	/*
6469	 * Toolbar is initialized before we get here.  Enable the menu item
6470	 * and set it properly.
6471	 */
6472	SetItemSensitivity(vtMenuEntries[vtMenu_activeicon].widget, True);
6473	update_activeicon();
6474#endif
6475    } else {
6476	TRACE(("Disabled active-icon\n"));
6477	xw->misc.active_icon = False;
6478    }
6479#endif /* NO_ACTIVE_ICON */
6480
6481#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
6482    VTInitI18N(xw);
6483#else
6484    xw->screen.xic = NULL;
6485#endif
6486#if OPT_NUM_LOCK
6487    VTInitModifiers(xw);
6488#if OPT_EXTRA_PASTE
6489    if (xw->keyboard.extra_translations) {
6490	XtOverrideTranslations((Widget) xw,
6491			       XtParseTranslationTable(xw->keyboard.extra_translations));
6492    }
6493#endif
6494#endif
6495
6496    set_cursor_gcs(xw);
6497
6498    /* Reset variables used by ANSI emulation. */
6499
6500    resetCharsets(screen);
6501
6502    XDefineCursor(screen->display, VShellWindow, screen->pointer_cursor);
6503
6504    set_cur_col(screen, 0);
6505    set_cur_row(screen, 0);
6506    set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1);
6507    set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1);
6508    set_tb_margins(screen, 0, screen->max_row);
6509
6510    memset(screen->sc, 0, sizeof(screen->sc));
6511
6512    /* Mark screen buffer as unallocated.  We wait until the run loop so
6513       that the child process does not fork and exec with all the dynamic
6514       memory it will never use.  If we were to do it here, the
6515       swap space for new process would be huge for huge savelines. */
6516#if OPT_TEK4014
6517    if (!tekWidget)		/* if not called after fork */
6518#endif
6519    {
6520	screen->visbuf = NULL;
6521	screen->saveBuf_index = NULL;
6522    }
6523
6524    screen->do_wrap = False;
6525    screen->scrolls = screen->incopy = 0;
6526    xtermSetCursorBox(screen);
6527
6528    screen->savedlines = 0;
6529
6530    for (i = 0; i < 2; ++i) {
6531	screen->whichBuf = !screen->whichBuf;
6532	CursorSave(xw);
6533    }
6534
6535    /*
6536     * Do this last, since it may change the layout via a resize.
6537     */
6538    if (xw->misc.scrollbar) {
6539	screen->fullVwin.sb_info.width = 0;
6540	ScrollBarOn(xw, False);
6541    }
6542    return;
6543}
6544
6545#if OPT_I18N_SUPPORT && OPT_INPUT_METHOD
6546
6547/* limit this feature to recent XFree86 since X11R6.x core dumps */
6548#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING)
6549#define USE_XIM_INSTANTIATE_CB
6550
6551static void
6552xim_instantiate_cb(Display * display,
6553		   XPointer client_data GCC_UNUSED,
6554		   XPointer call_data GCC_UNUSED)
6555{
6556    if (display != XtDisplay(term))
6557	return;
6558
6559    VTInitI18N(term);
6560}
6561
6562static void
6563xim_destroy_cb(XIM im GCC_UNUSED,
6564	       XPointer client_data GCC_UNUSED,
6565	       XPointer call_data GCC_UNUSED)
6566{
6567    term->screen.xic = NULL;
6568
6569    XRegisterIMInstantiateCallback(XtDisplay(term), NULL, NULL, NULL,
6570				   xim_instantiate_cb, NULL);
6571}
6572#endif /* X11R6+ */
6573
6574static void
6575xim_real_init(XtermWidget xw)
6576{
6577    TScreen *screen = TScreenOf(xw);
6578    unsigned i, j;
6579    char *p, *s, *t, *ns, *end, buf[32];
6580    XIMStyles *xim_styles;
6581    XIMStyle input_style = 0;
6582    Bool found;
6583    static struct {
6584	char *name;
6585	unsigned long code;
6586    } known_style[] = {
6587	{
6588	    "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing)
6589	},
6590	{
6591	    "OffTheSpot", (XIMPreeditArea | XIMStatusArea)
6592	},
6593	{
6594	    "Root", (XIMPreeditNothing | XIMStatusNothing)
6595	},
6596    };
6597
6598    screen->xic = NULL;
6599
6600    if (xw->misc.cannot_im) {
6601	return;
6602    }
6603
6604    if (!xw->misc.input_method || !*xw->misc.input_method) {
6605	if ((p = XSetLocaleModifiers("")) != NULL && *p)
6606	    screen->xim = XOpenIM(XtDisplay(xw), NULL, NULL, NULL);
6607    } else {
6608	s = xw->misc.input_method;
6609	i = 5 + strlen(s);
6610	t = (char *) MyStackAlloc(i, buf);
6611	if (t == NULL)
6612	    SysError(ERROR_VINIT);
6613
6614	for (ns = s; ns && *s;) {
6615	    while (*s && isspace(CharOf(*s)))
6616		s++;
6617	    if (!*s)
6618		break;
6619	    if ((ns = end = strchr(s, ',')) == 0)
6620		end = s + strlen(s);
6621	    while ((end != s) && isspace(CharOf(end[-1])))
6622		end--;
6623
6624	    if (end != s) {
6625		strcpy(t, "@im=");
6626		strncat(t, s, (unsigned) (end - s));
6627
6628		if ((p = XSetLocaleModifiers(t)) != 0 && *p
6629		    && (screen->xim = XOpenIM(XtDisplay(xw),
6630					      NULL,
6631					      NULL,
6632					      NULL)) != 0)
6633		    break;
6634
6635	    }
6636	    s = ns + 1;
6637	}
6638	MyStackFree(t, buf);
6639    }
6640
6641    if (screen->xim == NULL
6642	&& (p = XSetLocaleModifiers("@im=none")) != NULL
6643	&& *p) {
6644	screen->xim = XOpenIM(XtDisplay(xw), NULL, NULL, NULL);
6645    }
6646
6647    if (!screen->xim) {
6648	fprintf(stderr, "Failed to open input method\n");
6649	return;
6650    }
6651    TRACE(("VTInitI18N opened input method\n"));
6652
6653    if (XGetIMValues(screen->xim, XNQueryInputStyle, &xim_styles, NULL)
6654	|| !xim_styles
6655	|| !xim_styles->count_styles) {
6656	fprintf(stderr, "input method doesn't support any style\n");
6657	cleanupInputMethod(screen);
6658	xw->misc.cannot_im = True;
6659	return;
6660    }
6661
6662    found = False;
6663    for (s = xw->misc.preedit_type; s && !found;) {
6664	while (*s && isspace(CharOf(*s)))
6665	    s++;
6666	if (!*s)
6667	    break;
6668	if ((ns = end = strchr(s, ',')) != 0)
6669	    ns++;
6670	else
6671	    end = s + strlen(s);
6672	while ((end != s) && isspace(CharOf(end[-1])))
6673	    end--;
6674
6675	if (end != s) {		/* just in case we have a spurious comma */
6676	    TRACE(("looking for style '%.*s'\n", end - s, s));
6677	    for (i = 0; i < XtNumber(known_style); i++) {
6678		if ((int) strlen(known_style[i].name) == (end - s)
6679		    && !strncmp(s, known_style[i].name, (unsigned) (end - s))) {
6680		    input_style = known_style[i].code;
6681		    for (j = 0; j < xim_styles->count_styles; j++) {
6682			if (input_style == xim_styles->supported_styles[j]) {
6683			    found = True;
6684			    break;
6685			}
6686		    }
6687		    if (found)
6688			break;
6689		}
6690	    }
6691	}
6692
6693	s = ns;
6694    }
6695    XFree(xim_styles);
6696
6697    if (!found) {
6698	fprintf(stderr,
6699		"input method doesn't support my preedit type (%s)\n",
6700		xw->misc.preedit_type);
6701	cleanupInputMethod(screen);
6702	xw->misc.cannot_im = True;
6703	return;
6704    }
6705
6706    /*
6707     * Check for styles we do not yet support.
6708     */
6709    TRACE(("input_style %#lx\n", input_style));
6710    if (input_style == (XIMPreeditArea | XIMStatusArea)) {
6711	fprintf(stderr,
6712		"This program doesn't support the 'OffTheSpot' preedit type\n");
6713	cleanupInputMethod(screen);
6714	xw->misc.cannot_im = True;
6715	return;
6716    }
6717
6718    /*
6719     * For XIMPreeditPosition (or OverTheSpot), XIM client has to
6720     * prepare a font.
6721     * The font has to be locale-dependent XFontSet, whereas
6722     * XTerm use Unicode font.  This leads a problem that the
6723     * same font cannot be used for XIM preedit.
6724     */
6725    if (input_style != (XIMPreeditNothing | XIMStatusNothing)) {
6726	char **missing_charset_list;
6727	int missing_charset_count;
6728	char *def_string;
6729	XVaNestedList p_list;
6730	XPoint spot =
6731	{0, 0};
6732	XFontStruct **fonts;
6733	char **font_name_list;
6734
6735	screen->fs = XCreateFontSet(XtDisplay(xw),
6736				    xw->misc.f_x,
6737				    &missing_charset_list,
6738				    &missing_charset_count,
6739				    &def_string);
6740	if (screen->fs == NULL) {
6741	    fprintf(stderr, "Preparation of font set "
6742		    "\"%s\" for XIM failed.\n", xw->misc.f_x);
6743	    screen->fs = XCreateFontSet(XtDisplay(xw),
6744					DEFXIMFONT,
6745					&missing_charset_list,
6746					&missing_charset_count,
6747					&def_string);
6748	}
6749	if (screen->fs == NULL) {
6750	    fprintf(stderr, "Preparation of default font set "
6751		    "\"%s\" for XIM failed.\n", DEFXIMFONT);
6752	    cleanupInputMethod(screen);
6753	    xw->misc.cannot_im = True;
6754	    return;
6755	}
6756	(void) XExtentsOfFontSet(screen->fs);
6757	j = (unsigned) XFontsOfFontSet(screen->fs, &fonts, &font_name_list);
6758	for (i = 0, screen->fs_ascent = 0; i < j; i++) {
6759	    if (screen->fs_ascent < (*fonts)->ascent)
6760		screen->fs_ascent = (*fonts)->ascent;
6761	}
6762	p_list = XVaCreateNestedList(0,
6763				     XNSpotLocation, &spot,
6764				     XNFontSet, screen->fs,
6765				     NULL);
6766	screen->xic = XCreateIC(screen->xim,
6767				XNInputStyle, input_style,
6768				XNClientWindow, XtWindow(xw),
6769				XNFocusWindow, XtWindow(xw),
6770				XNPreeditAttributes, p_list,
6771				NULL);
6772    } else {
6773	screen->xic = XCreateIC(screen->xim, XNInputStyle, input_style,
6774				XNClientWindow, XtWindow(xw),
6775				XNFocusWindow, XtWindow(xw),
6776				NULL);
6777    }
6778
6779    if (!screen->xic) {
6780	fprintf(stderr, "Failed to create input context\n");
6781	cleanupInputMethod(screen);
6782    }
6783#if defined(USE_XIM_INSTANTIATE_CB)
6784    else {
6785	XIMCallback destroy_cb;
6786
6787	destroy_cb.callback = xim_destroy_cb;
6788	destroy_cb.client_data = NULL;
6789	if (XSetIMValues(screen->xim, XNDestroyCallback, &destroy_cb, NULL))
6790	    fprintf(stderr, "Could not set destroy callback to IM\n");
6791    }
6792#endif
6793
6794    return;
6795}
6796
6797static void
6798VTInitI18N(XtermWidget xw)
6799{
6800    if (xw->misc.open_im) {
6801	xim_real_init(xw);
6802
6803#if defined(USE_XIM_INSTANTIATE_CB)
6804	if (xw->screen.xic == NULL
6805	    && !xw->misc.cannot_im
6806	    && xw->misc.retry_im-- > 0) {
6807	    sleep(3);
6808	    XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
6809					   xim_instantiate_cb, NULL);
6810	}
6811#endif
6812    }
6813}
6814#endif /* OPT_I18N_SUPPORT && OPT_INPUT_METHOD */
6815
6816static Boolean
6817VTSetValues(Widget cur,
6818	    Widget request GCC_UNUSED,
6819	    Widget wnew,
6820	    ArgList args GCC_UNUSED,
6821	    Cardinal *num_args GCC_UNUSED)
6822{
6823    XtermWidget curvt = (XtermWidget) cur;
6824    XtermWidget newvt = (XtermWidget) wnew;
6825    Boolean refresh_needed = False;
6826    Boolean fonts_redone = False;
6827
6828    if ((T_COLOR(&(curvt->screen), TEXT_BG) !=
6829	 T_COLOR(&(newvt->screen), TEXT_BG)) ||
6830	(T_COLOR(&(curvt->screen), TEXT_FG) !=
6831	 T_COLOR(&(newvt->screen), TEXT_FG)) ||
6832	(curvt->screen.MenuFontName(curvt->screen.menu_font_number) !=
6833	 newvt->screen.MenuFontName(newvt->screen.menu_font_number)) ||
6834	(curvt->misc.default_font.f_n != newvt->misc.default_font.f_n)) {
6835	if (curvt->misc.default_font.f_n != newvt->misc.default_font.f_n)
6836	    newvt->screen.MenuFontName(fontMenu_default) = newvt->misc.default_font.f_n;
6837	if (xtermLoadFont(newvt,
6838			  xtermFontName(newvt->screen.MenuFontName(curvt->screen.menu_font_number)),
6839			  True, newvt->screen.menu_font_number)) {
6840	    /* resizing does the redisplay, so don't ask for it here */
6841	    refresh_needed = True;
6842	    fonts_redone = True;
6843	} else if (curvt->misc.default_font.f_n != newvt->misc.default_font.f_n)
6844	    newvt->screen.MenuFontName(fontMenu_default) = curvt->misc.default_font.f_n;
6845    }
6846    if (!fonts_redone
6847	&& (T_COLOR(&(curvt->screen), TEXT_CURSOR) !=
6848	    T_COLOR(&(newvt->screen), TEXT_CURSOR))) {
6849	set_cursor_gcs(newvt);
6850	refresh_needed = True;
6851    }
6852    if (curvt->misc.re_verse != newvt->misc.re_verse) {
6853	newvt->flags ^= REVERSE_VIDEO;
6854	ReverseVideo(newvt);
6855	/* ReverseVideo toggles */
6856	newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse);
6857	refresh_needed = True;
6858    }
6859    if ((T_COLOR(&(curvt->screen), MOUSE_FG) !=
6860	 T_COLOR(&(newvt->screen), MOUSE_FG)) ||
6861	(T_COLOR(&(curvt->screen), MOUSE_BG) !=
6862	 T_COLOR(&(newvt->screen), MOUSE_BG))) {
6863	recolor_cursor(&(newvt->screen),
6864		       newvt->screen.pointer_cursor,
6865		       T_COLOR(&(newvt->screen), MOUSE_FG),
6866		       T_COLOR(&(newvt->screen), MOUSE_BG));
6867	refresh_needed = True;
6868    }
6869    if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
6870	ToggleScrollBar(newvt);
6871    }
6872
6873    return refresh_needed;
6874}
6875
6876#define setGC(code) set_at = __LINE__, currentCgs = code
6877
6878#define OutsideSelection(screen,srow,scol)  \
6879	 ((srow) > (screen)->endH.row || \
6880	  ((srow) == (screen)->endH.row && \
6881	   (scol) >= (screen)->endH.col) || \
6882	  (srow) < (screen)->startH.row || \
6883	  ((srow) == (screen)->startH.row && \
6884	   (scol) < (screen)->startH.col))
6885
6886/*
6887 * Shows cursor at new cursor position in screen.
6888 */
6889void
6890ShowCursor(void)
6891{
6892    XtermWidget xw = term;
6893    TScreen *screen = &xw->screen;
6894    int x, y;
6895    IChar base;
6896    unsigned flags;
6897    CellColor fg_bg = 0;
6898    GC currentGC;
6899    CgsEnum currentCgs = gcMAX;
6900    VTwin *currentWin = WhichVWin(screen);
6901    int set_at;
6902    Bool in_selection;
6903    Bool reversed;
6904    Bool filled;
6905    Pixel fg_pix;
6906    Pixel bg_pix;
6907    Pixel tmp;
6908#if OPT_HIGHLIGHT_COLOR
6909    Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG);
6910    Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG);
6911    Boolean use_selbg;
6912    Boolean use_selfg;
6913#endif
6914#if OPT_WIDE_CHARS
6915    size_t off;
6916    int my_col = 0;
6917#endif
6918    int cursor_col;
6919    LineData *ld = 0;
6920
6921    if (screen->cursor_state == BLINKED_OFF)
6922	return;
6923
6924    if (screen->eventMode != NORMAL)
6925	return;
6926
6927    if (INX2ROW(screen, screen->cur_row) > screen->max_row)
6928	return;
6929
6930    screen->cursorp.row = screen->cur_row;
6931    cursor_col = screen->cursorp.col = screen->cur_col;
6932    screen->cursor_moved = False;
6933
6934#ifndef NO_ACTIVE_ICON
6935    if (IsIcon(screen)) {
6936	screen->cursor_state = ON;
6937	return;
6938    }
6939#endif /* NO_ACTIVE_ICON */
6940
6941    ld = getLineData(screen, screen->cur_row);
6942
6943    base = ld->charData[cursor_col];
6944    flags = ld->attribs[cursor_col];
6945
6946    if_OPT_WIDE_CHARS(screen, {
6947	if (base == HIDDEN_CHAR && cursor_col > 0) {
6948	    /* if cursor points to non-initial part of wide character,
6949	     * back it up
6950	     */
6951	    --cursor_col;
6952	    base = ld->charData[cursor_col];
6953	}
6954	my_col = cursor_col;
6955	if (base == 0)
6956	    base = ' ';
6957	if (isWide((int) base))
6958	    my_col += 1;
6959    });
6960
6961    if (base == 0) {
6962	base = ' ';
6963    }
6964#if OPT_ISO_COLORS
6965#ifdef EXP_BOGUS_FG
6966    /*
6967     * If the cursor happens to be on blanks, and we have not set both
6968     * foreground and background color, do not treat it as a colored cell.
6969     */
6970    if (base == ' ') {
6971	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
6972	    TRACE(("ShowCursor - do not treat as a colored cell\n"));
6973	    flags &= ~(FG_COLOR | BG_COLOR);
6974	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
6975	    TRACE(("ShowCursor - should we treat as a colored cell?\n"));
6976	    if (!(xw->flags & FG_COLOR))
6977		if (CheckBogusForeground(screen, "ShowCursor"))
6978		    flags &= ~(FG_COLOR | BG_COLOR);
6979	}
6980    }
6981#else /* !EXP_BOGUS_FG */
6982    /*
6983     * If the cursor happens to be on blanks, and the foreground color is set
6984     * but not the background, do not treat it as a colored cell.
6985     */
6986    if ((flags & TERM_COLOR_FLAGS(xw)) == BG_COLOR
6987	&& base == ' ') {
6988	flags &= ~TERM_COLOR_FLAGS(xw);
6989    }
6990#endif
6991#endif
6992
6993    /*
6994     * Compare the current cell to the last set of colors used for the
6995     * cursor and update the GC's if needed.
6996     */
6997    if_OPT_ISO_COLORS(screen, {
6998	fg_bg = ld->color[cursor_col];
6999    });
7000    fg_pix = getXtermForeground(xw, flags, extract_fg(xw, fg_bg, flags));
7001    bg_pix = getXtermBackground(xw, flags, extract_bg(xw, fg_bg, flags));
7002
7003    if (OutsideSelection(screen, screen->cur_row, screen->cur_col))
7004	in_selection = False;
7005    else
7006	in_selection = True;
7007
7008    reversed = ReverseOrHilite(screen, flags, in_selection);
7009
7010    /* This is like updatedXtermGC(), except that we have to worry about
7011     * whether the window has focus, since in that case we want just an
7012     * outline for the cursor.
7013     */
7014    filled = (screen->select || screen->always_highlight) && !screen->cursor_underline;
7015#if OPT_HIGHLIGHT_COLOR
7016    use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix);
7017    use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix);
7018#endif
7019    if (filled) {
7020	if (reversed) {		/* text is reverse video */
7021	    if (getCgsGC(xw, currentWin, gcVTcursNormal)) {
7022		setGC(gcVTcursNormal);
7023	    } else {
7024		if (flags & BOLDATTR(screen)) {
7025		    setGC(gcBold);
7026		} else {
7027		    setGC(gcNorm);
7028		}
7029	    }
7030	    EXCHANGE(fg_pix, bg_pix, tmp);
7031#if OPT_HIGHLIGHT_COLOR
7032	    if (screen->hilite_reverse) {
7033		if (use_selbg && !use_selfg)
7034		    fg_pix = bg_pix;
7035		if (use_selfg && !use_selbg)
7036		    bg_pix = fg_pix;
7037		if (use_selbg)
7038		    bg_pix = selbg_pix;
7039		if (use_selfg)
7040		    fg_pix = selfg_pix;
7041	    }
7042#endif
7043	} else {		/* normal video */
7044	    if (getCgsGC(xw, currentWin, gcVTcursReverse)) {
7045		setGC(gcVTcursReverse);
7046	    } else {
7047		if (flags & BOLDATTR(screen)) {
7048		    setGC(gcBoldReverse);
7049		} else {
7050		    setGC(gcNormReverse);
7051		}
7052	    }
7053	}
7054	if (T_COLOR(screen, TEXT_CURSOR) == xw->dft_foreground) {
7055	    setCgsBack(xw, currentWin, currentCgs, fg_pix);
7056	}
7057	setCgsFore(xw, currentWin, currentCgs, bg_pix);
7058    } else {			/* not selected */
7059	if (reversed) {		/* text is reverse video */
7060	    EXCHANGE(fg_pix, bg_pix, tmp);
7061	    setGC(gcNormReverse);
7062	} else {		/* normal video */
7063	    setGC(gcNorm);
7064	}
7065#if OPT_HIGHLIGHT_COLOR
7066	if (screen->hilite_reverse) {
7067	    if (in_selection && !reversed) {
7068		;		/* really INVERSE ... */
7069	    } else if (in_selection || reversed) {
7070		if (use_selbg) {
7071		    if (use_selfg) {
7072			bg_pix = fg_pix;
7073		    } else {
7074			fg_pix = bg_pix;
7075		    }
7076		}
7077		if (use_selbg) {
7078		    bg_pix = selbg_pix;
7079		}
7080		if (use_selfg) {
7081		    fg_pix = selfg_pix;
7082		}
7083	    }
7084	} else {
7085	    if (in_selection) {
7086		if (use_selbg) {
7087		    bg_pix = selbg_pix;
7088		}
7089		if (use_selfg) {
7090		    fg_pix = selfg_pix;
7091		}
7092	    }
7093	}
7094#endif
7095	setCgsFore(xw, currentWin, currentCgs, fg_pix);
7096	setCgsBack(xw, currentWin, currentCgs, bg_pix);
7097    }
7098
7099    if (screen->cursor_busy == 0
7100	&& (screen->cursor_state != ON || screen->cursor_GC != set_at)) {
7101
7102	screen->cursor_GC = set_at;
7103	TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s, set_at %d\n",
7104	       screen->cur_row, screen->cur_col,
7105	       (filled ? "filled" : "outline"), set_at));
7106
7107	currentGC = getCgsGC(xw, currentWin, currentCgs);
7108	drawXtermText(xw, flags & DRAWX_MASK, currentGC,
7109		      x = LineCursorX(screen, ld, cursor_col),
7110		      y = CursorY(screen, screen->cur_row),
7111		      LineCharSet(screen, ld),
7112		      &base, 1, 0);
7113
7114#if OPT_WIDE_CHARS
7115	if_OPT_WIDE_CHARS(screen, {
7116	    for_each_combData(off, ld) {
7117		if (!(ld->combData[off][my_col]))
7118		    break;
7119		drawXtermText(xw, (flags & DRAWX_MASK) | NOBACKGROUND,
7120			      currentGC, x, y,
7121			      LineCharSet(screen, ld),
7122			      ld->combData[off] + my_col,
7123			      1, isWide((int) base));
7124	    }
7125	});
7126#endif
7127
7128	if (!filled) {
7129	    GC outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline);
7130	    if (outlineGC == 0)
7131		outlineGC = currentGC;
7132
7133	    screen->box->x = (short) x;
7134	    if (!screen->cursor_underline)
7135		screen->box->y = (short) y;
7136	    else
7137		screen->box->y = (short) (y + FontHeight(screen) - 2);
7138	    XDrawLines(screen->display, VWindow(screen), outlineGC,
7139		       screen->box, NBOX, CoordModePrevious);
7140	}
7141    }
7142    screen->cursor_state = ON;
7143
7144    return;
7145}
7146
7147/*
7148 * hide cursor at previous cursor position in screen.
7149 */
7150void
7151HideCursor(void)
7152{
7153    XtermWidget xw = term;
7154    TScreen *screen = &xw->screen;
7155    GC currentGC;
7156    int x, y;
7157    IChar base;
7158    unsigned flags;
7159    CellColor fg_bg = 0;
7160    Bool in_selection;
7161#if OPT_WIDE_CHARS
7162    size_t off;
7163    int my_col = 0;
7164#endif
7165    int cursor_col;
7166    LineData *ld = 0;
7167
7168    if (screen->cursor_state == OFF)	/* FIXME */
7169	return;
7170    if (INX2ROW(screen, screen->cursorp.row) > screen->max_row)
7171	return;
7172
7173    cursor_col = screen->cursorp.col;
7174
7175#ifndef NO_ACTIVE_ICON
7176    if (IsIcon(screen)) {
7177	screen->cursor_state = OFF;
7178	return;
7179    }
7180#endif /* NO_ACTIVE_ICON */
7181
7182    ld = getLineData(screen, screen->cursorp.row);
7183
7184    base = ld->charData[cursor_col];
7185    flags = ld->attribs[cursor_col];
7186
7187    if_OPT_WIDE_CHARS(screen, {
7188	if (base == HIDDEN_CHAR && cursor_col > 0) {
7189	    /* if cursor points to non-initial part of wide character,
7190	     * back it up
7191	     */
7192	    --cursor_col;
7193	    base = ld->charData[cursor_col];
7194	}
7195	my_col = cursor_col;
7196	if (base == 0)
7197	    base = ' ';
7198	if (isWide((int) base))
7199	    my_col += 1;
7200    });
7201
7202    if (base == 0) {
7203	base = ' ';
7204    }
7205#ifdef EXP_BOGUS_FG
7206    /*
7207     * If the cursor happens to be on blanks, and we have not set both
7208     * foreground and background color, do not treat it as a colored cell.
7209     */
7210#if OPT_ISO_COLORS
7211    if (base == ' ') {
7212	if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
7213	    TRACE(("HideCursor - do not treat as a colored cell\n"));
7214	    flags &= ~(FG_COLOR | BG_COLOR);
7215	} else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
7216	    TRACE(("HideCursor - should we treat as a colored cell?\n"));
7217	    if (!(xw->flags & FG_COLOR))
7218		if (CheckBogusForeground(screen, "HideCursor"))
7219		    flags &= ~(FG_COLOR | BG_COLOR);
7220	}
7221    }
7222#endif
7223#endif
7224#if OPT_ISO_COLORS
7225    fg_bg = 0;
7226#endif
7227
7228    /*
7229     * Compare the current cell to the last set of colors used for the
7230     * cursor and update the GC's if needed.
7231     */
7232    if_OPT_ISO_COLORS(screen, {
7233	fg_bg = ld->color[cursor_col];
7234    });
7235
7236    if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col))
7237	in_selection = False;
7238    else
7239	in_selection = True;
7240
7241    currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection);
7242
7243    TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n",
7244	   screen->cursorp.row, screen->cursorp.col));
7245    drawXtermText(xw, flags & DRAWX_MASK, currentGC,
7246		  x = LineCursorX(screen, ld, cursor_col),
7247		  y = CursorY(screen, screen->cursorp.row),
7248		  LineCharSet(screen, ld),
7249		  &base, 1, 0);
7250
7251#if OPT_WIDE_CHARS
7252    if_OPT_WIDE_CHARS(screen, {
7253	for_each_combData(off, ld) {
7254	    if (!(ld->combData[off][my_col]))
7255		break;
7256	    drawXtermText(xw, (flags & DRAWX_MASK) | NOBACKGROUND,
7257			  currentGC, x, y,
7258			  LineCharSet(screen, ld),
7259			  ld->combData[off] + my_col,
7260			  1, isWide((int) base));
7261	}
7262    });
7263#endif
7264    screen->cursor_state = OFF;
7265    resetXtermGC(xw, flags, in_selection);
7266
7267    return;
7268}
7269
7270#if OPT_BLINK_CURS || OPT_BLINK_TEXT
7271static void
7272StartBlinking(TScreen * screen)
7273{
7274    if (screen->blink_timer == 0) {
7275	unsigned long interval = (unsigned long) ((screen->cursor_state == ON)
7276						  ? screen->blink_on
7277						  : screen->blink_off);
7278	if (interval == 0)	/* wow! */
7279	    interval = 1;	/* let's humor him anyway */
7280	screen->blink_timer = XtAppAddTimeOut(app_con,
7281					      interval,
7282					      HandleBlinking,
7283					      screen);
7284    }
7285}
7286
7287static void
7288StopBlinking(TScreen * screen)
7289{
7290    if (screen->blink_timer)
7291	XtRemoveTimeOut(screen->blink_timer);
7292    screen->blink_timer = 0;
7293}
7294
7295#if OPT_BLINK_TEXT
7296static Bool
7297LineHasBlinking(TScreen * screen, LineData * ld)
7298{
7299    int col;
7300    Bool result = False;
7301
7302    for (col = 0; col < MaxCols(screen); ++col) {
7303	if (ld->attribs[col] & BLINK) {
7304	    result = True;
7305	    break;
7306	}
7307    }
7308    return result;
7309}
7310#endif
7311
7312/*
7313 * Blink the cursor by alternately showing/hiding cursor.  We leave the timer
7314 * running all the time (even though that's a little inefficient) to make the
7315 * logic simple.
7316 */
7317static void
7318HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED)
7319{
7320    TScreen *screen = (TScreen *) closure;
7321    Bool resume = False;
7322
7323    screen->blink_timer = 0;
7324    screen->blink_state = !screen->blink_state;
7325
7326#if OPT_BLINK_CURS
7327    if (DoStartBlinking(screen)) {
7328	if (screen->cursor_state == ON) {
7329	    if (screen->select || screen->always_highlight) {
7330		HideCursor();
7331		if (screen->cursor_state == OFF)
7332		    screen->cursor_state = BLINKED_OFF;
7333	    }
7334	} else if (screen->cursor_state == BLINKED_OFF) {
7335	    screen->cursor_state = OFF;
7336	    ShowCursor();
7337	    if (screen->cursor_state == OFF)
7338		screen->cursor_state = BLINKED_OFF;
7339	}
7340	resume = True;
7341    }
7342#endif
7343
7344#if OPT_BLINK_TEXT
7345    /*
7346     * Inspect the line on the current screen to see if any have the BLINK flag
7347     * associated with them.  Prune off any that have had the corresponding
7348     * cells reset.  If any are left, repaint those lines with ScrnRefresh().
7349     */
7350    if (!(screen->blink_as_bold)) {
7351	int row;
7352	int first_row = screen->max_row;
7353	int last_row = -1;
7354
7355	for (row = screen->max_row; row >= 0; row--) {
7356	    LineData *ld = getLineData(screen, ROW2INX(screen, row));
7357	    if (LineTstBlinked(ld)) {
7358		if (LineHasBlinking(screen, ld)) {
7359		    resume = True;
7360		    if (row > last_row)
7361			last_row = row;
7362		    if (row < first_row)
7363			first_row = row;
7364		} else {
7365		    LineClrBlinked(ld);
7366		}
7367	    }
7368	}
7369	/*
7370	 * FIXME: this could be a little more efficient, e.g,. by limiting the
7371	 * columns which are updated.
7372	 */
7373	if (first_row <= last_row) {
7374	    ScrnRefresh(term,
7375			first_row,
7376			0,
7377			last_row + 1 - first_row,
7378			MaxCols(screen),
7379			True);
7380	}
7381    }
7382#endif
7383
7384    /*
7385     * If either the cursor or text is blinking, restart the timer.
7386     */
7387    if (resume)
7388	StartBlinking(screen);
7389}
7390#endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */
7391
7392/*
7393 * Implement soft or hard (full) reset of the VTxxx emulation.  There are a
7394 * couple of differences from real DEC VTxxx terminals (to avoid breaking
7395 * applications which have come to rely on xterm doing this):
7396 *
7397 *	+ autowrap mode should be reset (instead it's reset to the resource
7398 *	  default).
7399 *	+ the popup menu offers a choice of resetting the savedLines, or not.
7400 *	  (but the control sequence does this anyway).
7401 */
7402void
7403VTReset(XtermWidget xw, Bool full, Bool saved)
7404{
7405    TScreen *screen = &xw->screen;
7406
7407    if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) {
7408	Bell(XkbBI_MinorError, 0);
7409	return;
7410    }
7411
7412    if (saved) {
7413	screen->savedlines = 0;
7414	ScrollBarDrawThumb(screen->scrollWidget);
7415    }
7416
7417    /* make cursor visible */
7418    screen->cursor_set = ON;
7419
7420    /* reset scrolling region */
7421    set_tb_margins(screen, 0, screen->max_row);
7422
7423    bitclr(&xw->flags, ORIGIN);
7424
7425    if_OPT_ISO_COLORS(screen, {
7426	reset_SGR_Colors(xw);
7427    });
7428
7429    /* Reset character-sets to initial state */
7430    resetCharsets(screen);
7431
7432#if OPT_MOD_FKEYS
7433    /* Reset modifier-resources to initial state */
7434    xw->keyboard.modify_now = xw->keyboard.modify_1st;
7435#endif
7436
7437    /* Reset DECSCA */
7438    bitclr(&xw->flags, PROTECTED);
7439    screen->protected_mode = OFF_PROTECT;
7440
7441    if (full) {			/* RIS */
7442	if (screen->bellOnReset)
7443	    Bell(XkbBI_TerminalBell, 0);
7444
7445	/* reset the mouse mode */
7446	screen->send_mouse_pos = MOUSE_OFF;
7447	screen->send_focus_pos = OFF;
7448	screen->waitingForTrackInfo = False;
7449	screen->eventMode = NORMAL;
7450
7451	xtermShowPointer(xw, True);
7452
7453	TabReset(xw->tabs);
7454	xw->keyboard.flags = MODE_SRM;
7455#if OPT_INITIAL_ERASE
7456	if (xw->keyboard.reset_DECBKM == 1)
7457	    xw->keyboard.flags |= MODE_DECBKM;
7458	else if (xw->keyboard.reset_DECBKM == 2)
7459#endif
7460	    if (xw->screen.backarrow_key)
7461		xw->keyboard.flags |= MODE_DECBKM;
7462	TRACE(("full reset DECBKM %s\n",
7463	       BtoS(xw->keyboard.flags & MODE_DECBKM)));
7464	update_appcursor();
7465	update_appkeypad();
7466	update_decbkm();
7467	show_8bit_control(False);
7468	reset_decudk();
7469
7470	FromAlternate(xw);
7471	ClearScreen(xw);
7472	screen->cursor_state = OFF;
7473	if (xw->flags & REVERSE_VIDEO)
7474	    ReverseVideo(xw);
7475
7476	xw->flags = xw->initflags;
7477	update_reversevideo();
7478	update_autowrap();
7479	update_reversewrap();
7480	update_autolinefeed();
7481
7482	screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL));
7483	update_jumpscroll();
7484
7485	if (screen->c132 && (xw->flags & IN132COLUMNS)) {
7486	    Dimension reqWidth = (Dimension) (80 * FontWidth(screen)
7487					      + 2 * screen->border
7488					      + ScrollbarWidth(screen));
7489	    Dimension reqHeight = (Dimension) (FontHeight(screen)
7490					       * MaxRows(screen)
7491					       + 2 * screen->border);
7492	    Dimension replyWidth;
7493	    Dimension replyHeight;
7494
7495	    TRACE(("Making resize-request to restore 80-columns %dx%d\n",
7496		   reqHeight, reqWidth));
7497	    REQ_RESIZE((Widget) xw,
7498		       reqWidth,
7499		       reqHeight,
7500		       &replyWidth, &replyHeight);
7501	    repairSizeHints();
7502	    XSync(screen->display, False);	/* synchronize */
7503	    if (XtAppPending(app_con))
7504		xevents();
7505	}
7506
7507	CursorSet(screen, 0, 0, xw->flags);
7508	CursorSave(xw);
7509    } else {			/* DECSTR */
7510	/*
7511	 * There's a tiny difference, to accommodate usage of xterm.
7512	 * We reset autowrap to the resource values rather than turning
7513	 * it off.
7514	 */
7515	xw->keyboard.flags &= ~(MODE_DECCKM | MODE_KAM | MODE_DECKPAM);
7516	bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP);
7517	bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE);
7518	if_OPT_ISO_COLORS(screen, {
7519	    reset_SGR_Colors(xw);
7520	});
7521	update_appcursor();
7522	update_autowrap();
7523	update_reversewrap();
7524
7525	CursorSave(xw);
7526	screen->sc[screen->whichBuf].row =
7527	    screen->sc[screen->whichBuf].col = 0;
7528    }
7529    longjmp(vtjmpbuf, 1);	/* force ground state in parser */
7530}
7531
7532/*
7533 * set_character_class - takes a string of the form
7534 *
7535 *   low[-high]:val[,low[-high]:val[...]]
7536 *
7537 * and sets the indicated ranges to the indicated values.
7538 */
7539static int
7540set_character_class(char *s)
7541{
7542    int i;			/* iterator, index into s */
7543    int len;			/* length of s */
7544    int acc;			/* accumulator */
7545    int low, high;		/* bounds of range [0..127] */
7546    int base;			/* 8, 10, 16 (octal, decimal, hex) */
7547    int numbers;		/* count of numbers per range */
7548    int digits;			/* count of digits in a number */
7549    static char *errfmt = "%s:  %s in range string \"%s\" (position %d)\n";
7550
7551    if (!s || !s[0])
7552	return -1;
7553
7554    base = 10;			/* in case we ever add octal, hex */
7555    low = high = -1;		/* out of range */
7556
7557    for (i = 0, len = (int) strlen(s), acc = 0, numbers = digits = 0;
7558	 i < len; i++) {
7559	Char c = CharOf(s[i]);
7560
7561	if (isspace(c)) {
7562	    continue;
7563	} else if (isdigit(c)) {
7564	    acc = acc * base + (c - '0');
7565	    digits++;
7566	    continue;
7567	} else if (c == '-') {
7568	    low = acc;
7569	    acc = 0;
7570	    if (digits == 0) {
7571		fprintf(stderr, errfmt, ProgramName, "missing number", s, i);
7572		return (-1);
7573	    }
7574	    digits = 0;
7575	    numbers++;
7576	    continue;
7577	} else if (c == ':') {
7578	    if (numbers == 0)
7579		low = acc;
7580	    else if (numbers == 1)
7581		high = acc;
7582	    else {
7583		fprintf(stderr, errfmt, ProgramName, "too many numbers",
7584			s, i);
7585		return (-1);
7586	    }
7587	    digits = 0;
7588	    numbers++;
7589	    acc = 0;
7590	    continue;
7591	} else if (c == ',') {
7592	    /*
7593	     * now, process it
7594	     */
7595
7596	    if (high < 0) {
7597		high = low;
7598		numbers++;
7599	    }
7600	    if (numbers != 2) {
7601		fprintf(stderr, errfmt, ProgramName, "bad value number",
7602			s, i);
7603	    } else if (SetCharacterClassRange(low, high, acc) != 0) {
7604		fprintf(stderr, errfmt, ProgramName, "bad range", s, i);
7605	    }
7606
7607	    low = high = -1;
7608	    acc = 0;
7609	    digits = 0;
7610	    numbers = 0;
7611	    continue;
7612	} else {
7613	    fprintf(stderr, errfmt, ProgramName, "bad character", s, i);
7614	    return (-1);
7615	}			/* end if else if ... else */
7616
7617    }
7618
7619    if (low < 0 && high < 0)
7620	return (0);
7621
7622    /*
7623     * now, process it
7624     */
7625
7626    if (high < 0)
7627	high = low;
7628    if (numbers < 1 || numbers > 2) {
7629	fprintf(stderr, errfmt, ProgramName, "bad value number", s, i);
7630    } else if (SetCharacterClassRange(low, high, acc) != 0) {
7631	fprintf(stderr, errfmt, ProgramName, "bad range", s, i);
7632    }
7633
7634    return (0);
7635}
7636
7637/* ARGSUSED */
7638static void
7639HandleKeymapChange(Widget w,
7640		   XEvent * event GCC_UNUSED,
7641		   String * params,
7642		   Cardinal *param_count)
7643{
7644    static XtTranslations keymap, original;
7645    static XtResource key_resources[] =
7646    {
7647	{XtNtranslations, XtCTranslations, XtRTranslationTable,
7648	 sizeof(XtTranslations), 0, XtRTranslationTable, (XtPointer) NULL}
7649    };
7650    char mapName[1000];
7651    char mapClass[1000];
7652    char *pmapName;
7653    char *pmapClass;
7654    size_t len;
7655
7656    if (*param_count != 1)
7657	return;
7658
7659    if (original == NULL)
7660	original = w->core.tm.translations;
7661
7662    if (strcmp(params[0], "None") == 0) {
7663	XtOverrideTranslations(w, original);
7664	return;
7665    }
7666
7667    len = strlen(params[0]) + 7;
7668
7669    pmapName = (char *) MyStackAlloc(len, mapName);
7670    pmapClass = (char *) MyStackAlloc(len, mapClass);
7671    if (pmapName == NULL
7672	|| pmapClass == NULL)
7673	SysError(ERROR_KMMALLOC1);
7674
7675    (void) sprintf(pmapName, "%sKeymap", params[0]);
7676    (void) strcpy(pmapClass, pmapName);
7677    if (islower(CharOf(pmapClass[0])))
7678	pmapClass[0] = x_toupper(pmapClass[0]);
7679    XtGetSubresources(w, (XtPointer) &keymap, pmapName, pmapClass,
7680		      key_resources, (Cardinal) 1, NULL, (Cardinal) 0);
7681    if (keymap != NULL)
7682	XtOverrideTranslations(w, keymap);
7683
7684    MyStackFree(pmapName, mapName);
7685    MyStackFree(pmapClass, mapClass);
7686}
7687
7688/* ARGSUSED */
7689static void
7690HandleBell(Widget w GCC_UNUSED,
7691	   XEvent * event GCC_UNUSED,
7692	   String * params,	/* [0] = volume */
7693	   Cardinal *param_count)	/* 0 or 1 */
7694{
7695    int percent = (*param_count) ? atoi(params[0]) : 0;
7696
7697    Bell(XkbBI_TerminalBell, percent);
7698}
7699
7700/* ARGSUSED */
7701static void
7702HandleVisualBell(Widget w GCC_UNUSED,
7703		 XEvent * event GCC_UNUSED,
7704		 String * params GCC_UNUSED,
7705		 Cardinal *param_count GCC_UNUSED)
7706{
7707    VisualBell();
7708}
7709
7710/* ARGSUSED */
7711static void
7712HandleIgnore(Widget w,
7713	     XEvent * event,
7714	     String * params GCC_UNUSED,
7715	     Cardinal *param_count GCC_UNUSED)
7716{
7717    XtermWidget xw;
7718
7719    TRACE(("Handle ignore for %p\n", w));
7720    if ((xw = getXtermWidget(w)) != 0) {
7721	/* do nothing, but check for funny escape sequences */
7722	(void) SendMousePosition(xw, event);
7723    }
7724}
7725
7726/* ARGSUSED */
7727static void
7728DoSetSelectedFont(Widget w,
7729		  XtPointer client_data GCC_UNUSED,
7730		  Atom * selection GCC_UNUSED,
7731		  Atom * type,
7732		  XtPointer value,
7733		  unsigned long *length,
7734		  int *format)
7735{
7736    XtermWidget xw = getXtermWidget(w);
7737
7738    if ((xw == 0) || *type != XA_STRING || *format != 8) {
7739	Bell(XkbBI_MinorError, 0);
7740    } else {
7741	Boolean failed = False;
7742	int oldFont = xw->screen.menu_font_number;
7743	char *save = xw->screen.MenuFontName(fontMenu_fontsel);
7744	char *val;
7745	char *test = 0;
7746	char *used = 0;
7747	unsigned len = *length;
7748	unsigned tst;
7749
7750	/*
7751	 * Some versions of X deliver null-terminated selections, some do not.
7752	 */
7753	for (tst = 0; tst < len; ++tst) {
7754	    if (((char *) value)[tst] == '\0') {
7755		len = tst;
7756		break;
7757	    }
7758	}
7759
7760	if (len > 0 && (val = TypeMallocN(char, len + 1)) != 0) {
7761	    memcpy(val, value, len);
7762	    val[len] = '\0';
7763	    used = x_strtrim(val);
7764	    TRACE(("DoSetSelectedFont(%s)\n", val));
7765	    /* Do some sanity checking to avoid sending a long selection
7766	       back to the server in an OpenFont that is unlikely to succeed.
7767	       XLFD allows up to 255 characters and no control characters;
7768	       we are a little more liberal here. */
7769	    if (len < 1000
7770		&& !strchr(val, '\n')
7771		&& (test = x_strdup(val)) != 0) {
7772		xw->screen.MenuFontName(fontMenu_fontsel) = test;
7773		if (!xtermLoadFont(term,
7774				   xtermFontName(val),
7775				   True,
7776				   fontMenu_fontsel)) {
7777		    failed = True;
7778		    free(test);
7779		    xw->screen.MenuFontName(fontMenu_fontsel) = save;
7780		}
7781	    } else {
7782		failed = True;
7783	    }
7784	    if (failed) {
7785		(void) xtermLoadFont(term,
7786				     xtermFontName(xw->screen.MenuFontName(oldFont)),
7787				     True,
7788				     oldFont);
7789		Bell(XkbBI_MinorError, 0);
7790	    }
7791	    if (used != val)
7792		free(used);
7793	    free(val);
7794	}
7795    }
7796}
7797
7798void
7799FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe)
7800{
7801    TScreen *screen = &(xw->screen);
7802    static AtomPtr *atoms;
7803    unsigned int atomCount = 0;
7804    AtomPtr *pAtom;
7805    unsigned a;
7806    Atom target;
7807
7808    if (!atom_name)
7809	atom_name = (screen->mappedSelect
7810		     ? screen->mappedSelect[0]
7811		     : "PRIMARY");
7812    TRACE(("FindFontSelection(%s)\n", atom_name));
7813
7814    for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
7815	if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0)
7816	    break;
7817    }
7818    if (!a) {
7819	atoms = (AtomPtr *) XtRealloc((char *) atoms,
7820				      sizeof(AtomPtr) * (atomCount + 1));
7821	*(pAtom = &atoms[atomCount++]) = XmuMakeAtom(atom_name);
7822    }
7823
7824    target = XmuInternAtom(XtDisplay(xw), *pAtom);
7825    if (justprobe) {
7826	screen->MenuFontName(fontMenu_fontsel) =
7827	    XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : 0;
7828	TRACE(("...selected fontname '%s'\n",
7829	       NonNull(screen->MenuFontName(fontMenu_fontsel))));
7830    } else {
7831	XtGetSelectionValue((Widget) xw, target, XA_STRING,
7832			    DoSetSelectedFont, NULL,
7833			    XtLastTimestampProcessed(XtDisplay(xw)));
7834    }
7835    return;
7836}
7837
7838void
7839set_cursor_gcs(XtermWidget xw)
7840{
7841    TScreen *screen = &(xw->screen);
7842    VTwin *win = WhichVWin(screen);
7843
7844    Pixel cc = T_COLOR(screen, TEXT_CURSOR);
7845    Pixel fg = T_COLOR(screen, TEXT_FG);
7846    Pixel bg = T_COLOR(screen, TEXT_BG);
7847    Boolean changed = False;
7848
7849    /*
7850     * Let's see, there are three things that have "color":
7851     *
7852     *     background
7853     *     text
7854     *     cursorblock
7855     *
7856     * And, there are four situations when drawing a cursor, if we decide
7857     * that we like have a solid block of cursor color with the letter
7858     * that it is highlighting shown in the background color to make it
7859     * stand out:
7860     *
7861     *     selected window, normal video - background on cursor
7862     *     selected window, reverse video - foreground on cursor
7863     *     unselected window, normal video - foreground on background
7864     *     unselected window, reverse video - background on foreground
7865     *
7866     * Since the last two are really just normalGC and reverseGC, we only
7867     * need two new GC's.  Under monochrome, we get the same effect as
7868     * above by setting cursor color to foreground.
7869     */
7870
7871    TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg));
7872    if (win != 0 && (cc != bg)) {
7873	/* set the fonts to the current one */
7874	setCgsFont(xw, win, gcVTcursNormal, 0);
7875	setCgsFont(xw, win, gcVTcursFilled, 0);
7876	setCgsFont(xw, win, gcVTcursReverse, 0);
7877	setCgsFont(xw, win, gcVTcursOutline, 0);
7878
7879	/* we have a colored cursor */
7880	setCgsFore(xw, win, gcVTcursNormal, fg);
7881	setCgsBack(xw, win, gcVTcursNormal, cc);
7882
7883	setCgsFore(xw, win, gcVTcursFilled, cc);
7884	setCgsBack(xw, win, gcVTcursFilled, fg);
7885
7886	if (screen->always_highlight) {
7887	    /* both GC's use the same color */
7888	    setCgsFore(xw, win, gcVTcursReverse, bg);
7889	    setCgsBack(xw, win, gcVTcursReverse, cc);
7890
7891	    setCgsFore(xw, win, gcVTcursOutline, bg);
7892	    setCgsBack(xw, win, gcVTcursOutline, cc);
7893	} else {
7894	    setCgsFore(xw, win, gcVTcursReverse, bg);
7895	    setCgsBack(xw, win, gcVTcursReverse, cc);
7896
7897	    setCgsFore(xw, win, gcVTcursOutline, cc);
7898	    setCgsBack(xw, win, gcVTcursOutline, bg);
7899	}
7900	changed = True;
7901    }
7902
7903    if (changed) {
7904	TRACE(("...set_cursor_gcs - done\n"));
7905    }
7906}
7907
7908#ifdef NO_LEAKS
7909void
7910noleaks_charproc(void)
7911{
7912    if (v_buffer != 0)
7913	free(v_buffer);
7914}
7915#endif
7916