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