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