1 /* $XTermId: charproc.c,v 1.1852 2021/11/12 22:10:53 tom Exp $ */
2
3 /*
4 * Copyright 1999-2020,2021 by Thomas E. Dickey
5 *
6 * All Rights Reserved
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the
29 * sale, use or other dealings in this Software without prior written
30 * authorization.
31 *
32 *
33 * Copyright 1988 X Consortium
34 *
35 * Permission to use, copy, modify, distribute, and sell this software and its
36 * documentation for any purpose is hereby granted without fee, provided that
37 * the above copyright notice appear in all copies and that both that
38 * copyright notice and this permission notice appear in supporting
39 * documentation.
40 *
41 * The above copyright notice and this permission notice shall be included in
42 * all copies or substantial portions of the Software.
43 *
44 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
48 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
49 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
50 *
51 * Except as contained in this notice, the name of the X Consortium shall not be
52 * used in advertising or otherwise to promote the sale, use or other dealings
53 * in this Software without prior written authorization from the X Consortium.
54 *
55 */
56 /*
57 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
58 *
59 * All Rights Reserved
60 *
61 * Permission to use, copy, modify, and distribute this software and its
62 * documentation for any purpose and without fee is hereby granted,
63 * provided that the above copyright notice appear in all copies and that
64 * both that copyright notice and this permission notice appear in
65 * supporting documentation, and that the name of Digital Equipment
66 * Corporation not be used in advertising or publicity pertaining to
67 * distribution of the software without specific, written prior permission.
68 *
69 *
70 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76 * SOFTWARE.
77 */
78
79 /* charproc.c */
80
81 #include <version.h>
82 #include <xterm.h>
83
84 #include <X11/Xatom.h>
85 #include <X11/Xutil.h>
86 #include <X11/Xmu/Atoms.h>
87 #include <X11/Xmu/CharSet.h>
88 #include <X11/Xmu/Converters.h>
89
90 #if OPT_INPUT_METHOD
91
92 #if defined(HAVE_LIB_XAW)
93 #include <X11/Xaw/XawImP.h>
94 #elif defined(HAVE_LIB_XAW3D)
95 #include <X11/Xaw3d/XawImP.h>
96 #elif defined(HAVE_LIB_XAW3DXFT)
97 #include <X11/Xaw3dxft/XawImP.h>
98 #elif defined(HAVE_LIB_NEXTAW)
99 #include <X11/neXtaw/XawImP.h>
100 #elif defined(HAVE_LIB_XAWPLUS)
101 #include <X11/XawPlus/XawImP.h>
102 #endif
103
104 #endif
105
106 #if OPT_WIDE_CHARS
107 #include <xutf8.h>
108 #include <wcwidth.h>
109 #include <precompose.h>
110 #ifdef HAVE_LANGINFO_CODESET
111 #include <langinfo.h>
112 #endif
113 #endif
114
115 #if USE_DOUBLE_BUFFER
116 #include <X11/extensions/Xdbe.h>
117 #endif
118
119 #include <stdio.h>
120 #include <ctype.h>
121 #include <assert.h>
122
123 #if defined(HAVE_SCHED_YIELD)
124 #include <sched.h>
125 #endif
126
127 #include <VTparse.h>
128 #include <data.h>
129 #include <error.h>
130 #include <menu.h>
131 #include <main.h>
132 #include <fontutils.h>
133 #include <charclass.h>
134 #include <xstrings.h>
135 #include <graphics.h>
136
137 #ifdef NO_LEAKS
138 #include <xtermcap.h>
139 #endif
140
141 typedef int (*BitFunc) (unsigned * /* p */ ,
142 unsigned /* mask */ );
143
144 static IChar doinput(XtermWidget /* xw */ );
145 static int set_character_class(char * /*s */ );
146 static void FromAlternate(XtermWidget /* xw */ );
147 static void ReallyReset(XtermWidget /* xw */ ,
148 Bool /* full */ ,
149 Bool /* saved */ );
150 static void RequestResize(XtermWidget /* xw */ ,
151 int /* rows */ ,
152 int /* cols */ ,
153 Bool /* text */ );
154 static void SwitchBufs(XtermWidget /* xw */ ,
155 int /* toBuf */ ,
156 Bool /* clearFirst */ );
157 static void ToAlternate(XtermWidget /* xw */ ,
158 Bool /* clearFirst */ );
159 static void ansi_modes(XtermWidget /* xw */ ,
160 BitFunc /* func */ );
161 static int bitclr(unsigned *p, unsigned mask);
162 static int bitcpy(unsigned *p, unsigned q, unsigned mask);
163 static int bitset(unsigned *p, unsigned mask);
164 static void dpmodes(XtermWidget /* xw */ ,
165 BitFunc /* func */ );
166 static void restoremodes(XtermWidget /* xw */ );
167 static void savemodes(XtermWidget /* xw */ );
168 static void window_ops(XtermWidget /* xw */ );
169
170 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
171 #define SettableCursorBlink(screen) \
172 (((screen)->cursor_blink != cbAlways) && \
173 ((screen)->cursor_blink != cbNever))
174 #define UpdateCursorBlink(xw) \
175 SetCursorBlink(xw, TScreenOf(xw)->cursor_blink)
176 static void SetCursorBlink(XtermWidget /* xw */ ,
177 BlinkOps /* enable */ );
178 static void HandleBlinking(XtPointer /* closure */ ,
179 XtIntervalId * /* id */ );
180 static void StartBlinking(XtermWidget /* xw */ );
181 static void StopBlinking(XtermWidget /* xw */ );
182 #else
183 #define StartBlinking(xw) /* nothing */
184 #define StopBlinking(xw) /* nothing */
185 #endif
186
187 #ifndef NO_ACTIVE_ICON
188 static Boolean discount_frame_extents(XtermWidget /* xw */ ,
189 int * /* height */ ,
190 int * /* width */ );
191 #else
192 #define discount_frame_extents(xw, height, width) False
193 #endif
194
195 #if OPT_INPUT_METHOD
196 static void PreeditPosition(XtermWidget /* xw */ );
197 #endif
198
199 #define DEFAULT -1
200 #define BELLSUPPRESSMSEC 200
201
202 static ANSI reply;
203 static PARAMS parms;
204
205 #define nparam parms.count
206
207 #define InitParams() init_params()
208 #define GetParam(n) parms.params[(n)]
209 #define SetParam(n,v) parms.params[(n)] = v
210 #define ParamPair(n) nparam - (n), parms.params + (n)
211
212 static jmp_buf vtjmpbuf;
213
214 /* event handlers */
215 static void HandleBell PROTO_XT_ACTIONS_ARGS;
216 static void HandleIgnore PROTO_XT_ACTIONS_ARGS;
217 static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS;
218 static void HandleVisualBell PROTO_XT_ACTIONS_ARGS;
219 #if HANDLE_STRUCT_NOTIFY
220 static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS;
221 #endif
222
223 /*
224 * NOTE: VTInitialize zeros out the entire ".screen" component of the
225 * XtermWidget, so make sure to add an assignment statement in VTInitialize()
226 * for each new ".screen" field added to this resource list.
227 */
228
229 /* Defaults */
230 #if OPT_ISO_COLORS
231
232 /*
233 * If we default to colorMode enabled, compile-in defaults for the ANSI colors.
234 */
235 #if DFT_COLORMODE
236 #define DFT_COLOR(name) name
237 #else
238 #define DFT_COLOR(name) XtDefaultForeground
239 #endif
240 #endif
241
242 static char _Font_Selected_[] = "yes"; /* string is arbitrary */
243
244 static const char *defaultTranslations;
245 /* *INDENT-OFF* */
246 static XtActionsRec actionsList[] = {
247 { "allow-bold-fonts", HandleAllowBoldFonts },
248 { "allow-send-events", HandleAllowSends },
249 { "bell", HandleBell },
250 { "clear-saved-lines", HandleClearSavedLines },
251 { "copy-selection", HandleCopySelection },
252 { "create-menu", HandleCreateMenu },
253 { "delete-is-del", HandleDeleteIsDEL },
254 { "dired-button", DiredButton },
255 { "hard-reset", HandleHardReset },
256 { "ignore", HandleIgnore },
257 { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */
258 { "insert-eight-bit", HandleEightBitKeyPressed },
259 { "insert-selection", HandleInsertSelection },
260 { "insert-seven-bit", HandleKeyPressed },
261 { "interpret", HandleInterpret },
262 { "keymap", HandleKeymapChange },
263 { "pointer-motion", HandlePointerMotion },
264 { "pointer-button", HandlePointerButton },
265 { "popup-menu", HandlePopupMenu },
266 { "print", HandlePrintScreen },
267 { "print-everything", HandlePrintEverything },
268 { "print-redir", HandlePrintControlMode },
269 { "quit", HandleQuit },
270 { "redraw", HandleRedraw },
271 { "scroll-back", HandleScrollBack },
272 { "scroll-forw", HandleScrollForward },
273 { "scroll-to", HandleScrollTo },
274 { "secure", HandleSecure },
275 { "select-cursor-end", HandleKeyboardSelectEnd },
276 { "select-cursor-extend", HandleKeyboardSelectExtend },
277 { "select-cursor-start", HandleKeyboardSelectStart },
278 { "select-end", HandleSelectEnd },
279 { "select-extend", HandleSelectExtend },
280 { "select-set", HandleSelectSet },
281 { "select-start", HandleSelectStart },
282 { "send-signal", HandleSendSignal },
283 { "set-8-bit-control", Handle8BitControl },
284 { "set-allow132", HandleAllow132 },
285 { "set-altscreen", HandleAltScreen },
286 { "set-appcursor", HandleAppCursor },
287 { "set-appkeypad", HandleAppKeypad },
288 { "set-autolinefeed", HandleAutoLineFeed },
289 { "set-autowrap", HandleAutoWrap },
290 { "set-backarrow", HandleBackarrow },
291 { "set-bellIsUrgent", HandleBellIsUrgent },
292 { "set-cursesemul", HandleCursesEmul },
293 { "set-jumpscroll", HandleJumpscroll },
294 { "set-keep-clipboard", HandleKeepClipboard },
295 { "set-keep-selection", HandleKeepSelection },
296 { "set-marginbell", HandleMarginBell },
297 { "set-old-function-keys", HandleOldFunctionKeys },
298 { "set-pop-on-bell", HandleSetPopOnBell },
299 { "set-reverse-video", HandleReverseVideo },
300 { "set-reversewrap", HandleReverseWrap },
301 { "set-scroll-on-key", HandleScrollKey },
302 { "set-scroll-on-tty-output", HandleScrollTtyOutput },
303 { "set-scrollbar", HandleScrollbar },
304 { "set-select", HandleSetSelect },
305 { "set-sun-keyboard", HandleSunKeyboard },
306 { "set-titeInhibit", HandleTiteInhibit },
307 { "set-visual-bell", HandleSetVisualBell },
308 { "set-vt-font", HandleSetFont },
309 { "soft-reset", HandleSoftReset },
310 { "start-cursor-extend", HandleKeyboardStartExtend },
311 { "start-extend", HandleStartExtend },
312 { "string", HandleStringEvent },
313 { "vi-button", ViButton },
314 { "visual-bell", HandleVisualBell },
315 #ifdef ALLOWLOGGING
316 { "set-logging", HandleLogging },
317 #endif
318 #if OPT_ALLOW_XXX_OPS
319 { "allow-color-ops", HandleAllowColorOps },
320 { "allow-font-ops", HandleAllowFontOps },
321 { "allow-mouse-ops", HandleAllowMouseOps },
322 { "allow-tcap-ops", HandleAllowTcapOps },
323 { "allow-title-ops", HandleAllowTitleOps },
324 { "allow-window-ops", HandleAllowWindowOps },
325 #endif
326 #if OPT_BLINK_CURS
327 { "set-cursorblink", HandleCursorBlink },
328 #endif
329 #if OPT_BOX_CHARS
330 { "set-font-linedrawing", HandleFontBoxChars },
331 { "set-font-packed", HandleFontPacked },
332 #endif
333 #if OPT_DABBREV
334 { "dabbrev-expand", HandleDabbrevExpand },
335 #endif
336 #if OPT_DEC_CHRSET
337 { "set-font-doublesize", HandleFontDoublesize },
338 #endif
339 #if OPT_DEC_SOFTFONT
340 { "set-font-loading", HandleFontLoading },
341 #endif
342 #if OPT_SCREEN_DUMPS
343 { "dump-html", HandleDumpHtml },
344 { "dump-svg", HandleDumpSvg },
345 #endif
346 #if OPT_EXEC_XTERM
347 { "spawn-new-terminal", HandleSpawnTerminal },
348 #endif
349 #if OPT_HP_FUNC_KEYS
350 { "set-hp-function-keys", HandleHpFunctionKeys },
351 #endif
352 #if OPT_LOAD_VTFONTS
353 { "load-vt-fonts", HandleLoadVTFonts },
354 #endif
355 #if OPT_MAXIMIZE
356 { "deiconify", HandleDeIconify },
357 { "fullscreen", HandleFullscreen },
358 { "iconify", HandleIconify },
359 { "maximize", HandleMaximize },
360 { "restore", HandleRestoreSize },
361 #endif
362 #if OPT_NUM_LOCK
363 { "alt-sends-escape", HandleAltEsc },
364 { "meta-sends-escape", HandleMetaEsc },
365 { "set-num-lock", HandleNumLock },
366 #endif
367 #ifdef OPT_PRINT_ON_EXIT
368 { "print-immediate", HandlePrintImmediate },
369 { "print-on-error", HandlePrintOnError },
370 #endif
371 #if OPT_READLINE
372 { "readline-button", ReadLineButton },
373 #endif
374 #if OPT_RENDERFONT
375 { "set-render-font", HandleRenderFont },
376 #endif
377 #if OPT_SCO_FUNC_KEYS
378 { "set-sco-function-keys", HandleScoFunctionKeys },
379 #endif
380 #if OPT_SCROLL_LOCK
381 { "scroll-lock", HandleScrollLock },
382 #endif
383 #if OPT_SELECTION_OPS
384 { "exec-formatted", HandleExecFormatted },
385 { "exec-selectable", HandleExecSelectable },
386 { "insert-formatted", HandleInsertFormatted },
387 { "insert-selectable", HandleInsertSelectable },
388 #endif
389 #if OPT_SHIFT_FONTS
390 { "larger-vt-font", HandleLargerFont },
391 { "smaller-vt-font", HandleSmallerFont },
392 #endif
393 #if OPT_SIXEL_GRAPHICS
394 { "set-sixel-scrolling", HandleSixelScrolling },
395 #endif
396 #if OPT_GRAPHICS
397 { "set-private-colors", HandleSetPrivateColorRegisters },
398 #endif
399 #if OPT_SUN_FUNC_KEYS
400 { "set-sun-function-keys", HandleSunFunctionKeys },
401 #endif
402 #if OPT_TEK4014
403 { "set-terminal-type", HandleSetTerminalType },
404 { "set-visibility", HandleVisibility },
405 { "set-tek-text", HandleSetTekText },
406 { "tek-page", HandleTekPage },
407 { "tek-reset", HandleTekReset },
408 { "tek-copy", HandleTekCopy },
409 #endif
410 #if OPT_TOOLBAR
411 { "set-toolbar", HandleToolbar },
412 #endif
413 #if OPT_WIDE_CHARS
414 { "set-utf8-mode", HandleUTF8Mode },
415 { "set-utf8-fonts", HandleUTF8Fonts },
416 { "set-utf8-title", HandleUTF8Title },
417 #endif
418 };
419 /* *INDENT-ON* */
420
421 #define SPS screen.printer_state
422
423 static XtResource xterm_resources[] =
424 {
425 Bres(XtNallowPasteControls, XtCAllowPasteControls,
426 screen.allowPasteControl0, False),
427 Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False),
428 Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR),
429 Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT),
430 Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE),
431 Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP),
432 Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE),
433 Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW),
434 Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False),
435 Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC),
436 Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True),
437 Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False),
438 Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False),
439 Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False),
440 Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False),
441 Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False),
442 Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True),
443 Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False),
444 Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False),
445 Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS),
446 Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False),
447 Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True),
448 Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True),
449 Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False),
450 Bres(XtNc132, XtCC132, screen.c132, False),
451 Sres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll_s, DEF_CD_XTRA_SCROLL),
452 Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False),
453 Bres(XtNcurses, XtCCurses, screen.curses, False),
454 Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True),
455 Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine,
456 screen.cutToBeginningOfLine, True),
457 Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL),
458 Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True),
459 Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False),
460 Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True),
461 Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True),
462 Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True),
463 Bres(XtNhighlightSelection, XtCHighlightSelection,
464 screen.highlight_selection, False),
465 Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False),
466 Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False),
467 Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True),
468 Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False),
469 Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True),
470 Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False),
471 Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True),
472 Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False),
473 Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False),
474 Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC),
475 Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False),
476 Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False),
477 Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False),
478 Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False),
479 Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False),
480 Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False),
481 Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True),
482 Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False),
483 Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False),
484 Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False),
485 Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False),
486 Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False),
487 Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False),
488 Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True),
489 Bres(XtNselectToClipboard, XtCSelectToClipboard,
490 screen.selectToClipboard, False),
491 Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False),
492 Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False),
493 Sres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll_s, DEF_TI_XTRA_SCROLL),
494 Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False),
495 Bres(XtNunderLine, XtCUnderLine, screen.underline, True),
496 Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False),
497 Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False),
498
499 Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"),
500
501 Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC),
502 Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource),
503 Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER),
504 Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1),
505 Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE),
506 Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME),
507 Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL),
508 Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE),
509 Ires(XtNprinterControlMode, XtCPrinterControlMode,
510 SPS.printer_controlmode, 0),
511 Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES),
512 Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1),
513 Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100),
514 Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES),
515 Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1),
516 Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES),
517
518 Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL),
519 Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL),
520 Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL),
521 Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL),
522 Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL),
523 Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL),
524 Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL),
525 Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL),
526
527 Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""),
528 Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT),
529 Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL),
530 Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID),
531 Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"),
532 Sres(XtNdisallowedColorOps, XtCDisallowedColorOps,
533 screen.disallowedColorOps, DEF_DISALLOWED_COLOR),
534 Sres(XtNdisallowedFontOps, XtCDisallowedFontOps,
535 screen.disallowedFontOps, DEF_DISALLOWED_FONT),
536 Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps,
537 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE),
538 Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls,
539 screen.disallowedPasteControls, DEF_DISALLOWED_PASTE_CONTROLS),
540 Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps,
541 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP),
542 Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps,
543 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW),
544 Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META),
545 Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes,
546 screen.eightbit_select_types, NULL),
547 Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT),
548 Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL),
549 Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT),
550 Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""),
551 Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL),
552 Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL),
553
554 Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground),
555 Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground),
556 Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground),
557 Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground),
558 Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground),
559
560 {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
561 XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
562 XtRImmediate, (XtPointer) SouthWestGravity},
563
564 Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"),
565
566 #ifdef ALLOWLOGGING
567 Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False),
568 Bres(XtNlogging, XtCLogging, misc.log_on, False),
569 Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL),
570 #endif
571
572 #ifndef NO_ACTIVE_ICON
573 Sres("activeIcon", "ActiveIcon", misc.active_icon_s, "default"),
574 Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2),
575 Sres("iconFont", "IconFont", screen.icon_fontname, "nil2"),
576 Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground),
577 #endif /* NO_ACTIVE_ICON */
578
579 #if OPT_BLINK_CURS
580 Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True),
581 Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"),
582 #endif
583 Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False),
584
585 #if OPT_BLINK_TEXT
586 Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD),
587 #endif
588
589 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
590 Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600),
591 Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300),
592 #endif
593
594 #if OPT_BOX_CHARS
595 Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False),
596 Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True),
597 Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False),
598 Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True),
599 #endif
600
601 #if OPT_BROKEN_OSC
602 Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True),
603 #endif
604
605 #if OPT_BROKEN_ST
606 Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False),
607 #endif
608
609 #if OPT_C1_PRINT
610 Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False),
611 #endif
612
613 #if OPT_CLIP_BOLD
614 Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True),
615 Bres(XtNuseBorderClipping, XtCUseBorderClipping,
616 screen.use_border_clipping, False),
617 #endif
618
619 #if OPT_DEC_CHRSET
620 Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True),
621 Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET),
622 #endif
623
624 #if OPT_DEC_RECTOPS
625 Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC),
626 #endif
627
628 #if OPT_HIGHLIGHT_COLOR
629 Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground),
630 Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground),
631 Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True),
632 Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe),
633 #endif /* OPT_HIGHLIGHT_COLOR */
634
635 #if OPT_INPUT_METHOD
636 Bres(XtNopenIm, XtCOpenIm, misc.open_im, True),
637 Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL),
638 Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type,
639 "OverTheSpot,Root"),
640 Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3),
641 #endif
642
643 #if OPT_ISO_COLORS
644 Bres(XtNboldColors, XtCColorMode, screen.boldColors, True),
645 Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0),
646 Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE),
647
648 Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False),
649 Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False),
650 Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False),
651 Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False),
652 Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False),
653 Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False),
654 #if OPT_WIDE_ATTRS
655 Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False),
656 #endif
657 #if OPT_DIRECT_COLOR
658 Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True),
659 #endif
660
661 COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")),
662 COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")),
663 COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")),
664 COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")),
665 COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)),
666 COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")),
667 COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")),
668 COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")),
669 COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")),
670 COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")),
671 COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")),
672 COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")),
673 COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)),
674 COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")),
675 COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")),
676 COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")),
677 COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)),
678 COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)),
679 COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)),
680 COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)),
681
682 #if OPT_WIDE_ATTRS
683 COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)),
684 #endif
685
686 #endif /* OPT_ISO_COLORS */
687
688 CLICK_RES("2", screen.onClick[1], "word"),
689 CLICK_RES("3", screen.onClick[2], "line"),
690 CLICK_RES("4", screen.onClick[3], 0),
691 CLICK_RES("5", screen.onClick[4], 0),
692
693 Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"),
694
695 #if OPT_MOD_FKEYS
696 Ires(XtNmodifyKeyboard, XtCModifyKeyboard,
697 keyboard.modify_1st.allow_keys, 0),
698 Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys,
699 keyboard.modify_1st.cursor_keys, 2),
700 Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys,
701 keyboard.modify_1st.function_keys, 2),
702 Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys,
703 keyboard.modify_1st.keypad_keys, 0),
704 Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys,
705 keyboard.modify_1st.other_keys, 0),
706 Ires(XtNmodifyStringKeys, XtCModifyStringKeys,
707 keyboard.modify_1st.string_keys, 0),
708 Ires(XtNformatOtherKeys, XtCFormatOtherKeys,
709 keyboard.format_keys, 0),
710 #endif
711
712 #if OPT_NUM_LOCK
713 Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False),
714 Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True),
715 #endif
716
717 #if OPT_PRINT_COLORS
718 Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1),
719 #endif
720
721 #if OPT_REGIS_GRAPHICS
722 Sres(XtNregisDefaultFont, XtCRegisDefaultFont,
723 screen.graphics_regis_default_font, ""),
724 Sres(XtNregisScreenSize, XtCRegisScreenSize,
725 screen.graphics_regis_screensize, "auto"),
726 #endif
727
728 #if OPT_GRAPHICS
729 Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID),
730 Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size,
731 "1000x1000"),
732 #endif
733
734 #if OPT_SHIFT_FONTS
735 Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True),
736 #endif
737
738 #if OPT_SIXEL_GRAPHICS
739 Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, False),
740 Bres(XtNsixelScrollsRight, XtCSixelScrollsRight,
741 screen.sixel_scrolls_right, False),
742 #endif
743
744 #if OPT_GRAPHICS
745 Ires(XtNnumColorRegisters, XtCNumColorRegisters,
746 screen.numcolorregisters, 0),
747 Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters,
748 screen.privatecolorregisters, True),
749 #endif
750
751 #if OPT_SUNPC_KBD
752 Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10),
753 #endif
754
755 #if OPT_TEK4014
756 Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False),
757 Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False),
758 Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False),
759 #endif
760
761 #if OPT_TOOLBAR
762 Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0),
763 Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25),
764 #endif
765
766 #if OPT_WIDE_CHARS
767 Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False),
768 Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False),
769 Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True),
770 Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False),
771 Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False),
772 Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True),
773 Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False),
774 Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2),
775 Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655),
776 Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536),
777 Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"),
778 Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"),
779 Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"),
780 Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT),
781 Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT),
782 Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL),
783 #endif
784
785 #if OPT_LUIT_PROG
786 Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"),
787 Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER),
788 #endif
789
790 #if OPT_INPUT_METHOD
791 Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT),
792 #endif
793
794 #if OPT_SCROLL_LOCK
795 Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False),
796 Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False),
797 #endif
798
799 /* these are used only for testing ncurses, not in the manual page */
800 #if OPT_XMC_GLITCH
801 Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False),
802 Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True),
803 Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1),
804 Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0),
805 #endif
806
807 #ifdef SCROLLBAR_RIGHT
808 Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False),
809 #endif
810
811 #if OPT_RENDERFONT
812 Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False),
813 #define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0")
814 RES_FACESIZE(1),
815 RES_FACESIZE(2),
816 RES_FACESIZE(3),
817 RES_FACESIZE(4),
818 RES_FACESIZE(5),
819 RES_FACESIZE(6),
820 Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE),
821 Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME),
822 Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"),
823 Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE),
824 #if OPT_RENDERWIDE
825 Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME),
826 #endif
827 #endif
828 };
829
830 static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg,
831 ArgList args, Cardinal *num_args);
832 static void VTClassInit(void);
833 static void VTDestroy(Widget w);
834 static void VTExpose(Widget w, XEvent *event, Region region);
835 static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args,
836 Cardinal *num_args);
837 static void VTRealize(Widget w, XtValueMask * valuemask,
838 XSetWindowAttributes * values);
839 static void VTResize(Widget w);
840
841 #if OPT_INPUT_METHOD
842 static void VTInitI18N(XtermWidget);
843 #endif
844
845 #ifdef VMS
846 globaldef {
847 "xtermclassrec"
848 } noshare
849
850 #else
851 static
852 #endif /* VMS */
853 WidgetClassRec xtermClassRec =
854 {
855 {
856 /* core_class fields */
857 (WidgetClass) & widgetClassRec, /* superclass */
858 "VT100", /* class_name */
859 sizeof(XtermWidgetRec), /* widget_size */
860 VTClassInit, /* class_initialize */
861 NULL, /* class_part_initialize */
862 False, /* class_inited */
863 VTInitialize, /* initialize */
864 NULL, /* initialize_hook */
865 VTRealize, /* realize */
866 actionsList, /* actions */
867 XtNumber(actionsList), /* num_actions */
868 xterm_resources, /* resources */
869 XtNumber(xterm_resources), /* num_resources */
870 NULLQUARK, /* xrm_class */
871 True, /* compress_motion */
872 False, /* compress_exposure */
873 True, /* compress_enterleave */
874 False, /* visible_interest */
875 VTDestroy, /* destroy */
876 VTResize, /* resize */
877 VTExpose, /* expose */
878 VTSetValues, /* set_values */
879 NULL, /* set_values_hook */
880 XtInheritSetValuesAlmost, /* set_values_almost */
881 NULL, /* get_values_hook */
882 NULL, /* accept_focus */
883 XtVersion, /* version */
884 NULL, /* callback_offsets */
885 0, /* tm_table */
886 XtInheritQueryGeometry, /* query_geometry */
887 XtInheritDisplayAccelerator, /* display_accelerator */
888 NULL /* extension */
889 }
890 };
891
892 #ifdef VMS
893 globaldef {
894 "xtermwidgetclass"
895 }
896 noshare
897 #endif /* VMS */
898 WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec;
899
900 /*
901 * Add input-actions for widgets that are overlooked (scrollbar and toolbar):
902 *
903 * a) Sometimes the scrollbar passes through translations, sometimes it
904 * doesn't. We add the KeyPress translations here, just to be sure.
905 * b) In the normal (non-toolbar) configuration, the xterm widget covers
906 * almost all of the window. With a toolbar, there's a relatively
907 * large area that the user would expect to enter keystrokes since the
908 * program can get the focus.
909 */
910 void
xtermAddInput(Widget w)911 xtermAddInput(Widget w)
912 {
913 /* *INDENT-OFF* */
914 XtActionsRec input_actions[] = {
915 { "insert", HandleKeyPressed }, /* alias */
916 { "insert-eight-bit", HandleEightBitKeyPressed },
917 { "insert-seven-bit", HandleKeyPressed },
918 { "pointer-motion", HandlePointerMotion },
919 { "pointer-button", HandlePointerButton },
920 { "secure", HandleSecure },
921 { "string", HandleStringEvent },
922 { "scroll-back", HandleScrollBack },
923 { "scroll-forw", HandleScrollForward },
924 { "scroll-to", HandleScrollTo },
925 { "select-cursor-end", HandleKeyboardSelectEnd },
926 { "select-cursor-extend", HandleKeyboardSelectExtend },
927 { "select-cursor-start", HandleKeyboardSelectStart },
928 { "insert-selection", HandleInsertSelection },
929 { "select-start", HandleSelectStart },
930 { "select-extend", HandleSelectExtend },
931 { "start-extend", HandleStartExtend },
932 { "select-end", HandleSelectEnd },
933 { "clear-saved-lines", HandleClearSavedLines },
934 { "popup-menu", HandlePopupMenu },
935 { "bell", HandleBell },
936 { "ignore", HandleIgnore },
937 #if OPT_DABBREV
938 { "dabbrev-expand", HandleDabbrevExpand },
939 #endif
940 #if OPT_MAXIMIZE
941 { "fullscreen", HandleFullscreen },
942 #endif
943 #if OPT_SCROLL_LOCK
944 { "scroll-lock", HandleScrollLock },
945 #endif
946 #if OPT_SHIFT_FONTS
947 { "larger-vt-font", HandleLargerFont },
948 { "smaller-vt-font", HandleSmallerFont },
949 #endif
950 };
951 /* *INDENT-ON* */
952
953 TRACE_TRANS("BEFORE", w);
954 XtAppAddActions(app_con, input_actions, XtNumber(input_actions));
955 XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations));
956 TRACE_TRANS("AFTER:", w);
957
958 #if OPT_EXTRA_PASTE
959 if (term && term->keyboard.extra_translations)
960 XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations));
961 #endif
962 }
963
964 #if OPT_ISO_COLORS
965 #ifdef EXP_BOGUS_FG
966 static Bool
CheckBogusForeground(TScreen * screen,const char * tag)967 CheckBogusForeground(TScreen *screen, const char *tag)
968 {
969 int row = -1, col = -1, pass;
970 Bool isClear = True;
971
972 (void) tag;
973 for (pass = 0; pass < 2; ++pass) {
974 row = screen->cur_row;
975 for (; isClear && (row <= screen->max_row); ++row) {
976 CLineData *ld = getLineData(screen, row);
977
978 if (ld != 0) {
979 IAttr *attribs = ld->attribs;
980
981 col = (row == screen->cur_row) ? screen->cur_col : 0;
982 for (; isClear && (col <= screen->max_col); ++col) {
983 unsigned flags = attribs[col];
984 if (pass) {
985 flags &= ~FG_COLOR;
986 attribs[col] = (IAttr) flags;
987 } else if ((flags & BG_COLOR)) {
988 isClear = False;
989 } else if ((flags & FG_COLOR)) {
990 unsigned ch = ld->charData[col];
991 isClear = ((ch == ' ') || (ch == 0));
992 } else {
993 isClear = False;
994 }
995 }
996 }
997 }
998 }
999 TRACE(("%s checked %d,%d to %d,%d %s pass %d\n",
1000 tag, screen->cur_row, screen->cur_col,
1001 row, col,
1002 isClear && pass ? "cleared" : "unchanged",
1003 pass));
1004
1005 return isClear;
1006 }
1007 #endif
1008
1009 /*
1010 * The terminal's foreground and background colors are set via two mechanisms:
1011 * text (cur_foreground, cur_background values that are passed down to
1012 * XDrawImageString and XDrawString)
1013 * area (X11 graphics context used in XClearArea and XFillRectangle)
1014 */
1015 void
SGR_Foreground(XtermWidget xw,int color)1016 SGR_Foreground(XtermWidget xw, int color)
1017 {
1018 TScreen *screen = TScreenOf(xw);
1019 Pixel fg;
1020
1021 if (color >= 0) {
1022 UIntSet(xw->flags, FG_COLOR);
1023 } else {
1024 UIntClr(xw->flags, FG_COLOR);
1025 }
1026 fg = getXtermFG(xw, xw->flags, color);
1027 xw->cur_foreground = color;
1028
1029 setCgsFore(xw, WhichVWin(screen), gcNorm, fg);
1030 setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg);
1031
1032 setCgsFore(xw, WhichVWin(screen), gcBold, fg);
1033 setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg);
1034
1035 #ifdef EXP_BOGUS_FG
1036 /*
1037 * If we've just turned off the foreground color, check for blank cells
1038 * which have no background color, but do have foreground color. This
1039 * could happen due to setting the foreground color just before scrolling.
1040 *
1041 * Those cells look uncolored, but will confuse ShowCursor(), which looks
1042 * for the colors in the current cell, and will see the foreground color.
1043 * In that case, remove the foreground color from the blank cells.
1044 */
1045 if (color < 0) {
1046 CheckBogusForeground(screen, "SGR_Foreground");
1047 }
1048 #endif
1049 }
1050
1051 void
SGR_Background(XtermWidget xw,int color)1052 SGR_Background(XtermWidget xw, int color)
1053 {
1054 TScreen *screen = TScreenOf(xw);
1055 Pixel bg;
1056
1057 /*
1058 * An indexing operation may have set screen->scroll_amt, which would
1059 * normally result in calling FlushScroll() in WriteText(). However,
1060 * if we're changing the background color now, then the new value
1061 * should not apply to the pending blank lines.
1062 */
1063 if (screen->scroll_amt && (color != xw->cur_background))
1064 FlushScroll(xw);
1065
1066 if (color >= 0) {
1067 UIntSet(xw->flags, BG_COLOR);
1068 } else {
1069 UIntClr(xw->flags, BG_COLOR);
1070 }
1071 bg = getXtermBG(xw, xw->flags, color);
1072 xw->cur_background = color;
1073
1074 setCgsBack(xw, WhichVWin(screen), gcNorm, bg);
1075 setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg);
1076
1077 setCgsBack(xw, WhichVWin(screen), gcBold, bg);
1078 setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg);
1079 }
1080
1081 /* Invoked after updating bold/underline flags, computes the extended color
1082 * index to use for foreground. (See also 'extract_fg()').
1083 */
1084 static void
setExtendedFG(XtermWidget xw)1085 setExtendedFG(XtermWidget xw)
1086 {
1087 int fg = xw->sgr_foreground;
1088
1089 if (TScreenOf(xw)->colorAttrMode
1090 || (fg < 0)) {
1091 fg = MapToColorMode(fg, TScreenOf(xw), xw->flags);
1092 }
1093
1094 /* This implements the IBM PC-style convention of 8-colors, with one
1095 * bit for bold, thus mapping the 0-7 codes to 8-15. It won't make
1096 * much sense for 16-color applications, but we keep it to retain
1097 * compatibility with ANSI-color applications.
1098 */
1099 #if OPT_PC_COLORS /* XXXJTL should be settable at runtime (resource or OSC?) */
1100 if (TScreenOf(xw)->boldColors
1101 && (!xw->sgr_38_xcolors)
1102 && (fg >= 0)
1103 && (fg < 8)
1104 && (xw->flags & BOLD))
1105 fg |= 8;
1106 #endif
1107
1108 SGR_Foreground(xw, fg);
1109 }
1110
1111 /* Invoked after updating inverse flag, computes the extended color
1112 * index to use for background. (See also 'extract_bg()').
1113 */
1114 static void
setExtendedBG(XtermWidget xw)1115 setExtendedBG(XtermWidget xw)
1116 {
1117 int bg = xw->sgr_background;
1118
1119 if (TScreenOf(xw)->colorAttrMode
1120 || (bg < 0)) {
1121 if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE))
1122 bg = COLOR_RV;
1123 }
1124
1125 SGR_Background(xw, bg);
1126 }
1127
1128 void
setExtendedColors(XtermWidget xw)1129 setExtendedColors(XtermWidget xw)
1130 {
1131 setExtendedFG(xw);
1132 setExtendedBG(xw);
1133 }
1134
1135 static void
reset_SGR_Foreground(XtermWidget xw)1136 reset_SGR_Foreground(XtermWidget xw)
1137 {
1138 xw->sgr_foreground = -1;
1139 xw->sgr_38_xcolors = False;
1140 clrDirectFG(xw->flags);
1141 setExtendedFG(xw);
1142 }
1143
1144 static void
reset_SGR_Background(XtermWidget xw)1145 reset_SGR_Background(XtermWidget xw)
1146 {
1147 xw->sgr_background = -1;
1148 clrDirectBG(xw->flags);
1149 setExtendedBG(xw);
1150 }
1151
1152 static void
reset_SGR_Colors(XtermWidget xw)1153 reset_SGR_Colors(XtermWidget xw)
1154 {
1155 reset_SGR_Foreground(xw);
1156 reset_SGR_Background(xw);
1157 }
1158 #endif /* OPT_ISO_COLORS */
1159
1160 #if OPT_WIDE_ATTRS
1161 /*
1162 * Call this before changing the state of ATR_ITALIC, to update the GC fonts.
1163 */
1164 static void
setItalicFont(XtermWidget xw,Bool enable)1165 setItalicFont(XtermWidget xw, Bool enable)
1166 {
1167 if (enable) {
1168 if ((xw->flags & ATR_ITALIC) == 0) {
1169 xtermLoadItalics(xw);
1170 TRACE(("setItalicFont: enabling Italics\n"));
1171 xtermUpdateFontGCs(xw, getItalicFont);
1172 }
1173 } else if ((xw->flags & ATR_ITALIC) != 0) {
1174 TRACE(("setItalicFont: disabling Italics\n"));
1175 xtermUpdateFontGCs(xw, getNormalFont);
1176 }
1177 }
1178
1179 static void
ResetItalics(XtermWidget xw)1180 ResetItalics(XtermWidget xw)
1181 {
1182 setItalicFont(xw, False);
1183 UIntClr(xw->flags, ATR_ITALIC);
1184 }
1185
1186 #else
1187 #define ResetItalics(xw) /* nothing */
1188 #endif
1189
1190 static void
initCharset(TScreen * screen,int which,DECNRCM_codes code)1191 initCharset(TScreen *screen, int which, DECNRCM_codes code)
1192 {
1193 screen->gsets[which] = code;
1194 }
1195
1196 void
saveCharsets(TScreen * screen,DECNRCM_codes * target)1197 saveCharsets(TScreen *screen, DECNRCM_codes * target)
1198 {
1199 int g;
1200 for (g = 0; g < NUM_GSETS; ++g) {
1201 target[g] = screen->gsets[g];
1202 }
1203 }
1204
1205 void
restoreCharsets(TScreen * screen,DECNRCM_codes * source)1206 restoreCharsets(TScreen *screen, DECNRCM_codes * source)
1207 {
1208 int g;
1209 for (g = 0; g < NUM_GSETS; ++g) {
1210 screen->gsets[g] = source[g];
1211 }
1212 }
1213
1214 void
resetCharsets(TScreen * screen)1215 resetCharsets(TScreen *screen)
1216 {
1217 TRACE(("resetCharsets\n"));
1218
1219 initCharset(screen, 0, nrc_ASCII);
1220 initCharset(screen, 1, nrc_ASCII);
1221 initCharset(screen, 2, nrc_ASCII);
1222 initCharset(screen, 3, nrc_ASCII);
1223
1224 screen->curgl = 0; /* G0 => GL. */
1225 screen->curgr = 2; /* G2 => GR. */
1226 screen->curss = 0; /* No single shift. */
1227
1228 #if OPT_VT52_MODE
1229 if (screen->vtXX_level == 0)
1230 initCharset(screen, 1, nrc_DEC_Spec_Graphic); /* Graphics */
1231 #endif
1232 }
1233
1234 static void
modified_DECNRCM(XtermWidget xw)1235 modified_DECNRCM(XtermWidget xw)
1236 {
1237 #if OPT_WIDE_CHARS
1238 TScreen *screen = TScreenOf(xw);
1239 if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) {
1240 int enabled = ((xw->flags & NATIONAL) != 0);
1241 int modefix;
1242 EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix);
1243 switchPtyData(screen, !enabled);
1244 TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF"));
1245 }
1246 #else
1247 (void) xw;
1248 #endif
1249 }
1250
1251 /*
1252 * VT300 and up support three ANSI conformance levels, defined according to
1253 * the dpANSI X3.134.1 standard. DEC's manuals equate levels 1 and 2, and
1254 * are unclear. This code is written based on the manuals.
1255 */
1256 static void
set_ansi_conformance(TScreen * screen,int level)1257 set_ansi_conformance(TScreen *screen, int level)
1258 {
1259 TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n",
1260 level,
1261 screen->vtXX_level * 100,
1262 screen->terminal_id,
1263 screen->ansi_level));
1264 if (screen->vtXX_level >= 3) {
1265 switch (screen->ansi_level = level) {
1266 case 1:
1267 /* FALLTHRU */
1268 case 2:
1269 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */
1270 initCharset(screen, 1, nrc_ASCII); /* G1 is ISO Latin-1 */
1271 screen->curgl = 0;
1272 screen->curgr = 1;
1273 break;
1274 case 3:
1275 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */
1276 screen->curgl = 0;
1277 break;
1278 }
1279 }
1280 }
1281
1282 /*
1283 * Set scrolling margins. VTxxx terminals require that the top/bottom are
1284 * different, so we have at least two lines in the scrolling region.
1285 */
1286 static void
set_tb_margins(TScreen * screen,int top,int bottom)1287 set_tb_margins(TScreen *screen, int top, int bottom)
1288 {
1289 TRACE(("set_tb_margins %d..%d, prior %d..%d\n",
1290 top, bottom,
1291 screen->top_marg,
1292 screen->bot_marg));
1293 if (bottom > top) {
1294 screen->top_marg = top;
1295 screen->bot_marg = bottom;
1296 }
1297 if (screen->top_marg > screen->max_row)
1298 screen->top_marg = screen->max_row;
1299 if (screen->bot_marg > screen->max_row)
1300 screen->bot_marg = screen->max_row;
1301 }
1302
1303 static void
set_lr_margins(TScreen * screen,int left,int right)1304 set_lr_margins(TScreen *screen, int left, int right)
1305 {
1306 TRACE(("set_lr_margins %d..%d, prior %d..%d\n",
1307 left, right,
1308 screen->lft_marg,
1309 screen->rgt_marg));
1310 if (right > left) {
1311 screen->lft_marg = left;
1312 screen->rgt_marg = right;
1313 }
1314 if (screen->lft_marg > screen->max_col)
1315 screen->lft_marg = screen->max_col;
1316 if (screen->rgt_marg > screen->max_col)
1317 screen->rgt_marg = screen->max_col;
1318 }
1319
1320 #define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row)
1321 #define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col)
1322
1323 void
resetMargins(XtermWidget xw)1324 resetMargins(XtermWidget xw)
1325 {
1326 TScreen *screen = TScreenOf(xw);
1327
1328 reset_tb_margins(screen);
1329 reset_lr_margins(screen);
1330 }
1331
1332 static void
resetMarginMode(XtermWidget xw)1333 resetMarginMode(XtermWidget xw)
1334 {
1335 UIntClr(xw->flags, LEFT_RIGHT);
1336 resetMargins(xw);
1337 }
1338
1339 static void
resetRendition(XtermWidget xw)1340 resetRendition(XtermWidget xw)
1341 {
1342 TScreen *screen = TScreenOf(xw);
1343 (void) screen;
1344 ResetItalics(xw);
1345 UIntClr(xw->flags,
1346 (SGR_MASK | SGR_MASK2 | INVISIBLE));
1347 }
1348
1349 void
set_max_col(TScreen * screen,int cols)1350 set_max_col(TScreen *screen, int cols)
1351 {
1352 TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col));
1353 if (cols < 0)
1354 cols = 0;
1355 screen->max_col = cols;
1356 }
1357
1358 void
set_max_row(TScreen * screen,int rows)1359 set_max_row(TScreen *screen, int rows)
1360 {
1361 TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row));
1362 if (rows < 0)
1363 rows = 0;
1364 screen->max_row = rows;
1365 }
1366
1367 #if OPT_MOD_FKEYS
1368 static void
set_mod_fkeys(XtermWidget xw,int which,int what,Bool enabled)1369 set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled)
1370 {
1371 #define SET_MOD_FKEYS(field) \
1372 xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \
1373 ? xw->keyboard.modify_1st.field \
1374 : what; \
1375 TRACE(("set modify_now.%s to %d\n", #field, \
1376 xw->keyboard.modify_now.field));
1377
1378 switch (which) {
1379 case 0:
1380 SET_MOD_FKEYS(allow_keys);
1381 break;
1382 case 1:
1383 SET_MOD_FKEYS(cursor_keys);
1384 break;
1385 case 2:
1386 SET_MOD_FKEYS(function_keys);
1387 break;
1388 case 3:
1389 SET_MOD_FKEYS(keypad_keys);
1390 break;
1391 case 4:
1392 SET_MOD_FKEYS(other_keys);
1393 break;
1394 case 5:
1395 SET_MOD_FKEYS(string_keys);
1396 break;
1397 }
1398 }
1399 #endif /* OPT_MOD_FKEYS */
1400
1401 #if OPT_TRACE
1402 #define DATA(name) { name, #name }
1403 static const struct {
1404 Const PARSE_T *table;
1405 const char *name;
1406 } all_tables[] = {
1407
1408 DATA(ansi_table)
1409 ,DATA(cigtable)
1410 ,DATA(csi2_table)
1411 ,DATA(csi_ex_table)
1412 ,DATA(csi_quo_table)
1413 ,DATA(csi_table)
1414 ,DATA(dec2_table)
1415 ,DATA(dec3_table)
1416 ,DATA(dec_table)
1417 ,DATA(eigtable)
1418 ,DATA(esc_sp_table)
1419 ,DATA(esc_table)
1420 ,DATA(scrtable)
1421 ,DATA(scs96table)
1422 ,DATA(scstable)
1423 ,DATA(sos_table)
1424 #if OPT_BLINK_CURS
1425 ,DATA(csi_sp_table)
1426 #endif
1427 #if OPT_DEC_LOCATOR
1428 ,DATA(csi_tick_table)
1429 #endif
1430 #if OPT_DEC_RECTOPS
1431 ,DATA(csi_dollar_table)
1432 ,DATA(csi_star_table)
1433 ,DATA(csi_dec_dollar_table)
1434 #endif
1435 #if OPT_WIDE_CHARS
1436 ,DATA(esc_pct_table)
1437 ,DATA(scs_amp_table)
1438 ,DATA(scs_pct_table)
1439 ,DATA(scs_2qt_table)
1440 #endif
1441 #if OPT_VT52_MODE
1442 ,DATA(vt52_table)
1443 ,DATA(vt52_esc_table)
1444 ,DATA(vt52_ignore_table)
1445 #endif
1446 #if OPT_XTERM_SGR
1447 ,DATA(csi_hash_table)
1448 #endif
1449 #undef DATA
1450 };
1451
1452 #define WHICH_TABLE(name) if (table == name) result = #name
1453 static const char *
which_table(Const PARSE_T * table)1454 which_table(Const PARSE_T * table)
1455 {
1456 const char *result = "?";
1457 Cardinal n;
1458 for (n = 0; n < XtNumber(all_tables); ++n) {
1459 if (table == all_tables[n].table) {
1460 result = all_tables[n].name;
1461 break;
1462 }
1463 }
1464
1465 return result;
1466 }
1467
1468 static void
check_tables(void)1469 check_tables(void)
1470 {
1471 Cardinal n;
1472 int ch;
1473 int total_codes = 0;
1474 int total_ground = 0;
1475 int total_ignored = 0;
1476
1477 TRACE(("** check_tables\n"));
1478 for (n = 0; n < XtNumber(all_tables); ++n) {
1479 Const PARSE_T *table = all_tables[n].table;
1480 TRACE(("*** %s\n", all_tables[n].name));
1481 /*
1482 * Most of the tables should use the same codes in 0..31, 128..159
1483 * as the "ansi" table.
1484 */
1485 if (strncmp(all_tables[n].name, "ansi", 4) &&
1486 strncmp(all_tables[n].name, "sos_", 4) &&
1487 strncmp(all_tables[n].name, "vt52", 4)) {
1488 for (ch = 0; ch < 32; ++ch) {
1489 int c1 = ch + 128;
1490 PARSE_T st_l = table[ch];
1491 PARSE_T st_r = table[c1];
1492 if (st_l != ansi_table[ch]) {
1493 TRACE((" %3d: %d vs %d\n", ch, st_l, ansi_table[ch]));
1494 }
1495 if (st_r != ansi_table[c1]) {
1496 TRACE((" %3d: %d vs %d\n", c1, st_r, ansi_table[c1]));
1497 }
1498 }
1499 }
1500 /*
1501 * All of the tables should have their GL/GR parts encoded the same.
1502 */
1503 for (ch = 32; ch < 127; ++ch) {
1504 PARSE_T st_l = table[ch];
1505 PARSE_T st_r = table[ch + 128];
1506 if (st_l != st_r) {
1507 if (st_r == CASE_IGNORE &&
1508 !strncmp(all_tables[n].name, "vt52", 4)) {
1509 ;
1510 } else {
1511 TRACE((" %3d: %d vs %d\n", ch, st_l, st_r));
1512 }
1513 }
1514 }
1515 /*
1516 * Just for amusement, show how sparse the encoding tables are.
1517 */
1518 for (ch = 0; ch < 256; ++ch) {
1519 ++total_codes;
1520 switch (table[ch]) {
1521 case CASE_GROUND_STATE:
1522 total_ground++;
1523 break;
1524 case CASE_ESC_IGNORE:
1525 /* FALLTHRU */
1526 case CASE_IGNORE:
1527 /* FALLTHRU */
1528 case CASE_VT52_IGNORE:
1529 total_ignored++;
1530 break;
1531 }
1532 }
1533 }
1534 TRACE(("VTPrsTbl:\n"));
1535 TRACE(("%d total codes\n", total_codes));
1536 TRACE(("%d total ignored\n", total_ignored));
1537 TRACE(("%d total reset/ground\n", total_ground));
1538 }
1539
1540 static void
check_bitmasks(void)1541 check_bitmasks(void)
1542 {
1543 #define dMSK 0x100
1544 #define DATA(mode,name) { mode, name, #name }
1545 #define DMSK(what) (dMSK | (what))
1546 #define DGRP(offs) (1 << ((offs) - 1))
1547 static struct {
1548 int mode;
1549 int code;
1550 Const char *name;
1551 } table[] = {
1552 DATA(DGRP(1), INVERSE),
1553 DATA(DGRP(1), UNDERLINE),
1554 DATA(DGRP(1), BOLD),
1555 DATA(DGRP(1), BLINK),
1556 DATA(DMSK(DGRP(1)), SGR_MASK),
1557 DATA(DGRP(2), BG_COLOR),
1558 DATA(DGRP(2), FG_COLOR),
1559 DATA(DGRP(2), PROTECTED),
1560 DATA(DGRP(4), CHARDRAWN),
1561 #if OPT_WIDE_ATTRS
1562 DATA(DGRP(2), ATR_FAINT),
1563 DATA(DGRP(2), ATR_ITALIC),
1564 DATA(DGRP(2), ATR_STRIKEOUT),
1565 DATA(DGRP(2), ATR_DBL_UNDER),
1566 DATA(DGRP(2), ATR_DIRECT_FG),
1567 DATA(DGRP(2), ATR_DIRECT_BG),
1568 #endif
1569 DATA(DMSK(DGRP(2)), SGR_MASK2),
1570 DATA(DGRP(3), WRAPAROUND),
1571 DATA(DGRP(3), REVERSEWRAP),
1572 DATA(DGRP(3), REVERSE_VIDEO),
1573 DATA(DGRP(3), LINEFEED),
1574 DATA(DGRP(3), ORIGIN),
1575 DATA(DGRP(3), INSERT),
1576 DATA(DGRP(3), SMOOTHSCROLL),
1577 DATA(DGRP(3), IN132COLUMNS),
1578 DATA(DGRP(3), INVISIBLE),
1579 DATA(DMSK(DGRP(3)), ATTRIBUTES),
1580 DATA(DGRP(5), NATIONAL),
1581 DATA(DGRP(5), LEFT_RIGHT),
1582 DATA(DGRP(5), NOCLEAR_COLM),
1583 DATA(DGRP(4), NOBACKGROUND),
1584 DATA(DGRP(4), NOTRANSLATION),
1585 DATA(DGRP(4), DOUBLEWFONT),
1586 DATA(DGRP(4), DOUBLEHFONT),
1587 DATA(DGRP(4), CHARBYCHAR),
1588 DATA(DGRP(4), NORESOLUTION),
1589 DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK),
1590 DATA(-1, EOF)
1591 };
1592 #undef DATA
1593 int j, k;
1594 TRACE(("** check_bitmasks:\n"));
1595 for (j = 0; table[j].mode >= 0; ++j) {
1596 TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name));
1597 if (table[j].mode & dMSK) {
1598 int mask = dMSK;
1599 for (k = 0; table[k].mode >= 0; ++k) {
1600 if (j == k)
1601 continue;
1602 if (table[k].mode & dMSK)
1603 continue;
1604 if ((table[j].mode & table[k].mode) != 0)
1605 mask |= table[k].mode;
1606 }
1607 if (mask != table[j].mode) {
1608 TRACE(("...expected %08X\n", mask));
1609 }
1610 } else {
1611 for (k = 0; table[k].mode >= 0; ++k) {
1612 if (j == k)
1613 continue;
1614 if (table[k].mode & dMSK)
1615 continue;
1616 if ((table[j].code & table[k].code) != 0) {
1617 TRACE(("...same bits %s\n", table[k].name));
1618 }
1619 }
1620 }
1621 }
1622 }
1623 #endif
1624
1625 static int
init_params(void)1626 init_params(void)
1627 {
1628 while (parms.count-- > 0) {
1629 parms.is_sub[parms.count] = 0;
1630 parms.params[parms.count] = 0;
1631 }
1632 parms.count = 0;
1633 parms.has_subparams = 0;
1634 return 0;
1635 }
1636
1637 #if OPT_TRACE > 0
1638 static void
dump_params(void)1639 dump_params(void)
1640 {
1641 int n;
1642 int arg;
1643 TRACE(("params %d (%d)\n", nparam, parms.has_subparams));
1644 for (arg = 1, n = 0; n < nparam; ++n) {
1645 TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n]));
1646 if (!parms.is_sub[n])
1647 ++arg;
1648 }
1649 }
1650 #define DumpParams() dump_params()
1651 #else
1652 #define DumpParams() /* nothing */
1653 #endif
1654
1655 /* allocate larger buffer if needed/possible */
1656 #define SafeAlloc(type, area, used, size) \
1657 type *new_string = area; \
1658 size_t new_length = size; \
1659 if (new_length == 0) { \
1660 new_length = 1024; \
1661 new_string = TypeMallocN(type, new_length); \
1662 } else if (used+1 >= new_length) { \
1663 new_length = size * 2; \
1664 new_string = TypeMallocN(type, new_length); \
1665 if (new_string != 0 \
1666 && area != 0 \
1667 && used != 0) { \
1668 memcpy(new_string, area, used * sizeof(type)); \
1669 } \
1670 }
1671 #define SafeFree(area, size) \
1672 if (area != new_string) { \
1673 free(area); \
1674 area = new_string; \
1675 } \
1676 size = new_length
1677
1678 #define WriteNow() { \
1679 unsigned single = 0; \
1680 \
1681 if (screen->curss) { \
1682 dotext(xw, \
1683 screen->gsets[(int) (screen->curss)], \
1684 sp->print_area, \
1685 (Cardinal) 1); \
1686 screen->curss = 0; \
1687 single++; \
1688 } \
1689 if (sp->print_used > single) { \
1690 dotext(xw, \
1691 screen->gsets[(int) (screen->curgl)], \
1692 sp->print_area + single, \
1693 (Cardinal) (sp->print_used - single)); \
1694 } \
1695 sp->print_used = 0; \
1696 } \
1697
1698 #define PARSE_SRM 1
1699
1700 struct ParseState {
1701 unsigned check_recur;
1702 #if OPT_VT52_MODE
1703 Bool vt52_cup;
1704 #endif
1705 Const PARSE_T *groundtable;
1706 Const PARSE_T *parsestate;
1707 int scstype;
1708 int scssize;
1709 Bool private_function; /* distinguish private-mode from standard */
1710 int string_mode; /* nonzero iff we're processing a string */
1711 int lastchar; /* positive iff we had a graphic character */
1712 int nextstate;
1713 #if OPT_WIDE_CHARS
1714 int last_was_wide;
1715 #endif
1716 /* Buffer for processing printable text */
1717 IChar *print_area;
1718 size_t print_size;
1719 size_t print_used;
1720 /* Buffer for processing strings (e.g., OSC ... ST) */
1721 Char *string_area;
1722 size_t string_size;
1723 size_t string_used;
1724 /* Buffer for deferring input */
1725 Char *defer_area;
1726 size_t defer_size;
1727 size_t defer_used;
1728 };
1729
1730 static struct ParseState myState;
1731
1732 static void
init_groundtable(TScreen * screen,struct ParseState * sp)1733 init_groundtable(TScreen *screen, struct ParseState *sp)
1734 {
1735 (void) screen;
1736
1737 #if OPT_VT52_MODE
1738 if (!(screen->vtXX_level)) {
1739 sp->groundtable = vt52_table;
1740 } else if (screen->terminal_id >= 100)
1741 #endif
1742 {
1743 sp->groundtable = ansi_table;
1744 }
1745 }
1746
1747 static void
select_charset(struct ParseState * sp,int type,int size)1748 select_charset(struct ParseState *sp, int type, int size)
1749 {
1750 TRACE(("select_charset G%d size %d -> G%d size %d\n",
1751 sp->scstype, sp->scssize,
1752 type, size));
1753
1754 sp->scstype = type;
1755 sp->scssize = size;
1756 if (size == 94) {
1757 sp->parsestate = scstable;
1758 } else {
1759 sp->parsestate = scs96table;
1760 }
1761 }
1762 /* *INDENT-OFF* */
1763 static const struct {
1764 DECNRCM_codes result;
1765 int prefix;
1766 int suffix;
1767 int min_level;
1768 int max_level;
1769 int need_nrc;
1770 } scs_table[] = {
1771 { nrc_ASCII, 0, 'B', 1, 9, 0 },
1772 { nrc_British, 0, 'A', 1, 9, 0 },
1773 { nrc_DEC_Spec_Graphic, 0, '0', 1, 9, 0 },
1774 { nrc_DEC_Alt_Chars, 0, '1', 1, 1, 0 },
1775 { nrc_DEC_Alt_Graphics, 0, '2', 1, 1, 0 },
1776 /* VT2xx */
1777 { nrc_DEC_Supp, 0, '<', 2, 9, 0 },
1778 { nrc_Dutch, 0, '4', 2, 9, 1 },
1779 { nrc_Finnish, 0, '5', 2, 9, 1 },
1780 { nrc_Finnish2, 0, 'C', 2, 9, 1 },
1781 { nrc_French, 0, 'R', 2, 9, 1 },
1782 { nrc_French2, 0, 'f', 2, 9, 1 },
1783 { nrc_French_Canadian, 0, 'Q', 2, 9, 1 },
1784 { nrc_German, 0, 'K', 2, 9, 1 },
1785 { nrc_Italian, 0, 'Y', 2, 9, 1 },
1786 { nrc_Norwegian_Danish2, 0, 'E', 2, 9, 1 },
1787 { nrc_Norwegian_Danish3, 0, '6', 2, 9, 1 },
1788 { nrc_Spanish, 0, 'Z', 2, 9, 1 },
1789 { nrc_Swedish, 0, '7', 2, 9, 1 },
1790 { nrc_Swedish2, 0, 'H', 2, 9, 1 },
1791 { nrc_Swiss, 0, '=', 2, 9, 1 },
1792 /* VT3xx */
1793 { nrc_British_Latin_1, 0, 'A', 3, 9, 1 },
1794 { nrc_DEC_Supp_Graphic, '%', '5', 3, 9, 0 },
1795 { nrc_DEC_Technical, 0, '>', 3, 9, 0 },
1796 { nrc_French_Canadian2, 0, '9', 3, 9, 1 },
1797 { nrc_Norwegian_Danish, 0, '`', 3, 9, 1 },
1798 { nrc_Portugese, '%', '6', 3, 9, 1 },
1799 { nrc_ISO_Latin_1_Supp, 0, 'A', 3, 9, 0 },
1800 /* VT5xx */
1801 { nrc_Greek, '"', '>', 5, 9, 1 },
1802 { nrc_Hebrew, '%', '=', 5, 9, 1 },
1803 { nrc_Turkish, '%', '2', 5, 9, 1 },
1804 { nrc_DEC_Cyrillic, '&', '4', 5, 9, 0 },
1805 { nrc_DEC_Greek_Supp, '"', '?', 5, 9, 0 },
1806 { nrc_DEC_Hebrew_Supp, '"', '4', 5, 9, 0 },
1807 { nrc_DEC_Turkish_Supp, '%', '0', 5, 9, 0 },
1808 { nrc_ISO_Greek_Supp, 0, 'F', 5, 9, 0 },
1809 { nrc_ISO_Hebrew_Supp, 0, 'H', 5, 9, 0 },
1810 { nrc_ISO_Latin_2_Supp, 0, 'B', 5, 9, 0 },
1811 { nrc_ISO_Latin_5_Supp, 0, 'M', 5, 9, 0 },
1812 { nrc_ISO_Latin_Cyrillic,0, 'L', 5, 9, 0 },
1813 /* VT5xx (not implemented) */
1814 #if 0
1815 { nrc_Russian, '&', '5', 5, 9, 1 },
1816 { nrc_SCS_NRCS, '%', '3', 5, 9, 0 },
1817 #endif
1818 };
1819 /* *INDENT-ON* */
1820
1821 #if OPT_DEC_RECTOPS
1822 static char *
encode_scs(DECNRCM_codes value)1823 encode_scs(DECNRCM_codes value)
1824 {
1825 static char buffer[3];
1826 Cardinal n;
1827 char *result = buffer;
1828 for (n = 0; n < XtNumber(scs_table); ++n) {
1829 if (scs_table[n].result == value) {
1830 if (scs_table[n].prefix)
1831 *result++ = (char) scs_table[n].prefix;
1832 if (scs_table[n].suffix)
1833 *result++ = (char) scs_table[n].suffix;
1834 break;
1835 }
1836 }
1837 *result = '\0';
1838 return buffer;
1839 }
1840 #endif
1841
1842 void
xtermDecodeSCS(XtermWidget xw,int which,int sgroup,int prefix,int suffix)1843 xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix)
1844 {
1845 TScreen *screen = TScreenOf(xw);
1846 Cardinal n;
1847 DECNRCM_codes result = nrc_Unknown;
1848
1849 suffix &= 0x7f;
1850 for (n = 0; n < XtNumber(scs_table); ++n) {
1851 if (prefix == scs_table[n].prefix
1852 && suffix == scs_table[n].suffix
1853 && sgroup == scs_table[n].min_level
1854 && screen->vtXX_level >= scs_table[n].min_level
1855 && screen->vtXX_level <= scs_table[n].max_level
1856 && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) {
1857 result = scs_table[n].result;
1858 break;
1859 }
1860 }
1861 if (result != nrc_Unknown) {
1862 initCharset(screen, which, result);
1863 TRACE(("setting G%d to table #%d %s",
1864 which, n, visibleScsCode((int) result)));
1865 } else {
1866 TRACE(("...unknown GSET"));
1867 initCharset(screen, which, nrc_ASCII);
1868 }
1869 #if OPT_TRACE
1870 TRACE((" ("));
1871 if (prefix)
1872 TRACE(("prefix='%c', ", prefix));
1873 TRACE(("suffix='%c', sgroup=%d", suffix, sgroup));
1874 TRACE((")\n"));
1875 #endif
1876 }
1877
1878 /*
1879 * Given a parameter number, and subparameter (starting in each case from zero)
1880 * return the corresponding index into the parameter array. If the combination
1881 * is not found, return -1.
1882 */
1883 static int
subparam_index(int p,int s)1884 subparam_index(int p, int s)
1885 {
1886 int result = -1;
1887 int j, p2, s2;
1888
1889 for (j = p2 = 0; j < nparam; ++j, ++p2) {
1890 if (parms.is_sub[j]) {
1891 s2 = 0;
1892
1893 do {
1894 if ((p == p2) && (s == s2)) {
1895 result = j;
1896 break;
1897 }
1898 ++s2;
1899 } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j]));
1900
1901 if (result >= 0)
1902 break;
1903
1904 --j; /* undo the last "while" */
1905 } else if (p == p2) {
1906 if (s == 0) {
1907 result = j;
1908 }
1909 break;
1910 }
1911 }
1912 TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result));
1913 return result;
1914 }
1915
1916 /*
1917 * Check if the given item in the parameter array has subparameters.
1918 * If so, return the number of subparameters to use as a loop limit, etc.
1919 */
1920 static int
param_has_subparams(int item)1921 param_has_subparams(int item)
1922 {
1923 int result = 0;
1924 if (parms.has_subparams) {
1925 int n = subparam_index(item, 0);
1926 if (n >= 0 && parms.is_sub[n]) {
1927 while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) {
1928 result++;
1929 }
1930 }
1931 }
1932 TRACE(("...param_has_subparams(%d) ->%d\n", item, result));
1933 return result;
1934 }
1935
1936 #if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS
1937 /*
1938 * Given an index into the parameter array, return the corresponding parameter
1939 * number (starting from zero).
1940 */
1941 static int
param_number(int item)1942 param_number(int item)
1943 {
1944 int result = -1;
1945 int j, p;
1946
1947 for (j = p = 0; j < nparam; ++j, ++p) {
1948 if (p >= item) {
1949 result = j;
1950 break;
1951 }
1952 if (parms.is_sub[j]) {
1953 while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) {
1954 /* EMPTY */
1955 }
1956 --j;
1957 }
1958 }
1959
1960 TRACE2(("...param_number(%d) = %d\n", item, result));
1961 return result;
1962 }
1963
1964 static int
get_subparam(int p,int s)1965 get_subparam(int p, int s)
1966 {
1967 int item = subparam_index(p, s);
1968 int result = (item >= 0) ? parms.params[item] : DEFAULT;
1969 TRACE(("...get_subparam[%d] = %d\n", item, result));
1970 return result;
1971 }
1972
1973 /*
1974 * Some background -
1975 *
1976 * Todd Larason provided the initial changes to support 256-colors in July 1999.
1977 * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and
1978 * was unsure if there would be some standard using those codes. His response
1979 * was that this was documented (it turns out, in equally vague terms) in ITU
1980 * T.416
1981 *
1982 * Discussing this with Todd Larason in mid-1999, my point was that given the
1983 * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going
1984 * to be effective (more than $100 then, more than $200 in 2012)
1985 *
1986 * We overlooked the detail about ":" as a subparameter delimiter (documented
1987 * in 5.4.2 in ECMA-48). Some discussion in KDE in mid-2006 led Lars Doelle
1988 * to discuss the issue with me. Lars' initial concern dealt with the fact
1989 * that a sequence such as
1990 * CSI 38 ; 5 ; 1 m
1991 * violated the principle that SGR parameters could be used in any order.
1992 * Further discussion (see KDE #107487) resolved that the standard expected
1993 * that the sequence would look like
1994 * CSI 38 ; 5 : 1 m
1995 * which still violates that principle, since the "5:1" parameter has to
1996 * follow the "38" to be useful.
1997 *
1998 * This function accepts either format (per request by Paul Leonerd Evans).
1999 * It also accepts
2000 * CSI 38 : 5 : 1 m
2001 * according to Lars' original assumption. While implementing that, I added
2002 * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value.
2003 * ISO-8613-6 documents that as "direct color".
2004 *
2005 * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's
2006 * quirk in the description of direct color: it mentions a color space
2007 * identifier parameter which should follow the "2" (as parameter 1). In the
2008 * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as
2009 * well as parameters 7 and 8. Like parameter 1, parameters 7 and 8 are not
2010 * defined clearly in the standard, and a close reading indicates they are
2011 * optional, saying they "may be used". This implementation ignores parameters
2012 * 6 (and above), and provides for the color space identifier by checking the
2013 * number of parameters:
2014 * 3 after "2" (no color space identifier)
2015 * 4 or more after "2" (color space identifier)
2016 *
2017 * By the way - all of the parameters are decimal integers, and missing
2018 * parameters represent a default value. ISO-8613-6 is clear about that.
2019 *
2020 * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter.
2021 * ECMA-48 says only:
2022 *
2023 * 5.4.2 Parameter string format
2024 *
2025 * A parameter string which does not start with a bit combination in the
2026 * range 03/12 to 03/15 shall have the following format:
2027 *
2028 * a) A parameter string consists of one or more parameter
2029 * sub-strings, each of which represents a number in decimal
2030 * notation.
2031 *
2032 * b) Each parameter sub-string consists of one or more bit
2033 * combinations from 03/00 to 03/10; the bit combinations from
2034 * 03/00 to 03/09 represent the digits ZERO to NINE; bit
2035 * combination 03/10 may be used as a separator in a parameter
2036 * sub-string, for example, to separate the fractional part of a
2037 * decimal number from the integer part of that number.
2038 *
2039 * That is, there is no mention in ECMA-48 of the possibility that a parameter
2040 * string might be a list of parameters, as done in ISO-8613-3 (nor does
2041 * ECMA-48 provide an example where the ":" separator might be used). Because
2042 * of this, xterm treats other cases than those needed for ISO-8613-3 as an
2043 * error, and stops interpreting the sequence.
2044 */
2045 #define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0))
2046 static Boolean
parse_extended_colors(XtermWidget xw,int * colorp,int * itemp,Boolean * extended)2047 parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended)
2048 {
2049 Boolean result = False;
2050 int item = *itemp;
2051 int next = item;
2052 int base = param_number(item);
2053 int code = -1;
2054 int values[3]; /* maximum number of subparameters */
2055 int need = 0; /* number of subparameters needed */
2056 int have;
2057 int n;
2058
2059 /*
2060 * On entry, 'item' points to the 38/48 code in the parameter array.
2061 * If that has subparameters, we will expect all of the values to
2062 * be subparameters of that item.
2063 */
2064 if ((have = param_has_subparams(item)) != 0) {
2065 /* accept CSI 38 : 5 : 1 m */
2066 /* accept CSI 38 : 2 : 1 : 2 : 3 m */
2067 code = get_subparam(base, 1);
2068 need = extended_colors_limit(code);
2069 next = item + have;
2070 for (n = 0; n < need && n < 3; ++n) {
2071 values[n] = get_subparam(base, 2 + n + (have > 4));
2072 }
2073 } else if (++item < nparam) {
2074 ++base;
2075 if ((have = param_has_subparams(item)) != 0) {
2076 /* accept CSI 38 ; 5 : 1 m */
2077 /* accept CSI 38 ; 2 : 1 : 2 : 3 m */
2078 code = get_subparam(base, 0);
2079 need = extended_colors_limit(code);
2080 next = base + have;
2081 for (n = 0; n < need && n < 3; ++n) {
2082 values[n] = get_subparam(base, 1 + n + (have > 3));
2083 }
2084 } else {
2085 /* accept CSI 38 ; 5 ; 1 m */
2086 /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */
2087 code = GetParam(item);
2088 need = extended_colors_limit(code);
2089 next = item + need;
2090 for (n = 0; n < need && n < 3; ++n) {
2091 values[n] = GetParam(item + 1 + n);
2092 }
2093 }
2094 }
2095 item = next;
2096
2097 *extended = False;
2098 switch (code) {
2099 case 2:
2100 /* direct color in rgb space */
2101 if ((values[0] >= 0 && values[0] < 256) &&
2102 (values[1] >= 0 && values[1] < 256) &&
2103 (values[2] >= 0 && values[2] < 256)) {
2104 #if OPT_DIRECT_COLOR
2105 if (TScreenOf(xw)->direct_color && xw->has_rgb) {
2106 *colorp = getDirectColor(xw, values[0], values[1], values[2]);
2107 result = True;
2108 *extended = True;
2109 } else
2110 #endif
2111 {
2112 *colorp = xtermClosestColor(xw, values[0], values[1], values[2]);
2113 result = okIndexedColor(*colorp);
2114 }
2115 } else {
2116 *colorp = -1;
2117 }
2118 break;
2119 case 5:
2120 /* indexed color */
2121 *colorp = values[0];
2122 result = okIndexedColor(*colorp);
2123 break;
2124 default:
2125 *colorp = -1;
2126 break;
2127 }
2128
2129 TRACE(("...resulting color %d/%d %s\n",
2130 *colorp, NUM_ANSI_COLORS,
2131 result ? "OK" : "ERR"));
2132
2133 *itemp = item;
2134 return result;
2135 }
2136 #endif /* ...extended_colors */
2137
2138 static int
optional_param(int which)2139 optional_param(int which)
2140 {
2141 return (nparam > which) ? GetParam(which) : DEFAULT;
2142 }
2143
2144 static int
zero_if_default(int which)2145 zero_if_default(int which)
2146 {
2147 int result = (nparam > which) ? GetParam(which) : 0;
2148 if (result <= 0)
2149 result = 0;
2150 return result;
2151 }
2152
2153 static int
one_if_default(int which)2154 one_if_default(int which)
2155 {
2156 int result = (nparam > which) ? GetParam(which) : 0;
2157 if (result <= 0)
2158 result = 1;
2159 return result;
2160 }
2161
2162 /*
2163 * Color palette changes using the OSC controls require a repaint of the
2164 * screen - but not immediately. Do the repaint as soon as we detect a
2165 * state which will not lead to another color palette change.
2166 */
2167 static void
repaintWhenPaletteChanged(XtermWidget xw,struct ParseState * sp)2168 repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp)
2169 {
2170 Boolean ignore = False;
2171
2172 switch (sp->nextstate) {
2173 case CASE_ESC:
2174 ignore = ((sp->parsestate == ansi_table) ||
2175 (sp->parsestate == sos_table));
2176 #if USE_DOUBLE_BUFFER
2177 if (resource.buffered && TScreenOf(xw)->needSwap) {
2178 ignore = False;
2179 }
2180 #endif
2181 break;
2182 case CASE_OSC:
2183 ignore = ((sp->parsestate == ansi_table) ||
2184 (sp->parsestate == esc_table));
2185 break;
2186 case CASE_IGNORE:
2187 ignore = (sp->parsestate == sos_table);
2188 break;
2189 case CASE_ST:
2190 ignore = ((sp->parsestate == esc_table) ||
2191 (sp->parsestate == sos_table));
2192 break;
2193 case CASE_ESC_DIGIT:
2194 ignore = (sp->parsestate == csi_table);
2195 break;
2196 case CASE_ESC_SEMI:
2197 ignore = (sp->parsestate == csi2_table);
2198 break;
2199 }
2200
2201 if (!ignore) {
2202 TRACE(("repaintWhenPaletteChanged\n"));
2203 xw->work.palette_changed = False;
2204 xtermRepaint(xw);
2205 xtermFlushDbe(xw);
2206 }
2207 }
2208
2209 #if OPT_C1_PRINT || OPT_WIDE_CHARS
2210 #define ParseSOS(screen) ((screen)->c1_printable == 0)
2211 #else
2212 #define ParseSOS(screen) 0
2213 #endif
2214
2215 #define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable
2216
2217 static void
illegal_parse(XtermWidget xw,unsigned c,struct ParseState * sp)2218 illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp)
2219 {
2220 ResetState(sp);
2221 sp->nextstate = sp->parsestate[E2A(c)];
2222 Bell(xw, XkbBI_MinorError, 0);
2223 }
2224
2225 static void
init_parser(XtermWidget xw,struct ParseState * sp)2226 init_parser(XtermWidget xw, struct ParseState *sp)
2227 {
2228 TScreen *screen = TScreenOf(xw);
2229
2230 memset(sp, 0, sizeof(*sp));
2231 sp->scssize = 94; /* number of printable/nonspace ASCII */
2232 sp->lastchar = -1; /* not a legal IChar */
2233 sp->nextstate = -1; /* not a legal state */
2234
2235 init_groundtable(screen, sp);
2236 ResetState(sp);
2237 }
2238
2239 static void
init_reply(unsigned type)2240 init_reply(unsigned type)
2241 {
2242 memset(&reply, 0, sizeof(reply));
2243 reply.a_type = (Char) type;
2244 }
2245
2246 static void
deferparsing(unsigned c,struct ParseState * sp)2247 deferparsing(unsigned c, struct ParseState *sp)
2248 {
2249 SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size);
2250 if (new_string == 0) {
2251 xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n",
2252 (unsigned long) new_length, c);
2253 return;
2254 }
2255 SafeFree(sp->defer_area, sp->defer_size);
2256 sp->defer_area[(sp->defer_used)++] = CharOf(c);
2257 }
2258
2259 #if OPT_VT52_MODE
2260 static void
update_vt52_vt100_settings(void)2261 update_vt52_vt100_settings(void)
2262 {
2263 update_autowrap();
2264 update_reversewrap();
2265 update_autolinefeed();
2266 update_appcursor();
2267 update_appkeypad();
2268 update_allow132();
2269 }
2270 #endif
2271
2272 static Boolean
doparsing(XtermWidget xw,unsigned c,struct ParseState * sp)2273 doparsing(XtermWidget xw, unsigned c, struct ParseState *sp)
2274 {
2275 TScreen *screen = TScreenOf(xw);
2276 int item;
2277 int count;
2278 int value;
2279 int laststate;
2280 int thischar = -1;
2281 XTermRect myRect;
2282 #if OPT_DEC_RECTOPS
2283 int thispage = 1;
2284 #endif
2285
2286 if (sp->check_recur) {
2287 /* Defer parsing when parser is already running as the parser is not
2288 * safe to reenter.
2289 */
2290 deferparsing(c, sp);
2291 return True;
2292 }
2293 sp->check_recur++;
2294
2295 do {
2296 #if OPT_WIDE_CHARS
2297 int this_is_wide = 0;
2298
2299 /*
2300 * Handle zero-width combining characters. Make it faster by noting
2301 * that according to the Unicode charts, the majority of Western
2302 * character sets do not use this feature. There are some unassigned
2303 * codes at 0x242, but no zero-width characters until past 0x300.
2304 */
2305 if (c >= 0x300
2306 && screen->wide_chars
2307 && CharWidth(screen, c) == 0
2308 && !isWideControl(c)) {
2309 int prev, test;
2310 Boolean used = True;
2311 int use_row;
2312 int use_col;
2313
2314 WriteNow();
2315 use_row = (screen->char_was_written
2316 ? screen->last_written_row
2317 : screen->cur_row);
2318 use_col = (screen->char_was_written
2319 ? screen->last_written_col
2320 : screen->cur_col);
2321
2322 /*
2323 * Check if the latest data can be added to the base character.
2324 * If there is already a combining character stored for the cell,
2325 * we cannot, since that would change the order.
2326 */
2327 if (screen->normalized_c
2328 && !IsCellCombined(screen, use_row, use_col)) {
2329 prev = (int) XTERM_CELL(use_row, use_col);
2330 test = do_precomposition(prev, (int) c);
2331 TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n",
2332 prev, CharWidth(screen, prev),
2333 (int) c, CharWidth(screen, c),
2334 test, CharWidth(screen, test)));
2335 } else {
2336 prev = -1;
2337 test = -1;
2338 }
2339
2340 /* substitute combined character with precomposed character
2341 * only if it does not change the width of the base character
2342 */
2343 if (test != -1
2344 && CharWidth(screen, test) == CharWidth(screen, prev)) {
2345 putXtermCell(screen, use_row, use_col, test);
2346 } else if (screen->char_was_written
2347 || getXtermCell(screen, use_row, use_col) >= ' ') {
2348 addXtermCombining(screen, use_row, use_col, c);
2349 } else {
2350 /*
2351 * none of the above... we will add the combining character as
2352 * a base character.
2353 */
2354 used = False;
2355 }
2356
2357 if (used) {
2358 if (!screen->scroll_amt)
2359 ScrnUpdate(xw, use_row, use_col, 1, 1, 1);
2360 continue;
2361 }
2362 }
2363 #endif
2364
2365 /* Intercept characters for printer controller mode */
2366 if (PrinterOf(screen).printer_controlmode == 2) {
2367 if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0)
2368 continue;
2369 }
2370
2371 /*
2372 * VT52 is a little ugly in the one place it has a parameterized
2373 * control sequence, since the parameter falls after the character
2374 * that denotes the type of sequence.
2375 */
2376 #if OPT_VT52_MODE
2377 if (sp->vt52_cup) {
2378 if (nparam < NPARAM - 1) {
2379 SetParam(nparam++, (int) (c & 0x7f) - 32);
2380 parms.is_sub[nparam] = 0;
2381 }
2382 if (nparam < 2)
2383 continue;
2384 sp->vt52_cup = False;
2385 CursorSet(screen, zero_if_default(0), zero_if_default(1), xw->flags);
2386 sp->parsestate = vt52_table;
2387 SetParam(0, 0);
2388 SetParam(1, 0);
2389 continue;
2390 }
2391 #endif
2392
2393 laststate = sp->nextstate;
2394 if (c == ANSI_DEL
2395 && sp->parsestate == sp->groundtable
2396 && sp->scssize == 96
2397 && sp->scstype != 0) {
2398 /*
2399 * Handle special case of shifts for 96-character sets by checking
2400 * if we have a DEL. The other special case for SPACE will always
2401 * be printable.
2402 */
2403 sp->nextstate = CASE_PRINT;
2404 } else
2405 #if OPT_WIDE_CHARS
2406 if (c > 255) {
2407 /*
2408 * The parsing tables all have 256 entries. If we're supporting
2409 * wide characters, we handle them by treating them the same as
2410 * printing characters.
2411 */
2412 if (sp->parsestate == sp->groundtable) {
2413 sp->nextstate = CASE_PRINT;
2414 } else if (sp->parsestate == sos_table) {
2415 c &= WIDEST_ICHAR;
2416 if (c > 255) {
2417 TRACE(("Found code > 255 while in SOS state: %04X\n", c));
2418 c = BAD_ASCII;
2419 }
2420 } else {
2421 sp->nextstate = CASE_GROUND_STATE;
2422 }
2423 } else
2424 #endif
2425 sp->nextstate = sp->parsestate[E2A(c)];
2426
2427 #if OPT_BROKEN_OSC
2428 /*
2429 * Linux console palette escape sequences start with an OSC, but do
2430 * not terminate correctly. Some scripts do not check before writing
2431 * them, making xterm appear to hang (it's awaiting a valid string
2432 * terminator). Just ignore these if we see them - there's no point
2433 * in emulating bad code.
2434 */
2435 if (screen->brokenLinuxOSC
2436 && sp->parsestate == sos_table) {
2437 if (sp->string_used) {
2438 switch (sp->string_area[0]) {
2439 case 'P':
2440 if (sp->string_used <= 7)
2441 break;
2442 /* FALLTHRU */
2443 case 'R':
2444 illegal_parse(xw, c, sp);
2445 TRACE(("Reset to ground state (brokenLinuxOSC)\n"));
2446 break;
2447 }
2448 }
2449 }
2450 #endif
2451
2452 #if OPT_BROKEN_ST
2453 /*
2454 * Before patch #171, carriage control embedded within an OSC string
2455 * would terminate it. Some (buggy, of course) applications rely on
2456 * this behavior. Accommodate them by allowing one to compile xterm
2457 * and emulate the old behavior.
2458 */
2459 if (screen->brokenStringTerm
2460 && sp->parsestate == sos_table
2461 && c < 32) {
2462 switch (c) {
2463 case ANSI_EOT: /* FALLTHRU */
2464 case ANSI_BS: /* FALLTHRU */
2465 case ANSI_HT: /* FALLTHRU */
2466 case ANSI_LF: /* FALLTHRU */
2467 case ANSI_VT: /* FALLTHRU */
2468 case ANSI_FF: /* FALLTHRU */
2469 case ANSI_CR: /* FALLTHRU */
2470 case ANSI_SO: /* FALLTHRU */
2471 case ANSI_SI: /* FALLTHRU */
2472 case ANSI_XON: /* FALLTHRU */
2473 case ANSI_CAN:
2474 illegal_parse(xw, c, sp);
2475 TRACE(("Reset to ground state (brokenStringTerm)\n"));
2476 break;
2477 }
2478 }
2479 #endif
2480
2481 #if OPT_C1_PRINT
2482 /*
2483 * This is not completely foolproof, but will allow an application
2484 * with values in the C1 range to use them as printable characters,
2485 * provided that they are not intermixed with an escape sequence.
2486 */
2487 if (screen->c1_printable
2488 && (c >= 128 && c < 256)) {
2489 sp->nextstate = (sp->parsestate == esc_table
2490 ? CASE_ESC_IGNORE
2491 : sp->parsestate[E2A(160)]);
2492 TRACE(("allowC1Printable %04X %s ->%s\n",
2493 c, which_table(sp->parsestate),
2494 visibleVTparse(sp->nextstate)));
2495 }
2496 #endif
2497
2498 #if OPT_WIDE_CHARS
2499 /*
2500 * If we have a C1 code and the c1_printable flag is not set, simply
2501 * ignore it when it was translated from UTF-8. That is because the
2502 * value could not have been present as-is in the UTF-8.
2503 *
2504 * To see that CASE_IGNORE is a consistent value, note that it is
2505 * always used for NUL and other uninteresting C0 controls.
2506 */
2507 #if OPT_C1_PRINT
2508 if (!screen->c1_printable)
2509 #endif
2510 if (screen->wide_chars
2511 && (c >= 128 && c < 160)) {
2512 sp->nextstate = CASE_IGNORE;
2513 }
2514
2515 /*
2516 * If this character is a different width than the last one, put the
2517 * previous text into the buffer and draw it now.
2518 */
2519 this_is_wide = isWide((int) c);
2520 if (this_is_wide != sp->last_was_wide) {
2521 WriteNow();
2522 }
2523 #endif
2524
2525 /*
2526 * Accumulate string for printable text. This may be 8/16-bit
2527 * characters.
2528 */
2529 if (sp->nextstate == CASE_PRINT) {
2530 SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size);
2531 if (new_string == 0) {
2532 xtermWarning("Cannot allocate %lu bytes for printable text\n",
2533 (unsigned long) new_length);
2534 continue;
2535 }
2536 SafeFree(sp->print_area, sp->print_size);
2537 #if OPT_VT52_MODE
2538 /*
2539 * Strip output text to 7-bits for VT52. We should do this for
2540 * VT100 also (which is a 7-bit device), but xterm has been
2541 * doing this for so long we shouldn't change this behavior.
2542 */
2543 if (screen->vtXX_level < 1)
2544 c &= 0x7f;
2545 #endif
2546 sp->print_area[sp->print_used++] = (IChar) c;
2547 sp->lastchar = thischar = (int) c;
2548 #if OPT_WIDE_CHARS
2549 sp->last_was_wide = this_is_wide;
2550 #endif
2551 if (morePtyData(screen, VTbuffer)) {
2552 continue;
2553 }
2554 }
2555
2556 if (sp->nextstate == CASE_PRINT
2557 || (laststate == CASE_PRINT && sp->print_used)) {
2558 WriteNow();
2559 }
2560
2561 /*
2562 * Accumulate string for APC, DCS, PM, OSC, SOS controls
2563 * This should always be 8-bit characters.
2564 */
2565 if (sp->parsestate == sos_table) {
2566 SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size);
2567 if (new_string == 0) {
2568 xtermWarning("Cannot allocate %lu bytes for string mode %d\n",
2569 (unsigned long) new_length, sp->string_mode);
2570 continue;
2571 }
2572 SafeFree(sp->string_area, sp->string_size);
2573 #if OPT_WIDE_CHARS
2574 /*
2575 * We cannot display codes above 255, but let's try to
2576 * accommodate the application a little by not aborting the
2577 * string.
2578 */
2579 if ((c & WIDEST_ICHAR) > 255) {
2580 sp->nextstate = CASE_PRINT;
2581 c = BAD_ASCII;
2582 }
2583 #endif
2584 sp->string_area[(sp->string_used)++] = CharOf(c);
2585 } else if (sp->parsestate != esc_table) {
2586 /* if we were accumulating, we're not any more */
2587 sp->string_mode = 0;
2588 sp->string_used = 0;
2589 }
2590
2591 DumpParams();
2592 TRACE(("parse %04X -> %s %s (used=%lu)\n",
2593 c, visibleVTparse(sp->nextstate),
2594 which_table(sp->parsestate),
2595 (unsigned long) sp->string_used));
2596
2597 /*
2598 * If the parameter list has subparameters (tokens separated by ":")
2599 * reject any controls that do not accept subparameters.
2600 */
2601 if (parms.has_subparams) {
2602 switch (sp->nextstate) {
2603 case CASE_GROUND_STATE:
2604 case CASE_CSI_IGNORE:
2605 /* FALLTHRU */
2606
2607 case CASE_ESC_DIGIT:
2608 case CASE_ESC_SEMI:
2609 case CASE_ESC_COLON:
2610 /* these states are required to parse parameter lists */
2611 break;
2612
2613 case CASE_SGR:
2614 TRACE(("...possible subparam usage\n"));
2615 break;
2616
2617 case CASE_CSI_DEC_DOLLAR_STATE:
2618 case CASE_CSI_DOLLAR_STATE:
2619 case CASE_CSI_HASH_STATE:
2620 case CASE_CSI_EX_STATE:
2621 case CASE_CSI_QUOTE_STATE:
2622 case CASE_CSI_SPACE_STATE:
2623 case CASE_CSI_STAR_STATE:
2624 case CASE_CSI_TICK_STATE:
2625 case CASE_DEC2_STATE:
2626 case CASE_DEC3_STATE:
2627 case CASE_DEC_STATE:
2628 /* use this branch when we do not yet have the final character */
2629 TRACE(("...unexpected subparam usage\n"));
2630 InitParams();
2631 sp->nextstate = CASE_CSI_IGNORE;
2632 break;
2633
2634 default:
2635 /* use this branch for cases where we have the final character
2636 * in the table that processed the parameter list.
2637 */
2638 TRACE(("...unexpected subparam usage\n"));
2639 ResetState(sp);
2640 continue;
2641 }
2642 }
2643
2644 if (xw->work.palette_changed) {
2645 repaintWhenPaletteChanged(xw, sp);
2646 }
2647
2648 switch (sp->nextstate) {
2649 case CASE_PRINT:
2650 TRACE(("CASE_PRINT - printable characters\n"));
2651 break;
2652
2653 case CASE_GROUND_STATE:
2654 TRACE(("CASE_GROUND_STATE - exit ignore mode\n"));
2655 ResetState(sp);
2656 break;
2657
2658 case CASE_IGNORE:
2659 TRACE(("CASE_IGNORE - Ignore character %02X\n", c));
2660 break;
2661
2662 case CASE_ENQ:
2663 TRACE(("CASE_ENQ - answerback\n"));
2664 if (((xw->keyboard.flags & MODE_SRM) == 0)
2665 ? (sp->check_recur == 0)
2666 : (sp->check_recur <= 1)) {
2667 for (count = 0; screen->answer_back[count] != 0; count++)
2668 unparseputc(xw, screen->answer_back[count]);
2669 unparse_end(xw);
2670 }
2671 break;
2672
2673 case CASE_BELL:
2674 TRACE(("CASE_BELL - bell\n"));
2675 if (sp->string_mode == ANSI_OSC) {
2676 if (sp->string_used)
2677 sp->string_area[--(sp->string_used)] = '\0';
2678 if (sp->check_recur <= 1)
2679 do_osc(xw, sp->string_area, sp->string_used, (int) c);
2680 ResetState(sp);
2681 } else {
2682 /* bell */
2683 Bell(xw, XkbBI_TerminalBell, 0);
2684 }
2685 break;
2686
2687 case CASE_BS:
2688 TRACE(("CASE_BS - backspace\n"));
2689 CursorBack(xw, 1);
2690 break;
2691
2692 case CASE_CR:
2693 TRACE(("CASE_CR\n"));
2694 CarriageReturn(xw);
2695 break;
2696
2697 case CASE_ESC:
2698 if_OPT_VT52_MODE(screen, {
2699 sp->parsestate = vt52_esc_table;
2700 break;
2701 });
2702 sp->parsestate = esc_table;
2703 break;
2704
2705 #if OPT_VT52_MODE
2706 case CASE_VT52_CUP:
2707 TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n"));
2708 sp->vt52_cup = True;
2709 ResetState(sp);
2710 break;
2711
2712 case CASE_VT52_IGNORE:
2713 TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n"));
2714 sp->parsestate = vt52_ignore_table;
2715 break;
2716 #endif
2717
2718 case CASE_VMOT:
2719 TRACE(("CASE_VMOT\n"));
2720 /*
2721 * form feed, line feed, vertical tab
2722 */
2723 xtermAutoPrint(xw, c);
2724 xtermIndex(xw, 1);
2725 if (xw->flags & LINEFEED)
2726 CarriageReturn(xw);
2727 else
2728 do_xevents(xw);
2729 break;
2730
2731 case CASE_CBT:
2732 TRACE(("CASE_CBT\n"));
2733 /* cursor backward tabulation */
2734 count = one_if_default(0);
2735 while ((count-- > 0)
2736 && (TabToPrevStop(xw))) ;
2737 ResetState(sp);
2738 break;
2739
2740 case CASE_CHT:
2741 TRACE(("CASE_CHT\n"));
2742 /* cursor forward tabulation */
2743 count = one_if_default(0);
2744 while ((count-- > 0)
2745 && (TabToNextStop(xw))) ;
2746 ResetState(sp);
2747 break;
2748
2749 case CASE_TAB:
2750 /* tab */
2751 TabToNextStop(xw);
2752 break;
2753
2754 case CASE_SI:
2755 screen->curgl = 0;
2756 if_OPT_VT52_MODE(screen, {
2757 ResetState(sp);
2758 });
2759 break;
2760
2761 case CASE_SO:
2762 screen->curgl = 1;
2763 if_OPT_VT52_MODE(screen, {
2764 ResetState(sp);
2765 });
2766 break;
2767
2768 case CASE_DECDHL:
2769 xterm_DECDHL(xw, c == '3');
2770 ResetState(sp);
2771 break;
2772
2773 case CASE_DECSWL:
2774 xterm_DECSWL(xw);
2775 ResetState(sp);
2776 break;
2777
2778 case CASE_DECDWL:
2779 xterm_DECDWL(xw);
2780 ResetState(sp);
2781 break;
2782
2783 case CASE_SCR_STATE:
2784 /* enter scr state */
2785 sp->parsestate = scrtable;
2786 break;
2787
2788 case CASE_SCS0_STATE:
2789 /* enter scs state 0 */
2790 select_charset(sp, 0, 94);
2791 break;
2792
2793 case CASE_SCS1_STATE:
2794 /* enter scs state 1 */
2795 select_charset(sp, 1, 94);
2796 break;
2797
2798 case CASE_SCS2_STATE:
2799 /* enter scs state 2 */
2800 select_charset(sp, 2, 94);
2801 break;
2802
2803 case CASE_SCS3_STATE:
2804 /* enter scs state 3 */
2805 select_charset(sp, 3, 94);
2806 break;
2807
2808 case CASE_SCS1A_STATE:
2809 /* enter scs state 1 */
2810 select_charset(sp, 1, 96);
2811 break;
2812
2813 case CASE_SCS2A_STATE:
2814 /* enter scs state 2 */
2815 select_charset(sp, 2, 96);
2816 break;
2817
2818 case CASE_SCS3A_STATE:
2819 /* enter scs state 3 */
2820 select_charset(sp, 3, 96);
2821 break;
2822
2823 case CASE_ESC_IGNORE:
2824 /* unknown escape sequence */
2825 sp->parsestate = eigtable;
2826 break;
2827
2828 case CASE_ESC_DIGIT:
2829 /* digit in csi or dec mode */
2830 if (nparam > 0) {
2831 value = zero_if_default(nparam - 1);
2832 SetParam(nparam - 1, (10 * value) + ((int) c - '0'));
2833 if (GetParam(nparam - 1) > MAX_I_PARAM)
2834 SetParam(nparam - 1, MAX_I_PARAM);
2835 if (sp->parsestate == csi_table)
2836 sp->parsestate = csi2_table;
2837 }
2838 break;
2839
2840 case CASE_ESC_SEMI:
2841 /* semicolon in csi or dec mode */
2842 if (nparam < NPARAM) {
2843 parms.is_sub[nparam] = 0;
2844 SetParam(nparam++, DEFAULT);
2845 }
2846 if (sp->parsestate == csi_table)
2847 sp->parsestate = csi2_table;
2848 break;
2849
2850 /*
2851 * A _few_ commands accept colon-separated subparameters.
2852 * Mark the parameter list so that we can exclude (most) bogus
2853 * commands with simple/fast checks.
2854 */
2855 case CASE_ESC_COLON:
2856 if (nparam < NPARAM) {
2857 parms.has_subparams = 1;
2858 if (nparam == 0) {
2859 parms.is_sub[nparam] = 1;
2860 SetParam(nparam++, DEFAULT);
2861 } else if (parms.is_sub[nparam - 1] == 0) {
2862 parms.is_sub[nparam - 1] = 1;
2863 parms.is_sub[nparam] = 2;
2864 parms.params[nparam] = 0;
2865 ++nparam;
2866 } else {
2867 parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1];
2868 parms.params[nparam] = 0;
2869 ++nparam;
2870 }
2871 }
2872 break;
2873
2874 case CASE_DEC_STATE:
2875 /* enter dec mode */
2876 sp->parsestate = dec_table;
2877 break;
2878
2879 case CASE_DEC2_STATE:
2880 /* enter dec2 mode */
2881 sp->parsestate = dec2_table;
2882 break;
2883
2884 case CASE_DEC3_STATE:
2885 /* enter dec3 mode */
2886 sp->parsestate = dec3_table;
2887 break;
2888
2889 case CASE_ICH:
2890 TRACE(("CASE_ICH - insert char\n"));
2891 InsertChar(xw, (unsigned) one_if_default(0));
2892 ResetState(sp);
2893 break;
2894
2895 case CASE_CUU:
2896 TRACE(("CASE_CUU - cursor up\n"));
2897 CursorUp(screen, one_if_default(0));
2898 ResetState(sp);
2899 break;
2900
2901 case CASE_CUD:
2902 TRACE(("CASE_CUD - cursor down\n"));
2903 CursorDown(screen, one_if_default(0));
2904 ResetState(sp);
2905 break;
2906
2907 case CASE_CUF:
2908 TRACE(("CASE_CUF - cursor forward\n"));
2909 CursorForward(xw, one_if_default(0));
2910 ResetState(sp);
2911 break;
2912
2913 case CASE_CUB:
2914 TRACE(("CASE_CUB - cursor backward\n"));
2915 CursorBack(xw, one_if_default(0));
2916 ResetState(sp);
2917 break;
2918
2919 case CASE_CUP:
2920 TRACE(("CASE_CUP - cursor position\n"));
2921 if_OPT_XMC_GLITCH(screen, {
2922 Jump_XMC(xw);
2923 });
2924 CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags);
2925 ResetState(sp);
2926 break;
2927
2928 case CASE_VPA:
2929 TRACE(("CASE_VPA - vertical position absolute\n"));
2930 CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags);
2931 ResetState(sp);
2932 break;
2933
2934 case CASE_HPA:
2935 TRACE(("CASE_HPA - horizontal position absolute\n"));
2936 CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags);
2937 ResetState(sp);
2938 break;
2939
2940 case CASE_VPR:
2941 TRACE(("CASE_VPR - vertical position relative\n"));
2942 CursorSet(screen,
2943 CursorRow(xw) + one_if_default(0),
2944 CursorCol(xw),
2945 xw->flags);
2946 ResetState(sp);
2947 break;
2948
2949 case CASE_HPR:
2950 TRACE(("CASE_HPR - horizontal position relative\n"));
2951 CursorSet(screen,
2952 CursorRow(xw),
2953 CursorCol(xw) + one_if_default(0),
2954 xw->flags);
2955 ResetState(sp);
2956 break;
2957
2958 case CASE_HP_BUGGY_LL:
2959 TRACE(("CASE_HP_BUGGY_LL\n"));
2960 /* Some HP-UX applications have the bug that they
2961 assume ESC F goes to the lower left corner of
2962 the screen, regardless of what terminfo says. */
2963 if (screen->hp_ll_bc)
2964 CursorSet(screen, screen->max_row, 0, xw->flags);
2965 ResetState(sp);
2966 break;
2967
2968 case CASE_ED:
2969 TRACE(("CASE_ED - erase display\n"));
2970 do_cd_xtra_scroll(xw, zero_if_default(0));
2971 do_erase_display(xw, zero_if_default(0), OFF_PROTECT);
2972 ResetState(sp);
2973 break;
2974
2975 case CASE_EL:
2976 TRACE(("CASE_EL - erase line\n"));
2977 do_erase_line(xw, zero_if_default(0), OFF_PROTECT);
2978 ResetState(sp);
2979 break;
2980
2981 case CASE_ECH:
2982 TRACE(("CASE_ECH - erase char\n"));
2983 /* ECH */
2984 do_erase_char(xw, one_if_default(0), OFF_PROTECT);
2985 ResetState(sp);
2986 break;
2987
2988 case CASE_IL:
2989 TRACE(("CASE_IL - insert line\n"));
2990 InsertLine(xw, one_if_default(0));
2991 ResetState(sp);
2992 break;
2993
2994 case CASE_DL:
2995 TRACE(("CASE_DL - delete line\n"));
2996 DeleteLine(xw, one_if_default(0), True);
2997 ResetState(sp);
2998 break;
2999
3000 case CASE_DCH:
3001 TRACE(("CASE_DCH - delete char\n"));
3002 DeleteChar(xw, (unsigned) one_if_default(0));
3003 ResetState(sp);
3004 break;
3005
3006 case CASE_TRACK_MOUSE:
3007 /*
3008 * A single parameter other than zero is always scroll-down.
3009 * A zero-parameter is used to reset the mouse mode, and is
3010 * not useful for scrolling anyway.
3011 */
3012 if (nparam > 1 || GetParam(0) == 0) {
3013 CELL start;
3014
3015 TRACE(("CASE_TRACK_MOUSE\n"));
3016 /* Track mouse as long as in window and between
3017 * specified rows
3018 */
3019 start.row = one_if_default(2) - 1;
3020 start.col = GetParam(1) - 1;
3021 TrackMouse(xw,
3022 GetParam(0),
3023 &start,
3024 GetParam(3) - 1, GetParam(4) - 2);
3025 } else {
3026 TRACE(("CASE_SD - scroll down\n"));
3027 /* SD */
3028 RevScroll(xw, one_if_default(0));
3029 do_xevents(xw);
3030 }
3031 ResetState(sp);
3032 break;
3033
3034 case CASE_SD:
3035 /*
3036 * Cater to ECMA-48's typographical error...
3037 */
3038 TRACE(("CASE_SD - scroll down\n"));
3039 RevScroll(xw, one_if_default(0));
3040 do_xevents(xw);
3041 ResetState(sp);
3042 break;
3043
3044 case CASE_DECID:
3045 TRACE(("CASE_DECID\n"));
3046 if_OPT_VT52_MODE(screen, {
3047 unparseputc(xw, ANSI_ESC);
3048 unparseputc(xw, '/');
3049 unparseputc(xw, 'Z');
3050 unparse_end(xw);
3051 ResetState(sp);
3052 break;
3053 });
3054 SetParam(0, DEFAULT); /* Default ID parameter */
3055 /* FALLTHRU */
3056 case CASE_DA1:
3057 TRACE(("CASE_DA1\n"));
3058 if (GetParam(0) <= 0) { /* less than means DEFAULT */
3059 count = 0;
3060 init_reply(ANSI_CSI);
3061 reply.a_pintro = '?';
3062
3063 /*
3064 * The first parameter corresponds to the highest operating
3065 * level (i.e., service level) of the emulation. A DEC
3066 * terminal can be setup to respond with a different DA
3067 * response, but there's no control sequence that modifies
3068 * this. We set it via a resource.
3069 */
3070 if (screen->terminal_id < 200) {
3071 switch (screen->terminal_id) {
3072 case 132:
3073 reply.a_param[count++] = 4; /* VT132 */
3074 #if OPT_REGIS_GRAPHICS
3075 reply.a_param[count++] = 6; /* no STP, AVO, GPO (ReGIS) */
3076 #else
3077 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */
3078 #endif
3079 break;
3080 case 131:
3081 reply.a_param[count++] = 7; /* VT131 */
3082 break;
3083 case 125:
3084 reply.a_param[count++] = 12; /* VT125 */
3085 #if OPT_REGIS_GRAPHICS
3086 reply.a_param[count++] = 0 | 2 | 1; /* no STP, AVO, GPO (ReGIS) */
3087 #else
3088 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */
3089 #endif
3090 reply.a_param[count++] = 0; /* no printer */
3091 reply.a_param[count++] = XTERM_PATCH; /* ROM version */
3092 break;
3093 case 102:
3094 reply.a_param[count++] = 6; /* VT102 */
3095 break;
3096 case 101:
3097 reply.a_param[count++] = 1; /* VT101 */
3098 reply.a_param[count++] = 0; /* no options */
3099 break;
3100 default: /* VT100 */
3101 reply.a_param[count++] = 1; /* VT100 */
3102 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */
3103 break;
3104 }
3105 } else {
3106 reply.a_param[count++] = (ParmType) (60
3107 + screen->terminal_id
3108 / 100);
3109 reply.a_param[count++] = 1; /* 132-columns */
3110 reply.a_param[count++] = 2; /* printer */
3111 #if OPT_REGIS_GRAPHICS
3112 if (optRegisGraphics(screen)) {
3113 reply.a_param[count++] = 3; /* ReGIS graphics */
3114 }
3115 #endif
3116 #if OPT_SIXEL_GRAPHICS
3117 if (optSixelGraphics(screen)) {
3118 reply.a_param[count++] = 4; /* sixel graphics */
3119 }
3120 #endif
3121 reply.a_param[count++] = 6; /* selective-erase */
3122 #if OPT_SUNPC_KBD
3123 if (xw->keyboard.type == keyboardIsVT220)
3124 #endif
3125 reply.a_param[count++] = 8; /* user-defined-keys */
3126 reply.a_param[count++] = 9; /* national replacement charsets */
3127 reply.a_param[count++] = 15; /* technical characters */
3128 reply.a_param[count++] = 16; /* locator port */
3129 if (screen->terminal_id >= 400) {
3130 reply.a_param[count++] = 17; /* terminal state interrogation */
3131 reply.a_param[count++] = 18; /* windowing extension */
3132 reply.a_param[count++] = 21; /* horizontal scrolling */
3133 }
3134 if_OPT_ISO_COLORS(screen, {
3135 reply.a_param[count++] = 22; /* ANSI color, VT525 */
3136 });
3137 reply.a_param[count++] = 28; /* rectangular editing */
3138 #if OPT_DEC_LOCATOR
3139 reply.a_param[count++] = 29; /* ANSI text locator */
3140 #endif
3141 }
3142 reply.a_nparam = (ParmType) count;
3143 reply.a_inters = 0;
3144 reply.a_final = 'c';
3145 unparseseq(xw, &reply);
3146 }
3147 ResetState(sp);
3148 break;
3149
3150 case CASE_DA2:
3151 TRACE(("CASE_DA2\n"));
3152 if (GetParam(0) <= 0) { /* less than means DEFAULT */
3153 count = 0;
3154 init_reply(ANSI_CSI);
3155 reply.a_pintro = '>';
3156
3157 if (screen->terminal_id >= 200) {
3158 switch (screen->terminal_id) {
3159 case 220:
3160 default:
3161 reply.a_param[count++] = 1; /* VT220 */
3162 break;
3163 case 240:
3164 case 241:
3165 /* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */
3166 reply.a_param[count++] = 2; /* VT240 */
3167 break;
3168 case 320:
3169 /* http://www.vt100.net/docs/vt320-uu/appendixe.html */
3170 reply.a_param[count++] = 24; /* VT320 */
3171 break;
3172 case 330:
3173 reply.a_param[count++] = 18; /* VT330 */
3174 break;
3175 case 340:
3176 reply.a_param[count++] = 19; /* VT340 */
3177 break;
3178 case 382:
3179 reply.a_param[count++] = 32; /* VT382 */
3180 break;
3181 case 420:
3182 reply.a_param[count++] = 41; /* VT420 */
3183 break;
3184 case 510:
3185 /* http://www.vt100.net/docs/vt510-rm/DA2 */
3186 reply.a_param[count++] = 61; /* VT510 */
3187 break;
3188 case 520:
3189 reply.a_param[count++] = 64; /* VT520 */
3190 break;
3191 case 525:
3192 reply.a_param[count++] = 65; /* VT525 */
3193 break;
3194 }
3195 } else {
3196 reply.a_param[count++] = 0; /* VT100 (nonstandard) */
3197 }
3198 reply.a_param[count++] = XTERM_PATCH; /* Version */
3199 reply.a_param[count++] = 0; /* options (none) */
3200 reply.a_nparam = (ParmType) count;
3201 reply.a_inters = 0;
3202 reply.a_final = 'c';
3203 unparseseq(xw, &reply);
3204 }
3205 ResetState(sp);
3206 break;
3207
3208 case CASE_DECRPTUI:
3209 TRACE(("CASE_DECRPTUI\n"));
3210 if ((screen->vtXX_level >= 4)
3211 && (GetParam(0) <= 0)) { /* less than means DEFAULT */
3212 unparseputc1(xw, ANSI_DCS);
3213 unparseputc(xw, '!');
3214 unparseputc(xw, '|');
3215 /* report the "terminal unit id" as 4 pairs of hexadecimal
3216 * digits -- meaningless for a terminal emulator, but some
3217 * host may care about the format.
3218 */
3219 for (count = 0; count < 8; ++count) {
3220 unparseputc(xw, '0');
3221 }
3222 unparseputc1(xw, ANSI_ST);
3223 unparse_end(xw);
3224 }
3225 ResetState(sp);
3226 break;
3227
3228 case CASE_TBC:
3229 TRACE(("CASE_TBC - tab clear\n"));
3230 if ((value = GetParam(0)) <= 0) /* less than means default */
3231 TabClear(xw->tabs, screen->cur_col);
3232 else if (value == 3)
3233 TabZonk(xw->tabs);
3234 ResetState(sp);
3235 break;
3236
3237 case CASE_SET:
3238 TRACE(("CASE_SET - set mode\n"));
3239 ansi_modes(xw, bitset);
3240 ResetState(sp);
3241 break;
3242
3243 case CASE_RST:
3244 TRACE(("CASE_RST - reset mode\n"));
3245 ansi_modes(xw, bitclr);
3246 ResetState(sp);
3247 break;
3248
3249 case CASE_SGR:
3250 for (item = 0; item < nparam; ++item) {
3251 int op = GetParam(item);
3252 int skip;
3253
3254 if_OPT_XMC_GLITCH(screen, {
3255 Mark_XMC(xw, op);
3256 });
3257 TRACE(("CASE_SGR %d\n", op));
3258
3259 /*
3260 * Only SGR 38/48 accept subparameters, and in those cases
3261 * the values will not be seen at this point.
3262 */
3263 if ((skip = param_has_subparams(item))) {
3264 switch (op) {
3265 case 38:
3266 /* FALLTHRU */
3267 case 48:
3268 if_OPT_ISO_COLORS(screen, {
3269 break;
3270 });
3271 /* FALLTHRU */
3272 default:
3273 TRACE(("...unexpected subparameter in SGR\n"));
3274 item += skip; /* ignore this */
3275 op = NPARAM; /* will never use this, anyway */
3276 break;
3277 }
3278 }
3279
3280 switch (op) {
3281 case DEFAULT:
3282 /* FALLTHRU */
3283 case 0:
3284 resetRendition(xw);
3285 if_OPT_ISO_COLORS(screen, {
3286 reset_SGR_Colors(xw);
3287 });
3288 break;
3289 case 1: /* Bold */
3290 UIntSet(xw->flags, BOLD);
3291 if_OPT_ISO_COLORS(screen, {
3292 setExtendedFG(xw);
3293 });
3294 break;
3295 #if OPT_WIDE_ATTRS
3296 case 2: /* faint, decreased intensity or second colour */
3297 UIntSet(xw->flags, ATR_FAINT);
3298 if_OPT_ISO_COLORS(screen, {
3299 setExtendedFG(xw);
3300 });
3301 break;
3302 case 3: /* italicized */
3303 setItalicFont(xw, UseItalicFont(screen));
3304 UIntSet(xw->flags, ATR_ITALIC);
3305 if_OPT_ISO_COLORS(screen, {
3306 setExtendedFG(xw);
3307 });
3308 break;
3309 #endif
3310 case 4: /* Underscore */
3311 UIntSet(xw->flags, UNDERLINE);
3312 if_OPT_ISO_COLORS(screen, {
3313 setExtendedFG(xw);
3314 });
3315 break;
3316 case 5: /* Blink (less than 150 per minute) */
3317 /* FALLTHRU */
3318 case 6: /* Blink (150 per minute, or more) */
3319 UIntSet(xw->flags, BLINK);
3320 StartBlinking(xw);
3321 if_OPT_ISO_COLORS(screen, {
3322 setExtendedFG(xw);
3323 });
3324 break;
3325 case 7:
3326 UIntSet(xw->flags, INVERSE);
3327 if_OPT_ISO_COLORS(screen, {
3328 setExtendedBG(xw);
3329 });
3330 break;
3331 case 8:
3332 UIntSet(xw->flags, INVISIBLE);
3333 break;
3334 #if OPT_WIDE_ATTRS
3335 case 9: /* crossed-out characters */
3336 UIntSet(xw->flags, ATR_STRIKEOUT);
3337 break;
3338 #endif
3339 #if OPT_WIDE_ATTRS
3340 case 21: /* doubly-underlined */
3341 UIntSet(xw->flags, ATR_DBL_UNDER);
3342 break;
3343 #endif
3344 case 22: /* reset 'bold' */
3345 UIntClr(xw->flags, BOLD);
3346 #if OPT_WIDE_ATTRS
3347 UIntClr(xw->flags, ATR_FAINT);
3348 #endif
3349 if_OPT_ISO_COLORS(screen, {
3350 setExtendedFG(xw);
3351 });
3352 break;
3353 #if OPT_WIDE_ATTRS
3354 case 23: /* not italicized */
3355 ResetItalics(xw);
3356 if_OPT_ISO_COLORS(screen, {
3357 setExtendedFG(xw);
3358 });
3359 break;
3360 #endif
3361 case 24:
3362 UIntClr(xw->flags, UNDERLINE);
3363 #if OPT_WIDE_ATTRS
3364 UIntClr(xw->flags, ATR_DBL_UNDER);
3365 #endif
3366 if_OPT_ISO_COLORS(screen, {
3367 setExtendedFG(xw);
3368 });
3369 break;
3370 case 25: /* reset 'blink' */
3371 UIntClr(xw->flags, BLINK);
3372 if_OPT_ISO_COLORS(screen, {
3373 setExtendedFG(xw);
3374 });
3375 break;
3376 case 27:
3377 UIntClr(xw->flags, INVERSE);
3378 if_OPT_ISO_COLORS(screen, {
3379 setExtendedBG(xw);
3380 });
3381 break;
3382 case 28:
3383 UIntClr(xw->flags, INVISIBLE);
3384 break;
3385 #if OPT_WIDE_ATTRS
3386 case 29: /* not crossed out */
3387 UIntClr(xw->flags, ATR_STRIKEOUT);
3388 break;
3389 #endif
3390 case 30:
3391 /* FALLTHRU */
3392 case 31:
3393 /* FALLTHRU */
3394 case 32:
3395 /* FALLTHRU */
3396 case 33:
3397 /* FALLTHRU */
3398 case 34:
3399 /* FALLTHRU */
3400 case 35:
3401 /* FALLTHRU */
3402 case 36:
3403 /* FALLTHRU */
3404 case 37:
3405 if_OPT_ISO_COLORS(screen, {
3406 xw->sgr_foreground = (op - 30);
3407 xw->sgr_38_xcolors = False;
3408 clrDirectFG(xw->flags);
3409 setExtendedFG(xw);
3410 });
3411 break;
3412 case 38:
3413 /* This is more complicated than I'd like, but it should
3414 * properly eat all the parameters for unsupported modes.
3415 */
3416 if_OPT_ISO_COLORS(screen, {
3417 Boolean extended;
3418 if (parse_extended_colors(xw, &value, &item,
3419 &extended)) {
3420 xw->sgr_foreground = value;
3421 xw->sgr_38_xcolors = True;
3422 setDirectFG(xw->flags, extended);
3423 setExtendedFG(xw);
3424 }
3425 });
3426 break;
3427 case 39:
3428 if_OPT_ISO_COLORS(screen, {
3429 reset_SGR_Foreground(xw);
3430 });
3431 break;
3432 case 40:
3433 /* FALLTHRU */
3434 case 41:
3435 /* FALLTHRU */
3436 case 42:
3437 /* FALLTHRU */
3438 case 43:
3439 /* FALLTHRU */
3440 case 44:
3441 /* FALLTHRU */
3442 case 45:
3443 /* FALLTHRU */
3444 case 46:
3445 /* FALLTHRU */
3446 case 47:
3447 if_OPT_ISO_COLORS(screen, {
3448 xw->sgr_background = (op - 40);
3449 clrDirectBG(xw->flags);
3450 setExtendedBG(xw);
3451 });
3452 break;
3453 case 48:
3454 if_OPT_ISO_COLORS(screen, {
3455 Boolean extended;
3456 if (parse_extended_colors(xw, &value, &item,
3457 &extended)) {
3458 xw->sgr_background = value;
3459 setDirectBG(xw->flags, extended);
3460 setExtendedBG(xw);
3461 }
3462 });
3463 break;
3464 case 49:
3465 if_OPT_ISO_COLORS(screen, {
3466 reset_SGR_Background(xw);
3467 });
3468 break;
3469 case 90:
3470 /* FALLTHRU */
3471 case 91:
3472 /* FALLTHRU */
3473 case 92:
3474 /* FALLTHRU */
3475 case 93:
3476 /* FALLTHRU */
3477 case 94:
3478 /* FALLTHRU */
3479 case 95:
3480 /* FALLTHRU */
3481 case 96:
3482 /* FALLTHRU */
3483 case 97:
3484 if_OPT_AIX_COLORS(screen, {
3485 xw->sgr_foreground = (op - 90 + 8);
3486 clrDirectFG(xw->flags);
3487 setExtendedFG(xw);
3488 });
3489 break;
3490 case 100:
3491 #if !OPT_AIX_COLORS
3492 if_OPT_ISO_COLORS(screen, {
3493 reset_SGR_Foreground(xw);
3494 reset_SGR_Background(xw);
3495 });
3496 break;
3497 #endif
3498 case 101:
3499 /* FALLTHRU */
3500 case 102:
3501 /* FALLTHRU */
3502 case 103:
3503 /* FALLTHRU */
3504 case 104:
3505 /* FALLTHRU */
3506 case 105:
3507 /* FALLTHRU */
3508 case 106:
3509 /* FALLTHRU */
3510 case 107:
3511 if_OPT_AIX_COLORS(screen, {
3512 xw->sgr_background = (op - 100 + 8);
3513 clrDirectBG(xw->flags);
3514 setExtendedBG(xw);
3515 });
3516 break;
3517 default:
3518 /* later: skip += NPARAM; */
3519 break;
3520 }
3521 }
3522 ResetState(sp);
3523 break;
3524
3525 /* DSR (except for the '?') is a superset of CPR */
3526 case CASE_DSR:
3527 sp->private_function = True;
3528
3529 /* FALLTHRU */
3530 case CASE_CPR:
3531 TRACE(("CASE_DSR - device status report\n"));
3532 count = 0;
3533 init_reply(ANSI_CSI);
3534 reply.a_pintro = CharOf(sp->private_function ? '?' : 0);
3535 reply.a_inters = 0;
3536 reply.a_final = 'n';
3537
3538 switch (GetParam(0)) {
3539 case 5:
3540 TRACE(("...request operating status\n"));
3541 /* operating status */
3542 reply.a_param[count++] = 0; /* (no malfunction ;-) */
3543 break;
3544 case 6:
3545 TRACE(("...request %s\n",
3546 (sp->private_function
3547 ? "DECXCPR"
3548 : "CPR")));
3549 /* CPR */
3550 /* DECXCPR (with page=1) */
3551 value = (screen->cur_row + 1);
3552 if ((xw->flags & ORIGIN) != 0) {
3553 value -= screen->top_marg;
3554 }
3555 reply.a_param[count++] = (ParmType) value;
3556
3557 value = (screen->cur_col + 1);
3558 if ((xw->flags & ORIGIN) != 0) {
3559 value -= screen->lft_marg;
3560 }
3561 reply.a_param[count++] = (ParmType) value;
3562
3563 if (sp->private_function
3564 && screen->vtXX_level >= 4) { /* VT420 */
3565 reply.a_param[count++] = 1;
3566 }
3567 reply.a_final = 'R';
3568 break;
3569 case 15:
3570 TRACE(("...request printer status\n"));
3571 if (sp->private_function
3572 && screen->vtXX_level >= 2) { /* VT220 */
3573 reply.a_param[count++] = 13; /* no printer detected */
3574 }
3575 break;
3576 case 25:
3577 TRACE(("...request UDK status\n"));
3578 if (sp->private_function
3579 && screen->vtXX_level >= 2) { /* VT220 */
3580 reply.a_param[count++] = 20; /* UDK always unlocked */
3581 }
3582 break;
3583 case 26:
3584 TRACE(("...request keyboard status\n"));
3585 if (sp->private_function
3586 && screen->vtXX_level >= 2) { /* VT220 */
3587 reply.a_param[count++] = 27;
3588 reply.a_param[count++] = 1; /* North American */
3589 if (screen->vtXX_level >= 3) { /* VT320 */
3590 reply.a_param[count++] = 0; /* ready */
3591 }
3592 if (screen->vtXX_level >= 4) { /* VT420 */
3593 reply.a_param[count++] = 0; /* LK201 */
3594 }
3595 }
3596 break;
3597 case 53: /* according to existing xterm handling */
3598 /* FALLTHRU */
3599 case 55: /* according to the VT330/VT340 Text Programming Manual */
3600 TRACE(("...request locator status\n"));
3601 if (sp->private_function
3602 && screen->vtXX_level >= 3) { /* VT330 */
3603 #if OPT_DEC_LOCATOR
3604 reply.a_param[count++] = 50; /* locator ready */
3605 #else
3606 reply.a_param[count++] = 53; /* no locator */
3607 #endif
3608 }
3609 break;
3610 case 56:
3611 TRACE(("...request locator type\n"));
3612 if (sp->private_function
3613 && screen->vtXX_level >= 3) { /* VT330 */
3614 reply.a_param[count++] = 57;
3615 #if OPT_DEC_LOCATOR
3616 reply.a_param[count++] = 1; /* mouse */
3617 #else
3618 reply.a_param[count++] = 0; /* unknown */
3619 #endif
3620 }
3621 break;
3622 case 62:
3623 TRACE(("...request DECMSR - macro space\n"));
3624 if (sp->private_function
3625 && screen->vtXX_level >= 4) { /* VT420 */
3626 reply.a_pintro = 0;
3627 reply.a_radix[count] = 16; /* no data */
3628 reply.a_param[count++] = 0; /* no space for macros */
3629 reply.a_inters = '*';
3630 reply.a_final = L_CURL;
3631 }
3632 break;
3633 case 63:
3634 TRACE(("...request DECCKSR - memory checksum\n"));
3635 /* DECCKSR - Memory checksum */
3636 if (sp->private_function
3637 && screen->vtXX_level >= 4) { /* VT420 */
3638 init_reply(ANSI_DCS);
3639 reply.a_param[count++] = (ParmType) GetParam(1); /* PID */
3640 reply.a_delim = "!~"; /* delimiter */
3641 reply.a_radix[count] = 16; /* use hex */
3642 reply.a_param[count++] = 0; /* no data */
3643 }
3644 break;
3645 case 75:
3646 TRACE(("...request data integrity\n"));
3647 if (sp->private_function
3648 && screen->vtXX_level >= 4) { /* VT420 */
3649 reply.a_param[count++] = 70; /* no errors */
3650 }
3651 break;
3652 case 85:
3653 TRACE(("...request multi-session configuration\n"));
3654 if (sp->private_function
3655 && screen->vtXX_level >= 4) { /* VT420 */
3656 reply.a_param[count++] = 83; /* not configured */
3657 }
3658 break;
3659 default:
3660 break;
3661 }
3662
3663 if ((reply.a_nparam = (ParmType) count) != 0)
3664 unparseseq(xw, &reply);
3665
3666 ResetState(sp);
3667 sp->private_function = False;
3668 break;
3669
3670 case CASE_MC:
3671 TRACE(("CASE_MC - media control\n"));
3672 xtermMediaControl(xw, GetParam(0), False);
3673 ResetState(sp);
3674 break;
3675
3676 case CASE_DEC_MC:
3677 TRACE(("CASE_DEC_MC - DEC media control\n"));
3678 xtermMediaControl(xw, GetParam(0), True);
3679 ResetState(sp);
3680 break;
3681
3682 case CASE_HP_MEM_LOCK:
3683 /* FALLTHRU */
3684 case CASE_HP_MEM_UNLOCK:
3685 TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK)
3686 ? "CASE_HP_MEM_LOCK"
3687 : "CASE_HP_MEM_UNLOCK")));
3688 if (screen->scroll_amt)
3689 FlushScroll(xw);
3690 if (sp->parsestate[c] == CASE_HP_MEM_LOCK)
3691 set_tb_margins(screen, screen->cur_row, screen->bot_marg);
3692 else
3693 set_tb_margins(screen, 0, screen->bot_marg);
3694 ResetState(sp);
3695 break;
3696
3697 case CASE_DECSTBM:
3698 TRACE(("CASE_DECSTBM - set scrolling region\n"));
3699 {
3700 int top;
3701 int bot;
3702 top = one_if_default(0);
3703 if (nparam < 2 || (bot = GetParam(1)) == DEFAULT
3704 || bot > MaxRows(screen)
3705 || bot == 0)
3706 bot = MaxRows(screen);
3707 if (bot > top) {
3708 if (screen->scroll_amt)
3709 FlushScroll(xw);
3710 set_tb_margins(screen, top - 1, bot - 1);
3711 CursorSet(screen, 0, 0, xw->flags);
3712 }
3713 ResetState(sp);
3714 }
3715 break;
3716
3717 case CASE_DECREQTPARM:
3718 TRACE(("CASE_DECREQTPARM\n"));
3719 if (screen->terminal_id < 200) { /* VT102 */
3720 value = zero_if_default(0);
3721 if (value == 0 || value == 1) {
3722 init_reply(ANSI_CSI);
3723 reply.a_pintro = 0;
3724 reply.a_nparam = 7;
3725 reply.a_param[0] = (ParmType) (value + 2);
3726 reply.a_param[1] = 1; /* no parity */
3727 reply.a_param[2] = 1; /* eight bits */
3728 reply.a_param[3] = 128; /* transmit 38.4k baud */
3729 reply.a_param[4] = 128; /* receive 38.4k baud */
3730 reply.a_param[5] = 1; /* clock multiplier ? */
3731 reply.a_param[6] = 0; /* STP flags ? */
3732 reply.a_inters = 0;
3733 reply.a_final = 'x';
3734 unparseseq(xw, &reply);
3735 }
3736 }
3737 ResetState(sp);
3738 break;
3739
3740 case CASE_DECSET:
3741 /* DECSET */
3742 #if OPT_VT52_MODE
3743 if (screen->vtXX_level != 0)
3744 #endif
3745 dpmodes(xw, bitset);
3746 ResetState(sp);
3747 #if OPT_TEK4014
3748 if (TEK4014_ACTIVE(xw)) {
3749 TRACE(("Tek4014 is now active...\n"));
3750 if (sp->check_recur)
3751 sp->check_recur--;
3752 return False;
3753 }
3754 #endif
3755 break;
3756
3757 case CASE_DECRST:
3758 /* DECRST */
3759 dpmodes(xw, bitclr);
3760 init_groundtable(screen, sp);
3761 ResetState(sp);
3762 break;
3763
3764 case CASE_DECALN:
3765 TRACE(("CASE_DECALN - alignment test\n"));
3766 if (screen->cursor_state)
3767 HideCursor(xw);
3768 /*
3769 * DEC STD 070 (see pages D-19 to D-20) does not mention left/right
3770 * margins. The section is dated March 1985, not updated for the
3771 * VT420 (introduced in 1990).
3772 */
3773 UIntClr(xw->flags, ORIGIN);
3774 screen->do_wrap = False;
3775 resetRendition(xw);
3776 resetMargins(xw);
3777 xterm_ResetDouble(xw);
3778 CursorSet(screen, 0, 0, xw->flags);
3779 xtermParseRect(xw, 0, 0, &myRect);
3780 ScrnFillRectangle(xw, &myRect, 'E', 0, False);
3781 ResetState(sp);
3782 break;
3783
3784 case CASE_GSETS5:
3785 if (screen->vtXX_level >= 5) {
3786 TRACE(("CASE_GSETS5(%d) = '%c'\n", sp->scstype, c));
3787 xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c);
3788 }
3789 ResetState(sp);
3790 break;
3791
3792 case CASE_GSETS3:
3793 if (screen->vtXX_level >= 3) {
3794 TRACE(("CASE_GSETS3(%d) = '%c'\n", sp->scstype, c));
3795 xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c);
3796 }
3797 ResetState(sp);
3798 break;
3799
3800 case CASE_GSETS:
3801 if (strchr("012AB", (int) c) != 0) {
3802 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
3803 xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c);
3804 } else if (screen->vtXX_level >= 2) {
3805 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c));
3806 xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c);
3807 }
3808 ResetState(sp);
3809 break;
3810
3811 case CASE_ANSI_SC:
3812 if (IsLeftRightMode(xw)) {
3813 int left;
3814 int right;
3815
3816 TRACE(("CASE_DECSLRM - set left and right margin\n"));
3817 left = one_if_default(0);
3818 if (nparam < 2 || (right = GetParam(1)) == DEFAULT
3819 || right > MaxCols(screen)
3820 || right == 0)
3821 right = MaxCols(screen);
3822 if (right > left) {
3823 set_lr_margins(screen, left - 1, right - 1);
3824 CursorSet(screen, 0, 0, xw->flags);
3825 }
3826 } else {
3827 TRACE(("CASE_ANSI_SC - save cursor\n"));
3828 CursorSave(xw);
3829 }
3830 ResetState(sp);
3831 break;
3832
3833 case CASE_DECSC:
3834 TRACE(("CASE_DECSC - save cursor\n"));
3835 CursorSave(xw);
3836 ResetState(sp);
3837 break;
3838
3839 case CASE_ANSI_RC:
3840 /* FALLTHRU */
3841 case CASE_DECRC:
3842 TRACE(("CASE_%sRC - restore cursor\n",
3843 (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_"));
3844 CursorRestore(xw);
3845 if_OPT_ISO_COLORS(screen, {
3846 setExtendedFG(xw);
3847 });
3848 ResetState(sp);
3849 break;
3850
3851 case CASE_DECKPAM:
3852 TRACE(("CASE_DECKPAM\n"));
3853 xw->keyboard.flags |= MODE_DECKPAM;
3854 update_appkeypad();
3855 ResetState(sp);
3856 break;
3857
3858 case CASE_DECKPNM:
3859 TRACE(("CASE_DECKPNM\n"));
3860 UIntClr(xw->keyboard.flags, MODE_DECKPAM);
3861 update_appkeypad();
3862 ResetState(sp);
3863 break;
3864
3865 case CASE_CSI_QUOTE_STATE:
3866 sp->parsestate = csi_quo_table;
3867 break;
3868
3869 #if OPT_BLINK_CURS
3870 case CASE_CSI_SPACE_STATE:
3871 sp->parsestate = csi_sp_table;
3872 break;
3873
3874 case CASE_DECSCUSR:
3875 TRACE(("CASE_DECSCUSR\n"));
3876 {
3877 Boolean change = True;
3878 int blinks = screen->cursor_blink_esc;
3879
3880 HideCursor(xw);
3881
3882 switch (GetParam(0)) {
3883 case DEFAULT:
3884 /* FALLTHRU */
3885 case DEFAULT_STYLE:
3886 /* FALLTHRU */
3887 case BLINK_BLOCK:
3888 blinks = True;
3889 screen->cursor_shape = CURSOR_BLOCK;
3890 break;
3891 case STEADY_BLOCK:
3892 blinks = False;
3893 screen->cursor_shape = CURSOR_BLOCK;
3894 break;
3895 case BLINK_UNDERLINE:
3896 blinks = True;
3897 screen->cursor_shape = CURSOR_UNDERLINE;
3898 break;
3899 case STEADY_UNDERLINE:
3900 blinks = False;
3901 screen->cursor_shape = CURSOR_UNDERLINE;
3902 break;
3903 case BLINK_BAR:
3904 blinks = True;
3905 screen->cursor_shape = CURSOR_BAR;
3906 break;
3907 case STEADY_BAR:
3908 blinks = False;
3909 screen->cursor_shape = CURSOR_BAR;
3910 break;
3911 default:
3912 change = False;
3913 break;
3914 }
3915 TRACE(("cursor_shape:%d blinks:%s\n",
3916 screen->cursor_shape, BtoS(blinks)));
3917 if (change) {
3918 xtermSetCursorBox(screen);
3919 if (SettableCursorBlink(screen)) {
3920 screen->cursor_blink_esc = blinks;
3921 UpdateCursorBlink(xw);
3922 }
3923 }
3924 }
3925 ResetState(sp);
3926 break;
3927 #endif
3928
3929 #if OPT_SCROLL_LOCK
3930 case CASE_DECLL:
3931 TRACE(("CASE_DECLL\n"));
3932 if (nparam > 0) {
3933 for (count = 0; count < nparam; ++count) {
3934 int op = zero_if_default(count);
3935 switch (op) {
3936 case 0:
3937 case DEFAULT:
3938 xtermClearLEDs(screen);
3939 break;
3940 case 1:
3941 /* FALLTHRU */
3942 case 2:
3943 /* FALLTHRU */
3944 case 3:
3945 xtermShowLED(screen,
3946 (Cardinal) op,
3947 True);
3948 break;
3949 case 21:
3950 /* FALLTHRU */
3951 case 22:
3952 /* FALLTHRU */
3953 case 23:
3954 xtermShowLED(screen,
3955 (Cardinal) (op - 20),
3956 True);
3957 break;
3958 }
3959 }
3960 } else {
3961 xtermClearLEDs(screen);
3962 }
3963 ResetState(sp);
3964 break;
3965 #endif
3966
3967 #if OPT_VT52_MODE
3968 case CASE_VT52_FINISH:
3969 TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n",
3970 screen->terminal_id,
3971 screen->vtXX_level));
3972 if (screen->terminal_id >= 100
3973 && screen->vtXX_level == 0) {
3974 sp->groundtable =
3975 sp->parsestate = ansi_table;
3976 /*
3977 * On restore, the terminal does not recognize DECRQSS for
3978 * DECSCL (per vttest).
3979 */
3980 screen->vtXX_level = 1;
3981 xw->flags = screen->vt52_save_flags;
3982 screen->curgl = screen->vt52_save_curgl;
3983 screen->curgr = screen->vt52_save_curgr;
3984 screen->curss = screen->vt52_save_curss;
3985 restoreCharsets(screen, screen->vt52_save_gsets);
3986 update_vt52_vt100_settings();
3987 }
3988 break;
3989 #endif
3990
3991 case CASE_ANSI_LEVEL_1:
3992 TRACE(("CASE_ANSI_LEVEL_1\n"));
3993 set_ansi_conformance(screen, 1);
3994 ResetState(sp);
3995 break;
3996
3997 case CASE_ANSI_LEVEL_2:
3998 TRACE(("CASE_ANSI_LEVEL_2\n"));
3999 set_ansi_conformance(screen, 2);
4000 ResetState(sp);
4001 break;
4002
4003 case CASE_ANSI_LEVEL_3:
4004 TRACE(("CASE_ANSI_LEVEL_3\n"));
4005 set_ansi_conformance(screen, 3);
4006 ResetState(sp);
4007 break;
4008
4009 case CASE_DECSCL:
4010 TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1)));
4011 /*
4012 * This changes the emulation level, and is not recognized by
4013 * VT100s. However, a VT220 or above can be set to conformance
4014 * level 1 to act like a VT100.
4015 */
4016 if (screen->terminal_id >= 200) {
4017 /*
4018 * Disallow unrecognized parameters, as well as attempts to set
4019 * the operating level higher than the given terminal-id.
4020 */
4021 if (GetParam(0) >= 61
4022 && GetParam(0) <= 60 + (screen->terminal_id / 100)) {
4023 int new_vtXX_level = GetParam(0) - 60;
4024 int case_value = zero_if_default(1);
4025 /*
4026 * Note:
4027 *
4028 * The VT300, VT420, VT520 manuals claim that DECSCL does a
4029 * hard reset (RIS).
4030 *
4031 * Both the VT220 manual and DEC STD 070 (which documents
4032 * levels 1-4 in detail) state that it is a soft reset.
4033 *
4034 * Perhaps both sets of manuals are right (unlikely).
4035 * Kermit says it's soft.
4036 */
4037 ReallyReset(xw, False, False);
4038 init_parser(xw, sp);
4039 screen->vtXX_level = new_vtXX_level;
4040 if (new_vtXX_level > 1) {
4041 switch (case_value) {
4042 case 1:
4043 show_8bit_control(False);
4044 break;
4045 case 0:
4046 case 2:
4047 show_8bit_control(True);
4048 break;
4049 }
4050 }
4051 }
4052 }
4053 ResetState(sp);
4054 break;
4055
4056 case CASE_DECSCA:
4057 TRACE(("CASE_DECSCA\n"));
4058 screen->protected_mode = DEC_PROTECT;
4059 if (GetParam(0) <= 0 || GetParam(0) == 2) {
4060 UIntClr(xw->flags, PROTECTED);
4061 TRACE(("...clear PROTECTED\n"));
4062 } else if (GetParam(0) == 1) {
4063 xw->flags |= PROTECTED;
4064 TRACE(("...set PROTECTED\n"));
4065 }
4066 ResetState(sp);
4067 break;
4068
4069 case CASE_DECSED:
4070 TRACE(("CASE_DECSED\n"));
4071 do_erase_display(xw, zero_if_default(0), DEC_PROTECT);
4072 ResetState(sp);
4073 break;
4074
4075 case CASE_DECSEL:
4076 TRACE(("CASE_DECSEL\n"));
4077 do_erase_line(xw, zero_if_default(0), DEC_PROTECT);
4078 ResetState(sp);
4079 break;
4080
4081 case CASE_GRAPHICS_ATTRIBUTES:
4082 #if OPT_GRAPHICS
4083 TRACE(("CASE_GRAPHICS_ATTRIBUTES\n"));
4084 {
4085 /* request: item, action, value */
4086 /* reply: item, status, value */
4087 if (nparam != 3) {
4088 TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam));
4089 } else {
4090 int status = 3; /* assume failure */
4091 int result = 0;
4092 int result2 = 0;
4093
4094 TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n",
4095 GetParam(0), GetParam(1), GetParam(2)));
4096 switch (GetParam(0)) {
4097 case 1: /* color register count */
4098 switch (GetParam(1)) {
4099 case 1: /* read */
4100 status = 0; /* success */
4101 result = (int) get_color_register_count(screen);
4102 break;
4103 case 2: /* reset */
4104 screen->numcolorregisters = 0;
4105 status = 0; /* success */
4106 result = (int) get_color_register_count(screen);
4107 break;
4108 case 3: /* set */
4109 if (GetParam(2) > 1 &&
4110 (unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) {
4111 screen->numcolorregisters = GetParam(2);
4112 status = 0; /* success */
4113 result = (int) get_color_register_count(screen);
4114 }
4115 break;
4116 case 4: /* read maximum */
4117 status = 0; /* success */
4118 result = MAX_COLOR_REGISTERS;
4119 break;
4120 default:
4121 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n",
4122 GetParam(1)));
4123 status = 2; /* error in Pa */
4124 break;
4125 }
4126 if (status == 0 && !(optSixelGraphics(screen)
4127 || optRegisGraphics(screen)))
4128 status = 3;
4129 break;
4130 # if OPT_SIXEL_GRAPHICS
4131 case 2: /* graphics geometry */
4132 switch (GetParam(1)) {
4133 case 1: /* read */
4134 TRACE(("Get sixel graphics geometry\n"));
4135 status = 0; /* success */
4136 result = Min(Width(screen), (int) screen->graphics_max_wide);
4137 result2 = Min(Height(screen), (int) screen->graphics_max_high);
4138 break;
4139 case 2: /* reset */
4140 /* FALLTHRU */
4141 case 3: /* set */
4142 break;
4143 case 4: /* read maximum */
4144 status = 0; /* success */
4145 result = screen->graphics_max_wide;
4146 result2 = screen->graphics_max_high;
4147 break;
4148 default:
4149 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n",
4150 GetParam(1)));
4151 status = 2; /* error in Pa */
4152 break;
4153 }
4154 if (status == 0 && !optSixelGraphics(screen))
4155 status = 3;
4156 break;
4157 #endif
4158 # if OPT_REGIS_GRAPHICS
4159 case 3: /* ReGIS geometry */
4160 switch (GetParam(1)) {
4161 case 1: /* read */
4162 status = 0; /* success */
4163 result = screen->graphics_regis_def_wide;
4164 result2 = screen->graphics_regis_def_high;
4165 break;
4166 case 2: /* reset */
4167 /* FALLTHRU */
4168 case 3: /* set */
4169 /* FALLTHRU */
4170 case 4: /* read maximum */
4171 /* not implemented */
4172 break;
4173 default:
4174 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n",
4175 GetParam(1)));
4176 status = 2; /* error in Pa */
4177 break;
4178 }
4179 if (status == 0 && !optRegisGraphics(screen))
4180 status = 3;
4181 break;
4182 #endif
4183 default:
4184 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n",
4185 GetParam(0)));
4186 status = 1;
4187 break;
4188 }
4189
4190 init_reply(ANSI_CSI);
4191 reply.a_pintro = '?';
4192 count = 0;
4193 reply.a_param[count++] = (ParmType) GetParam(0);
4194 reply.a_param[count++] = (ParmType) status;
4195 if (status == 0) {
4196 reply.a_param[count++] = (ParmType) result;
4197 if (GetParam(0) >= 2)
4198 reply.a_param[count++] = (ParmType) result2;
4199 }
4200 reply.a_nparam = (ParmType) count;
4201 reply.a_inters = 0;
4202 reply.a_final = 'S';
4203 unparseseq(xw, &reply);
4204 }
4205 }
4206 #endif
4207 ResetState(sp);
4208 break;
4209
4210 case CASE_ST:
4211 TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n",
4212 (unsigned long) sp->string_used,
4213 sp->string_mode));
4214 ResetState(sp);
4215 if (!sp->string_used)
4216 break;
4217 sp->string_area[--(sp->string_used)] = '\0';
4218 if (sp->check_recur <= 1)
4219 switch (sp->string_mode) {
4220 case ANSI_APC:
4221 /* ignored */
4222 break;
4223 case ANSI_DCS:
4224 do_dcs(xw, sp->string_area, sp->string_used);
4225 break;
4226 case ANSI_OSC:
4227 do_osc(xw, sp->string_area, sp->string_used, ANSI_ST);
4228 break;
4229 case ANSI_PM:
4230 /* ignored */
4231 break;
4232 case ANSI_SOS:
4233 /* ignored */
4234 break;
4235 default:
4236 TRACE(("unknown mode\n"));
4237 break;
4238 }
4239 break;
4240
4241 case CASE_SOS:
4242 TRACE(("CASE_SOS: Start of String\n"));
4243 if (ParseSOS(screen)) {
4244 sp->string_mode = ANSI_SOS;
4245 sp->parsestate = sos_table;
4246 } else {
4247 illegal_parse(xw, c, sp);
4248 }
4249 break;
4250
4251 case CASE_PM:
4252 TRACE(("CASE_PM: Privacy Message\n"));
4253 if (ParseSOS(screen)) {
4254 sp->string_mode = ANSI_PM;
4255 sp->parsestate = sos_table;
4256 } else {
4257 illegal_parse(xw, c, sp);
4258 }
4259 break;
4260
4261 case CASE_DCS:
4262 TRACE(("CASE_DCS: Device Control String\n"));
4263 sp->string_mode = ANSI_DCS;
4264 sp->parsestate = sos_table;
4265 break;
4266
4267 case CASE_APC:
4268 TRACE(("CASE_APC: Application Program Command\n"));
4269 if (ParseSOS(screen)) {
4270 sp->string_mode = ANSI_APC;
4271 sp->parsestate = sos_table;
4272 } else {
4273 illegal_parse(xw, c, sp);
4274 }
4275 break;
4276
4277 case CASE_SPA:
4278 TRACE(("CASE_SPA - start protected area\n"));
4279 screen->protected_mode = ISO_PROTECT;
4280 xw->flags |= PROTECTED;
4281 ResetState(sp);
4282 break;
4283
4284 case CASE_EPA:
4285 TRACE(("CASE_EPA - end protected area\n"));
4286 UIntClr(xw->flags, PROTECTED);
4287 ResetState(sp);
4288 break;
4289
4290 case CASE_SU:
4291 TRACE(("CASE_SU - scroll up\n"));
4292 xtermScroll(xw, one_if_default(0));
4293 ResetState(sp);
4294 break;
4295
4296 case CASE_SL: /* ISO 6429, non-DEC */
4297 TRACE(("CASE_SL - scroll left\n"));
4298 xtermScrollLR(xw, one_if_default(0), True);
4299 ResetState(sp);
4300 break;
4301
4302 case CASE_SR: /* ISO 6429, non-DEC */
4303 TRACE(("CASE_SR - scroll right\n"));
4304 xtermScrollLR(xw, one_if_default(0), False);
4305 ResetState(sp);
4306 break;
4307
4308 case CASE_DECDC:
4309 TRACE(("CASE_DC - delete column\n"));
4310 if (screen->vtXX_level >= 4) {
4311 xtermColScroll(xw, one_if_default(0), True, screen->cur_col);
4312 }
4313 ResetState(sp);
4314 break;
4315
4316 case CASE_DECIC:
4317 TRACE(("CASE_IC - insert column\n"));
4318 if (screen->vtXX_level >= 4) {
4319 xtermColScroll(xw, one_if_default(0), False, screen->cur_col);
4320 }
4321 ResetState(sp);
4322 break;
4323
4324 case CASE_DECBI:
4325 TRACE(("CASE_BI - back index\n"));
4326 if (screen->vtXX_level >= 4) {
4327 xtermColIndex(xw, True);
4328 }
4329 ResetState(sp);
4330 break;
4331
4332 case CASE_DECFI:
4333 TRACE(("CASE_FI - forward index\n"));
4334 if (screen->vtXX_level >= 4) {
4335 xtermColIndex(xw, False);
4336 }
4337 ResetState(sp);
4338 break;
4339
4340 case CASE_IND:
4341 TRACE(("CASE_IND - index\n"));
4342 xtermIndex(xw, 1);
4343 do_xevents(xw);
4344 ResetState(sp);
4345 break;
4346
4347 case CASE_CPL:
4348 TRACE(("CASE_CPL - cursor prev line\n"));
4349 CursorPrevLine(xw, one_if_default(0));
4350 ResetState(sp);
4351 break;
4352
4353 case CASE_CNL:
4354 TRACE(("CASE_CNL - cursor next line\n"));
4355 CursorNextLine(xw, one_if_default(0));
4356 ResetState(sp);
4357 break;
4358
4359 case CASE_NEL:
4360 TRACE(("CASE_NEL\n"));
4361 xtermIndex(xw, 1);
4362 CarriageReturn(xw);
4363 ResetState(sp);
4364 break;
4365
4366 case CASE_HTS:
4367 TRACE(("CASE_HTS - horizontal tab set\n"));
4368 TabSet(xw->tabs, screen->cur_col);
4369 ResetState(sp);
4370 break;
4371
4372 case CASE_REPORT_VERSION:
4373 TRACE(("CASE_REPORT_VERSION - report terminal version\n"));
4374 if (GetParam(0) <= 0) {
4375 unparseputc1(xw, ANSI_DCS);
4376 unparseputc(xw, '>');
4377 unparseputc(xw, '|');
4378 unparseputs(xw, xtermVersion());
4379 unparseputc1(xw, ANSI_ST);
4380 unparse_end(xw);
4381 }
4382 ResetState(sp);
4383 break;
4384
4385 case CASE_RI:
4386 TRACE(("CASE_RI - reverse index\n"));
4387 RevIndex(xw, 1);
4388 ResetState(sp);
4389 break;
4390
4391 case CASE_SS2:
4392 TRACE(("CASE_SS2\n"));
4393 screen->curss = 2;
4394 ResetState(sp);
4395 break;
4396
4397 case CASE_SS3:
4398 TRACE(("CASE_SS3\n"));
4399 screen->curss = 3;
4400 ResetState(sp);
4401 break;
4402
4403 case CASE_CSI_STATE:
4404 /* enter csi state */
4405 InitParams();
4406 SetParam(nparam++, DEFAULT);
4407 sp->parsestate = csi_table;
4408 break;
4409
4410 case CASE_ESC_SP_STATE:
4411 /* esc space */
4412 sp->parsestate = esc_sp_table;
4413 break;
4414
4415 case CASE_CSI_EX_STATE:
4416 /* csi exclamation */
4417 sp->parsestate = csi_ex_table;
4418 break;
4419
4420 case CASE_CSI_TICK_STATE:
4421 /* csi tick (') */
4422 sp->parsestate = csi_tick_table;
4423 break;
4424
4425 #if OPT_DEC_LOCATOR
4426 case CASE_DECEFR:
4427 TRACE(("CASE_DECEFR - Enable Filter Rectangle\n"));
4428 if (okSendMousePos(xw) == DEC_LOCATOR) {
4429 MotionOff(screen, xw);
4430 if ((screen->loc_filter_top = GetParam(0)) < 1)
4431 screen->loc_filter_top = LOC_FILTER_POS;
4432 if (nparam < 2
4433 || (screen->loc_filter_left = GetParam(1)) < 1)
4434 screen->loc_filter_left = LOC_FILTER_POS;
4435 if (nparam < 3
4436 || (screen->loc_filter_bottom = GetParam(2)) < 1)
4437 screen->loc_filter_bottom = LOC_FILTER_POS;
4438 if (nparam < 4
4439 || (screen->loc_filter_right = GetParam(3)) < 1)
4440 screen->loc_filter_right = LOC_FILTER_POS;
4441 InitLocatorFilter(xw);
4442 }
4443 ResetState(sp);
4444 break;
4445
4446 case CASE_DECELR:
4447 MotionOff(screen, xw);
4448 if (GetParam(0) <= 0 || GetParam(0) > 2) {
4449 screen->send_mouse_pos = MOUSE_OFF;
4450 TRACE(("DECELR - Disable Locator Reports\n"));
4451 } else {
4452 TRACE(("DECELR - Enable Locator Reports\n"));
4453 screen->send_mouse_pos = DEC_LOCATOR;
4454 xtermShowPointer(xw, True);
4455 if (GetParam(0) == 2) {
4456 screen->locator_reset = True;
4457 } else {
4458 screen->locator_reset = False;
4459 }
4460 if (nparam < 2 || GetParam(1) != 1) {
4461 screen->locator_pixels = False;
4462 } else {
4463 screen->locator_pixels = True;
4464 }
4465 screen->loc_filter = False;
4466 }
4467 ResetState(sp);
4468 break;
4469
4470 case CASE_DECSLE:
4471 TRACE(("DECSLE - Select Locator Events\n"));
4472 for (count = 0; count < nparam; ++count) {
4473 switch (zero_if_default(count)) {
4474 case 0:
4475 MotionOff(screen, xw);
4476 screen->loc_filter = False;
4477 screen->locator_events = 0;
4478 break;
4479 case 1:
4480 screen->locator_events |= LOC_BTNS_DN;
4481 break;
4482 case 2:
4483 UIntClr(screen->locator_events, LOC_BTNS_DN);
4484 break;
4485 case 3:
4486 screen->locator_events |= LOC_BTNS_UP;
4487 break;
4488 case 4:
4489 UIntClr(screen->locator_events, LOC_BTNS_UP);
4490 break;
4491 }
4492 }
4493 ResetState(sp);
4494 break;
4495
4496 case CASE_DECRQLP:
4497 TRACE(("DECRQLP - Request Locator Position\n"));
4498 if (GetParam(0) < 2) {
4499 /* Issue DECLRP Locator Position Report */
4500 GetLocatorPosition(xw);
4501 }
4502 ResetState(sp);
4503 break;
4504 #endif /* OPT_DEC_LOCATOR */
4505
4506 #if OPT_DEC_RECTOPS
4507 case CASE_CSI_DOLLAR_STATE:
4508 TRACE(("CASE_CSI_DOLLAR_STATE\n"));
4509 /* csi dollar ($) */
4510 if (screen->vtXX_level >= 3)
4511 sp->parsestate = csi_dollar_table;
4512 else
4513 sp->parsestate = eigtable;
4514 break;
4515
4516 case CASE_CSI_STAR_STATE:
4517 TRACE(("CASE_CSI_STAR_STATE\n"));
4518 /* csi star (*) */
4519 if (screen->vtXX_level >= 4)
4520 sp->parsestate = csi_star_table;
4521 else
4522 sp->parsestate = eigtable;
4523 break;
4524
4525 case CASE_DECRQCRA:
4526 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) {
4527 int checksum;
4528 int pid;
4529
4530 TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n"));
4531 xtermCheckRect(xw, ParamPair(0), &checksum);
4532 init_reply(ANSI_DCS);
4533 count = 0;
4534 checksum &= 0xffff;
4535 pid = GetParam(0);
4536 reply.a_param[count++] = (ParmType) pid;
4537 reply.a_delim = "!~"; /* delimiter */
4538 reply.a_radix[count] = 16;
4539 reply.a_param[count++] = (ParmType) checksum;
4540 reply.a_nparam = (ParmType) count;
4541 TRACE(("...checksum(%d) = %04X\n", pid, checksum));
4542 unparseseq(xw, &reply);
4543 }
4544 ResetState(sp);
4545 break;
4546
4547 case CASE_DECCRA:
4548 if (screen->vtXX_level >= 4) {
4549 TRACE(("CASE_DECCRA - Copy rectangular area\n"));
4550 xtermParseRect(xw, ParamPair(0), &myRect);
4551 ScrnCopyRectangle(xw, &myRect, ParamPair(5));
4552 }
4553 ResetState(sp);
4554 break;
4555
4556 case CASE_DECERA:
4557 if (screen->vtXX_level >= 4) {
4558 TRACE(("CASE_DECERA - Erase rectangular area\n"));
4559 xtermParseRect(xw, ParamPair(0), &myRect);
4560 ScrnFillRectangle(xw, &myRect, ' ', xw->flags, True);
4561 }
4562 ResetState(sp);
4563 break;
4564
4565 case CASE_DECFRA:
4566 if (screen->vtXX_level >= 4) {
4567 value = zero_if_default(0);
4568
4569 TRACE(("CASE_DECFRA - Fill rectangular area\n"));
4570 if (nparam > 0 && CharWidth(screen, value) > 0) {
4571 xtermParseRect(xw, ParamPair(1), &myRect);
4572 ScrnFillRectangle(xw, &myRect, value, xw->flags, True);
4573 }
4574 }
4575 ResetState(sp);
4576 break;
4577
4578 case CASE_DECSERA:
4579 if (screen->vtXX_level >= 4) {
4580 TRACE(("CASE_DECSERA - Selective erase rectangular area\n"));
4581 xtermParseRect(xw, ParamPair(0), &myRect);
4582 ScrnWipeRectangle(xw, &myRect);
4583 }
4584 ResetState(sp);
4585 break;
4586
4587 case CASE_DECSACE:
4588 TRACE(("CASE_DECSACE - Select attribute change extent\n"));
4589 screen->cur_decsace = zero_if_default(0);
4590 ResetState(sp);
4591 break;
4592
4593 case CASE_DECCARA:
4594 if (screen->vtXX_level >= 4) {
4595 TRACE(("CASE_DECCARA - Change attributes in rectangular area\n"));
4596 xtermParseRect(xw, ParamPair(0), &myRect);
4597 ScrnMarkRectangle(xw, &myRect, False, ParamPair(4));
4598 }
4599 ResetState(sp);
4600 break;
4601
4602 case CASE_DECRARA:
4603 if (screen->vtXX_level >= 4) {
4604 TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n"));
4605 xtermParseRect(xw, ParamPair(0), &myRect);
4606 ScrnMarkRectangle(xw, &myRect, True, ParamPair(4));
4607 }
4608 ResetState(sp);
4609 break;
4610
4611 case CASE_DECSCPP:
4612 if (screen->vtXX_level >= 3) {
4613 TRACE(("CASE_DECSCPP\n"));
4614 /* default and 0 are "80", with "132" as the other legal choice */
4615 switch (zero_if_default(0)) {
4616 case 0:
4617 case 80:
4618 value = 80;
4619 break;
4620 case 132:
4621 value = 132;
4622 break;
4623 default:
4624 value = -1;
4625 break;
4626 }
4627 if (value > 0) {
4628 if (screen->cur_col + 1 > value)
4629 CursorSet(screen, screen->cur_row, value - 1, xw->flags);
4630 UIntClr(xw->flags, IN132COLUMNS);
4631 if (value == 132)
4632 UIntSet(xw->flags, IN132COLUMNS);
4633 RequestResize(xw, -1, value, True);
4634 }
4635 }
4636 ResetState(sp);
4637 break;
4638
4639 case CASE_DECSNLS:
4640 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetWinLines)) {
4641 TRACE(("CASE_DECSNLS\n"));
4642 value = zero_if_default(0);
4643 if (value >= 1 && value <= 255) {
4644 RequestResize(xw, value, -1, True);
4645 }
4646 }
4647 ResetState(sp);
4648 break;
4649
4650 case CASE_DECRQPSR:
4651 #define reply_char(n,c) do { reply.a_radix[(n)] = 1; reply.a_param[(n)++] = (ParmType)(c); } while (0)
4652 #define reply_bit(n,c) ((n) ? (c) : 0)
4653 if (screen->vtXX_level >= 3) {
4654 TRACE(("CASE_DECRQPSR\n"));
4655 switch (GetParam(0)) {
4656 case 1:
4657 TRACE(("...DECCIR\n"));
4658 init_reply(ANSI_DCS);
4659 count = 0;
4660 reply_char(count, '1');
4661 reply_char(count, '$');
4662 reply_char(count, 'u');
4663 reply.a_param[count++] = (ParmType) (screen->cur_row + 1);
4664 reply.a_param[count++] = (ParmType) (screen->cur_col + 1);
4665 reply.a_param[count++] = (ParmType) thispage;
4666 reply_char(count, ';');
4667 reply_char(count, (0x40
4668 | reply_bit(xw->flags & INVERSE, 8)
4669 | reply_bit(xw->flags & BLINK, 4)
4670 | reply_bit(xw->flags & UNDERLINE, 2)
4671 | reply_bit(xw->flags & BOLD, 1)
4672 ));
4673 reply_char(count, ';');
4674 reply_char(count, 0x40 |
4675 reply_bit(screen->protected_mode &
4676 DEC_PROTECT, 1)
4677 );
4678 reply_char(count, ';');
4679 reply_char(count, (0x40
4680 | reply_bit(screen->do_wrap, 8)
4681 | reply_bit((screen->curss == 3), 4)
4682 | reply_bit((screen->curss == 2), 2)
4683 | reply_bit(xw->flags & ORIGIN, 1)
4684 ));
4685 reply_char(count, ';');
4686 reply.a_param[count++] = screen->curgl;
4687 reply.a_param[count++] = screen->curgr;
4688 reply_char(count, ';');
4689 reply_char(count, 0x4f); /* assert all 96's */
4690 reply_char(count, ';');
4691 for (item = 0; item < NUM_GSETS; ++item) {
4692 char *temp = encode_scs(screen->gsets[item]);
4693 while (*temp != '\0') {
4694 reply_char(count, *temp++);
4695 }
4696 }
4697 reply.a_nparam = (ParmType) count;
4698 unparseseq(xw, &reply);
4699 break;
4700 case 2:
4701 TRACE(("...DECTABSR\n"));
4702 init_reply(ANSI_DCS);
4703 reply.a_delim = "/";
4704 count = 0;
4705 reply_char(count, '2');
4706 reply_char(count, '$');
4707 reply_char(count, 'u');
4708 for (item = 0; item < MAX_TABS; ++item) {
4709 if (count + 1 >= NPARAM)
4710 break;
4711 if (TabIsSet(xw->tabs, item)) {
4712 reply.a_param[count++] = (ParmType) (item + 1);
4713 }
4714 if (item > screen->max_col)
4715 break;
4716 }
4717 reply.a_nparam = (ParmType) count;
4718 unparseseq(xw, &reply);
4719 break;
4720 }
4721 }
4722 ResetState(sp);
4723 break;
4724
4725 case CASE_RQM:
4726 TRACE(("CASE_RQM\n"));
4727 do_ansi_rqm(xw, ParamPair(0));
4728 ResetState(sp);
4729 break;
4730
4731 case CASE_DECRQM:
4732 TRACE(("CASE_DECRQM\n"));
4733 do_dec_rqm(xw, ParamPair(0));
4734 ResetState(sp);
4735 break;
4736
4737 case CASE_CSI_DEC_DOLLAR_STATE:
4738 TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n"));
4739 /* csi ? dollar ($) */
4740 sp->parsestate = csi_dec_dollar_table;
4741 break;
4742 #else
4743 case CASE_CSI_DOLLAR_STATE:
4744 /* csi dollar ($) */
4745 sp->parsestate = eigtable;
4746 break;
4747
4748 case CASE_CSI_STAR_STATE:
4749 /* csi dollar (*) */
4750 sp->parsestate = eigtable;
4751 break;
4752
4753 case CASE_CSI_DEC_DOLLAR_STATE:
4754 /* csi ? dollar ($) */
4755 sp->parsestate = eigtable;
4756 break;
4757 #endif /* OPT_DEC_RECTOPS */
4758
4759 #if OPT_XTERM_SGR
4760 case CASE_CSI_HASH_STATE:
4761 TRACE(("CASE_CSI_HASH_STATE\n"));
4762 /* csi hash (#) */
4763 sp->parsestate = csi_hash_table;
4764 break;
4765
4766 case CASE_XTERM_CHECKSUM:
4767 #if OPT_DEC_RECTOPS
4768 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) {
4769 TRACE(("CASE_XTERM_CHECKSUM\n"));
4770 screen->checksum_ext = zero_if_default(0);
4771 }
4772 #endif
4773 ResetState(sp);
4774 break;
4775
4776 case CASE_XTERM_PUSH_SGR:
4777 TRACE(("CASE_XTERM_PUSH_SGR\n"));
4778 value = 0;
4779 if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) {
4780 value = DEFAULT;
4781 } else if (nparam > 0) {
4782 for (count = 0; count < nparam; ++count) {
4783 item = zero_if_default(count);
4784 /* deprecated - for compatibility */
4785 #if OPT_ISO_COLORS
4786 if (item == psFG_COLOR_obs) {
4787 item = psFG_COLOR;
4788 } else if (item == psBG_COLOR_obs) {
4789 item = psBG_COLOR;
4790 }
4791 #endif
4792 if (item > 0 && item < MAX_PUSH_SGR) {
4793 value |= (1 << (item - 1));
4794 }
4795 }
4796 }
4797 xtermPushSGR(xw, value);
4798 ResetState(sp);
4799 break;
4800
4801 case CASE_XTERM_REPORT_SGR:
4802 TRACE(("CASE_XTERM_REPORT_SGR\n"));
4803 xtermParseRect(xw, ParamPair(0), &myRect);
4804 xtermReportSGR(xw, &myRect);
4805 ResetState(sp);
4806 break;
4807
4808 case CASE_XTERM_POP_SGR:
4809 TRACE(("CASE_XTERM_POP_SGR\n"));
4810 xtermPopSGR(xw);
4811 ResetState(sp);
4812 break;
4813
4814 case CASE_XTERM_PUSH_COLORS:
4815 TRACE(("CASE_XTERM_PUSH_COLORS\n"));
4816 if (nparam == 0) {
4817 xtermPushColors(xw, DEFAULT);
4818 } else {
4819 for (count = 0; count < nparam; ++count) {
4820 xtermPushColors(xw, GetParam(count));
4821 }
4822 }
4823 ResetState(sp);
4824 break;
4825
4826 case CASE_XTERM_POP_COLORS:
4827 TRACE(("CASE_XTERM_POP_COLORS\n"));
4828 if (nparam == 0) {
4829 xtermPopColors(xw, DEFAULT);
4830 } else {
4831 for (count = 0; count < nparam; ++count) {
4832 xtermPopColors(xw, GetParam(count));
4833 }
4834 }
4835 ResetState(sp);
4836 break;
4837
4838 case CASE_XTERM_REPORT_COLORS:
4839 TRACE(("CASE_XTERM_REPORT_COLORS\n"));
4840 xtermReportColors(xw);
4841 ResetState(sp);
4842 break;
4843 #endif
4844
4845 case CASE_S7C1T:
4846 TRACE(("CASE_S7C1T\n"));
4847 if (screen->vtXX_level >= 2) {
4848 show_8bit_control(False);
4849 ResetState(sp);
4850 }
4851 break;
4852
4853 case CASE_S8C1T:
4854 TRACE(("CASE_S8C1T\n"));
4855 if (screen->vtXX_level >= 2) {
4856 show_8bit_control(True);
4857 ResetState(sp);
4858 }
4859 break;
4860
4861 case CASE_OSC:
4862 TRACE(("CASE_OSC: Operating System Command\n"));
4863 sp->parsestate = sos_table;
4864 sp->string_mode = ANSI_OSC;
4865 break;
4866
4867 case CASE_RIS:
4868 TRACE(("CASE_RIS\n"));
4869 VTReset(xw, True, True);
4870 /* NOTREACHED */
4871
4872 case CASE_DECSTR:
4873 TRACE(("CASE_DECSTR\n"));
4874 VTReset(xw, False, False);
4875 /* NOTREACHED */
4876
4877 case CASE_REP:
4878 TRACE(("CASE_REP\n"));
4879 if (CharWidth(screen, sp->lastchar) > 0) {
4880 IChar repeated[2];
4881 count = one_if_default(0);
4882 repeated[0] = (IChar) sp->lastchar;
4883 while (count-- > 0) {
4884 dotext(xw,
4885 screen->gsets[(int) (screen->curgl)],
4886 repeated, 1);
4887 }
4888 }
4889 ResetState(sp);
4890 break;
4891
4892 case CASE_LS2:
4893 TRACE(("CASE_LS2\n"));
4894 screen->curgl = 2;
4895 ResetState(sp);
4896 break;
4897
4898 case CASE_LS3:
4899 TRACE(("CASE_LS3\n"));
4900 screen->curgl = 3;
4901 ResetState(sp);
4902 break;
4903
4904 case CASE_LS3R:
4905 TRACE(("CASE_LS3R\n"));
4906 screen->curgr = 3;
4907 ResetState(sp);
4908 break;
4909
4910 case CASE_LS2R:
4911 TRACE(("CASE_LS2R\n"));
4912 screen->curgr = 2;
4913 ResetState(sp);
4914 break;
4915
4916 case CASE_LS1R:
4917 TRACE(("CASE_LS1R\n"));
4918 screen->curgr = 1;
4919 ResetState(sp);
4920 break;
4921
4922 case CASE_XTERM_SAVE:
4923 savemodes(xw);
4924 ResetState(sp);
4925 break;
4926
4927 case CASE_XTERM_RESTORE:
4928 restoremodes(xw);
4929 ResetState(sp);
4930 break;
4931
4932 case CASE_XTERM_WINOPS:
4933 TRACE(("CASE_XTERM_WINOPS\n"));
4934 window_ops(xw);
4935 ResetState(sp);
4936 break;
4937 #if OPT_WIDE_CHARS
4938 case CASE_ESC_PERCENT:
4939 TRACE(("CASE_ESC_PERCENT\n"));
4940 sp->parsestate = esc_pct_table;
4941 break;
4942
4943 case CASE_UTF8:
4944 /* If we did not set UTF-8 mode from resource or the
4945 * command-line, allow it to be enabled/disabled by
4946 * control sequence.
4947 */
4948 TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n",
4949 screen->wide_chars,
4950 screen->utf8_mode,
4951 BtoS(c == 'G')));
4952 if ((!screen->wide_chars) && (c == 'G')) {
4953 WriteNow();
4954 ChangeToWide(xw);
4955 }
4956 if (screen->wide_chars
4957 && !screen->utf8_always) {
4958 switchPtyData(screen, c == 'G');
4959 TRACE(("UTF8 mode %s\n",
4960 BtoS(screen->utf8_mode)));
4961 } else {
4962 TRACE(("UTF8 mode NOT turned %s (%s)\n",
4963 BtoS(c == 'G'),
4964 (screen->utf8_mode == uAlways)
4965 ? "UTF-8 mode set from command-line"
4966 : "wideChars resource was not set"));
4967 }
4968 ResetState(sp);
4969 break;
4970
4971 case CASE_SCS_DQUOTE:
4972 TRACE(("CASE_SCS_DQUOTE\n"));
4973 sp->parsestate = scs_2qt_table;
4974 break;
4975
4976 case CASE_GSETS_DQUOTE:
4977 if (screen->vtXX_level >= 5) {
4978 TRACE(("CASE_GSETS_DQUOTE(%d) = '%c'\n", sp->scstype, c));
4979 xtermDecodeSCS(xw, sp->scstype, 5, '"', (int) c);
4980 }
4981 ResetState(sp);
4982 break;
4983
4984 case CASE_SCS_AMPRSND:
4985 TRACE(("CASE_SCS_AMPRSND\n"));
4986 sp->parsestate = scs_amp_table;
4987 break;
4988
4989 case CASE_GSETS_AMPRSND:
4990 if (screen->vtXX_level >= 5) {
4991 TRACE(("CASE_GSETS_AMPRSND(%d) = '%c'\n", sp->scstype, c));
4992 xtermDecodeSCS(xw, sp->scstype, 5, '&', (int) c);
4993 }
4994 ResetState(sp);
4995 break;
4996
4997 case CASE_SCS_PERCENT:
4998 TRACE(("CASE_SCS_PERCENT\n"));
4999 sp->parsestate = scs_pct_table;
5000 break;
5001
5002 case CASE_GSETS_PERCENT:
5003 if (screen->vtXX_level >= 3) {
5004 TRACE(("CASE_GSETS_PERCENT(%d) = '%c'\n", sp->scstype, c));
5005 switch (c) {
5006 case '0': /* DEC Turkish */
5007 case '2': /* Turkish */
5008 case '=': /* Hebrew */
5009 value = 5;
5010 break;
5011 case '5': /* DEC Supplemental Graphics */
5012 case '6': /* Portuguese */
5013 default:
5014 value = 3;
5015 break;
5016 }
5017 xtermDecodeSCS(xw, sp->scstype, value, '%', (int) c);
5018 }
5019 ResetState(sp);
5020 break;
5021 #endif
5022 case CASE_XTERM_SHIFT_ESCAPE:
5023 TRACE(("CASE_XTERM_SHIFT_ESCAPE\n"));
5024 value = ((nparam == 0)
5025 ? 0
5026 : one_if_default(0));
5027 if (value >= 0 && value <= 1)
5028 xw->keyboard.shift_escape = value;
5029 ResetState(sp);
5030 break;
5031
5032 #if OPT_MOD_FKEYS
5033 case CASE_SET_MOD_FKEYS:
5034 TRACE(("CASE_SET_MOD_FKEYS\n"));
5035 if (nparam >= 1) {
5036 set_mod_fkeys(xw,
5037 GetParam(0),
5038 ((nparam > 1)
5039 ? GetParam(1)
5040 : DEFAULT),
5041 True);
5042 } else {
5043 for (value = 1; value <= 5; ++value)
5044 set_mod_fkeys(xw, value, DEFAULT, True);
5045 }
5046 ResetState(sp);
5047 break;
5048
5049 case CASE_SET_MOD_FKEYS0:
5050 TRACE(("CASE_SET_MOD_FKEYS0\n"));
5051 if (nparam >= 1 && GetParam(0) != DEFAULT) {
5052 set_mod_fkeys(xw, GetParam(0), -1, False);
5053 } else {
5054 xw->keyboard.modify_now.function_keys = -1;
5055 }
5056 ResetState(sp);
5057 break;
5058 #endif
5059 case CASE_HIDE_POINTER:
5060 TRACE(("CASE_HIDE_POINTER\n"));
5061 if (nparam >= 1 && GetParam(0) != DEFAULT) {
5062 screen->pointer_mode = GetParam(0);
5063 } else {
5064 screen->pointer_mode = DEF_POINTER_MODE;
5065 }
5066 ResetState(sp);
5067 break;
5068
5069 case CASE_XTERM_SM_TITLE:
5070 TRACE(("CASE_XTERM_SM_TITLE\n"));
5071 if (nparam >= 1) {
5072 int n;
5073 for (n = 0; n < nparam; ++n) {
5074 if (GetParam(n) != DEFAULT)
5075 screen->title_modes |= (1 << GetParam(n));
5076 }
5077 } else {
5078 screen->title_modes = DEF_TITLE_MODES;
5079 }
5080 TRACE(("...title_modes %#x\n", screen->title_modes));
5081 ResetState(sp);
5082 break;
5083
5084 case CASE_XTERM_RM_TITLE:
5085 TRACE(("CASE_XTERM_RM_TITLE\n"));
5086 if (nparam >= 1) {
5087 int n;
5088 for (n = 0; n < nparam; ++n) {
5089 if (GetParam(n) != DEFAULT)
5090 screen->title_modes &= ~(1 << GetParam(n));
5091 }
5092 } else {
5093 screen->title_modes = DEF_TITLE_MODES;
5094 }
5095 TRACE(("...title_modes %#x\n", screen->title_modes));
5096 ResetState(sp);
5097 break;
5098
5099 case CASE_CSI_IGNORE:
5100 sp->parsestate = cigtable;
5101 break;
5102
5103 case CASE_DECSWBV:
5104 TRACE(("CASE_DECSWBV\n"));
5105 switch (zero_if_default(0)) {
5106 case 2:
5107 /* FALLTHRU */
5108 case 3:
5109 /* FALLTHRU */
5110 case 4:
5111 screen->warningVolume = bvLow;
5112 break;
5113 case 5:
5114 /* FALLTHRU */
5115 case 6:
5116 /* FALLTHRU */
5117 case 7:
5118 /* FALLTHRU */
5119 case 8:
5120 screen->warningVolume = bvHigh;
5121 break;
5122 default:
5123 screen->warningVolume = bvOff;
5124 break;
5125 }
5126 TRACE(("...warningVolume %d\n", screen->warningVolume));
5127 ResetState(sp);
5128 break;
5129
5130 case CASE_DECSMBV:
5131 TRACE(("CASE_DECSMBV\n"));
5132 switch (zero_if_default(0)) {
5133 case 2:
5134 /* FALLTHRU */
5135 case 3:
5136 /* FALLTHRU */
5137 case 4:
5138 screen->marginVolume = bvLow;
5139 break;
5140 case 0:
5141 /* FALLTHRU */
5142 case 5:
5143 /* FALLTHRU */
5144 case 6:
5145 /* FALLTHRU */
5146 case 7:
5147 /* FALLTHRU */
5148 case 8:
5149 screen->marginVolume = bvHigh;
5150 break;
5151 default:
5152 screen->marginVolume = bvOff;
5153 break;
5154 }
5155 TRACE(("...marginVolume %d\n", screen->marginVolume));
5156 ResetState(sp);
5157 break;
5158 }
5159 if (sp->parsestate == sp->groundtable)
5160 sp->lastchar = thischar;
5161 } while (0);
5162
5163 #if OPT_WIDE_CHARS
5164 screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse)
5165 && (sp->parsestate != sos_table));
5166 #endif
5167
5168 if (sp->check_recur)
5169 sp->check_recur--;
5170 return True;
5171 }
5172
5173 static void
VTparse(XtermWidget xw)5174 VTparse(XtermWidget xw)
5175 {
5176 Boolean keep_running;
5177
5178 /* We longjmp back to this point in VTReset() */
5179 (void) setjmp(vtjmpbuf);
5180 init_parser(xw, &myState);
5181
5182 do {
5183 keep_running = doparsing(xw, doinput(xw), &myState);
5184 if (myState.check_recur == 0 && myState.defer_used != 0) {
5185 while (myState.defer_used) {
5186 Char *deferred = myState.defer_area;
5187 size_t len = myState.defer_used;
5188 size_t i;
5189 myState.defer_area = NULL;
5190 myState.defer_size = 0;
5191 myState.defer_used = 0;
5192 for (i = 0; i < len; i++) {
5193 (void) doparsing(xw, deferred[i], &myState);
5194 }
5195 free(deferred);
5196 }
5197 } else {
5198 free(myState.defer_area);
5199 }
5200 myState.defer_area = NULL;
5201 myState.defer_size = 0;
5202 myState.defer_used = 0;
5203 } while (keep_running);
5204 }
5205
5206 static Char *v_buffer; /* pointer to physical buffer */
5207 static Char *v_bufstr = NULL; /* beginning of area to write */
5208 static Char *v_bufptr; /* end of area to write */
5209 static Char *v_bufend; /* end of physical buffer */
5210
5211 /* Write data to the pty as typed by the user, pasted with the mouse,
5212 or generated by us in response to a query ESC sequence. */
5213
5214 void
v_write(int f,const Char * data,unsigned len)5215 v_write(int f, const Char *data, unsigned len)
5216 {
5217 TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len)));
5218 if (v_bufstr == NULL) {
5219 if (len > 0) {
5220 v_buffer = (Char *) XtMalloc((Cardinal) len);
5221 v_bufstr = v_buffer;
5222 v_bufptr = v_buffer;
5223 v_bufend = v_buffer + len;
5224 }
5225 if (v_bufstr == NULL) {
5226 return;
5227 }
5228 }
5229 if_DEBUG({
5230 fprintf(stderr, "v_write called with %u bytes (%ld left over)",
5231 len, (long) (v_bufptr - v_bufstr));
5232 if (len > 1 && len < 10)
5233 fprintf(stderr, " \"%.*s\"", len, (const char *) data);
5234 fprintf(stderr, "\n");
5235 });
5236
5237 #ifdef VMS
5238 if ((1 << f) != pty_mask) {
5239 tt_write((const char *) data, len);
5240 return;
5241 }
5242 #else /* VMS */
5243 if (!FD_ISSET(f, &pty_mask)) {
5244 IGNORE_RC(write(f, (const char *) data, (size_t) len));
5245 return;
5246 }
5247 #endif /* VMS */
5248
5249 /*
5250 * Append to the block we already have.
5251 * Always doing this simplifies the code, and
5252 * isn't too bad, either. If this is a short
5253 * block, it isn't too expensive, and if this is
5254 * a long block, we won't be able to write it all
5255 * anyway.
5256 */
5257
5258 if (len > 0) {
5259 #if OPT_DABBREV
5260 TScreenOf(term)->dabbrev_working = False; /* break dabbrev sequence */
5261 #endif
5262 if (v_bufend < v_bufptr + len) { /* we've run out of room */
5263 if (v_bufstr != v_buffer) {
5264 /* there is unused space, move everything down */
5265 /* possibly overlapping memmove here */
5266 if_DEBUG({
5267 fprintf(stderr, "moving data down %ld\n",
5268 (long) (v_bufstr - v_buffer));
5269 });
5270 memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr));
5271 v_bufptr -= v_bufstr - v_buffer;
5272 v_bufstr = v_buffer;
5273 }
5274 if (v_bufend < v_bufptr + len) {
5275 /* still won't fit: get more space */
5276 /* Don't use XtRealloc because an error is not fatal. */
5277 unsigned size = (unsigned) (v_bufptr - v_buffer);
5278 v_buffer = TypeRealloc(Char, size + len, v_buffer);
5279 if (v_buffer) {
5280 if_DEBUG({
5281 fprintf(stderr, "expanded buffer to %u\n",
5282 size + len);
5283 });
5284 v_bufstr = v_buffer;
5285 v_bufptr = v_buffer + size;
5286 v_bufend = v_bufptr + len;
5287 } else {
5288 /* no memory: ignore entire write request */
5289 xtermWarning("cannot allocate buffer space\n");
5290 v_buffer = v_bufstr; /* restore clobbered pointer */
5291 }
5292 }
5293 }
5294 if (v_bufend >= v_bufptr + len) {
5295 /* new stuff will fit */
5296 memmove(v_bufptr, data, (size_t) len);
5297 v_bufptr += len;
5298 }
5299 }
5300
5301 /*
5302 * Write out as much of the buffer as we can.
5303 * Be careful not to overflow the pty's input silo.
5304 * We are conservative here and only write
5305 * a small amount at a time.
5306 *
5307 * If we can't push all the data into the pty yet, we expect write
5308 * to return a non-negative number less than the length requested
5309 * (if some data written) or -1 and set errno to EAGAIN,
5310 * EWOULDBLOCK, or EINTR (if no data written).
5311 *
5312 * (Not all systems do this, sigh, so the code is actually
5313 * a little more forgiving.)
5314 */
5315
5316 #define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */
5317
5318 if (v_bufptr > v_bufstr) {
5319 int riten;
5320
5321 #ifdef VMS
5322 riten = tt_write(v_bufstr,
5323 ((v_bufptr - v_bufstr <= VMS_TERM_BUFFER_SIZE)
5324 ? v_bufptr - v_bufstr
5325 : VMS_TERM_BUFFER_SIZE));
5326 if (riten == 0)
5327 return (riten);
5328 #else /* VMS */
5329 riten = (int) write(f, v_bufstr,
5330 (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE)
5331 ? v_bufptr - v_bufstr
5332 : MAX_PTY_WRITE));
5333 if (riten < 0)
5334 #endif /* VMS */
5335 {
5336 if_DEBUG({
5337 perror("write");
5338 });
5339 riten = 0;
5340 }
5341 if_DEBUG({
5342 fprintf(stderr, "write called with %ld, wrote %d\n",
5343 ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE)
5344 ? (long) (v_bufptr - v_bufstr)
5345 : MAX_PTY_WRITE),
5346 riten);
5347 });
5348 v_bufstr += riten;
5349 if (v_bufstr >= v_bufptr) /* we wrote it all */
5350 v_bufstr = v_bufptr = v_buffer;
5351 }
5352
5353 /*
5354 * If we have lots of unused memory allocated, return it
5355 */
5356 if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */
5357 /* save pointers across realloc */
5358 int start = (int) (v_bufstr - v_buffer);
5359 int size = (int) (v_bufptr - v_buffer);
5360 unsigned allocsize = (unsigned) (size ? size : 1);
5361
5362 v_buffer = TypeRealloc(Char, allocsize, v_buffer);
5363 if (v_buffer) {
5364 v_bufstr = v_buffer + start;
5365 v_bufptr = v_buffer + size;
5366 v_bufend = v_buffer + allocsize;
5367 if_DEBUG({
5368 fprintf(stderr, "shrunk buffer to %u\n", allocsize);
5369 });
5370 } else {
5371 /* should we print a warning if couldn't return memory? */
5372 v_buffer = v_bufstr - start; /* restore clobbered pointer */
5373 }
5374 }
5375 }
5376
5377 static void
updateCursor(XtermWidget xw)5378 updateCursor(XtermWidget xw)
5379 {
5380 TScreen *screen = TScreenOf(xw);
5381
5382 if (screen->cursor_set != screen->cursor_state) {
5383 if (screen->cursor_set)
5384 ShowCursor(xw);
5385 else
5386 HideCursor(xw);
5387 }
5388 }
5389
5390 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
5391 static void
reallyStopBlinking(XtermWidget xw)5392 reallyStopBlinking(XtermWidget xw)
5393 {
5394 TScreen *screen = TScreenOf(xw);
5395
5396 if (screen->cursor_state == BLINKED_OFF) {
5397 /* force cursor to display if it is enabled */
5398 screen->cursor_state = !screen->cursor_set;
5399 updateCursor(xw);
5400 xevents(xw);
5401 }
5402 }
5403 #endif
5404
5405 static void
update_the_screen(XtermWidget xw)5406 update_the_screen(XtermWidget xw)
5407 {
5408 TScreen *screen = TScreenOf(xw);
5409 Boolean moved;
5410
5411 if (screen->scroll_amt)
5412 FlushScroll(xw);
5413 moved = CursorMoved(screen);
5414 if (screen->cursor_set && moved) {
5415 if (screen->cursor_state)
5416 HideCursor(xw);
5417 ShowCursor(xw);
5418 #if OPT_INPUT_METHOD
5419 PreeditPosition(xw);
5420 #endif
5421 } else {
5422 #if OPT_INPUT_METHOD
5423 if (moved)
5424 PreeditPosition(xw);
5425 #endif
5426 updateCursor(xw);
5427 }
5428 }
5429
5430 #ifdef VMS
5431 #define ptymask() (v_bufptr > v_bufstr ? pty_mask : 0)
5432
5433 static void
in_put(XtermWidget xw)5434 in_put(XtermWidget xw)
5435 {
5436 static PtySelect select_mask;
5437 static PtySelect write_mask;
5438 int update = VTbuffer->update;
5439 int size;
5440
5441 int status;
5442 Dimension replyWidth, replyHeight;
5443 XtGeometryResult stat;
5444
5445 TScreen *screen = TScreenOf(xw);
5446 char *cp;
5447 int i;
5448
5449 select_mask = pty_mask; /* force initial read */
5450 for (;;) {
5451
5452 /* if the terminal changed size, resize the widget */
5453 if (tt_changed) {
5454 tt_changed = False;
5455
5456 stat = REQ_RESIZE((Widget) xw,
5457 ((Dimension) FontWidth(screen)
5458 * (tt_width)
5459 + 2 * screen->border
5460 + screen->fullVwin.sb_info.width),
5461 ((Dimension) FontHeight(screen)
5462 * (tt_length)
5463 + 2 * screen->border),
5464 &replyWidth, &replyHeight);
5465
5466 if (stat == XtGeometryYes || stat == XtGeometryDone) {
5467 xw->core.width = replyWidth;
5468 xw->core.height = replyHeight;
5469
5470 ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
5471 }
5472 repairSizeHints();
5473 }
5474
5475 if (screen->eventMode == NORMAL
5476 && readPtyData(xw, &select_mask, VTbuffer)) {
5477 if (screen->scrollWidget
5478 && screen->scrollttyoutput
5479 && screen->topline < 0)
5480 /* Scroll to bottom */
5481 WindowScroll(xw, 0, False);
5482 break;
5483 }
5484 update_the_screen(xw);
5485
5486 if (QLength(screen->display)) {
5487 select_mask = X_mask;
5488 } else {
5489 write_mask = ptymask();
5490 XFlush(screen->display);
5491 select_mask = Select_mask;
5492 if (screen->eventMode != NORMAL)
5493 select_mask = X_mask;
5494 }
5495 if (write_mask & ptymask()) {
5496 v_write(screen->respond, 0, 0); /* flush buffer */
5497 }
5498
5499 if (select_mask & X_mask) {
5500 xevents(xw);
5501 if (VTbuffer->update != update)
5502 break;
5503 }
5504 }
5505 }
5506 #else /* VMS */
5507
5508 static void
in_put(XtermWidget xw)5509 in_put(XtermWidget xw)
5510 {
5511 static PtySelect select_mask;
5512 static PtySelect write_mask;
5513
5514 TScreen *screen = TScreenOf(xw);
5515 int i;
5516 int update = VTbuffer->update;
5517 #if USE_DOUBLE_BUFFER
5518 int should_wait = 1;
5519 #endif
5520
5521 static struct timeval select_timeout;
5522
5523 #if OPT_BLINK_CURS
5524 /*
5525 * Compute the timeout for the blinking cursor to be much smaller than
5526 * the "on" or "off" interval.
5527 */
5528 int tick = ((screen->blink_on < screen->blink_off)
5529 ? screen->blink_on
5530 : screen->blink_off);
5531 tick *= (1000 / 8); /* 1000 for msec/usec, 8 for "much" smaller */
5532 if (tick < 1)
5533 tick = 1;
5534 #endif
5535
5536 for (;;) {
5537 int size;
5538 int time_select;
5539
5540 if (screen->eventMode == NORMAL
5541 && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) {
5542 if (screen->scrollWidget
5543 && screen->scrollttyoutput
5544 && screen->topline < 0)
5545 WindowScroll(xw, 0, False); /* Scroll to bottom */
5546 /* stop speed reading at some point to look for X stuff */
5547 TRACE(("VTbuffer uses %ld/%d\n",
5548 (long) (VTbuffer->last - VTbuffer->buffer),
5549 BUF_SIZE));
5550 if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) {
5551 FD_CLR(screen->respond, &select_mask);
5552 break;
5553 }
5554 #if USE_DOUBLE_BUFFER
5555 if (resource.buffered && should_wait) {
5556 /* wait for potential extra data (avoids some flickering) */
5557 usleep((unsigned) DbeMsecs(xw));
5558 should_wait = 0;
5559 }
5560 #endif
5561 #if defined(HAVE_SCHED_YIELD)
5562 /*
5563 * If we've read a full (small/fragment) buffer, let the operating
5564 * system have a turn, and we'll resume reading until we've either
5565 * read only a fragment of the buffer, or we've filled the large
5566 * buffer (see above). Doing this helps keep up with large bursts
5567 * of output.
5568 */
5569 if (size == FRG_SIZE) {
5570 select_timeout.tv_sec = 0;
5571 i = Select(max_plus1, &select_mask, &write_mask, 0,
5572 &select_timeout);
5573 if (i > 0 && FD_ISSET(screen->respond, &select_mask)) {
5574 sched_yield();
5575 } else
5576 break;
5577 } else {
5578 break;
5579 }
5580 #else
5581 (void) size; /* unused in this branch */
5582 break;
5583 #endif
5584 }
5585 update_the_screen(xw);
5586
5587 XFlush(screen->display); /* always flush writes before waiting */
5588
5589 /* Update the masks and, unless X events are already in the queue,
5590 wait for I/O to be possible. */
5591 XFD_COPYSET(&Select_mask, &select_mask);
5592 /* in selection mode xterm does not read pty */
5593 if (screen->eventMode != NORMAL)
5594 FD_CLR(screen->respond, &select_mask);
5595
5596 if (v_bufptr > v_bufstr) {
5597 XFD_COPYSET(&pty_mask, &write_mask);
5598 } else
5599 FD_ZERO(&write_mask);
5600 select_timeout.tv_sec = 0;
5601 time_select = 0;
5602
5603 /*
5604 * if there's either an XEvent or an XtTimeout pending, just take
5605 * a quick peek, i.e. timeout from the select() immediately. If
5606 * there's nothing pending, let select() block a little while, but
5607 * for a shorter interval than the arrow-style scrollbar timeout.
5608 * The blocking is optional, because it tends to increase the load
5609 * on the host.
5610 */
5611 if (xtermAppPending()) {
5612 select_timeout.tv_usec = 0;
5613 time_select = 1;
5614 } else if (screen->awaitInput) {
5615 select_timeout.tv_usec = 50000;
5616 time_select = 1;
5617 #if OPT_BLINK_CURS
5618 } else if ((screen->blink_timer != 0 &&
5619 ((screen->select & FOCUS) || screen->always_highlight)) ||
5620 (screen->cursor_state == BLINKED_OFF)) {
5621 select_timeout.tv_usec = tick;
5622 while (select_timeout.tv_usec > 1000000) {
5623 select_timeout.tv_usec -= 1000000;
5624 select_timeout.tv_sec++;
5625 }
5626 time_select = 1;
5627 #endif
5628 #if OPT_SESSION_MGT
5629 } else if (resource.sessionMgt) {
5630 if (ice_fd >= 0)
5631 FD_SET(ice_fd, &select_mask);
5632 #endif
5633 }
5634 if (need_cleanup)
5635 NormalExit();
5636 xtermFlushDbe(xw);
5637 i = Select(max_plus1, &select_mask, &write_mask, 0,
5638 (time_select ? &select_timeout : 0));
5639 if (i < 0) {
5640 if (errno != EINTR)
5641 SysError(ERROR_SELECT);
5642 continue;
5643 }
5644
5645 /* if there is room to write more data to the pty, go write more */
5646 if (FD_ISSET(screen->respond, &write_mask)) {
5647 v_write(screen->respond, (Char *) 0, 0); /* flush buffer */
5648 }
5649
5650 /* if there are X events already in our queue, it
5651 counts as being readable */
5652 if (xtermAppPending() ||
5653 FD_ISSET(ConnectionNumber(screen->display), &select_mask)) {
5654 xevents(xw);
5655 if (VTbuffer->update != update) /* HandleInterpret */
5656 break;
5657 }
5658
5659 }
5660 }
5661 #endif /* VMS */
5662
5663 static IChar
doinput(XtermWidget xw)5664 doinput(XtermWidget xw)
5665 {
5666 TScreen *screen = TScreenOf(xw);
5667
5668 while (!morePtyData(screen, VTbuffer))
5669 in_put(xw);
5670 return nextPtyData(screen, VTbuffer);
5671 }
5672
5673 #if OPT_INPUT_METHOD
5674 /*
5675 * For OverTheSpot, client has to inform the position for XIM preedit.
5676 */
5677 static void
PreeditPosition(XtermWidget xw)5678 PreeditPosition(XtermWidget xw)
5679 {
5680 TInput *input = lookupTInput(xw, (Widget) xw);
5681 TScreen *screen = TScreenOf(xw);
5682 CLineData *ld;
5683 XPoint spot;
5684 XVaNestedList list;
5685
5686 if (input && input->xic
5687 && (ld = getLineData(screen, screen->cur_row)) != 0) {
5688 spot.x = (short) LineCursorX(screen, ld, screen->cur_col);
5689 spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent);
5690 list = XVaCreateNestedList(0,
5691 XNSpotLocation, &spot,
5692 XNForeground, T_COLOR(screen, TEXT_FG),
5693 XNBackground, T_COLOR(screen, TEXT_BG),
5694 (void *) 0);
5695 XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0);
5696 XFree(list);
5697 }
5698 }
5699 #endif
5700
5701 static void
WrapLine(XtermWidget xw)5702 WrapLine(XtermWidget xw)
5703 {
5704 TScreen *screen = TScreenOf(xw);
5705 LineData *ld = getLineData(screen, screen->cur_row);
5706
5707 if (ld != 0) {
5708 /* mark that we had to wrap this line */
5709 LineSetFlag(ld, LINEWRAPPED);
5710 ShowWrapMarks(xw, screen->cur_row, ld);
5711 xtermAutoPrint(xw, '\n');
5712 xtermIndex(xw, 1);
5713 set_cur_col(screen, ScrnLeftMargin(xw));
5714 }
5715 }
5716
5717 /*
5718 * Process a string of characters according to the character set indicated by
5719 * charset. Worry about end of line conditions (wraparound if selected).
5720 *
5721 * It is possible to use CUP, etc., to move outside margins. In that case, the
5722 * right-margin is ineffective until the text (may) wrap and get within the
5723 * margins.
5724 */
5725 void
dotext(XtermWidget xw,DECNRCM_codes charset,IChar * buf,Cardinal len)5726 dotext(XtermWidget xw,
5727 DECNRCM_codes charset,
5728 IChar *buf, /* start of characters to process */
5729 Cardinal len) /* end */
5730 {
5731 TScreen *screen = TScreenOf(xw);
5732 #if OPT_WIDE_CHARS
5733 Cardinal chars_chomped = 1;
5734 int next_col = screen->cur_col;
5735 #else
5736 int next_col, this_col; /* must be signed */
5737 #endif
5738 Cardinal offset;
5739 int rmargin = ScrnRightMargin(xw);
5740
5741 #if OPT_WIDE_CHARS
5742 if (screen->vt100_graphics)
5743 #endif
5744 if (!(len = (Cardinal) xtermCharSetOut(xw, buf, buf + len, charset)))
5745 return;
5746
5747 if_OPT_XMC_GLITCH(screen, {
5748 Cardinal n;
5749 if (charset != '?') {
5750 for (n = 0; n < len; n++) {
5751 if (buf[n] == XMC_GLITCH)
5752 buf[n] = XMC_GLITCH + 1;
5753 }
5754 }
5755 });
5756
5757 #if OPT_WIDE_CHARS
5758 for (offset = 0;
5759 offset < len && (chars_chomped > 0 || screen->do_wrap);
5760 offset += chars_chomped) {
5761 #if OPT_DEC_CHRSET
5762 CLineData *ld = getLineData(screen, screen->cur_row);
5763 int real_rmargin = (CSET_DOUBLE(GetLineDblCS(ld))
5764 ? (rmargin / 2)
5765 : rmargin);
5766 #else
5767 int real_rmargin = rmargin;
5768 #endif
5769 int last_col = LineMaxCol(screen, ld);
5770 int width_here = 0;
5771 int last_chomp = 0;
5772 Boolean force_wrap;
5773
5774 chars_chomped = 0;
5775 do {
5776 int right = ((screen->cur_col > real_rmargin)
5777 ? last_col
5778 : real_rmargin);
5779 int width_available = right + 1 - screen->cur_col;
5780 Boolean need_wrap = False;
5781 Boolean did_wrap = False;
5782
5783 force_wrap = False;
5784
5785 if (screen->do_wrap) {
5786 screen->do_wrap = False;
5787 if ((xw->flags & WRAPAROUND)) {
5788 WrapLine(xw);
5789 right = ((screen->cur_col > real_rmargin)
5790 ? last_col
5791 : real_rmargin);
5792 width_available = right + 1 - screen->cur_col;
5793 next_col = screen->cur_col;
5794 did_wrap = True;
5795 }
5796 }
5797
5798 /*
5799 * This can happen with left/right margins...
5800 */
5801 if (width_available <= 0) {
5802 break;
5803 }
5804
5805 /*
5806 * Regarding the soft-hyphen aberration, see
5807 * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html
5808 */
5809 while (width_here <= width_available
5810 && chars_chomped < (len - offset)) {
5811 Cardinal n = chars_chomped + offset;
5812 if (!screen->utf8_mode
5813 || (screen->vt100_graphics && charset == '0')) {
5814 last_chomp = 1;
5815 } else if (screen->c1_printable &&
5816 buf[n] >= 0x80 &&
5817 buf[n] <= 0xa0) {
5818 last_chomp = 1;
5819 } else {
5820 last_chomp = CharWidth(screen, buf[n]);
5821 if (last_chomp <= 0) {
5822 IChar ch = buf[n];
5823 Bool eat_it = !screen->utf8_mode && (ch > 127);
5824 if (ch == 0xad) {
5825 /*
5826 * Only display soft-hyphen if it happens to be at
5827 * the right-margin. While that means that only
5828 * the displayed character could be selected for
5829 * pasting, a well-behaved application would never
5830 * send this, anyway...
5831 */
5832 if (width_here < width_available - 1) {
5833 eat_it = True;
5834 } else {
5835 last_chomp = 1;
5836 eat_it = False;
5837 }
5838 TRACE(("...will%s display soft-hyphen\n",
5839 eat_it ? " not" : ""));
5840 }
5841 /*
5842 * Supposedly we dealt with combining characters and
5843 * control characters in doparse(). Anything left over
5844 * is junk that we will not attempt to display.
5845 */
5846 if (eat_it) {
5847 TRACE(("...will not display U+%04X\n", ch));
5848 --len;
5849 while (n < len) {
5850 buf[n] = buf[n + 1];
5851 ++n;
5852 }
5853 last_chomp = 0;
5854 chars_chomped--;
5855 }
5856 }
5857 }
5858 width_here += last_chomp;
5859 chars_chomped++;
5860 }
5861
5862 if (width_here > width_available) {
5863 if (last_chomp > right + 1) {
5864 break; /* give up - it is too big */
5865 } else if (chars_chomped-- == 0) {
5866 /* This can happen with left/right margins... */
5867 break;
5868 }
5869 width_here -= last_chomp;
5870 if (chars_chomped > 0) {
5871 if (!(xw->flags & WRAPAROUND)) {
5872 buf[chars_chomped + offset - 1] = buf[len - 1];
5873 } else {
5874 need_wrap = True;
5875 }
5876 }
5877 } else if (width_here == width_available) {
5878 need_wrap = True;
5879 } else if (chars_chomped != (len - offset)) {
5880 need_wrap = True;
5881 }
5882
5883 if (chars_chomped != 0 && next_col <= last_col) {
5884 WriteText(xw, buf + offset, chars_chomped);
5885 } else if (!did_wrap
5886 && len > 0
5887 && (xw->flags & WRAPAROUND)
5888 && screen->cur_col > ScrnLeftMargin(xw)) {
5889 force_wrap = True;
5890 need_wrap = True;
5891 }
5892 next_col += width_here;
5893 screen->do_wrap = need_wrap;
5894 } while (force_wrap);
5895 }
5896
5897 /*
5898 * Remember that we wrote something to the screen, for use as a base of
5899 * combining characters. The logic above may have called cursor-forward
5900 * or carriage-return operations which resets this flag, so we set it at
5901 * the very end.
5902 */
5903 screen->char_was_written = True;
5904 #else /* ! OPT_WIDE_CHARS */
5905
5906 for (offset = 0; offset < len; offset += (Cardinal) this_col) {
5907 #if OPT_DEC_CHRSET
5908 CLineData *ld = getLineData(screen, screen->cur_row);
5909 #endif
5910 int right = ((screen->cur_col > rmargin)
5911 ? screen->max_col
5912 : rmargin);
5913
5914 int last_col = LineMaxCol(screen, ld);
5915 if (last_col > right)
5916 last_col = right;
5917 this_col = last_col - screen->cur_col + 1;
5918 if (screen->do_wrap) {
5919 screen->do_wrap = False;
5920 if ((xw->flags & WRAPAROUND)) {
5921 WrapLine(xw);
5922 }
5923 this_col = 1;
5924 }
5925 if (offset + (Cardinal) this_col > len) {
5926 this_col = (int) (len - offset);
5927 }
5928 next_col = screen->cur_col + this_col;
5929
5930 WriteText(xw, buf + offset, (unsigned) this_col);
5931
5932 /*
5933 * The call to WriteText updates screen->cur_col.
5934 * If screen->cur_col is less than next_col, we must have
5935 * hit the right margin - so set the do_wrap flag.
5936 */
5937 screen->do_wrap = (Boolean) (screen->cur_col < next_col);
5938 }
5939
5940 #endif /* OPT_WIDE_CHARS */
5941 }
5942
5943 #if OPT_WIDE_CHARS
5944 unsigned
visual_width(const IChar * str,Cardinal len)5945 visual_width(const IChar *str, Cardinal len)
5946 {
5947 /* returns the visual width of a string (doublewide characters count
5948 as 2, normalwide characters count as 1) */
5949 unsigned my_len = 0;
5950 while (len) {
5951 int ch = (int) *str++;
5952 if (isWide(ch))
5953 my_len += 2;
5954 else
5955 my_len++;
5956 len--;
5957 }
5958 return my_len;
5959 }
5960 #endif
5961
5962 #if HANDLE_STRUCT_NOTIFY
5963 /* Flag icon name with "***" on window output when iconified.
5964 */
5965 static void
HandleStructNotify(Widget w GCC_UNUSED,XtPointer closure GCC_UNUSED,XEvent * event,Boolean * cont GCC_UNUSED)5966 HandleStructNotify(Widget w GCC_UNUSED,
5967 XtPointer closure GCC_UNUSED,
5968 XEvent *event,
5969 Boolean *cont GCC_UNUSED)
5970 {
5971 XtermWidget xw = term;
5972 TScreen *screen = TScreenOf(xw);
5973
5974 (void) screen;
5975 TRACE_EVENT("HandleStructNotify", event, NULL, 0);
5976 switch (event->type) {
5977 case MapNotify:
5978 resetZIconBeep(xw);
5979 mapstate = !IsUnmapped;
5980 break;
5981 case UnmapNotify:
5982 mapstate = IsUnmapped;
5983 break;
5984 case MappingNotify:
5985 XRefreshKeyboardMapping(&(event->xmapping));
5986 VTInitModifiers(xw);
5987 break;
5988 case ConfigureNotify:
5989 if (event->xconfigure.window == XtWindow(toplevel)) {
5990 #if !OPT_TOOLBAR
5991 int height = event->xconfigure.height;
5992 int width = event->xconfigure.width;
5993 #endif
5994
5995 #if USE_DOUBLE_BUFFER
5996 discardRenderDraw(screen);
5997 #endif /* USE_DOUBLE_BUFFER */
5998 #if OPT_TOOLBAR
5999 /*
6000 * The notification is for the top-level widget, but we care about
6001 * vt100 (ignore the tek4014 window).
6002 */
6003 if (screen->Vshow) {
6004 VTwin *Vwin = WhichVWin(screen);
6005 TbInfo *info = &(Vwin->tb_info);
6006 TbInfo save = *info;
6007
6008 if (info->menu_bar) {
6009 XtVaGetValues(info->menu_bar,
6010 XtNheight, &info->menu_height,
6011 XtNborderWidth, &info->menu_border,
6012 (XtPointer) 0);
6013
6014 if (save.menu_height != info->menu_height
6015 || save.menu_border != info->menu_border) {
6016
6017 TRACE(("...menu_height %d\n", info->menu_height));
6018 TRACE(("...menu_border %d\n", info->menu_border));
6019 TRACE(("...had height %d, border %d\n",
6020 save.menu_height,
6021 save.menu_border));
6022
6023 /*
6024 * Window manager still may be using the old values.
6025 * Try to fool it.
6026 */
6027 REQ_RESIZE((Widget) xw,
6028 screen->fullVwin.fullwidth,
6029 (Dimension) (info->menu_height
6030 - save.menu_height
6031 + screen->fullVwin.fullheight),
6032 NULL, NULL);
6033 repairSizeHints();
6034 }
6035 }
6036 }
6037 #else
6038 if (!xw->work.doing_resize
6039 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
6040 && !(resource.buffered && UsingRenderFont(xw)) /* buggyXft */
6041 #endif
6042 && (height != xw->hints.height
6043 || width != xw->hints.width)) {
6044 /*
6045 * This is a special case: other calls to RequestResize that
6046 * could set the screensize arbitrarily are via escape
6047 * sequences, and we've limited resizing. But a configure
6048 * notify is from the window manager, presumably under control
6049 * of the interactive user (ignoring abuse of wmctrl). Ignore
6050 * the limit for this case.
6051 */
6052 int saved_limit = xw->misc.limit_resize;
6053 xw->misc.limit_resize = 0;
6054 RequestResize(xw, height, width, False);
6055 xw->misc.limit_resize = saved_limit;
6056 }
6057 #endif /* OPT_TOOLBAR */
6058 }
6059 break;
6060 }
6061 }
6062 #endif /* HANDLE_STRUCT_NOTIFY */
6063
6064 #if OPT_BLINK_CURS
6065 static int
DoStartBlinking(TScreen * screen)6066 DoStartBlinking(TScreen *screen)
6067 {
6068 int actual = ((screen->cursor_blink == cbTrue ||
6069 screen->cursor_blink == cbAlways)
6070 ? 1
6071 : 0);
6072 int wanted = screen->cursor_blink_esc ? 1 : 0;
6073 int result;
6074 if (screen->cursor_blink_xor) {
6075 result = actual ^ wanted;
6076 } else {
6077 result = actual | wanted;
6078 }
6079 return result;
6080 }
6081
6082 static void
SetCursorBlink(XtermWidget xw,BlinkOps enable)6083 SetCursorBlink(XtermWidget xw, BlinkOps enable)
6084 {
6085 TScreen *screen = TScreenOf(xw);
6086
6087 if (SettableCursorBlink(screen)) {
6088 screen->cursor_blink = enable;
6089 }
6090 if (DoStartBlinking(screen)) {
6091 StartBlinking(xw);
6092 } else {
6093 /* EMPTY */
6094 #if OPT_BLINK_TEXT
6095 reallyStopBlinking(xw);
6096 #else
6097 StopBlinking(xw);
6098 #endif
6099 }
6100 update_cursorblink();
6101 }
6102
6103 void
ToggleCursorBlink(XtermWidget xw)6104 ToggleCursorBlink(XtermWidget xw)
6105 {
6106 TScreen *screen = TScreenOf(xw);
6107
6108 if (screen->cursor_blink == cbTrue) {
6109 SetCursorBlink(xw, cbFalse);
6110 } else if (screen->cursor_blink == cbFalse) {
6111 SetCursorBlink(xw, cbTrue);
6112 }
6113 }
6114 #endif
6115
6116 /*
6117 * process ANSI modes set, reset
6118 */
6119 static void
ansi_modes(XtermWidget xw,BitFunc func)6120 ansi_modes(XtermWidget xw, BitFunc func)
6121 {
6122 int i;
6123
6124 for (i = 0; i < nparam; ++i) {
6125 switch (GetParam(i)) {
6126 case 2: /* KAM (if set, keyboard locked */
6127 (*func) (&xw->keyboard.flags, MODE_KAM);
6128 break;
6129
6130 case 4: /* IRM */
6131 (*func) (&xw->flags, INSERT);
6132 break;
6133
6134 case 12: /* SRM (if set, local echo */
6135 (*func) (&xw->keyboard.flags, MODE_SRM);
6136 break;
6137
6138 case 20: /* LNM */
6139 (*func) (&xw->flags, LINEFEED);
6140 update_autolinefeed();
6141 break;
6142 }
6143 }
6144 }
6145
6146 #define IsSM() (func == bitset)
6147
6148 #define set_bool_mode(flag) \
6149 flag = (Boolean) IsSM()
6150
6151 static void
really_set_mousemode(XtermWidget xw,Bool enabled,XtermMouseModes mode)6152 really_set_mousemode(XtermWidget xw,
6153 Bool enabled,
6154 XtermMouseModes mode)
6155 {
6156 TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF;
6157 if (okSendMousePos(xw) != MOUSE_OFF)
6158 xtermShowPointer(xw, True);
6159 }
6160
6161 #define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode)
6162
6163 #if OPT_PASTE64 || OPT_READLINE
6164 #define set_mouseflag(f) \
6165 (IsSM() \
6166 ? SCREEN_FLAG_set(screen, f) \
6167 : SCREEN_FLAG_unset(screen, f))
6168 #endif
6169
6170 /*
6171 * DEC 070, pp 5-71 to 5-72.
6172 */
6173 static void
set_column_mode(XtermWidget xw)6174 set_column_mode(XtermWidget xw)
6175 {
6176 TScreen *screen = TScreenOf(xw);
6177
6178 xterm_ResetDouble(xw);
6179 resetMargins(xw);
6180 UIntSet(xw->flags, LEFT_RIGHT);
6181 CursorSet(screen, 0, 0, xw->flags);
6182 }
6183
6184 /*
6185 * DEC 070, pp 5-29 to 5-30.
6186 */
6187 static void
set_left_right_margin_mode(XtermWidget xw)6188 set_left_right_margin_mode(XtermWidget xw)
6189 {
6190 TScreen *screen = TScreenOf(xw);
6191
6192 if (screen->vtXX_level >= 4) {
6193 if (IsLeftRightMode(xw)) {
6194 xterm_ResetDouble(xw);
6195 } else {
6196 reset_lr_margins(screen);
6197 }
6198 }
6199 }
6200
6201 /*
6202 * process DEC private modes set, reset
6203 */
6204 static void
dpmodes(XtermWidget xw,BitFunc func)6205 dpmodes(XtermWidget xw, BitFunc func)
6206 {
6207 TScreen *screen = TScreenOf(xw);
6208 int i, j;
6209 unsigned myflags;
6210
6211 TRACE(("changing %d DEC private modes\n", nparam));
6212 for (i = 0; i < nparam; ++i) {
6213 int code = GetParam(i);
6214
6215 TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code));
6216 switch ((DECSET_codes) code) {
6217 case srm_DECCKM:
6218 (*func) (&xw->keyboard.flags, MODE_DECCKM);
6219 update_appcursor();
6220 break;
6221 case srm_DECANM: /* ANSI/VT52 mode */
6222 if (IsSM()) { /* ANSI (VT100) */
6223 /*
6224 * Setting DECANM should have no effect, since this function
6225 * cannot be reached from vt52 mode.
6226 */
6227 /* EMPTY */ ;
6228 }
6229 #if OPT_VT52_MODE
6230 else if (screen->terminal_id >= 100) { /* VT52 */
6231 TRACE(("DECANM terminal_id %d, vtXX_level %d\n",
6232 screen->terminal_id,
6233 screen->vtXX_level));
6234 /*
6235 * According to DEC STD 070 section A.5.5, the various VT100
6236 * modes have undefined behavior when entering/exiting VT52
6237 * mode. xterm saves/restores/initializes the most commonly
6238 * used settings, but a real VT100 or VT520 may differ.
6239 *
6240 * For instance, DEC's documentation goes on to comment that
6241 * while the VT52 uses hardware tabs (8 columns), the emulation
6242 * (e.g., a VT420) does not alter those tab settings when
6243 * switching modes.
6244 */
6245 screen->vtXX_level = 0;
6246 screen->vt52_save_flags = xw->flags;
6247 xw->flags = 0;
6248 screen->vt52_save_curgl = screen->curgl;
6249 screen->vt52_save_curgr = screen->curgr;
6250 screen->vt52_save_curss = screen->curss;
6251 saveCharsets(screen, screen->vt52_save_gsets);
6252 resetCharsets(screen);
6253 InitParams(); /* ignore the remaining params, if any */
6254 update_vt52_vt100_settings();
6255 RequestResize(xw, -1, 80, True);
6256 }
6257 #endif
6258 break;
6259 case srm_DECCOLM:
6260 if (screen->c132) {
6261 Boolean willResize = ((j = IsSM()
6262 ? 132
6263 : 80)
6264 != ((xw->flags & IN132COLUMNS)
6265 ? 132
6266 : 80)
6267 || j != MaxCols(screen));
6268 if (!(xw->flags & NOCLEAR_COLM))
6269 ClearScreen(xw);
6270 if (willResize)
6271 RequestResize(xw, -1, j, True);
6272 (*func) (&xw->flags, IN132COLUMNS);
6273 set_column_mode(xw);
6274 }
6275 break;
6276 case srm_DECSCLM: /* (slow scroll) */
6277 if (IsSM()) {
6278 screen->jumpscroll = 0;
6279 if (screen->scroll_amt)
6280 FlushScroll(xw);
6281 } else
6282 screen->jumpscroll = 1;
6283 (*func) (&xw->flags, SMOOTHSCROLL);
6284 update_jumpscroll();
6285 break;
6286 case srm_DECSCNM:
6287 myflags = xw->flags;
6288 (*func) (&xw->flags, REVERSE_VIDEO);
6289 if ((xw->flags ^ myflags) & REVERSE_VIDEO)
6290 ReverseVideo(xw);
6291 /* update_reversevideo done in RevVid */
6292 break;
6293
6294 case srm_DECOM:
6295 (*func) (&xw->flags, ORIGIN);
6296 CursorSet(screen, 0, 0, xw->flags);
6297 break;
6298
6299 case srm_DECAWM:
6300 (*func) (&xw->flags, WRAPAROUND);
6301 update_autowrap();
6302 break;
6303 case srm_DECARM:
6304 /* ignore autorepeat
6305 * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only
6306 * for the whole display - not limited to a given window.
6307 */
6308 break;
6309 case srm_X10_MOUSE: /* MIT bogus sequence */
6310 MotionOff(screen, xw);
6311 set_mousemode(X10_MOUSE);
6312 break;
6313 #if OPT_TOOLBAR
6314 case srm_RXVT_TOOLBAR:
6315 ShowToolbar(IsSM());
6316 break;
6317 #endif
6318 #if OPT_BLINK_CURS
6319 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */
6320 if (SettableCursorBlink(screen)) {
6321 set_bool_mode(screen->cursor_blink_esc);
6322 UpdateCursorBlink(xw);
6323 }
6324 break;
6325 case srm_CURSOR_BLINK_OPS:
6326 /* intentionally ignored (this is user-preference) */
6327 break;
6328 case srm_XOR_CURSOR_BLINKS:
6329 /* intentionally ignored (this is user-preference) */
6330 break;
6331 #endif
6332 case srm_DECPFF: /* print form feed */
6333 set_bool_mode(PrinterOf(screen).printer_formfeed);
6334 break;
6335 case srm_DECPEX: /* print extent */
6336 set_bool_mode(PrinterOf(screen).printer_extent);
6337 break;
6338 case srm_DECTCEM: /* Show/hide cursor (VT200) */
6339 set_bool_mode(screen->cursor_set);
6340 break;
6341 case srm_RXVT_SCROLLBAR:
6342 if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF))
6343 ToggleScrollBar(xw);
6344 break;
6345 #if OPT_SHIFT_FONTS
6346 case srm_RXVT_FONTSIZE:
6347 set_bool_mode(xw->misc.shift_fonts);
6348 break;
6349 #endif
6350 #if OPT_TEK4014
6351 case srm_DECTEK:
6352 if (IsSM() && !(screen->inhibit & I_TEK)) {
6353 FlushLog(xw);
6354 TEK4014_ACTIVE(xw) = True;
6355 TRACE(("Tek4014 is now active...\n"));
6356 update_vttekmode();
6357 }
6358 break;
6359 #endif
6360 case srm_132COLS: /* 132 column mode */
6361 set_bool_mode(screen->c132);
6362 update_allow132();
6363 break;
6364 case srm_CURSES_HACK:
6365 set_bool_mode(screen->curses);
6366 update_cursesemul();
6367 break;
6368 case srm_DECNRCM: /* national charset (VT220) */
6369 if (screen->vtXX_level >= 2) {
6370 if ((*func) (&xw->flags, NATIONAL)) {
6371 modified_DECNRCM(xw);
6372 }
6373 }
6374 break;
6375 #if OPT_PRINT_GRAPHICS
6376 case srm_DECGEPM: /* Graphics Expanded Print Mode */
6377 set_bool_mode(screen->graphics_expanded_print_mode);
6378 break;
6379 #endif
6380 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
6381 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_mode)) {
6382 set_bool_mode(screen->marginbell);
6383 if (!screen->marginbell)
6384 screen->bellArmed = -1;
6385 update_marginbell();
6386 }
6387 break;
6388 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
6389 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_syntax)) {
6390 (*func) (&xw->flags, REVERSEWRAP);
6391 update_reversewrap();
6392 }
6393 break;
6394 #ifdef ALLOWLOGGING
6395 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
6396 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_background_mode)) {
6397 #ifdef ALLOWLOGFILEONOFF
6398 /*
6399 * if this feature is enabled, logging may be
6400 * enabled and disabled via escape sequences.
6401 */
6402 if (IsSM())
6403 StartLog(xw);
6404 else
6405 CloseLog(xw);
6406 #else
6407 Bell(xw, XkbBI_Info, 0);
6408 Bell(xw, XkbBI_Info, 0);
6409 #endif /* ALLOWLOGFILEONOFF */
6410 }
6411 break;
6412 #elif OPT_PRINT_GRAPHICS
6413 case srm_DECGPBM: /* Graphics Print Background Mode */
6414 set_bool_mode(screen->graphics_print_background_mode);
6415 break;
6416 #endif /* ALLOWLOGGING */
6417 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */
6418 if (!xw->misc.titeInhibit) {
6419 if (IsSM()) {
6420 CursorSave(xw);
6421 ToAlternate(xw, True);
6422 ClearScreen(xw);
6423 } else {
6424 FromAlternate(xw);
6425 CursorRestore(xw);
6426 }
6427 } else if (IsSM()) {
6428 do_ti_xtra_scroll(xw);
6429 }
6430 break;
6431 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */
6432 if (!xw->misc.titeInhibit) {
6433 if (IsSM()) {
6434 ToAlternate(xw, False);
6435 } else {
6436 if (screen->whichBuf)
6437 ClearScreen(xw);
6438 FromAlternate(xw);
6439 }
6440 } else if (IsSM()) {
6441 do_ti_xtra_scroll(xw);
6442 }
6443 break;
6444 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
6445 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_rotated_print_mode)) {
6446 if (!xw->misc.titeInhibit) {
6447 if (IsSM()) {
6448 ToAlternate(xw, False);
6449 } else {
6450 FromAlternate(xw);
6451 }
6452 } else if (IsSM()) {
6453 do_ti_xtra_scroll(xw);
6454 }
6455 }
6456 break;
6457 case srm_DECNKM:
6458 (*func) (&xw->keyboard.flags, MODE_DECKPAM);
6459 update_appkeypad();
6460 break;
6461 case srm_DECBKM:
6462 /* back-arrow mapped to backspace or delete(D) */
6463 (*func) (&xw->keyboard.flags, MODE_DECBKM);
6464 TRACE(("DECSET DECBKM %s\n",
6465 BtoS(xw->keyboard.flags & MODE_DECBKM)));
6466 update_decbkm();
6467 break;
6468 case srm_DECLRMM:
6469 if (screen->vtXX_level >= 4) { /* VT420 */
6470 (*func) (&xw->flags, LEFT_RIGHT);
6471 set_left_right_margin_mode(xw);
6472 }
6473 break;
6474 #if OPT_SIXEL_GRAPHICS
6475 case srm_DECSDM: /* sixel scrolling */
6476 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */
6477 (*func) (&xw->keyboard.flags, MODE_DECSDM);
6478 TRACE(("DECSET/DECRST DECSDM %s (resource default is %d)\n",
6479 BtoS(xw->keyboard.flags & MODE_DECSDM),
6480 TScreenOf(xw)->sixel_scrolling));
6481 update_decsdm();
6482 }
6483 break;
6484 #endif
6485 case srm_DECNCSM:
6486 if (screen->vtXX_level >= 5) { /* VT510 */
6487 (*func) (&xw->flags, NOCLEAR_COLM);
6488 }
6489 break;
6490 case srm_VT200_MOUSE: /* xterm bogus sequence */
6491 MotionOff(screen, xw);
6492 set_mousemode(VT200_MOUSE);
6493 break;
6494 case srm_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */
6495 MotionOff(screen, xw);
6496 set_mousemode(VT200_HIGHLIGHT_MOUSE);
6497 break;
6498 case srm_BTN_EVENT_MOUSE:
6499 MotionOff(screen, xw);
6500 set_mousemode(BTN_EVENT_MOUSE);
6501 break;
6502 case srm_ANY_EVENT_MOUSE:
6503 set_mousemode(ANY_EVENT_MOUSE);
6504 if (screen->send_mouse_pos == MOUSE_OFF) {
6505 MotionOff(screen, xw);
6506 } else {
6507 MotionOn(screen, xw);
6508 }
6509 break;
6510 #if OPT_FOCUS_EVENT
6511 case srm_FOCUS_EVENT_MOUSE:
6512 set_bool_mode(screen->send_focus_pos);
6513 break;
6514 #endif
6515 case srm_EXT_MODE_MOUSE:
6516 /* FALLTHRU */
6517 case srm_SGR_EXT_MODE_MOUSE:
6518 /* FALLTHRU */
6519 case srm_URXVT_EXT_MODE_MOUSE:
6520 /* FALLTHRU */
6521 case srm_PIXEL_POSITION_MOUSE:
6522 /*
6523 * Rather than choose an arbitrary precedence among the coordinate
6524 * modes, they are mutually exclusive. For consistency, a reset is
6525 * only effective against the matching mode.
6526 */
6527 if (IsSM()) {
6528 screen->extend_coords = code;
6529 } else if (screen->extend_coords == code) {
6530 screen->extend_coords = 0;
6531 }
6532 break;
6533 case srm_ALTERNATE_SCROLL:
6534 set_bool_mode(screen->alternateScroll);
6535 break;
6536 case srm_RXVT_SCROLL_TTY_OUTPUT:
6537 set_bool_mode(screen->scrollttyoutput);
6538 update_scrollttyoutput();
6539 break;
6540 case srm_RXVT_SCROLL_TTY_KEYPRESS:
6541 set_bool_mode(screen->scrollkey);
6542 update_scrollkey();
6543 break;
6544 case srm_EIGHT_BIT_META:
6545 if (screen->eight_bit_meta != ebNever) {
6546 set_bool_mode(screen->eight_bit_meta);
6547 }
6548 break;
6549 #if OPT_NUM_LOCK
6550 case srm_REAL_NUMLOCK:
6551 set_bool_mode(xw->misc.real_NumLock);
6552 update_num_lock();
6553 break;
6554 case srm_META_SENDS_ESC:
6555 set_bool_mode(screen->meta_sends_esc);
6556 update_meta_esc();
6557 break;
6558 #endif
6559 case srm_DELETE_IS_DEL:
6560 set_bool_mode(screen->delete_is_del);
6561 update_delete_del();
6562 break;
6563 #if OPT_NUM_LOCK
6564 case srm_ALT_SENDS_ESC:
6565 set_bool_mode(screen->alt_sends_esc);
6566 update_alt_esc();
6567 break;
6568 #endif
6569 case srm_KEEP_SELECTION:
6570 set_bool_mode(screen->keepSelection);
6571 update_keepSelection();
6572 break;
6573 case srm_SELECT_TO_CLIPBOARD:
6574 set_bool_mode(screen->selectToClipboard);
6575 update_selectToClipboard();
6576 break;
6577 case srm_BELL_IS_URGENT:
6578 set_bool_mode(screen->bellIsUrgent);
6579 update_bellIsUrgent();
6580 break;
6581 case srm_POP_ON_BELL:
6582 set_bool_mode(screen->poponbell);
6583 update_poponbell();
6584 break;
6585 case srm_KEEP_CLIPBOARD:
6586 set_bool_mode(screen->keepClipboard);
6587 update_keepClipboard();
6588 break;
6589 case srm_ALLOW_ALTBUF:
6590 if (IsSM()) {
6591 xw->misc.titeInhibit = False;
6592 } else if (!xw->misc.titeInhibit) {
6593 xw->misc.titeInhibit = True;
6594 FromAlternate(xw);
6595 }
6596 update_titeInhibit();
6597 break;
6598 case srm_SAVE_CURSOR:
6599 if (!xw->misc.titeInhibit) {
6600 if (IsSM())
6601 CursorSave(xw);
6602 else
6603 CursorRestore(xw);
6604 }
6605 break;
6606 #if OPT_TCAP_FKEYS
6607 case srm_TCAP_FKEYS:
6608 set_keyboard_type(xw, keyboardIsTermcap, IsSM());
6609 break;
6610 #endif
6611 #if OPT_SUN_FUNC_KEYS
6612 case srm_SUN_FKEYS:
6613 set_keyboard_type(xw, keyboardIsSun, IsSM());
6614 break;
6615 #endif
6616 #if OPT_HP_FUNC_KEYS
6617 case srm_HP_FKEYS:
6618 set_keyboard_type(xw, keyboardIsHP, IsSM());
6619 break;
6620 #endif
6621 #if OPT_SCO_FUNC_KEYS
6622 case srm_SCO_FKEYS:
6623 set_keyboard_type(xw, keyboardIsSCO, IsSM());
6624 break;
6625 #endif
6626 case srm_LEGACY_FKEYS:
6627 set_keyboard_type(xw, keyboardIsLegacy, IsSM());
6628 break;
6629 #if OPT_SUNPC_KBD
6630 case srm_VT220_FKEYS:
6631 set_keyboard_type(xw, keyboardIsVT220, IsSM());
6632 break;
6633 #endif
6634 #if OPT_PASTE64 || OPT_READLINE
6635 case srm_PASTE_IN_BRACKET:
6636 set_mouseflag(paste_brackets);
6637 break;
6638 #endif
6639 #if OPT_READLINE
6640 case srm_BUTTON1_MOVE_POINT:
6641 set_mouseflag(click1_moves);
6642 break;
6643 case srm_BUTTON2_MOVE_POINT:
6644 set_mouseflag(paste_moves);
6645 break;
6646 case srm_DBUTTON3_DELETE:
6647 set_mouseflag(dclick3_deletes);
6648 break;
6649 case srm_PASTE_QUOTE:
6650 set_mouseflag(paste_quotes);
6651 break;
6652 case srm_PASTE_LITERAL_NL:
6653 set_mouseflag(paste_literal_nl);
6654 break;
6655 #endif /* OPT_READLINE */
6656 #if OPT_GRAPHICS
6657 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */
6658 TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n",
6659 BtoS(screen->privatecolorregisters),
6660 BtoS(TScreenOf(xw)->privatecolorregisters)));
6661 set_bool_mode(screen->privatecolorregisters);
6662 update_privatecolorregisters();
6663 break;
6664 #endif
6665 #if OPT_SIXEL_GRAPHICS
6666 case srm_SIXEL_SCROLLS_RIGHT: /* sixel scrolling moves cursor to right */
6667 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */
6668 set_bool_mode(screen->sixel_scrolls_right);
6669 TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n",
6670 BtoS(screen->sixel_scrolls_right),
6671 BtoS(TScreenOf(xw)->sixel_scrolls_right)));
6672 }
6673 break;
6674 #endif
6675 default:
6676 TRACE(("DATA_ERROR: unknown private code %d\n", code));
6677 break;
6678 }
6679 }
6680 }
6681
6682 /*
6683 * process xterm private modes save
6684 */
6685 static void
savemodes(XtermWidget xw)6686 savemodes(XtermWidget xw)
6687 {
6688 TScreen *screen = TScreenOf(xw);
6689 int i;
6690
6691 for (i = 0; i < nparam; i++) {
6692 int code = GetParam(i);
6693
6694 TRACE(("savemodes %d\n", code));
6695 switch ((DECSET_codes) code) {
6696 case srm_DECCKM:
6697 DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM);
6698 break;
6699 case srm_DECANM: /* ANSI/VT52 mode */
6700 /* no effect */
6701 break;
6702 case srm_DECCOLM:
6703 if (screen->c132)
6704 DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS);
6705 break;
6706 case srm_DECSCLM: /* (slow scroll) */
6707 DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL);
6708 break;
6709 case srm_DECSCNM:
6710 DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO);
6711 break;
6712 case srm_DECOM:
6713 DoSM(DP_DECOM, xw->flags & ORIGIN);
6714 break;
6715 case srm_DECAWM:
6716 DoSM(DP_DECAWM, xw->flags & WRAPAROUND);
6717 break;
6718 case srm_DECARM:
6719 /* ignore autorepeat */
6720 break;
6721 case srm_X10_MOUSE: /* mouse bogus sequence */
6722 DoSM(DP_X_X10MSE, screen->send_mouse_pos);
6723 break;
6724 #if OPT_TOOLBAR
6725 case srm_RXVT_TOOLBAR:
6726 DoSM(DP_TOOLBAR, resource.toolBar);
6727 break;
6728 #endif
6729 #if OPT_BLINK_CURS
6730 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */
6731 if (SettableCursorBlink(screen)) {
6732 DoSM(DP_CRS_BLINK, screen->cursor_blink_esc);
6733 }
6734 break;
6735 case srm_CURSOR_BLINK_OPS:
6736 /* intentionally ignored (this is user-preference) */
6737 break;
6738 case srm_XOR_CURSOR_BLINKS:
6739 /* intentionally ignored (this is user-preference) */
6740 break;
6741 #endif
6742 case srm_DECPFF: /* print form feed */
6743 DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
6744 break;
6745 case srm_DECPEX: /* print extent */
6746 DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
6747 break;
6748 case srm_DECTCEM: /* Show/hide cursor (VT200) */
6749 DoSM(DP_CRS_VISIBLE, screen->cursor_set);
6750 break;
6751 case srm_RXVT_SCROLLBAR:
6752 DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0));
6753 break;
6754 #if OPT_SHIFT_FONTS
6755 case srm_RXVT_FONTSIZE:
6756 DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
6757 break;
6758 #endif
6759 #if OPT_TEK4014
6760 case srm_DECTEK:
6761 DoSM(DP_DECTEK, TEK4014_ACTIVE(xw));
6762 break;
6763 #endif
6764 case srm_132COLS: /* 132 column mode */
6765 DoSM(DP_X_DECCOLM, screen->c132);
6766 break;
6767 case srm_CURSES_HACK: /* curses hack */
6768 DoSM(DP_X_MORE, screen->curses);
6769 break;
6770 case srm_DECNRCM: /* national charset (VT220) */
6771 if (screen->vtXX_level >= 2) {
6772 DoSM(DP_DECNRCM, xw->flags & NATIONAL);
6773 }
6774 break;
6775 #if OPT_PRINT_GRAPHICS
6776 case srm_DECGEPM: /* Graphics Expanded Print Mode */
6777 DoSM(DP_DECGEPM, screen->graphics_expanded_print_mode);
6778 break;
6779 #endif
6780 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
6781 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCM, screen->graphics_print_color_mode)) {
6782 DoSM(DP_X_MARGIN, screen->marginbell);
6783 }
6784 break;
6785 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
6786 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCS, screen->graphics_print_color_syntax)) {
6787 DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP);
6788 }
6789 break;
6790 #ifdef ALLOWLOGGING
6791 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
6792 if_PRINT_GRAPHICS2(DoSM(DP_DECGPBM, screen->graphics_print_background_mode)) {
6793 #ifdef ALLOWLOGFILEONOFF
6794 DoSM(DP_X_LOGGING, screen->logging);
6795 #endif /* ALLOWLOGFILEONOFF */
6796 }
6797 break;
6798 #elif OPT_PRINT_GRAPHICS
6799 case srm_DECGPBM: /* Graphics Print Background Mode */
6800 DoSM(DP_DECGPBM, screen->graphics_print_background_mode);
6801 break;
6802 #endif /* ALLOWLOGGING */
6803 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */
6804 /* FALLTHRU */
6805 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */
6806 DoSM(DP_X_ALTBUF, screen->whichBuf);
6807 break;
6808 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
6809 if_PRINT_GRAPHICS2(DoSM(DP_DECGRPM, screen->graphics_rotated_print_mode)) {
6810 DoSM(DP_X_ALTBUF, screen->whichBuf);
6811 }
6812 break;
6813 case srm_DECNKM:
6814 DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM);
6815 break;
6816 case srm_DECBKM: /* backarrow mapping */
6817 DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM);
6818 break;
6819 case srm_DECLRMM: /* left-right */
6820 DoSM(DP_X_LRMM, LEFT_RIGHT);
6821 break;
6822 #if OPT_SIXEL_GRAPHICS
6823 case srm_DECSDM: /* sixel scrolling */
6824 DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM);
6825 update_decsdm();
6826 break;
6827 #endif
6828 case srm_DECNCSM: /* noclear */
6829 DoSM(DP_X_NCSM, NOCLEAR_COLM);
6830 break;
6831 case srm_VT200_MOUSE: /* mouse bogus sequence */
6832 /* FALLTHRU */
6833 case srm_VT200_HIGHLIGHT_MOUSE:
6834 /* FALLTHRU */
6835 case srm_BTN_EVENT_MOUSE:
6836 /* FALLTHRU */
6837 case srm_ANY_EVENT_MOUSE:
6838 DoSM(DP_X_MOUSE, screen->send_mouse_pos);
6839 break;
6840 #if OPT_FOCUS_EVENT
6841 case srm_FOCUS_EVENT_MOUSE:
6842 DoSM(DP_X_FOCUS, screen->send_focus_pos);
6843 break;
6844 #endif
6845 case srm_EXT_MODE_MOUSE:
6846 /* FALLTHRU */
6847 case srm_SGR_EXT_MODE_MOUSE:
6848 /* FALLTHRU */
6849 case srm_URXVT_EXT_MODE_MOUSE:
6850 /* FALLTHRU */
6851 case srm_PIXEL_POSITION_MOUSE:
6852 DoSM(DP_X_EXT_MOUSE, screen->extend_coords);
6853 break;
6854 case srm_ALTERNATE_SCROLL:
6855 DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
6856 break;
6857 case srm_RXVT_SCROLL_TTY_OUTPUT:
6858 DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
6859 break;
6860 case srm_RXVT_SCROLL_TTY_KEYPRESS:
6861 DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
6862 break;
6863 case srm_EIGHT_BIT_META:
6864 DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
6865 break;
6866 #if OPT_NUM_LOCK
6867 case srm_REAL_NUMLOCK:
6868 DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
6869 break;
6870 case srm_META_SENDS_ESC:
6871 DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc);
6872 break;
6873 #endif
6874 case srm_DELETE_IS_DEL:
6875 DoSM(DP_DELETE_IS_DEL, screen->delete_is_del);
6876 break;
6877 #if OPT_NUM_LOCK
6878 case srm_ALT_SENDS_ESC:
6879 DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
6880 break;
6881 #endif
6882 case srm_KEEP_SELECTION:
6883 DoSM(DP_KEEP_SELECTION, screen->keepSelection);
6884 break;
6885 case srm_SELECT_TO_CLIPBOARD:
6886 DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
6887 break;
6888 case srm_BELL_IS_URGENT:
6889 DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
6890 break;
6891 case srm_POP_ON_BELL:
6892 DoSM(DP_POP_ON_BELL, screen->poponbell);
6893 break;
6894 case srm_KEEP_CLIPBOARD:
6895 DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
6896 break;
6897 #if OPT_TCAP_FKEYS
6898 case srm_TCAP_FKEYS:
6899 /* FALLTHRU */
6900 #endif
6901 #if OPT_SUN_FUNC_KEYS
6902 case srm_SUN_FKEYS:
6903 /* FALLTHRU */
6904 #endif
6905 #if OPT_HP_FUNC_KEYS
6906 case srm_HP_FKEYS:
6907 /* FALLTHRU */
6908 #endif
6909 #if OPT_SCO_FUNC_KEYS
6910 case srm_SCO_FKEYS:
6911 /* FALLTHRU */
6912 #endif
6913 #if OPT_SUNPC_KBD
6914 case srm_VT220_FKEYS:
6915 /* FALLTHRU */
6916 #endif
6917 case srm_LEGACY_FKEYS:
6918 DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type);
6919 break;
6920 case srm_ALLOW_ALTBUF:
6921 DoSM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit);
6922 break;
6923 case srm_SAVE_CURSOR:
6924 if (!xw->misc.titeInhibit) {
6925 CursorSave(xw);
6926 }
6927 break;
6928 #if OPT_PASTE64 || OPT_READLINE
6929 case srm_PASTE_IN_BRACKET:
6930 SCREEN_FLAG_save(screen, paste_brackets);
6931 break;
6932 #endif
6933 #if OPT_READLINE
6934 case srm_BUTTON1_MOVE_POINT:
6935 SCREEN_FLAG_save(screen, click1_moves);
6936 break;
6937 case srm_BUTTON2_MOVE_POINT:
6938 SCREEN_FLAG_save(screen, paste_moves);
6939 break;
6940 case srm_DBUTTON3_DELETE:
6941 SCREEN_FLAG_save(screen, dclick3_deletes);
6942 break;
6943 case srm_PASTE_QUOTE:
6944 SCREEN_FLAG_save(screen, paste_quotes);
6945 break;
6946 case srm_PASTE_LITERAL_NL:
6947 SCREEN_FLAG_save(screen, paste_literal_nl);
6948 break;
6949 #endif /* OPT_READLINE */
6950 #if OPT_GRAPHICS
6951 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */
6952 TRACE(("save PRIVATE_COLOR_REGISTERS %s\n",
6953 BtoS(screen->privatecolorregisters)));
6954 DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
6955 update_privatecolorregisters();
6956 break;
6957 #endif
6958 #if OPT_SIXEL_GRAPHICS
6959 case srm_SIXEL_SCROLLS_RIGHT:
6960 TRACE(("save SIXEL_SCROLLS_RIGHT %s\n",
6961 BtoS(screen->sixel_scrolls_right)));
6962 DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
6963 break;
6964 #endif
6965 }
6966 }
6967 }
6968
6969 /*
6970 * process xterm private modes restore
6971 */
6972 static void
restoremodes(XtermWidget xw)6973 restoremodes(XtermWidget xw)
6974 {
6975 TScreen *screen = TScreenOf(xw);
6976 int i, j;
6977
6978 for (i = 0; i < nparam; i++) {
6979 int code = GetParam(i);
6980
6981 TRACE(("restoremodes %d\n", code));
6982 switch ((DECSET_codes) code) {
6983 case srm_DECCKM:
6984 bitcpy(&xw->keyboard.flags,
6985 screen->save_modes[DP_DECCKM], MODE_DECCKM);
6986 update_appcursor();
6987 break;
6988 case srm_DECANM: /* ANSI/VT52 mode */
6989 /* no effect */
6990 break;
6991 case srm_DECCOLM:
6992 if (screen->c132) {
6993 if (!(xw->flags & NOCLEAR_COLM))
6994 ClearScreen(xw);
6995 CursorSet(screen, 0, 0, xw->flags);
6996 if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS)
6997 ? 132 : 80) != ((xw->flags & IN132COLUMNS)
6998 ? 132 : 80) || j != MaxCols(screen))
6999 RequestResize(xw, -1, j, True);
7000 bitcpy(&xw->flags,
7001 screen->save_modes[DP_DECCOLM],
7002 IN132COLUMNS);
7003 }
7004 break;
7005 case srm_DECSCLM: /* (slow scroll) */
7006 if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) {
7007 screen->jumpscroll = 0;
7008 if (screen->scroll_amt)
7009 FlushScroll(xw);
7010 } else
7011 screen->jumpscroll = 1;
7012 bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL);
7013 update_jumpscroll();
7014 break;
7015 case srm_DECSCNM:
7016 if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) {
7017 bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO);
7018 ReverseVideo(xw);
7019 /* update_reversevideo done in RevVid */
7020 }
7021 break;
7022 case srm_DECOM:
7023 bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN);
7024 CursorSet(screen, 0, 0, xw->flags);
7025 break;
7026
7027 case srm_DECAWM:
7028 bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND);
7029 update_autowrap();
7030 break;
7031 case srm_DECARM:
7032 /* ignore autorepeat */
7033 break;
7034 case srm_X10_MOUSE: /* MIT bogus sequence */
7035 DoRM0(DP_X_X10MSE, screen->send_mouse_pos);
7036 really_set_mousemode(xw,
7037 screen->send_mouse_pos != MOUSE_OFF,
7038 (XtermMouseModes) screen->send_mouse_pos);
7039 break;
7040 #if OPT_TOOLBAR
7041 case srm_RXVT_TOOLBAR:
7042 DoRM(DP_TOOLBAR, resource.toolBar);
7043 ShowToolbar(resource.toolBar);
7044 break;
7045 #endif
7046 #if OPT_BLINK_CURS
7047 case srm_ATT610_BLINK: /* Start/stop blinking cursor */
7048 if (SettableCursorBlink(screen)) {
7049 DoRM(DP_CRS_BLINK, screen->cursor_blink_esc);
7050 UpdateCursorBlink(xw);
7051 }
7052 break;
7053 case srm_CURSOR_BLINK_OPS:
7054 /* intentionally ignored (this is user-preference) */
7055 break;
7056 case srm_XOR_CURSOR_BLINKS:
7057 /* intentionally ignored (this is user-preference) */
7058 break;
7059 #endif
7060 case srm_DECPFF: /* print form feed */
7061 DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed);
7062 break;
7063 case srm_DECPEX: /* print extent */
7064 DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent);
7065 break;
7066 case srm_DECTCEM: /* Show/hide cursor (VT200) */
7067 DoRM(DP_CRS_VISIBLE, screen->cursor_set);
7068 updateCursor(xw);
7069 break;
7070 case srm_RXVT_SCROLLBAR:
7071 if ((screen->fullVwin.sb_info.width != 0) !=
7072 screen->save_modes[DP_RXVT_SCROLLBAR]) {
7073 ToggleScrollBar(xw);
7074 }
7075 break;
7076 #if OPT_SHIFT_FONTS
7077 case srm_RXVT_FONTSIZE:
7078 DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts);
7079 break;
7080 #endif
7081 #if OPT_TEK4014
7082 case srm_DECTEK:
7083 if (!(screen->inhibit & I_TEK) &&
7084 (TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) {
7085 FlushLog(xw);
7086 TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK];
7087 update_vttekmode();
7088 }
7089 break;
7090 #endif
7091 case srm_132COLS: /* 132 column mode */
7092 DoRM(DP_X_DECCOLM, screen->c132);
7093 update_allow132();
7094 break;
7095 case srm_CURSES_HACK: /* curses hack */
7096 DoRM(DP_X_MORE, screen->curses);
7097 update_cursesemul();
7098 break;
7099 case srm_DECNRCM: /* national charset (VT220) */
7100 if (screen->vtXX_level >= 2) {
7101 if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL))
7102 modified_DECNRCM(xw);
7103 }
7104 break;
7105 #if OPT_PRINT_GRAPHICS
7106 case srm_DECGEPM: /* Graphics Expanded Print Mode */
7107 DoRM(DP_DECGEPM, screen->graphics_expanded_print_mode);
7108 break;
7109 #endif
7110 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */
7111 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCM, screen->graphics_print_color_mode)) {
7112 if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0)
7113 screen->bellArmed = -1;
7114 update_marginbell();
7115 }
7116 break;
7117 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */
7118 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCS, screen->graphics_print_color_syntax)) {
7119 bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP);
7120 update_reversewrap();
7121 }
7122 break;
7123 #ifdef ALLOWLOGGING
7124 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */
7125 if_PRINT_GRAPHICS2(DoRM(DP_DECGPBM, screen->graphics_print_background_mode)) {
7126 #ifdef ALLOWLOGFILEONOFF
7127 if (screen->save_modes[DP_X_LOGGING])
7128 StartLog(xw);
7129 else
7130 CloseLog(xw);
7131 #endif /* ALLOWLOGFILEONOFF */
7132 /* update_logging done by StartLog and CloseLog */
7133 }
7134 break;
7135 #elif OPT_PRINT_GRAPHICS
7136 case srm_DECGPBM: /* Graphics Print Background Mode */
7137 DoRM(DP_DECGPBM, screen->graphics_print_background_mode);
7138 break;
7139 #endif /* ALLOWLOGGING */
7140 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */
7141 /* FALLTHRU */
7142 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */
7143 if (!xw->misc.titeInhibit) {
7144 if (screen->save_modes[DP_X_ALTBUF])
7145 ToAlternate(xw, False);
7146 else
7147 FromAlternate(xw);
7148 /* update_altscreen done by ToAlt and FromAlt */
7149 } else if (screen->save_modes[DP_X_ALTBUF]) {
7150 do_ti_xtra_scroll(xw);
7151 }
7152 break;
7153 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */
7154 if_PRINT_GRAPHICS2(DoRM(DP_DECGRPM, screen->graphics_rotated_print_mode)) {
7155 if (!xw->misc.titeInhibit) {
7156 if (screen->save_modes[DP_X_ALTBUF])
7157 ToAlternate(xw, False);
7158 else
7159 FromAlternate(xw);
7160 /* update_altscreen done by ToAlt and FromAlt */
7161 } else if (screen->save_modes[DP_X_ALTBUF]) {
7162 do_ti_xtra_scroll(xw);
7163 }
7164 }
7165 break;
7166 case srm_DECNKM:
7167 bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM);
7168 update_appkeypad();
7169 break;
7170 case srm_DECBKM: /* backarrow mapping */
7171 bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM);
7172 update_decbkm();
7173 break;
7174 case srm_DECLRMM: /* left-right */
7175 bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT);
7176 if (IsLeftRightMode(xw)) {
7177 xterm_ResetDouble(xw);
7178 } else {
7179 reset_lr_margins(screen);
7180 }
7181 break;
7182 #if OPT_SIXEL_GRAPHICS
7183 case srm_DECSDM: /* sixel scrolling */
7184 bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM);
7185 update_decsdm();
7186 break;
7187 #endif
7188 case srm_DECNCSM: /* noclear */
7189 bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM);
7190 break;
7191 case srm_VT200_MOUSE: /* mouse bogus sequence */
7192 /* FALLTHRU */
7193 case srm_VT200_HIGHLIGHT_MOUSE:
7194 /* FALLTHRU */
7195 case srm_BTN_EVENT_MOUSE:
7196 /* FALLTHRU */
7197 case srm_ANY_EVENT_MOUSE:
7198 DoRM0(DP_X_MOUSE, screen->send_mouse_pos);
7199 really_set_mousemode(xw,
7200 screen->send_mouse_pos != MOUSE_OFF,
7201 (XtermMouseModes) screen->send_mouse_pos);
7202 break;
7203 #if OPT_FOCUS_EVENT
7204 case srm_FOCUS_EVENT_MOUSE:
7205 DoRM(DP_X_FOCUS, screen->send_focus_pos);
7206 break;
7207 #endif
7208 case srm_EXT_MODE_MOUSE:
7209 /* FALLTHRU */
7210 case srm_SGR_EXT_MODE_MOUSE:
7211 /* FALLTHRU */
7212 case srm_URXVT_EXT_MODE_MOUSE:
7213 /* FALLTHRU */
7214 case srm_PIXEL_POSITION_MOUSE:
7215 DoRM(DP_X_EXT_MOUSE, screen->extend_coords);
7216 break;
7217 case srm_ALLOW_ALTBUF:
7218 DoRM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit);
7219 if (xw->misc.titeInhibit)
7220 FromAlternate(xw);
7221 update_titeInhibit();
7222 break;
7223 case srm_SAVE_CURSOR:
7224 if (!xw->misc.titeInhibit) {
7225 CursorRestore(xw);
7226 }
7227 break;
7228 case srm_ALTERNATE_SCROLL:
7229 DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll);
7230 break;
7231 case srm_RXVT_SCROLL_TTY_OUTPUT:
7232 DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput);
7233 update_scrollttyoutput();
7234 break;
7235 case srm_RXVT_SCROLL_TTY_KEYPRESS:
7236 DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey);
7237 update_scrollkey();
7238 break;
7239 case srm_EIGHT_BIT_META:
7240 DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta);
7241 break;
7242 #if OPT_NUM_LOCK
7243 case srm_REAL_NUMLOCK:
7244 DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock);
7245 update_num_lock();
7246 break;
7247 case srm_META_SENDS_ESC:
7248 DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc);
7249 update_meta_esc();
7250 break;
7251 #endif
7252 case srm_DELETE_IS_DEL:
7253 DoRM(DP_DELETE_IS_DEL, screen->delete_is_del);
7254 update_delete_del();
7255 break;
7256 #if OPT_NUM_LOCK
7257 case srm_ALT_SENDS_ESC:
7258 DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc);
7259 update_alt_esc();
7260 break;
7261 #endif
7262 case srm_KEEP_SELECTION:
7263 DoRM(DP_KEEP_SELECTION, screen->keepSelection);
7264 update_keepSelection();
7265 break;
7266 case srm_SELECT_TO_CLIPBOARD:
7267 DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard);
7268 update_selectToClipboard();
7269 break;
7270 case srm_BELL_IS_URGENT:
7271 DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent);
7272 update_bellIsUrgent();
7273 break;
7274 case srm_POP_ON_BELL:
7275 DoRM(DP_POP_ON_BELL, screen->poponbell);
7276 update_poponbell();
7277 break;
7278 case srm_KEEP_CLIPBOARD:
7279 DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard);
7280 update_keepClipboard();
7281 break;
7282 #if OPT_TCAP_FKEYS
7283 case srm_TCAP_FKEYS:
7284 /* FALLTHRU */
7285 #endif
7286 #if OPT_SUN_FUNC_KEYS
7287 case srm_SUN_FKEYS:
7288 /* FALLTHRU */
7289 #endif
7290 #if OPT_HP_FUNC_KEYS
7291 case srm_HP_FKEYS:
7292 /* FALLTHRU */
7293 #endif
7294 #if OPT_SCO_FUNC_KEYS
7295 case srm_SCO_FKEYS:
7296 /* FALLTHRU */
7297 #endif
7298 #if OPT_SUNPC_KBD
7299 case srm_VT220_FKEYS:
7300 /* FALLTHRU */
7301 #endif
7302 case srm_LEGACY_FKEYS:
7303 xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE];
7304 break;
7305 #if OPT_PASTE64 || OPT_READLINE
7306 case srm_PASTE_IN_BRACKET:
7307 SCREEN_FLAG_restore(screen, paste_brackets);
7308 break;
7309 #endif
7310 #if OPT_READLINE
7311 case srm_BUTTON1_MOVE_POINT:
7312 SCREEN_FLAG_restore(screen, click1_moves);
7313 break;
7314 case srm_BUTTON2_MOVE_POINT:
7315 SCREEN_FLAG_restore(screen, paste_moves);
7316 break;
7317 case srm_DBUTTON3_DELETE:
7318 SCREEN_FLAG_restore(screen, dclick3_deletes);
7319 break;
7320 case srm_PASTE_QUOTE:
7321 SCREEN_FLAG_restore(screen, paste_quotes);
7322 break;
7323 case srm_PASTE_LITERAL_NL:
7324 SCREEN_FLAG_restore(screen, paste_literal_nl);
7325 break;
7326 #endif /* OPT_READLINE */
7327 #if OPT_GRAPHICS
7328 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */
7329 TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n",
7330 BtoS(screen->privatecolorregisters)));
7331 DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters);
7332 TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n",
7333 BtoS(screen->privatecolorregisters)));
7334 update_privatecolorregisters();
7335 break;
7336 #endif
7337 #if OPT_SIXEL_GRAPHICS
7338 case srm_SIXEL_SCROLLS_RIGHT:
7339 TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n",
7340 BtoS(screen->sixel_scrolls_right)));
7341 DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right);
7342 TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n",
7343 BtoS(screen->sixel_scrolls_right)));
7344 break;
7345 #endif
7346 }
7347 }
7348 }
7349
7350 /*
7351 * Convert an XTextProperty to a string.
7352 *
7353 * This frees the data owned by the XTextProperty, and returns in its place the
7354 * string, which must be freed by the caller.
7355 */
7356 static char *
property_to_string(XtermWidget xw,XTextProperty * text)7357 property_to_string(XtermWidget xw, XTextProperty * text)
7358 {
7359 TScreen *screen = TScreenOf(xw);
7360 Display *dpy = screen->display;
7361 char *result = 0;
7362 char **list = NULL;
7363 int length = 0;
7364 int rc;
7365
7366 TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n",
7367 text->value,
7368 TraceAtomName(dpy, text->encoding),
7369 text->format,
7370 text->nitems));
7371
7372 #if OPT_WIDE_CHARS
7373 /*
7374 * We will use the XmbTextPropertyToTextList call to extract UTF-8 data.
7375 * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to
7376 * ISO-8859-1.
7377 */
7378 rc = -1;
7379 if ((text->format != 8)
7380 || IsTitleMode(xw, tmGetUtf8)
7381 || (text->encoding == XA_UTF8_STRING(dpy) &&
7382 !(screen->wide_chars || screen->c1_printable) &&
7383 (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0)
7384 || (rc < 0))
7385 #endif
7386 if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0)
7387 rc = XTextPropertyToStringList(text, &list, &length);
7388
7389 if (rc >= 0) {
7390 int n, c, pass;
7391 size_t need;
7392
7393 for (pass = 0; pass < 2; ++pass) {
7394 for (n = 0, need = 0; n < length; n++) {
7395 char *s = list[n];
7396 while ((c = *s++) != '\0') {
7397 if (pass)
7398 result[need] = (char) c;
7399 ++need;
7400 }
7401 }
7402 if (pass)
7403 result[need] = '\0';
7404 else
7405 result = malloc(need + 1);
7406 if (result == 0)
7407 break;
7408 }
7409 XFreeStringList(list);
7410 }
7411 if (text->value != 0)
7412 XFree(text->value);
7413
7414 return result;
7415 }
7416
7417 static char *
get_icon_label(XtermWidget xw)7418 get_icon_label(XtermWidget xw)
7419 {
7420 XTextProperty text;
7421 char *result = 0;
7422
7423 if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
7424 result = property_to_string(xw, &text);
7425 }
7426 return result;
7427 }
7428
7429 static char *
get_window_label(XtermWidget xw)7430 get_window_label(XtermWidget xw)
7431 {
7432 XTextProperty text;
7433 char *result = 0;
7434
7435 if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) {
7436 result = property_to_string(xw, &text);
7437 }
7438 return result;
7439 }
7440
7441 /*
7442 * Report window label (icon or title) in dtterm protocol
7443 * ESC ] code label ESC backslash
7444 */
7445 static void
report_win_label(XtermWidget xw,int code,char * text)7446 report_win_label(XtermWidget xw,
7447 int code,
7448 char *text)
7449 {
7450 unparseputc(xw, ANSI_ESC);
7451 unparseputc(xw, ']');
7452 unparseputc(xw, code);
7453
7454 if (text != 0) {
7455 int copy = IsTitleMode(xw, tmGetBase16);
7456 if (copy) {
7457 TRACE(("Encoding hex:%s\n", text));
7458 text = x_encode_hex(text);
7459 }
7460 unparseputs(xw, text);
7461 if (copy)
7462 free(text);
7463 }
7464
7465 unparseputc(xw, ANSI_ESC);
7466 unparseputc(xw, '\\'); /* should be ST */
7467 unparse_end(xw);
7468 }
7469
7470 /*
7471 * Window operations (from CDE dtterm description, as well as extensions).
7472 * See also "allowWindowOps" resource.
7473 */
7474 static void
window_ops(XtermWidget xw)7475 window_ops(XtermWidget xw)
7476 {
7477 TScreen *screen = TScreenOf(xw);
7478 XWindowChanges values;
7479 XWindowAttributes win_attrs;
7480 #if OPT_MAXIMIZE
7481 unsigned root_width;
7482 unsigned root_height;
7483 #endif
7484 int code = zero_if_default(0);
7485 char *label;
7486
7487 TRACE(("window_ops %d\n", code));
7488 switch (code) {
7489 case ewRestoreWin: /* Restore (de-iconify) window */
7490 if (AllowWindowOps(xw, ewRestoreWin)) {
7491 xtermDeiconify(xw);
7492 }
7493 break;
7494
7495 case ewMinimizeWin: /* Minimize (iconify) window */
7496 if (AllowWindowOps(xw, ewMinimizeWin)) {
7497 xtermIconify(xw);
7498 }
7499 break;
7500
7501 case ewSetWinPosition: /* Move the window to the given position */
7502 if (AllowWindowOps(xw, ewSetWinPosition)) {
7503 unsigned value_mask;
7504
7505 values.x = (Position) zero_if_default(1);
7506 values.y = (Position) zero_if_default(2);
7507 TRACE(("...move window to %d,%d\n", values.x, values.y));
7508 value_mask = (CWX | CWY);
7509 XReconfigureWMWindow(screen->display,
7510 VShellWindow(xw),
7511 DefaultScreen(screen->display),
7512 value_mask,
7513 &values);
7514 }
7515 break;
7516
7517 case ewSetWinSizePixels: /* Resize the window to given size in pixels */
7518 if (AllowWindowOps(xw, ewSetWinSizePixels)) {
7519 RequestResize(xw, optional_param(1), optional_param(2), False);
7520 }
7521 break;
7522
7523 case ewRaiseWin: /* Raise the window to the front of the stack */
7524 if (AllowWindowOps(xw, ewRaiseWin)) {
7525 TRACE(("...raise window\n"));
7526 XRaiseWindow(screen->display, VShellWindow(xw));
7527 }
7528 break;
7529
7530 case ewLowerWin: /* Lower the window to the bottom of the stack */
7531 if (AllowWindowOps(xw, ewLowerWin)) {
7532 TRACE(("...lower window\n"));
7533 XLowerWindow(screen->display, VShellWindow(xw));
7534 }
7535 break;
7536
7537 case ewRefreshWin: /* Refresh the window */
7538 if (AllowWindowOps(xw, ewRefreshWin)) {
7539 TRACE(("...redraw window\n"));
7540 Redraw();
7541 }
7542 break;
7543
7544 case ewSetWinSizeChars: /* Resize the text-area, in characters */
7545 if (AllowWindowOps(xw, ewSetWinSizeChars)) {
7546 RequestResize(xw, optional_param(1), optional_param(2), True);
7547 }
7548 break;
7549
7550 #if OPT_MAXIMIZE
7551 case ewMaximizeWin: /* Maximize or restore */
7552 if (AllowWindowOps(xw, ewMaximizeWin)) {
7553 RequestMaximize(xw, zero_if_default(1));
7554 }
7555 break;
7556 case ewFullscreenWin: /* Fullscreen or restore */
7557 if (AllowWindowOps(xw, ewFullscreenWin)) {
7558 switch (zero_if_default(1)) {
7559 default:
7560 RequestMaximize(xw, 0);
7561 break;
7562 case 1:
7563 RequestMaximize(xw, 1);
7564 break;
7565 case 2:
7566 RequestMaximize(xw, !(screen->restore_data));
7567 break;
7568 }
7569 }
7570 break;
7571 #endif
7572
7573 case ewGetWinState: /* Report the window's state */
7574 if (AllowWindowOps(xw, ewGetWinState)) {
7575 TRACE(("...get window attributes\n"));
7576 init_reply(ANSI_CSI);
7577 reply.a_pintro = 0;
7578 reply.a_nparam = 1;
7579 reply.a_param[0] = (ParmType) (xtermIsIconified(xw) ? 2 : 1);
7580 reply.a_inters = 0;
7581 reply.a_final = 't';
7582 unparseseq(xw, &reply);
7583 }
7584 break;
7585
7586 case ewGetWinPosition: /* Report the window's position */
7587 if (AllowWindowOps(xw, ewGetWinPosition)) {
7588 Window win;
7589 Window result_win;
7590 int result_y, result_x;
7591
7592 TRACE(("...get window position\n"));
7593 init_reply(ANSI_CSI);
7594 reply.a_pintro = 0;
7595 reply.a_nparam = 3;
7596 reply.a_param[0] = 3;
7597 switch (zero_if_default(1)) {
7598 case 2: /* report the text-window's position */
7599 result_y = 0;
7600 result_x = 0;
7601 {
7602 Widget mw;
7603 for (mw = (Widget) xw; mw != 0; mw = XtParent(mw)) {
7604 result_x += mw->core.x;
7605 result_y += mw->core.y;
7606 if (mw == SHELL_OF(xw))
7607 break;
7608 }
7609 }
7610 result_x += OriginX(screen);
7611 result_y += OriginY(screen);
7612 break;
7613 default:
7614 win = WMFrameWindow(xw);
7615 xtermGetWinAttrs(screen->display,
7616 win,
7617 &win_attrs);
7618 XTranslateCoordinates(screen->display,
7619 VShellWindow(xw),
7620 win_attrs.root,
7621 -win_attrs.border_width,
7622 -win_attrs.border_width,
7623 &result_x, &result_y, &result_win);
7624 TRACE(("translated position %d,%d vs %d,%d\n",
7625 result_y, result_x,
7626 win_attrs.y, win_attrs.x));
7627 if (!discount_frame_extents(xw, &result_y, &result_x)) {
7628 TRACE(("...cancelled translation\n"));
7629 result_y = win_attrs.y;
7630 result_x = win_attrs.x;
7631 }
7632 break;
7633 }
7634 reply.a_param[1] = (ParmType) result_x;
7635 reply.a_param[2] = (ParmType) result_y;
7636 reply.a_inters = 0;
7637 reply.a_final = 't';
7638 unparseseq(xw, &reply);
7639 }
7640 break;
7641
7642 case ewGetWinSizePixels: /* Report the window's size in pixels */
7643 if (AllowWindowOps(xw, ewGetWinSizePixels)) {
7644 ParmType high = (ParmType) Height(screen);
7645 ParmType wide = (ParmType) Width(screen);
7646
7647 TRACE(("...get window size in pixels\n"));
7648 init_reply(ANSI_CSI);
7649 reply.a_pintro = 0;
7650 reply.a_nparam = 3;
7651 reply.a_param[0] = 4;
7652 switch (zero_if_default(1)) {
7653 case 2: /* report the shell-window's size */
7654 xtermGetWinAttrs(screen->display,
7655 WMFrameWindow(xw),
7656 &win_attrs);
7657 high = (ParmType) win_attrs.height;
7658 wide = (ParmType) win_attrs.width;
7659 /* FALLTHRU */
7660 default:
7661 reply.a_param[1] = high;
7662 reply.a_param[2] = wide;
7663 break;
7664 }
7665 reply.a_inters = 0;
7666 reply.a_final = 't';
7667 unparseseq(xw, &reply);
7668 }
7669 break;
7670
7671 #if OPT_MAXIMIZE
7672 case ewGetScreenSizePixels: /* Report the screen's size, in Pixels */
7673 if (AllowWindowOps(xw, ewGetScreenSizePixels)) {
7674 TRACE(("...get screen size in pixels\n"));
7675 (void) QueryMaximize(xw, &root_width, &root_height);
7676 init_reply(ANSI_CSI);
7677 reply.a_pintro = 0;
7678 reply.a_nparam = 3;
7679 reply.a_param[0] = 5;
7680 reply.a_param[1] = (ParmType) root_height;
7681 reply.a_param[2] = (ParmType) root_width;
7682 reply.a_inters = 0;
7683 reply.a_final = 't';
7684 unparseseq(xw, &reply);
7685 }
7686 break;
7687 case ewGetCharSizePixels: /* Report the font's size, in pixel */
7688 if (AllowWindowOps(xw, ewGetScreenSizeChars)) {
7689 TRACE(("...get font size in pixels\n"));
7690 TRACE(("...using font size %dx%d\n",
7691 FontHeight(screen),
7692 FontWidth(screen)));
7693 init_reply(ANSI_CSI);
7694 reply.a_pintro = 0;
7695 reply.a_nparam = 3;
7696 reply.a_param[0] = 6;
7697 reply.a_param[1] = (ParmType) FontHeight(screen);
7698 reply.a_param[2] = (ParmType) FontWidth(screen);
7699 reply.a_inters = 0;
7700 reply.a_final = 't';
7701 unparseseq(xw, &reply);
7702 }
7703 break;
7704 #endif
7705
7706 case ewGetWinSizeChars: /* Report the text's size in characters */
7707 if (AllowWindowOps(xw, ewGetWinSizeChars)) {
7708 TRACE(("...get window size in characters\n"));
7709 init_reply(ANSI_CSI);
7710 reply.a_pintro = 0;
7711 reply.a_nparam = 3;
7712 reply.a_param[0] = 8;
7713 reply.a_param[1] = (ParmType) MaxRows(screen);
7714 reply.a_param[2] = (ParmType) MaxCols(screen);
7715 reply.a_inters = 0;
7716 reply.a_final = 't';
7717 unparseseq(xw, &reply);
7718 }
7719 break;
7720
7721 #if OPT_MAXIMIZE
7722 case ewGetScreenSizeChars: /* Report the screen's size, in characters */
7723 if (AllowWindowOps(xw, ewGetScreenSizeChars)) {
7724 TRACE(("...get screen size in characters\n"));
7725 TRACE(("...using font size %dx%d\n",
7726 FontHeight(screen),
7727 FontWidth(screen)));
7728 (void) QueryMaximize(xw, &root_width, &root_height);
7729 init_reply(ANSI_CSI);
7730 reply.a_pintro = 0;
7731 reply.a_nparam = 3;
7732 reply.a_param[0] = 9;
7733 reply.a_param[1] = (ParmType) (root_height
7734 / (unsigned) FontHeight(screen));
7735 reply.a_param[2] = (ParmType) (root_width
7736 / (unsigned) FontWidth(screen));
7737 reply.a_inters = 0;
7738 reply.a_final = 't';
7739 unparseseq(xw, &reply);
7740 }
7741 break;
7742 #endif
7743
7744 case ewGetIconTitle: /* Report the icon's label */
7745 if (AllowWindowOps(xw, ewGetIconTitle)) {
7746 TRACE(("...get icon's label\n"));
7747 report_win_label(xw, 'L', label = get_icon_label(xw));
7748 free(label);
7749 }
7750 break;
7751
7752 case ewGetWinTitle: /* Report the window's title */
7753 if (AllowWindowOps(xw, ewGetWinTitle)) {
7754 TRACE(("...get window's label\n"));
7755 report_win_label(xw, 'l', label = get_window_label(xw));
7756 free(label);
7757 }
7758 break;
7759
7760 case ewPushTitle: /* save the window's title(s) on stack */
7761 if (AllowWindowOps(xw, ewPushTitle)) {
7762 SaveTitle *last = screen->save_title;
7763 SaveTitle *item = TypeCalloc(SaveTitle);
7764
7765 TRACE(("...push title onto stack\n"));
7766 if (item != 0) {
7767 switch (zero_if_default(1)) {
7768 case 0:
7769 item->iconName = get_icon_label(xw);
7770 item->windowName = get_window_label(xw);
7771 break;
7772 case 1:
7773 item->iconName = get_icon_label(xw);
7774 break;
7775 case 2:
7776 item->windowName = get_window_label(xw);
7777 break;
7778 }
7779 item->next = last;
7780 if (item->iconName == 0) {
7781 item->iconName = ((last == 0)
7782 ? get_icon_label(xw)
7783 : x_strdup(last->iconName));
7784 }
7785 if (item->windowName == 0) {
7786 item->windowName = ((last == 0)
7787 ? get_window_label(xw)
7788 : x_strdup(last->windowName));
7789 }
7790 screen->save_title = item;
7791 }
7792 }
7793 break;
7794
7795 case ewPopTitle: /* restore the window's title(s) from stack */
7796 if (AllowWindowOps(xw, ewPopTitle)) {
7797 SaveTitle *item = screen->save_title;
7798
7799 TRACE(("...pop title off stack\n"));
7800 if (item != 0) {
7801 switch (zero_if_default(1)) {
7802 case 0:
7803 ChangeIconName(xw, item->iconName);
7804 ChangeTitle(xw, item->windowName);
7805 break;
7806 case 1:
7807 ChangeIconName(xw, item->iconName);
7808 break;
7809 case 2:
7810 ChangeTitle(xw, item->windowName);
7811 break;
7812 }
7813 screen->save_title = item->next;
7814 free(item->iconName);
7815 free(item->windowName);
7816 free(item);
7817 }
7818 }
7819 break;
7820
7821 default: /* DECSLPP (24, 25, 36, 48, 72, 144) */
7822 if (AllowWindowOps(xw, ewSetWinLines)) {
7823 if (code >= 24)
7824 RequestResize(xw, code, -1, True);
7825 }
7826 break;
7827 }
7828 }
7829
7830 /*
7831 * set a bit in a word given a pointer to the word and a mask.
7832 */
7833 static int
bitset(unsigned * p,unsigned mask)7834 bitset(unsigned *p, unsigned mask)
7835 {
7836 unsigned before = *p;
7837 *p |= mask;
7838 return (before != *p);
7839 }
7840
7841 /*
7842 * clear a bit in a word given a pointer to the word and a mask.
7843 */
7844 static int
bitclr(unsigned * p,unsigned mask)7845 bitclr(unsigned *p, unsigned mask)
7846 {
7847 unsigned before = *p;
7848 *p &= ~mask;
7849 return (before != *p);
7850 }
7851
7852 /*
7853 * Copy bits from one word to another, given a mask
7854 */
7855 static int
bitcpy(unsigned * p,unsigned q,unsigned mask)7856 bitcpy(unsigned *p, unsigned q, unsigned mask)
7857 {
7858 unsigned before = *p;
7859 bitclr(p, mask);
7860 bitset(p, q & mask);
7861 return (before != *p);
7862 }
7863
7864 void
unparseputc1(XtermWidget xw,int c)7865 unparseputc1(XtermWidget xw, int c)
7866 {
7867 if (c >= 0x80 && c <= 0x9F) {
7868 if (!TScreenOf(xw)->control_eight_bits) {
7869 unparseputc(xw, A2E(ANSI_ESC));
7870 c = A2E(c - 0x40);
7871 }
7872 }
7873 unparseputc(xw, c);
7874 }
7875
7876 void
unparseseq(XtermWidget xw,ANSI * ap)7877 unparseseq(XtermWidget xw, ANSI *ap)
7878 {
7879 int c;
7880
7881 assert(ap->a_nparam < NPARAM);
7882 unparseputc1(xw, c = ap->a_type);
7883 if (c == ANSI_ESC
7884 || c == ANSI_DCS
7885 || c == ANSI_CSI
7886 || c == ANSI_OSC
7887 || c == ANSI_PM
7888 || c == ANSI_APC
7889 || c == ANSI_SS3) {
7890 int i;
7891 int inters;
7892 char temp[8];
7893
7894 if (ap->a_pintro != 0)
7895 unparseputc(xw, ap->a_pintro);
7896 for (i = 0; i < ap->a_nparam; ++i) {
7897 if (i != 0) {
7898 if (ap->a_radix[i] == 1 || ap->a_radix[i - 1] == 1) {
7899 ;
7900 } else if (ap->a_delim) {
7901 unparseputs(xw, ap->a_delim);
7902 } else {
7903 unparseputc(xw, ';');
7904 }
7905 }
7906 switch (ap->a_radix[i]) {
7907 case 16:
7908 sprintf(temp, "%04X", ap->a_param[i] & 0xffff);
7909 unparseputs(xw, temp);
7910 break;
7911 case 1:
7912 unparseputc(xw, ap->a_param[i]);
7913 break;
7914 default:
7915 unparseputn(xw, (unsigned) (UParm) ap->a_param[i]);
7916 break;
7917 }
7918 }
7919 if ((inters = ap->a_inters) != 0) {
7920 for (i = 3; i >= 0; --i) {
7921 c = CharOf(inters >> (8 * i));
7922 if (c != 0)
7923 unparseputc(xw, c);
7924 }
7925 }
7926 switch (ap->a_type) {
7927 case ANSI_DCS:
7928 /* FALLTHRU */
7929 case ANSI_OSC:
7930 /* FALLTHRU */
7931 case ANSI_PM:
7932 /* FALLTHRU */
7933 case ANSI_APC:
7934 unparseputc1(xw, ANSI_ST);
7935 break;
7936 default:
7937 unparseputc(xw, (char) ap->a_final);
7938 break;
7939 }
7940 }
7941 unparse_end(xw);
7942 }
7943
7944 void
unparseputn(XtermWidget xw,unsigned n)7945 unparseputn(XtermWidget xw, unsigned n)
7946 {
7947 unsigned q;
7948
7949 q = n / 10;
7950 if (q != 0)
7951 unparseputn(xw, q);
7952 unparseputc(xw, (char) ('0' + (n % 10)));
7953 }
7954
7955 void
unparseputs(XtermWidget xw,const char * s)7956 unparseputs(XtermWidget xw, const char *s)
7957 {
7958 if (s != 0) {
7959 while (*s)
7960 unparseputc(xw, *s++);
7961 }
7962 }
7963
7964 void
unparseputc(XtermWidget xw,int c)7965 unparseputc(XtermWidget xw, int c)
7966 {
7967 TScreen *screen = TScreenOf(xw);
7968 IChar *buf = screen->unparse_bfr;
7969 unsigned len;
7970
7971 if ((screen->unparse_len + 2) >= screen->unparse_max)
7972 unparse_end(xw);
7973
7974 len = screen->unparse_len;
7975
7976 #if OPT_TCAP_QUERY
7977 /*
7978 * If we're returning a termcap string, it has to be translated since
7979 * a DCS must not contain any characters except for the normal 7-bit
7980 * printable ASCII (counting tab, carriage return, etc). For now,
7981 * just use hexadecimal for the whole thing.
7982 */
7983 if (screen->tc_query_code >= 0) {
7984 char tmp[3];
7985 sprintf(tmp, "%02X", c & 0xFF);
7986 buf[len++] = CharOf(tmp[0]);
7987 buf[len++] = CharOf(tmp[1]);
7988 } else
7989 #endif
7990 if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) {
7991 buf[len++] = '\n';
7992 }
7993
7994 screen->unparse_len = len;
7995
7996 /* If send/receive mode is reset, we echo characters locally */
7997 if ((xw->keyboard.flags & MODE_SRM) == 0) {
7998 doparsing(xw, (unsigned) c, &myState);
7999 }
8000 }
8001
8002 void
unparse_end(XtermWidget xw)8003 unparse_end(XtermWidget xw)
8004 {
8005 TScreen *screen = TScreenOf(xw);
8006
8007 #if OPT_TCAP_QUERY
8008 /*
8009 * tcap-query works by simulating key-presses, which ordinarily would be
8010 * flushed out at the end of each key. For better efficiency, do not do
8011 * the flush unless we are about to fill the buffer used to capture the
8012 * response.
8013 */
8014 if ((screen->tc_query_code >= 0)
8015 && (screen->unparse_len + 2 < screen->unparse_max)) {
8016 return;
8017 }
8018 #endif
8019 if (screen->unparse_len) {
8020 TRACE(("unparse_end %u:%s\n",
8021 screen->unparse_len,
8022 visibleIChars(screen->unparse_bfr, screen->unparse_len)));
8023 #ifdef VMS
8024 tt_write(screen->unparse_bfr, screen->unparse_len);
8025 #else /* VMS */
8026 writePtyData(screen->respond, screen->unparse_bfr, screen->unparse_len);
8027 #endif /* VMS */
8028 screen->unparse_len = 0;
8029 }
8030 }
8031
8032 void
ToggleAlternate(XtermWidget xw)8033 ToggleAlternate(XtermWidget xw)
8034 {
8035 if (TScreenOf(xw)->whichBuf)
8036 FromAlternate(xw);
8037 else
8038 ToAlternate(xw, False);
8039 }
8040
8041 static void
ToAlternate(XtermWidget xw,Bool clearFirst)8042 ToAlternate(XtermWidget xw, Bool clearFirst)
8043 {
8044 TScreen *screen = TScreenOf(xw);
8045
8046 if (screen->whichBuf == 0) {
8047 TRACE(("ToAlternate\n"));
8048 if (!screen->editBuf_index[1]) {
8049 screen->editBuf_index[1] = allocScrnBuf(xw,
8050 (unsigned) MaxRows(screen),
8051 (unsigned) MaxCols(screen),
8052 &screen->editBuf_data[1]);
8053 }
8054 SwitchBufs(xw, 1, clearFirst);
8055 screen->visbuf = screen->editBuf_index[screen->whichBuf];
8056 update_altscreen();
8057 }
8058 }
8059
8060 static void
FromAlternate(XtermWidget xw)8061 FromAlternate(XtermWidget xw)
8062 {
8063 TScreen *screen = TScreenOf(xw);
8064
8065 if (screen->whichBuf != 0) {
8066 TRACE(("FromAlternate\n"));
8067 if (screen->scroll_amt) {
8068 FlushScroll(xw);
8069 }
8070 SwitchBufs(xw, 0, False);
8071 screen->visbuf = screen->editBuf_index[screen->whichBuf];
8072 update_altscreen();
8073 }
8074 }
8075
8076 static void
SwitchBufs(XtermWidget xw,int toBuf,Bool clearFirst)8077 SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst)
8078 {
8079 TScreen *screen = TScreenOf(xw);
8080 int rows, top;
8081
8082 screen->whichBuf = toBuf;
8083 if (screen->cursor_state)
8084 HideCursor(xw);
8085
8086 rows = MaxRows(screen);
8087 SwitchBufPtrs(screen, toBuf);
8088
8089 if ((top = INX2ROW(screen, 0)) < rows) {
8090 if (screen->scroll_amt) {
8091 FlushScroll(xw);
8092 }
8093 xtermClear2(xw,
8094 (int) OriginX(screen),
8095 (int) top * FontHeight(screen) + screen->border,
8096 (unsigned) Width(screen),
8097 (unsigned) ((rows - top) * FontHeight(screen)));
8098 if (clearFirst) {
8099 ClearBufRows(xw, top, rows);
8100 }
8101 }
8102 ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False);
8103 }
8104
8105 Bool
CheckBufPtrs(TScreen * screen)8106 CheckBufPtrs(TScreen *screen)
8107 {
8108 return (screen->visbuf != 0
8109 && screen->editBuf_index[0] != 0
8110 && screen->editBuf_index[1] != 0);
8111 }
8112
8113 /*
8114 * Swap buffer line pointers between alternate and regular screens.
8115 */
8116 void
SwitchBufPtrs(TScreen * screen,int toBuf)8117 SwitchBufPtrs(TScreen *screen, int toBuf)
8118 {
8119 if (CheckBufPtrs(screen)) {
8120 screen->visbuf = screen->editBuf_index[toBuf];
8121 }
8122 }
8123
8124 void
VTRun(XtermWidget xw)8125 VTRun(XtermWidget xw)
8126 {
8127 TScreen *screen = TScreenOf(xw);
8128
8129 TRACE(("VTRun ...\n"));
8130
8131 if (!screen->Vshow) {
8132 set_vt_visibility(True);
8133 }
8134 update_vttekmode();
8135 update_vtshow();
8136 update_tekshow();
8137 set_vthide_sensitivity();
8138
8139 ScrnAllocBuf(xw);
8140
8141 screen->cursor_state = OFF;
8142 screen->cursor_set = ON;
8143 #if OPT_BLINK_CURS
8144 if (DoStartBlinking(screen))
8145 StartBlinking(xw);
8146 #endif
8147
8148 #if OPT_TEK4014
8149 if (Tpushb > Tpushback) {
8150 fillPtyData(xw, VTbuffer, (char *) Tpushback, (int) (Tpushb - Tpushback));
8151 Tpushb = Tpushback;
8152 }
8153 #endif
8154 screen->is_running = True;
8155 if (screen->embed_high && screen->embed_wide) {
8156 ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags));
8157 }
8158 #if OPT_MAXIMIZE
8159 else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways)
8160 FullScreen(xw, True);
8161 #endif
8162 if (!setjmp(VTend))
8163 VTparse(xw);
8164 StopBlinking(xw);
8165 HideCursor(xw);
8166 screen->cursor_set = OFF;
8167 TRACE(("... VTRun\n"));
8168 }
8169
8170 /*ARGSUSED*/
8171 static void
VTExpose(Widget w GCC_UNUSED,XEvent * event,Region region GCC_UNUSED)8172 VTExpose(Widget w GCC_UNUSED,
8173 XEvent *event,
8174 Region region GCC_UNUSED)
8175 {
8176 DEBUG_MSG("Expose\n");
8177 if (event->type == Expose)
8178 HandleExposure(term, event);
8179 }
8180
8181 static void
VTGraphicsOrNoExpose(XEvent * event)8182 VTGraphicsOrNoExpose(XEvent *event)
8183 {
8184 XtermWidget xw = term;
8185 TScreen *screen = TScreenOf(xw);
8186 if (screen->incopy <= 0) {
8187 screen->incopy = 1;
8188 if (screen->scrolls > 0)
8189 screen->scrolls--;
8190 }
8191 if (event->type == GraphicsExpose)
8192 if (HandleExposure(xw, event))
8193 screen->cursor_state = OFF;
8194 if ((event->type == NoExpose)
8195 || ((XGraphicsExposeEvent *) event)->count == 0) {
8196 if (screen->incopy <= 0 && screen->scrolls > 0)
8197 screen->scrolls--;
8198 if (screen->scrolls)
8199 screen->incopy = -1;
8200 else
8201 screen->incopy = 0;
8202 }
8203 }
8204
8205 /*ARGSUSED*/
8206 static void
VTNonMaskableEvent(Widget w GCC_UNUSED,XtPointer closure GCC_UNUSED,XEvent * event,Boolean * cont GCC_UNUSED)8207 VTNonMaskableEvent(Widget w GCC_UNUSED,
8208 XtPointer closure GCC_UNUSED,
8209 XEvent *event,
8210 Boolean *cont GCC_UNUSED)
8211 {
8212 switch (event->type) {
8213 case GraphicsExpose:
8214 /* FALLTHRU */
8215 case NoExpose:
8216 VTGraphicsOrNoExpose(event);
8217 break;
8218 }
8219 }
8220
8221 static void
VTResize(Widget w)8222 VTResize(Widget w)
8223 {
8224 if (XtIsRealized(w)) {
8225 XtermWidget xw = (XtermWidget) w;
8226 ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags);
8227 }
8228 }
8229
8230 #define okDimension(src,dst) ((src <= MAX_U_COORD) \
8231 && ((dst = (Dimension) src) == src))
8232
8233 static void
RequestResize(XtermWidget xw,int rows,int cols,Bool text)8234 RequestResize(XtermWidget xw, int rows, int cols, Bool text)
8235 {
8236 TScreen *screen = TScreenOf(xw);
8237 Dimension replyWidth, replyHeight;
8238 Dimension askedWidth, askedHeight;
8239 XtGeometryResult status;
8240 XWindowAttributes attrs;
8241 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
8242 Boolean buggyXft = False;
8243 Cardinal ignore = 0;
8244 #endif
8245
8246 TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text));
8247
8248 /* check first if the row/column values fit into a Dimension */
8249 if (cols > 0) {
8250 if ((int) (askedWidth = (Dimension) cols) < cols) {
8251 TRACE(("... cols too large for Dimension\n"));
8252 return;
8253 }
8254 } else {
8255 askedWidth = 0;
8256 }
8257 if (rows > 0) {
8258 if ((int) (askedHeight = (Dimension) rows) < rows) {
8259 TRACE(("... rows too large for Dimension\n"));
8260 return;
8261 }
8262 } else {
8263 askedHeight = 0;
8264 }
8265
8266 xw->work.doing_resize = True;
8267
8268 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
8269 /*
8270 * Work around a bug seen when vttest switches from 132 columns back to 80
8271 * columns, while double-buffering is active. If Xft is active during the
8272 * resize, the screen will be blank thereafter. This workaround causes
8273 * some extra flickering, but that is preferable to a blank screen.
8274 *
8275 * Since the bitmap- and TrueType-fonts do not always have identical sizes,
8276 * do this switching early, to use the updated font-sizes in the request
8277 * for resizing the window.
8278 */
8279 #define ToggleXft() HandleRenderFont((Widget)xw, (XEvent *)0, (String *)0, &ignore)
8280 if (resource.buffered
8281 && UsingRenderFont(xw)) {
8282 ToggleXft();
8283 buggyXft = True;
8284 }
8285 #endif
8286
8287 /*
8288 * If the requested values will fit into a Dimension, and one or both are
8289 * zero, get the current corresponding screen dimension to use as a limit.
8290 */
8291 if (askedHeight == 0
8292 || askedWidth == 0
8293 || xw->misc.limit_resize > 0) {
8294 xtermGetWinAttrs(XtDisplay(xw),
8295 RootWindowOfScreen(XtScreen(xw)), &attrs);
8296 }
8297
8298 /*
8299 * Using the current font metrics, translate the requested character
8300 * rows/columns into pixels.
8301 */
8302 if (text) {
8303 unsigned long value;
8304
8305 if ((value = (unsigned long) rows) != 0) {
8306 if (rows < 0)
8307 value = (unsigned long) MaxRows(screen);
8308 value *= (unsigned long) FontHeight(screen);
8309 value += (unsigned long) (2 * screen->border);
8310 if (!okDimension(value, askedHeight))
8311 goto give_up;
8312 }
8313
8314 if ((value = (unsigned long) cols) != 0) {
8315 if (cols < 0)
8316 value = (unsigned long) MaxCols(screen);
8317 value *= (unsigned long) FontWidth(screen);
8318 value += (unsigned long) ((2 * screen->border)
8319 + ScrollbarWidth(screen));
8320 if (!okDimension(value, askedWidth))
8321 goto give_up;
8322 }
8323
8324 } else {
8325 if (rows < 0)
8326 askedHeight = FullHeight(screen);
8327 if (cols < 0)
8328 askedWidth = FullWidth(screen);
8329 }
8330
8331 if (rows == 0) {
8332 askedHeight = (Dimension) attrs.height;
8333 }
8334 if (cols == 0) {
8335 askedWidth = (Dimension) attrs.width;
8336 }
8337
8338 if (xw->misc.limit_resize > 0) {
8339 Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height);
8340 Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width);
8341 if ((int) high < attrs.height)
8342 high = (Dimension) attrs.height;
8343 if (askedHeight > high)
8344 askedHeight = high;
8345 if ((int) wide < attrs.width)
8346 wide = (Dimension) attrs.width;
8347 if (askedWidth > wide)
8348 askedWidth = wide;
8349 }
8350 #ifndef nothack
8351 getXtermSizeHints(xw);
8352 #endif
8353
8354 TRACE(("...requesting resize %dx%d\n", askedHeight, askedWidth));
8355 status = REQ_RESIZE((Widget) xw,
8356 askedWidth, askedHeight,
8357 &replyWidth, &replyHeight);
8358
8359 if (status == XtGeometryYes ||
8360 status == XtGeometryDone) {
8361 ScreenResize(xw, replyWidth, replyHeight, &xw->flags);
8362 }
8363 #ifndef nothack
8364 /*
8365 * XtMakeResizeRequest() has the undesirable side-effect of clearing
8366 * the window manager's hints, even on a failed request. This would
8367 * presumably be fixed if the shell did its own work.
8368 */
8369 if (xw->hints.flags
8370 && replyHeight
8371 && replyWidth) {
8372 xw->hints.height = replyHeight;
8373 xw->hints.width = replyWidth;
8374
8375 TRACE(("%s@%d -- ", __FILE__, __LINE__));
8376 TRACE_HINTS(&xw->hints);
8377 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints);
8378 TRACE(("%s@%d -- ", __FILE__, __LINE__));
8379 TRACE_WM_HINTS(xw);
8380 }
8381 #endif
8382
8383 XSync(screen->display, False); /* synchronize */
8384 if (xtermAppPending()) {
8385 xevents(xw);
8386 }
8387
8388 give_up:
8389 #if OPT_RENDERFONT && USE_DOUBLE_BUFFER
8390 if (buggyXft) {
8391 ToggleXft();
8392 if (xtermAppPending()) {
8393 xevents(xw);
8394 }
8395 }
8396 #endif
8397
8398 xw->work.doing_resize = False;
8399
8400 TRACE(("...RequestResize done\n"));
8401 return;
8402 }
8403
8404 static String xterm_trans =
8405 "<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
8406 <MappingNotify>: KeyboardMapping()\n";
8407
8408 int
VTInit(XtermWidget xw)8409 VTInit(XtermWidget xw)
8410 {
8411 Widget vtparent = SHELL_OF(xw);
8412
8413 TRACE(("VTInit " TRACE_L "\n"));
8414
8415 XtRealizeWidget(vtparent);
8416 XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
8417 (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent),
8418 &wm_delete_window, 1);
8419
8420 if (IsEmpty(xw->keyboard.print_translations)) {
8421 TRACE_TRANS("shell", vtparent);
8422 TRACE_TRANS("vt100", (Widget) (xw));
8423 xtermButtonInit(xw);
8424 }
8425
8426 ScrnAllocBuf(xw);
8427
8428 TRACE(("..." TRACE_R " VTInit\n"));
8429 return (1);
8430 }
8431
8432 static void
VTClassInit(void)8433 VTClassInit(void)
8434 {
8435 XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
8436 (XtConvertArgList) NULL, (Cardinal) 0);
8437 }
8438
8439 /*
8440 * Override the use of XtDefaultForeground/XtDefaultBackground to make some
8441 * colors, such as cursor color, use the actual foreground/background value
8442 * if there is no explicit resource value used.
8443 */
8444 static Pixel
fill_Tres(XtermWidget target,XtermWidget source,int offset)8445 fill_Tres(XtermWidget target, XtermWidget source, int offset)
8446 {
8447 char *name;
8448 ScrnColors temp;
8449 TScreen *src = TScreenOf(source);
8450 TScreen *dst = TScreenOf(target);
8451
8452 dst->Tcolors[offset] = src->Tcolors[offset];
8453 dst->Tcolors[offset].mode = False;
8454
8455 if ((name = x_strtrim(dst->Tcolors[offset].resource)) != 0)
8456 dst->Tcolors[offset].resource = name;
8457
8458 if (name == 0) {
8459 dst->Tcolors[offset].value = target->dft_foreground;
8460 } else if (isDefaultForeground(name)) {
8461 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
8462 ? target->dft_foreground
8463 : dst->Tcolors[TEXT_FG].value);
8464 } else if (isDefaultBackground(name)) {
8465 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG)
8466 ? target->dft_background
8467 : dst->Tcolors[TEXT_BG].value);
8468 } else {
8469 memset(&temp, 0, sizeof(temp));
8470 if (AllocateTermColor(target, &temp, offset, name, True)) {
8471 if (COLOR_DEFINED(&(temp), offset))
8472 free(temp.names[offset]);
8473 dst->Tcolors[offset].value = temp.colors[offset];
8474 } else if (offset == TEXT_FG || offset == TEXT_BG) {
8475 free(name);
8476 dst->Tcolors[offset].resource = 0;
8477 }
8478 }
8479 return dst->Tcolors[offset].value;
8480 }
8481
8482 /*
8483 * If one or both of the foreground/background colors cannot be allocated,
8484 * e.g., due to gross misconfiguration, recover by setting both to the
8485 * display's default values.
8486 */
8487 static void
repairColors(XtermWidget target)8488 repairColors(XtermWidget target)
8489 {
8490 TScreen *screen = TScreenOf(target);
8491
8492 if (screen->Tcolors[TEXT_FG].resource == 0 ||
8493 screen->Tcolors[TEXT_BG].resource == 0) {
8494 xtermWarning("unable to allocate fg/bg colors\n");
8495 screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground);
8496 screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground);
8497 if (screen->Tcolors[TEXT_FG].resource == 0 ||
8498 screen->Tcolors[TEXT_BG].resource == 0) {
8499 Exit(1);
8500 }
8501 screen->Tcolors[TEXT_FG].value = target->dft_foreground;
8502 screen->Tcolors[TEXT_BG].value = target->dft_background;
8503 }
8504 }
8505
8506 #if OPT_WIDE_CHARS
8507 static void
set_utf8_feature(TScreen * screen,int * feature)8508 set_utf8_feature(TScreen *screen, int *feature)
8509 {
8510 if (*feature == uDefault) {
8511 switch (screen->utf8_mode) {
8512 case uFalse:
8513 /* FALLTHRU */
8514 case uTrue:
8515 *feature = screen->utf8_mode;
8516 break;
8517 case uDefault:
8518 /* should not happen */
8519 *feature = uTrue;
8520 break;
8521 case uAlways:
8522 /* use this to disable menu entry */
8523 break;
8524 }
8525 }
8526 }
8527
8528 static void
VTInitialize_locale(XtermWidget xw)8529 VTInitialize_locale(XtermWidget xw)
8530 {
8531 TScreen *screen = TScreenOf(xw);
8532 Bool is_utf8 = xtermEnvUTF8();
8533
8534 TRACE(("VTInitialize_locale\n"));
8535 TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode));
8536 TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts));
8537 TRACE(("... request screen.utf8_title = %d\n", screen->utf8_title));
8538
8539 screen->utf8_always = (screen->utf8_mode == uAlways);
8540 if (screen->utf8_mode < 0)
8541 screen->utf8_mode = uFalse;
8542
8543 if (screen->utf8_mode > 3)
8544 screen->utf8_mode = uDefault;
8545
8546 screen->latin9_mode = 0;
8547 screen->unicode_font = 0;
8548 #if OPT_LUIT_PROG
8549 xw->misc.callfilter = 0;
8550 xw->misc.use_encoding = 0;
8551
8552 TRACE(("... setup for luit:\n"));
8553 TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str));
8554
8555 if (screen->utf8_mode == uFalse) {
8556 TRACE(("... command-line +u8 overrides\n"));
8557 } else
8558 #if OPT_MINI_LUIT
8559 if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) {
8560 int fl = (int) strlen(DefaultFontN(xw));
8561 if (fl > 11
8562 && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) {
8563 screen->unicode_font = 1;
8564 /* unicode font, use True */
8565 #ifdef HAVE_LANGINFO_CODESET
8566 if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968")
8567 || !strcmp(xtermEnvEncoding(), "ISO-8859-1")) {
8568 if (screen->utf8_mode == uDefault)
8569 screen->utf8_mode = uFalse;
8570 } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) {
8571 if (screen->utf8_mode == uDefault)
8572 screen->utf8_mode = uFalse;
8573 screen->latin9_mode = 1;
8574 } else {
8575 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
8576 screen->utf8_mode = uAlways;
8577 }
8578 #else
8579 xw->misc.callfilter = is_utf8 ? 0 : 1;
8580 screen->utf8_mode = uAlways;
8581 #endif
8582 } else {
8583 /* other encoding, use False */
8584 if (screen->utf8_mode == uDefault) {
8585 screen->utf8_mode = is_utf8 ? uAlways : uFalse;
8586 }
8587 }
8588 } else
8589 #endif /* OPT_MINI_LUIT */
8590 if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 ||
8591 x_strcasecmp(xw->misc.locale_str, "ON") == 0 ||
8592 x_strcasecmp(xw->misc.locale_str, "YES") == 0 ||
8593 x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 ||
8594 strcmp(xw->misc.locale_str, "1") == 0) {
8595 /* when true ... fully obeying LC_CTYPE locale */
8596 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1);
8597 screen->utf8_mode = uAlways;
8598 } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 ||
8599 x_strcasecmp(xw->misc.locale_str, "OFF") == 0 ||
8600 x_strcasecmp(xw->misc.locale_str, "NO") == 0 ||
8601 strcmp(xw->misc.locale_str, "0") == 0) {
8602 /* when false ... original value of utf8_mode is effective */
8603 if (screen->utf8_mode == uDefault) {
8604 screen->utf8_mode = is_utf8 ? uAlways : uFalse;
8605 }
8606 } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 ||
8607 x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) {
8608 /* when medium ... obeying locale only for UTF-8 and Asian */
8609 if (is_utf8) {
8610 screen->utf8_mode = uAlways;
8611 } else if (
8612 #ifdef MB_CUR_MAX
8613 MB_CUR_MAX > 1 ||
8614 #else
8615 !strncmp(xtermEnvLocale(), "ja", (size_t) 2) ||
8616 !strncmp(xtermEnvLocale(), "ko", (size_t) 2) ||
8617 !strncmp(xtermEnvLocale(), "zh", (size_t) 2) ||
8618 #endif
8619 !strncmp(xtermEnvLocale(), "th", (size_t) 2) ||
8620 !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) {
8621 xw->misc.callfilter = 1;
8622 screen->utf8_mode = uAlways;
8623 } else {
8624 screen->utf8_mode = uFalse;
8625 }
8626 } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 ||
8627 x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) {
8628 /* when UTF-8 ... UTF-8 mode */
8629 screen->utf8_mode = uAlways;
8630 } else {
8631 /* other words are regarded as encoding name passed to luit */
8632 xw->misc.callfilter = 1;
8633 screen->utf8_mode = uAlways;
8634 xw->misc.use_encoding = 1;
8635 }
8636 TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter)));
8637 TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding)));
8638 #else
8639 if (screen->utf8_mode == uDefault) {
8640 screen->utf8_mode = is_utf8 ? uAlways : uFalse;
8641 }
8642 #endif /* OPT_LUIT_PROG */
8643
8644 set_utf8_feature(screen, &screen->utf8_fonts);
8645 set_utf8_feature(screen, &screen->utf8_title);
8646
8647 screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse);
8648
8649 TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode));
8650 TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts));
8651 TRACE(("... updated screen.utf8_title = %d\n", screen->utf8_title));
8652 TRACE(("...VTInitialize_locale done\n"));
8653 }
8654 #endif
8655
8656 void
lookupSelectUnit(XtermWidget xw,Cardinal item,String value)8657 lookupSelectUnit(XtermWidget xw, Cardinal item, String value)
8658 {
8659 /* *INDENT-OFF* */
8660 static const struct {
8661 const char * name;
8662 SelectUnit code;
8663 } table[] = {
8664 { "char", Select_CHAR },
8665 { "word", Select_WORD },
8666 { "line", Select_LINE },
8667 { "group", Select_GROUP },
8668 { "page", Select_PAGE },
8669 { "all", Select_ALL },
8670 #if OPT_SELECT_REGEX
8671 { "regex", Select_REGEX },
8672 #endif
8673 };
8674 /* *INDENT-ON* */
8675
8676 TScreen *screen = TScreenOf(xw);
8677 String next = x_skip_nonblanks(value);
8678 Cardinal n;
8679
8680 screen->selectMap[item] = NSELECTUNITS;
8681 for (n = 0; n < XtNumber(table); ++n) {
8682 if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) {
8683 screen->selectMap[item] = table[n].code;
8684 #if OPT_SELECT_REGEX
8685 if (table[n].code == Select_REGEX) {
8686 screen->selectExpr[item] = x_strtrim(next);
8687 TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item]));
8688 }
8689 #endif
8690 break;
8691 }
8692 }
8693 }
8694
8695 static void
ParseOnClicks(XtermWidget wnew,XtermWidget wreq,Cardinal item)8696 ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item)
8697 {
8698 lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]);
8699 }
8700
8701 /*
8702 * Parse a comma-separated list, returning a string which the caller must
8703 * free, and updating the source pointer.
8704 */
8705 static char *
ParseList(const char ** source)8706 ParseList(const char **source)
8707 {
8708 const char *base = *source;
8709 const char *next;
8710 char *value = 0;
8711 char *result;
8712
8713 /* ignore empty values */
8714 while (*base == ',')
8715 ++base;
8716
8717 if (*base != '\0') {
8718 size_t size;
8719
8720 next = base;
8721 while (*next != '\0' && *next != ',')
8722 ++next;
8723 size = (size_t) (1 + next - base);
8724 value = malloc(size);
8725 if (value != 0) {
8726 memcpy(value, base, size);
8727 value[size - 1] = '\0';
8728 }
8729 *source = next;
8730 } else {
8731 *source = base;
8732 }
8733 result = x_strtrim(value);
8734 free(value);
8735 return result;
8736 }
8737
8738 static void
set_flags_from_list(char * target,const char * source,const FlagList * list)8739 set_flags_from_list(char *target,
8740 const char *source,
8741 const FlagList * list)
8742 {
8743 Cardinal n;
8744
8745 while (!IsEmpty(source)) {
8746 char *next = ParseList(&source);
8747 Boolean found = False;
8748 char flag = 1;
8749
8750 if (next == 0)
8751 break;
8752 if (*next == '~') {
8753 flag = 0;
8754 next++;
8755 }
8756 if (isdigit(CharOf(*next))) {
8757 char *temp;
8758 int value = (int) strtol(next, &temp, 0);
8759 if (!FullS2L(next, temp)) {
8760 xtermWarning("Expected a number: %s\n", next);
8761 } else {
8762 for (n = 0; list[n].name != 0; ++n) {
8763 if (list[n].code == value) {
8764 target[value] = flag;
8765 found = True;
8766 TRACE(("...found %s (%d)\n", list[n].name, value));
8767 break;
8768 }
8769 }
8770 }
8771 } else {
8772 for (n = 0; list[n].name != 0; ++n) {
8773 if (!x_wildstrcmp(next, list[n].name)) {
8774 int value = list[n].code;
8775 target[value] = flag;
8776 found = True;
8777 TRACE(("...found %s (%d)\n", list[n].name, value));
8778 }
8779 }
8780 }
8781 if (!found) {
8782 xtermWarning("Unrecognized keyword: %s\n", next);
8783 }
8784 free(next);
8785 }
8786 }
8787
8788 #define InitCursorShape(target, source) \
8789 target->cursor_shape = source->cursor_underline \
8790 ? CURSOR_UNDERLINE \
8791 : CURSOR_BLOCK
8792
8793 #if OPT_XRES_QUERY
8794 static XtResource *
findVT100Resource(const char * name)8795 findVT100Resource(const char *name)
8796 {
8797 Cardinal n;
8798 XtResource *result = 0;
8799
8800 if (!IsEmpty(name)) {
8801 XrmQuark quarkName = XrmPermStringToQuark(name);
8802 for (n = 0; n < XtNumber(xterm_resources); ++n) {
8803 if ((int) xterm_resources[n].resource_offset >= 0
8804 && !strcmp(xterm_resources[n].resource_name, name)) {
8805 result = &xterm_resources[n];
8806 break;
8807 } else if (xterm_resources[n].resource_name
8808 == (String) (intptr_t) quarkName) {
8809 result = &xterm_resources[n];
8810 break;
8811 }
8812 }
8813 }
8814 return result;
8815 }
8816
8817 static int
cmp_resources(const void * a,const void * b)8818 cmp_resources(const void *a, const void *b)
8819 {
8820 return strcmp((*(const String *) a),
8821 (*(const String *) b));
8822 }
8823
8824 static void
reportResources(XtermWidget xw)8825 reportResources(XtermWidget xw)
8826 {
8827 String *list = TypeMallocN(String, XtNumber(xterm_resources));
8828 Cardinal n;
8829 int widest = 0;
8830
8831 if (list == NULL)
8832 return;
8833
8834 for (n = 0; n < XtNumber(xterm_resources); ++n) {
8835 int width;
8836 list[n] = (((int) xterm_resources[n].resource_offset < 0)
8837 ? XrmQuarkToString((XrmQuark) (intptr_t)
8838 xterm_resources[n].resource_name)
8839 : xterm_resources[n].resource_name);
8840 width = (int) strlen(list[n]);
8841 if (widest < width)
8842 widest = width;
8843 }
8844 qsort(list, (size_t) XtNumber(xterm_resources), sizeof(String), cmp_resources);
8845 for (n = 0; n < XtNumber(xterm_resources); ++n) {
8846 char *value = vt100ResourceToString(xw, list[n]);
8847 printf("%-*s : %s\n", widest, list[n], value ? value : "(skip)");
8848 free(value);
8849 }
8850 free(list);
8851 }
8852
8853 char *
vt100ResourceToString(XtermWidget xw,const char * name)8854 vt100ResourceToString(XtermWidget xw, const char *name)
8855 {
8856 XtResource *data;
8857 char *result = NULL;
8858
8859 if ((data = findVT100Resource(name)) != 0) {
8860 int fake_offset = (int) data->resource_offset;
8861 void *res_addr;
8862 int real_offset;
8863 String res_type;
8864
8865 /*
8866 * X Toolkit "compiles" the resource-list into quarks and changes the
8867 * resource-offset at the same time to a negative value.
8868 */
8869 if (fake_offset < 0) {
8870 real_offset = -(fake_offset + 1);
8871 res_type = XrmQuarkToString((XrmQuark) (intptr_t) data->resource_type);
8872 } else {
8873 real_offset = fake_offset;
8874 res_type = data->resource_type;
8875 }
8876 res_addr = (void *) ((char *) xw + real_offset);
8877
8878 if (!strcmp(res_type, XtRString)) {
8879 char *value = *(char **) res_addr;
8880 if (value != NULL) {
8881 size_t need = strlen(value);
8882 if ((result = malloc(1 + need)) != 0)
8883 strcpy(result, value);
8884 }
8885 } else if (!strcmp(res_type, XtRInt)) {
8886 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0)
8887 sprintf(result, "%d", *(int *) res_addr);
8888 } else if (!strcmp(res_type, XtRFloat)) {
8889 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0)
8890 sprintf(result, "%f", (double) (*(float *) res_addr));
8891 } else if (!strcmp(res_type, XtRBoolean)) {
8892 if ((result = malloc((size_t) 6)) != 0)
8893 strcpy(result, *(Boolean *) res_addr ? "true" : "false");
8894 }
8895 }
8896 TRACE(("vt100ResourceToString(%s) %s\n", name, NonNull(result)));
8897 return result;
8898 }
8899 #endif /* OPT_XRES_QUERY */
8900
8901 /*
8902 * Decode a terminal-ID or graphics-terminal-ID, using the default terminal-ID
8903 * if the value is outside a (looser) range than limitedTerminalID. This uses
8904 * a wider range, to avoid being a nuisance when using X resources with
8905 * different configurations of xterm.
8906 */
8907 static int
decodeTerminalID(const char * value)8908 decodeTerminalID(const char *value)
8909 {
8910 const char *s;
8911 char *t;
8912 long result;
8913
8914 for (s = value; *s; s++) {
8915 if (!isalpha(CharOf(*s)))
8916 break;
8917 }
8918 result = strtol(s, &t, 10);
8919 if (t == s || *t != '\0' || result <= 0L || result > 1000L) {
8920 xtermWarning("unexpected value for terminalID: \"%s\"\n", value);
8921 result = atoi(DFT_DECID);
8922 }
8923 TRACE(("decodeTerminalID \"%s\" ->%d\n", value, (int) result));
8924 return (int) result;
8925 }
8926
8927 /*
8928 * Ensures that the value returned by decodeTerminalID is either in the range
8929 * of IDs matching a known terminal, or (failing that), set to the built-in
8930 * default. The DA response relies on having the ID being set to a known
8931 * value.
8932 */
8933 static int
limitedTerminalID(int terminal_id)8934 limitedTerminalID(int terminal_id)
8935 {
8936 if (terminal_id < MIN_DECID)
8937 terminal_id = MIN_DECID;
8938 else if (terminal_id > MAX_DECID)
8939 terminal_id = MAX_DECID;
8940 else
8941 terminal_id = atoi(DFT_DECID);
8942 return terminal_id;
8943 }
8944
8945 /* ARGSUSED */
8946 static void
VTInitialize(Widget wrequest,Widget new_arg,ArgList args GCC_UNUSED,Cardinal * num_args GCC_UNUSED)8947 VTInitialize(Widget wrequest,
8948 Widget new_arg,
8949 ArgList args GCC_UNUSED,
8950 Cardinal *num_args GCC_UNUSED)
8951 {
8952 #define Kolor(name) TScreenOf(wnew)->name.resource
8953 #define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name))
8954 #define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name))
8955 #define DftFg(name) isDefaultForeground(Kolor(name))
8956 #define DftBg(name) isDefaultBackground(Kolor(name))
8957
8958 #define DATA_END { NULL, -1 }
8959
8960 #if OPT_BLINK_CURS
8961 #define DATA(name) { #name, cb##name }
8962 static const FlagList tblBlinkOps[] =
8963 {
8964 DATA(Always)
8965 ,DATA(Never)
8966 ,DATA_END
8967 };
8968 #undef DATA
8969 #endif
8970
8971 #define DATA(name) { #name, ec##name }
8972 static const FlagList tblColorOps[] =
8973 {
8974 DATA(SetColor)
8975 ,DATA(GetColor)
8976 ,DATA(GetAnsiColor)
8977 ,DATA_END
8978 };
8979 #undef DATA
8980
8981 #define DATA(name) { #name, ef##name }
8982 static const FlagList tblFontOps[] =
8983 {
8984 DATA(SetFont)
8985 ,DATA(GetFont)
8986 ,DATA_END
8987 };
8988 #undef DATA
8989
8990 #define DATA(name) { #name, em##name }
8991 static const FlagList tblMouseOps[] =
8992 {
8993 DATA(X10)
8994 ,DATA(Locator)
8995 ,DATA(VT200Click)
8996 ,DATA(VT200Hilite)
8997 ,DATA(AnyButton)
8998 ,DATA(AnyEvent)
8999 ,DATA(FocusEvent)
9000 ,DATA(Extended)
9001 ,DATA(SGR)
9002 ,DATA(URXVT)
9003 ,DATA(AlternateScroll)
9004 ,DATA_END
9005 };
9006 #undef DATA
9007
9008 #define DATA(name) { #name, ep##name }
9009 #define DATA2(alias,name) { #alias, ep##name }
9010 static const FlagList tblPasteControls[] =
9011 {
9012 DATA(NUL)
9013 ,DATA(SOH)
9014 ,DATA(STX)
9015 ,DATA(ETX)
9016 ,DATA(EOT)
9017 ,DATA(ENQ)
9018 ,DATA(ACK)
9019 ,DATA(BEL)
9020 ,DATA(BS)
9021 ,DATA(HT)
9022 ,DATA(LF)
9023 ,DATA(VT)
9024 ,DATA(FF)
9025 ,DATA(CR)
9026 ,DATA(SO)
9027 ,DATA(SI)
9028 ,DATA(DLE)
9029 ,DATA(DC1)
9030 ,DATA(DC2)
9031 ,DATA(DC3)
9032 ,DATA(DC4)
9033 ,DATA(NAK)
9034 ,DATA(SYN)
9035 ,DATA(ETB)
9036 ,DATA(CAN)
9037 ,DATA(EM)
9038 ,DATA(SUB)
9039 ,DATA(ESC)
9040 ,DATA(FS)
9041 ,DATA(GS)
9042 ,DATA(RS)
9043 ,DATA(US)
9044 /* aliases */
9045 ,DATA2(NL, LF)
9046 ,DATA(C0)
9047 ,DATA(DEL)
9048 ,DATA_END
9049 };
9050 #undef DATA
9051 #undef DATA2
9052
9053 #define DATA(name) { #name, et##name }
9054 static const FlagList tblTcapOps[] =
9055 {
9056 DATA(SetTcap)
9057 ,DATA(GetTcap)
9058 ,DATA_END
9059 };
9060 #undef DATA
9061
9062 #define DATA(name) { #name, ew##name }
9063 static const FlagList tblWindowOps[] =
9064 {
9065 DATA(RestoreWin)
9066 ,DATA(MinimizeWin)
9067 ,DATA(SetWinPosition)
9068 ,DATA(SetWinSizePixels)
9069 ,DATA(RaiseWin)
9070 ,DATA(LowerWin)
9071 ,DATA(RefreshWin)
9072 ,DATA(SetWinSizeChars)
9073 #if OPT_MAXIMIZE
9074 ,DATA(MaximizeWin)
9075 ,DATA(FullscreenWin)
9076 #endif
9077 ,DATA(GetWinState)
9078 ,DATA(GetWinPosition)
9079 ,DATA(GetWinSizePixels)
9080 ,DATA(GetWinSizeChars)
9081 #if OPT_MAXIMIZE
9082 ,DATA(GetScreenSizeChars)
9083 #endif
9084 ,DATA(GetIconTitle)
9085 ,DATA(GetWinTitle)
9086 ,DATA(PushTitle)
9087 ,DATA(PopTitle)
9088 /* this item uses all remaining numbers in the sequence */
9089 ,DATA(SetWinLines)
9090 /* starting at this point, numbers do not apply */
9091 ,DATA(SetXprop)
9092 ,DATA(GetSelection)
9093 ,DATA(SetSelection)
9094 ,DATA(GetChecksum)
9095 ,DATA(SetChecksum)
9096 ,DATA_END
9097 };
9098 #undef DATA
9099
9100 #if OPT_RENDERFONT
9101 #define DATA(name) { #name, er##name }
9102 static const FlagList tblRenderFont[] =
9103 {
9104 DATA(Default)
9105 ,DATA(DefaultOff)
9106 ,DATA_END
9107 };
9108 #undef DATA
9109 #endif
9110
9111 #define DATA(name) { #name, ss##name }
9112 static const FlagList tblShift2S[] =
9113 {
9114 DATA(Always)
9115 ,DATA(Never)
9116 ,DATA_END
9117 };
9118 #undef DATA
9119
9120 #if OPT_WIDE_CHARS
9121 #define DATA(name) { #name, u##name }
9122 static const FlagList tblUtf8Mode[] =
9123 {
9124 DATA(Always)
9125 ,DATA(Default)
9126 ,DATA_END
9127 };
9128 #undef DATA
9129 #endif
9130
9131 #ifndef NO_ACTIVE_ICON
9132 #define DATA(name) { #name, ei##name }
9133 static const FlagList tblAIconOps[] =
9134 {
9135 DATA(Default)
9136 ,DATA_END
9137 };
9138 #undef DATA
9139 #endif
9140
9141 #define DATA(name) { #name, eb##name }
9142 static const FlagList tbl8BitMeta[] =
9143 {
9144 DATA(Never)
9145 ,DATA(Locale)
9146 ,DATA_END
9147 };
9148 #undef DATA
9149
9150 #define DATA(name) { #name, ed##name }
9151 static const FlagList tblCdXtraScroll[] =
9152 {
9153 DATA(Trim)
9154 ,DATA_END
9155 };
9156 #undef DATA
9157
9158 XtermWidget request = (XtermWidget) wrequest;
9159 XtermWidget wnew = (XtermWidget) new_arg;
9160 Widget my_parent = SHELL_OF(wnew);
9161 int i;
9162
9163 #if OPT_ISO_COLORS
9164 Bool color_ok;
9165 #endif
9166
9167 #if OPT_ISO_COLORS
9168 static XtResource fake_resources[] =
9169 {
9170 #if OPT_256_COLORS
9171 # include <256colres.h>
9172 #elif OPT_88_COLORS
9173 # include <88colres.h>
9174 #endif
9175 };
9176 #endif
9177
9178 TScreen *screen = TScreenOf(wnew);
9179 char *saveLocale = xtermSetLocale(LC_NUMERIC, "C");
9180 #if OPT_BLINK_CURS
9181 int ebValue;
9182 #endif
9183
9184 #if OPT_TRACE
9185 check_bitmasks();
9186 check_tables();
9187 #endif
9188
9189 TRACE(("VTInitialize wnew %p, %d / %d resources " TRACE_L "\n",
9190 (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES));
9191 assert(XtNumber(xterm_resources) < MAXRESOURCES);
9192
9193 /* Zero out the entire "screen" component of "wnew" widget, then do
9194 * field-by-field assignment of "screen" fields that are named in the
9195 * resource list.
9196 */
9197 memset(screen, 0, sizeof(wnew->screen));
9198
9199 /* DESCO Sys#67660
9200 * Zero out the entire "keyboard" component of "wnew" widget.
9201 */
9202 memset(&wnew->keyboard, 0, sizeof(wnew->keyboard));
9203
9204 /*
9205 * The workspace has no resources - clear it.
9206 */
9207 memset(&wnew->work, 0, sizeof(wnew->work));
9208
9209 /* dummy values so that we don't try to Realize the parent shell with height
9210 * or width of 0, which is illegal in X. The real size is computed in the
9211 * xtermWidget's Realize proc, but the shell's Realize proc is called first,
9212 * and must see a valid size.
9213 */
9214 wnew->core.height = wnew->core.width = 1;
9215
9216 /*
9217 * The definition of -rv now is that it changes the definition of
9218 * XtDefaultForeground and XtDefaultBackground. So, we no longer
9219 * need to do anything special.
9220 */
9221 screen->display = wnew->core.screen->display;
9222
9223 /* prep getVisualInfo() */
9224 wnew->visInfo = 0;
9225 wnew->numVisuals = 0;
9226 (void) getVisualInfo(wnew);
9227
9228 /*
9229 * We use the default foreground/background colors to compare/check if a
9230 * color-resource has been set.
9231 */
9232 #define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy))
9233 #define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy))
9234
9235 if (request->misc.re_verse) {
9236 wnew->dft_foreground = MyWhitePixel(screen->display);
9237 wnew->dft_background = MyBlackPixel(screen->display);
9238 } else {
9239 wnew->dft_foreground = MyBlackPixel(screen->display);
9240 wnew->dft_background = MyWhitePixel(screen->display);
9241 }
9242
9243 init_Tres(TEXT_FG);
9244 init_Tres(TEXT_BG);
9245 repairColors(wnew);
9246
9247 wnew->old_foreground = T_COLOR(screen, TEXT_FG);
9248 wnew->old_background = T_COLOR(screen, TEXT_BG);
9249
9250 TRACE(("Color resource initialization:\n"));
9251 TRACE((" Default foreground 0x%06lx\n", wnew->dft_foreground));
9252 TRACE((" Default background 0x%06lx\n", wnew->dft_background));
9253 TRACE((" Screen foreground 0x%06lx\n", T_COLOR(screen, TEXT_FG)));
9254 TRACE((" Screen background 0x%06lx\n", T_COLOR(screen, TEXT_BG)));
9255 TRACE((" Actual foreground 0x%06lx\n", wnew->old_foreground));
9256 TRACE((" Actual background 0x%06lx\n", wnew->old_background));
9257
9258 screen->mouse_button = 0;
9259 screen->mouse_row = -1;
9260 screen->mouse_col = -1;
9261
9262 #if OPT_BOX_CHARS
9263 init_Bres(screen.force_box_chars);
9264 init_Bres(screen.force_packed);
9265 init_Bres(screen.force_all_chars);
9266 init_Bres(screen.assume_all_chars);
9267 #endif
9268 init_Bres(screen.free_bold_box);
9269 init_Bres(screen.allowBoldFonts);
9270
9271 init_Bres(screen.c132);
9272 init_Bres(screen.curses);
9273 init_Bres(screen.hp_ll_bc);
9274 #if OPT_XMC_GLITCH
9275 init_Ires(screen.xmc_glitch);
9276 init_Ires(screen.xmc_attributes);
9277 init_Bres(screen.xmc_inline);
9278 init_Bres(screen.move_sgr_ok);
9279 #endif
9280 #if OPT_BLINK_CURS
9281 init_Sres(screen.cursor_blink_s);
9282 ebValue = extendedBoolean(wnew->screen.cursor_blink_s, tblBlinkOps, cbLAST);
9283 wnew->screen.cursor_blink = (BlinkOps) ebValue;
9284 init_Bres(screen.cursor_blink_xor);
9285 init_Ires(screen.blink_on);
9286 init_Ires(screen.blink_off);
9287 screen->cursor_blink_i = screen->cursor_blink;
9288 #endif
9289 init_Bres(screen.cursor_underline);
9290 /* resources allow for underline or block, not (yet) bar */
9291 InitCursorShape(screen, TScreenOf(request));
9292 #if OPT_BLINK_CURS
9293 TRACE(("cursor_shape:%d blinks:%d\n",
9294 screen->cursor_shape,
9295 screen->cursor_blink));
9296 #endif
9297 #if OPT_BLINK_TEXT
9298 init_Ires(screen.blink_as_bold);
9299 #endif
9300 init_Ires(screen.border);
9301 init_Bres(screen.jumpscroll);
9302 init_Bres(screen.fastscroll);
9303
9304 init_Bres(screen.old_fkeys);
9305 wnew->screen.old_fkeys0 = wnew->screen.old_fkeys;
9306 wnew->keyboard.type = screen->old_fkeys
9307 ? keyboardIsLegacy
9308 : keyboardIsDefault;
9309
9310 init_Mres(screen.delete_is_del);
9311 #ifdef ALLOWLOGGING
9312 init_Bres(misc.logInhibit);
9313 init_Bres(misc.log_on);
9314 init_Sres(screen.logfile);
9315 #endif
9316 init_Bres(screen.bellIsUrgent);
9317 init_Bres(screen.bellOnReset);
9318 init_Bres(screen.marginbell);
9319 init_Bres(screen.multiscroll);
9320 init_Ires(screen.nmarginbell);
9321 init_Ires(screen.savelines);
9322 init_Ires(screen.scrollBarBorder);
9323 init_Ires(screen.scrolllines);
9324 init_Bres(screen.alternateScroll);
9325 init_Bres(screen.scrollttyoutput);
9326 init_Bres(screen.scrollkey);
9327
9328 init_Dres(screen.scale_height);
9329 if (screen->scale_height < MIN_SCALE_HEIGHT)
9330 screen->scale_height = MIN_SCALE_HEIGHT;
9331 if (screen->scale_height > MAX_SCALE_HEIGHT)
9332 screen->scale_height = MAX_SCALE_HEIGHT;
9333
9334 init_Bres(misc.autoWrap);
9335 init_Bres(misc.login_shell);
9336 init_Bres(misc.reverseWrap);
9337 init_Bres(misc.scrollbar);
9338 init_Sres(misc.geo_metry);
9339 init_Sres(misc.T_geometry);
9340
9341 init_Sres(screen.term_id);
9342 screen->terminal_id = decodeTerminalID(TScreenOf(request)->term_id);
9343 /*
9344 * (1) If a known terminal model, and not a graphical terminal, preserve
9345 * the terminal id.
9346 * (2) Otherwise, if ReGIS or sixel graphics are enabled, preserve the ID,
9347 * even if it is not a known terminal.
9348 * (3) Otherwise force the terminal ID to the min, max, or VT420 depending
9349 * on the input.
9350 */
9351 switch (screen->terminal_id) {
9352 case 52: /* MIN_DECID */
9353 case 100:
9354 case 101:
9355 case 102:
9356 case 131:
9357 case 132:
9358 case 220:
9359 case 320:
9360 case 420: /* DFT_DECID, unless overridden in configure */
9361 case 510:
9362 case 520:
9363 case 525: /* MAX_DECID */
9364 break;
9365 default:
9366 #if OPT_REGIS_GRAPHICS
9367 if (optRegisGraphics(screen))
9368 break;
9369 #endif
9370 #if OPT_SIXEL_GRAPHICS
9371 if (optSixelGraphics(screen))
9372 break;
9373 #endif
9374 screen->terminal_id = limitedTerminalID(screen->terminal_id);
9375 break;
9376 }
9377 TRACE(("term_id '%s' -> terminal_id %d\n",
9378 screen->term_id,
9379 screen->terminal_id));
9380
9381 screen->vtXX_level = (screen->terminal_id / 100);
9382
9383 init_Ires(screen.title_modes);
9384 screen->title_modes0 = screen->title_modes;
9385
9386 init_Ires(screen.nextEventDelay);
9387 if (screen->nextEventDelay <= 0)
9388 screen->nextEventDelay = 1;
9389
9390 init_Bres(screen.visualbell);
9391 init_Bres(screen.flash_line);
9392 init_Ires(screen.visualBellDelay);
9393 init_Bres(screen.poponbell);
9394
9395 init_Bres(screen.eraseSavedLines0);
9396 screen->eraseSavedLines = screen->eraseSavedLines0;
9397
9398 init_Ires(misc.limit_resize);
9399
9400 #if OPT_NUM_LOCK
9401 init_Bres(misc.real_NumLock);
9402 init_Bres(misc.alwaysUseMods);
9403 #endif
9404
9405 #if OPT_INPUT_METHOD
9406 init_Bres(misc.open_im);
9407 init_Ires(misc.retry_im);
9408 init_Sres(misc.f_x);
9409 init_Sres(misc.input_method);
9410 init_Sres(misc.preedit_type);
9411 #endif
9412
9413 #if OPT_SHIFT_FONTS
9414 init_Bres(misc.shift_fonts);
9415 #endif
9416 #if OPT_SUNPC_KBD
9417 init_Ires(misc.ctrl_fkeys);
9418 #endif
9419 #if OPT_TEK4014
9420 TEK4014_SHOWN(wnew) = False; /* not a resource... */
9421 init_Bres(misc.tekInhibit);
9422 init_Bres(misc.tekSmall);
9423 init_Bres(misc.TekEmu);
9424 #endif
9425 #if OPT_TCAP_QUERY
9426 screen->tc_query_code = -1;
9427 #endif
9428 wnew->misc.re_verse0 = request->misc.re_verse;
9429 init_Bres(misc.re_verse);
9430 init_Ires(screen.multiClickTime);
9431 init_Ires(screen.bellSuppressTime);
9432 init_Sres(screen.charClass);
9433
9434 init_Bres(screen.always_highlight);
9435 init_Bres(screen.brokenSelections);
9436 init_Bres(screen.cutNewline);
9437 init_Bres(screen.cutToBeginningOfLine);
9438 init_Bres(screen.highlight_selection);
9439 init_Bres(screen.show_wrap_marks);
9440 init_Bres(screen.i18nSelections);
9441 init_Bres(screen.keepClipboard);
9442 init_Bres(screen.keepSelection);
9443 init_Bres(screen.selectToClipboard);
9444 init_Bres(screen.trim_selection);
9445
9446 screen->pointer_cursor = TScreenOf(request)->pointer_cursor;
9447 init_Ires(screen.pointer_mode);
9448 wnew->screen.pointer_mode0 = wnew->screen.pointer_mode;
9449
9450 init_Sres(screen.answer_back);
9451
9452 wnew->SPS.printer_checked = False;
9453 init_Sres(SPS.printer_command);
9454 init_Bres(SPS.printer_autoclose);
9455 init_Bres(SPS.printer_extent);
9456 init_Bres(SPS.printer_formfeed);
9457 init_Bres(SPS.printer_newline);
9458 init_Ires(SPS.printer_controlmode);
9459 #if OPT_PRINT_COLORS
9460 init_Ires(SPS.print_attributes);
9461 #endif
9462
9463 init_Sres(screen.keyboard_dialect);
9464
9465 init_Sres(screen.cursor_font_name);
9466 init_Sres(screen.pointer_shape);
9467
9468 init_Bres(screen.input_eight_bits);
9469 init_Bres(screen.output_eight_bits);
9470 init_Bres(screen.control_eight_bits);
9471 init_Bres(screen.backarrow_key);
9472 init_Bres(screen.alt_is_not_meta);
9473 init_Bres(screen.alt_sends_esc);
9474 init_Bres(screen.meta_sends_esc);
9475
9476 init_Bres(screen.allowPasteControl0);
9477 init_Bres(screen.allowSendEvent0);
9478 init_Bres(screen.allowColorOp0);
9479 init_Bres(screen.allowFontOp0);
9480 init_Bres(screen.allowMouseOp0);
9481 init_Bres(screen.allowTcapOp0);
9482 init_Bres(screen.allowTitleOp0);
9483 init_Bres(screen.allowWindowOp0);
9484
9485 #if OPT_SCROLL_LOCK
9486 init_Bres(screen.allowScrollLock0);
9487 init_Bres(screen.autoScrollLock);
9488 #endif
9489
9490 init_Sres(screen.disallowedColorOps);
9491
9492 set_flags_from_list(screen->disallow_color_ops,
9493 screen->disallowedColorOps,
9494 tblColorOps);
9495
9496 init_Sres(screen.disallowedFontOps);
9497
9498 set_flags_from_list(screen->disallow_font_ops,
9499 screen->disallowedFontOps,
9500 tblFontOps);
9501
9502 init_Sres(screen.disallowedMouseOps);
9503
9504 set_flags_from_list(screen->disallow_mouse_ops,
9505 screen->disallowedMouseOps,
9506 tblMouseOps);
9507
9508 init_Sres(screen.disallowedPasteControls);
9509
9510 set_flags_from_list(screen->disallow_paste_controls,
9511 screen->disallowedPasteControls,
9512 tblPasteControls);
9513
9514 init_Sres(screen.disallowedTcapOps);
9515
9516 set_flags_from_list(screen->disallow_tcap_ops,
9517 screen->disallowedTcapOps,
9518 tblTcapOps);
9519
9520 init_Sres(screen.disallowedWinOps);
9521
9522 set_flags_from_list(screen->disallow_win_ops,
9523 screen->disallowedWinOps,
9524 tblWindowOps);
9525
9526 init_Sres(screen.default_string);
9527 init_Sres(screen.eightbit_select_types);
9528 #if OPT_WIDE_CHARS
9529 init_Sres(screen.utf8_select_types);
9530 #endif
9531
9532 /* make a copy so that editres cannot change the resource after startup */
9533 screen->allowPasteControls = screen->allowPasteControl0;
9534 screen->allowSendEvents = screen->allowSendEvent0;
9535 screen->allowColorOps = screen->allowColorOp0;
9536 screen->allowFontOps = screen->allowFontOp0;
9537 screen->allowMouseOps = screen->allowMouseOp0;
9538 screen->allowTcapOps = screen->allowTcapOp0;
9539 screen->allowTitleOps = screen->allowTitleOp0;
9540 screen->allowWindowOps = screen->allowWindowOp0;
9541
9542 #if OPT_SCROLL_LOCK
9543 screen->allowScrollLock = screen->allowScrollLock0;
9544 #endif
9545
9546 init_Bres(screen.quiet_grab);
9547
9548 #ifndef NO_ACTIVE_ICON
9549 init_Sres(screen.icon_fontname);
9550 getIconicFont(screen)->fs = xtermLoadQueryFont(wnew,
9551 screen->icon_fontname);
9552 TRACE(("iconFont '%s' %sloaded successfully\n",
9553 screen->icon_fontname,
9554 getIconicFont(screen)->fs ? "" : "NOT "));
9555 init_Sres(misc.active_icon_s);
9556 wnew->work.active_icon =
9557 (Boolean) extendedBoolean(wnew->misc.active_icon_s,
9558 tblAIconOps, eiLAST);
9559 init_Ires(misc.icon_border_width);
9560 wnew->misc.icon_border_pixel = request->misc.icon_border_pixel;
9561 #endif /* NO_ACTIVE_ICON */
9562
9563 init_Bres(misc.signalInhibit);
9564 init_Bres(misc.titeInhibit);
9565 init_Bres(misc.color_inner_border);
9566 init_Bres(misc.dynamicColors);
9567 init_Bres(misc.resizeByPixel);
9568
9569 init_Sres(misc.cdXtraScroll_s);
9570 wnew->misc.cdXtraScroll =
9571 extendedBoolean(request->misc.cdXtraScroll_s, tblCdXtraScroll, edLast);
9572
9573 init_Sres(misc.tiXtraScroll_s);
9574 wnew->misc.tiXtraScroll =
9575 extendedBoolean(request->misc.tiXtraScroll_s, tblCdXtraScroll, edLast);
9576
9577 #if OPT_DEC_CHRSET
9578 for (i = 0; i < NUM_CHRSET; i++) {
9579 screen->double_fonts[i].warn = fwResource;
9580 }
9581 #endif
9582 for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) {
9583 init_Sres2(screen.MenuFontName, i);
9584 }
9585 for (i = 0; i < fMAX; i++) {
9586 screen->fnts[i].warn = fwResource;
9587 #if OPT_WIDE_ATTRS
9588 screen->ifnts[i].warn = fwResource;
9589 #endif
9590 }
9591 #ifndef NO_ACTIVE_ICON
9592 screen->fnt_icon.warn = fwResource;
9593 #endif
9594
9595 init_Ires(misc.fontWarnings);
9596
9597 initFontLists(wnew);
9598
9599 #define DefaultFontNames screen->menu_font_names[fontMenu_default]
9600
9601 /*
9602 * Process Xft font resources first, since faceName may contain X11 fonts
9603 * that should override the "font" resource.
9604 */
9605 #if OPT_RENDERFONT
9606 init_Bres(screen.force_xft_height);
9607 for (i = 0; i <= fontMenu_lastBuiltin; ++i) {
9608 init_Dres2(misc.face_size, i);
9609 }
9610
9611 #define ALLOC_FONTLIST(name,which,field) \
9612 init_Sres(misc.default_xft.field);\
9613 allocFontList(wnew,\
9614 name,\
9615 &(wnew->work.fonts),\
9616 which,\
9617 wnew->misc.default_xft.field,\
9618 True)
9619
9620 ALLOC_FONTLIST(XtNfaceName, fNorm, f_n);
9621
9622 #if OPT_WIDE_CHARS
9623 ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w);
9624 #endif
9625
9626 #undef ALLOC_FONTLIST
9627
9628 #endif
9629
9630 /*
9631 * Process X11 (XLFD) font specifications.
9632 */
9633 #define ALLOC_FONTLIST(name,which,field) \
9634 init_Sres(misc.default_font.field);\
9635 allocFontList(wnew,\
9636 name,\
9637 &(wnew->work.fonts),\
9638 which,\
9639 wnew->misc.default_font.field,\
9640 False)
9641
9642 ALLOC_FONTLIST(XtNfont, fNorm, f_n);
9643 ALLOC_FONTLIST(XtNboldFont, fBold, f_b);
9644
9645 DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew));
9646 DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew));
9647
9648 #if OPT_WIDE_CHARS
9649 ALLOC_FONTLIST(XtNwideFont, fWide, f_w);
9650 ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb);
9651
9652 DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew));
9653 DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew));
9654 #endif
9655
9656 #undef ALLOC_FONTLIST
9657
9658 screen->EscapeFontName() = NULL;
9659 screen->SelectFontName() = NULL;
9660
9661 screen->menu_font_number = fontMenu_default;
9662 init_Sres(screen.initial_font);
9663 if (screen->initial_font != 0) {
9664 int result = xtermGetFont(screen->initial_font);
9665 if (result >= 0)
9666 screen->menu_font_number = result;
9667 }
9668 #if OPT_BROKEN_OSC
9669 init_Bres(screen.brokenLinuxOSC);
9670 #endif
9671
9672 #if OPT_BROKEN_ST
9673 init_Bres(screen.brokenStringTerm);
9674 #endif
9675
9676 #if OPT_C1_PRINT
9677 init_Bres(screen.c1_printable);
9678 #endif
9679
9680 #if OPT_CLIP_BOLD
9681 init_Bres(screen.use_border_clipping);
9682 init_Bres(screen.use_clipping);
9683 #endif
9684
9685 #if OPT_DEC_CHRSET
9686 init_Bres(screen.font_doublesize);
9687 init_Ires(screen.cache_doublesize);
9688 if (screen->cache_doublesize > NUM_CHRSET)
9689 screen->cache_doublesize = NUM_CHRSET;
9690 if (screen->cache_doublesize == 0)
9691 screen->font_doublesize = False;
9692 TRACE(("Doublesize%s enabled, up to %d fonts\n",
9693 screen->font_doublesize ? "" : " not",
9694 screen->cache_doublesize));
9695 #endif
9696 #if OPT_DEC_RECTOPS
9697 init_Ires(screen.checksum_ext0);
9698 screen->checksum_ext = screen->checksum_ext0;
9699 #endif
9700
9701 #if OPT_ISO_COLORS
9702 init_Ires(screen.veryBoldColors);
9703 init_Bres(screen.boldColors);
9704 init_Bres(screen.colorAttrMode);
9705 init_Bres(screen.colorBDMode);
9706 init_Bres(screen.colorBLMode);
9707 init_Bres(screen.colorMode);
9708 init_Bres(screen.colorULMode);
9709 init_Bres(screen.italicULMode);
9710 init_Bres(screen.colorRVMode);
9711
9712 #if OPT_WIDE_ATTRS
9713 init_Bres(screen.colorITMode);
9714 #endif
9715 #if OPT_DIRECT_COLOR
9716 init_Bres(screen.direct_color);
9717 #endif
9718
9719 TRACE(("...will fake resources for color%d to color%d\n",
9720 MIN_ANSI_COLORS,
9721 NUM_ANSI_COLORS - 1));
9722
9723 for (i = 0, color_ok = False; i < MAXCOLORS; i++) {
9724 /*
9725 * Xt has a hardcoded limit on the maximum number of resources that can
9726 * be used in a widget. If we configured both luit (which implies
9727 * wide-characters) and 256-colors, it goes over that limit. Most
9728 * people would not need a resource-file with 256-colors; the default
9729 * values in our table are sufficient. Fake the resource setting by
9730 * copying the default value from the table. The #define's can be
9731 * overridden to make these true resources.
9732 */
9733 if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) {
9734 screen->Acolors[i].resource =
9735 x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr);
9736 if (screen->Acolors[i].resource == 0)
9737 screen->Acolors[i].resource = XtDefaultForeground;
9738 } else {
9739 screen->Acolors[i] = TScreenOf(request)->Acolors[i];
9740 screen->Acolors[i].resource =
9741 x_strtrim(screen->Acolors[i].resource);
9742 }
9743
9744 TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource));
9745 screen->Acolors[i].mode = False;
9746 if (DftFg(Acolors[i])) {
9747 screen->Acolors[i].value = T_COLOR(screen, TEXT_FG);
9748 screen->Acolors[i].mode = True;
9749 } else if (DftBg(Acolors[i])) {
9750 screen->Acolors[i].value = T_COLOR(screen, TEXT_BG);
9751 screen->Acolors[i].mode = True;
9752 } else {
9753 color_ok = True;
9754 }
9755 }
9756
9757 /*
9758 * Check if we're trying to use color in a monochrome screen. Disable
9759 * color in that case, since that would make ANSI colors unusable. A 4-bit
9760 * or 8-bit display is usable, so we do not have to check for anything more
9761 * specific.
9762 */
9763 if (color_ok) {
9764 if (getVisualDepth(wnew) <= 1) {
9765 TRACE(("disabling color since screen is monochrome\n"));
9766 color_ok = False;
9767 }
9768 }
9769
9770 /* If none of the colors are anything other than the foreground or
9771 * background, we'll assume this isn't color, no matter what the colorMode
9772 * resource says. (There doesn't seem to be any good way to determine if
9773 * the resource lookup failed versus the user having misconfigured this).
9774 */
9775 if (!color_ok) {
9776 screen->colorMode = False;
9777 TRACE(("All colors are foreground or background: disable colorMode\n"));
9778 }
9779 wnew->sgr_foreground = -1;
9780 wnew->sgr_background = -1;
9781 wnew->sgr_38_xcolors = False;
9782 clrDirectFG(wnew->flags);
9783 clrDirectFG(wnew->flags);
9784 #endif /* OPT_ISO_COLORS */
9785
9786 /*
9787 * Decode the resources that control the behavior on multiple mouse clicks.
9788 * A single click is always bound to normal character selection, but the
9789 * other flavors can be changed.
9790 */
9791 for (i = 0; i < NSELECTUNITS; ++i) {
9792 int ck = (i + 1);
9793 screen->maxClicks = ck;
9794 if (i == Select_CHAR)
9795 screen->selectMap[i] = Select_CHAR;
9796 else if (TScreenOf(request)->onClick[i] != 0)
9797 ParseOnClicks(wnew, request, (unsigned) i);
9798 else if (i <= Select_LINE)
9799 screen->selectMap[i] = (SelectUnit) i;
9800 else
9801 break;
9802 #if OPT_XRES_QUERY
9803 init_Sres(screen.onClick[i]);
9804 #endif
9805 TRACE(("on%dClicks %s=%d\n", ck,
9806 NonNull(TScreenOf(request)->onClick[i]),
9807 screen->selectMap[i]));
9808 if (screen->selectMap[i] == NSELECTUNITS)
9809 break;
9810 }
9811 TRACE(("maxClicks %d\n", screen->maxClicks));
9812
9813 init_Tres(MOUSE_FG);
9814 init_Tres(MOUSE_BG);
9815 init_Tres(TEXT_CURSOR);
9816 #if OPT_HIGHLIGHT_COLOR
9817 init_Tres(HIGHLIGHT_BG);
9818 init_Tres(HIGHLIGHT_FG);
9819 init_Bres(screen.hilite_reverse);
9820 init_Mres(screen.hilite_color);
9821 if (screen->hilite_color == Maybe) {
9822 screen->hilite_color = False;
9823 /*
9824 * If the highlight text/background are both set, and if they are
9825 * not equal to either the text/background or background/text, then
9826 * set the highlightColorMode automatically.
9827 */
9828 if (!DftFg(Tcolors[HIGHLIGHT_BG])
9829 && !DftBg(Tcolors[HIGHLIGHT_FG])
9830 && !TxtFg(Tcolors[HIGHLIGHT_BG])
9831 && !TxtBg(Tcolors[HIGHLIGHT_FG])
9832 && !TxtBg(Tcolors[HIGHLIGHT_BG])
9833 && !TxtFg(Tcolors[HIGHLIGHT_FG])) {
9834 TRACE(("...setting hilite_color automatically\n"));
9835 screen->hilite_color = True;
9836 }
9837 }
9838 #endif
9839
9840 #if OPT_TEK4014
9841 /*
9842 * The Tek4014 window has no separate resources for foreground, background
9843 * and cursor color. Since xterm always creates the vt100 widget first, we
9844 * can set the Tektronix colors here. That lets us use escape sequences to
9845 * set its dynamic colors and get consistent behavior whether or not the
9846 * window is displayed.
9847 */
9848 screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG];
9849 screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG];
9850 screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR];
9851 #endif
9852
9853 #ifdef SCROLLBAR_RIGHT
9854 init_Bres(misc.useRight);
9855 #endif
9856
9857 #if OPT_RENDERFONT
9858 init_Ires(misc.limit_fontsets);
9859 wnew->work.max_fontsets = (unsigned) wnew->misc.limit_fontsets;
9860
9861 init_Sres(misc.render_font_s);
9862 wnew->work.render_font =
9863 (Boolean) extendedBoolean(wnew->misc.render_font_s,
9864 tblRenderFont, erLast);
9865 if (wnew->work.render_font == erDefault) {
9866 if (IsEmpty(CurrentXftFont(wnew))) {
9867 free((void *) CurrentXftFont(wnew));
9868 CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO);
9869 TRACE(("will allow runtime switch to render_font using \"%s\"\n",
9870 CurrentXftFont(wnew)));
9871 } else {
9872 wnew->work.render_font = erTrue;
9873 TRACE(("initially using TrueType font\n"));
9874 }
9875 } else if (wnew->work.render_font == erDefaultOff) {
9876 wnew->work.render_font = erFalse;
9877 }
9878 /* minor tweak to make debug traces consistent: */
9879 if (wnew->work.render_font) {
9880 if (IsEmpty(CurrentXftFont(wnew))) {
9881 wnew->work.render_font = False;
9882 TRACE(("reset render_font since there is no face_name\n"));
9883 }
9884 }
9885 #endif
9886
9887 #if OPT_WIDE_CHARS
9888 /* setup data for next call */
9889 init_Sres(screen.utf8_mode_s);
9890 request->screen.utf8_mode =
9891 extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast);
9892
9893 init_Sres(screen.utf8_fonts_s);
9894 request->screen.utf8_fonts =
9895 extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast);
9896
9897 init_Sres(screen.utf8_title_s);
9898 request->screen.utf8_title =
9899 extendedBoolean(request->screen.utf8_title_s, tblUtf8Mode, uLast);
9900
9901 /*
9902 * Make a copy in the input/request so that DefaultFontN() works for
9903 * the "CHECKFONT" option.
9904 */
9905 copyFontList(&(request->work.fonts.x11.list_n),
9906 wnew->work.fonts.x11.list_n);
9907
9908 VTInitialize_locale(request);
9909 init_Bres(screen.normalized_c);
9910 init_Bres(screen.utf8_latin1);
9911 init_Bres(screen.utf8_weblike);
9912
9913 #if OPT_LUIT_PROG
9914 init_Bres(misc.callfilter);
9915 init_Bres(misc.use_encoding);
9916 init_Sres(misc.locale_str);
9917 init_Sres(misc.localefilter);
9918 #endif
9919
9920 init_Ires(screen.utf8_inparse);
9921 init_Ires(screen.utf8_mode);
9922 init_Ires(screen.utf8_fonts);
9923 init_Ires(screen.utf8_title);
9924 init_Ires(screen.max_combining);
9925
9926 init_Ires(screen.utf8_always); /* from utf8_mode, used in doparse */
9927
9928 if (screen->max_combining < 0) {
9929 screen->max_combining = 0;
9930 }
9931 if (screen->max_combining > 5) {
9932 screen->max_combining = 5;
9933 }
9934
9935 init_Bres(screen.vt100_graphics);
9936 init_Bres(screen.wide_chars);
9937 init_Bres(misc.mk_width);
9938 init_Bres(misc.cjk_width);
9939
9940 init_Ires(misc.mk_samplesize);
9941 init_Ires(misc.mk_samplepass);
9942
9943 if (wnew->misc.mk_samplesize > 0xffff)
9944 wnew->misc.mk_samplesize = 0xffff;
9945 if (wnew->misc.mk_samplesize < 0)
9946 wnew->misc.mk_samplesize = 0;
9947
9948 if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize)
9949 wnew->misc.mk_samplepass = wnew->misc.mk_samplesize;
9950 if (wnew->misc.mk_samplepass < 0)
9951 wnew->misc.mk_samplepass = 0;
9952
9953 if (TScreenOf(request)->utf8_mode) {
9954 TRACE(("setting wide_chars on\n"));
9955 screen->wide_chars = True;
9956 } else {
9957 TRACE(("setting utf8_mode to 0\n"));
9958 screen->utf8_mode = uFalse;
9959 }
9960 mk_wcwidth_init(screen->utf8_mode);
9961 TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode));
9962
9963 #if OPT_MINI_LUIT
9964 if (TScreenOf(request)->latin9_mode) {
9965 screen->latin9_mode = True;
9966 }
9967 if (TScreenOf(request)->unicode_font) {
9968 screen->unicode_font = True;
9969 }
9970 TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode));
9971 TRACE(("initialized unicode_font to %d\n", screen->unicode_font));
9972 #endif
9973
9974 decode_wcwidth(wnew);
9975 xtermSaveVTFonts(wnew);
9976 #endif /* OPT_WIDE_CHARS */
9977
9978 init_Sres(screen.eight_bit_meta_s);
9979 wnew->screen.eight_bit_meta =
9980 extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, ebLast);
9981 if (wnew->screen.eight_bit_meta == ebLocale) {
9982 #if OPT_WIDE_CHARS
9983 if (xtermEnvUTF8()) {
9984 wnew->screen.eight_bit_meta = ebFalse;
9985 TRACE(("...eightBitMeta is false due to locale\n"));
9986 } else
9987 #endif /* OPT_WIDE_CHARS */
9988 {
9989 wnew->screen.eight_bit_meta = ebTrue;
9990 TRACE(("...eightBitMeta is true due to locale\n"));
9991 }
9992 }
9993
9994 init_Bres(screen.always_bold_mode);
9995 init_Bres(screen.bold_mode);
9996 init_Bres(screen.underline);
9997
9998 wnew->cur_foreground = 0;
9999 wnew->cur_background = 0;
10000
10001 wnew->keyboard.flags = MODE_SRM;
10002
10003 if (screen->backarrow_key)
10004 wnew->keyboard.flags |= MODE_DECBKM;
10005 TRACE(("initialized DECBKM %s\n",
10006 BtoS(wnew->keyboard.flags & MODE_DECBKM)));
10007
10008 #if OPT_SIXEL_GRAPHICS
10009 init_Bres(screen.sixel_scrolling);
10010 if (screen->sixel_scrolling)
10011 wnew->keyboard.flags |= MODE_DECSDM;
10012 TRACE(("initialized DECSDM %s\n",
10013 BtoS(wnew->keyboard.flags & MODE_DECSDM)));
10014 #endif
10015
10016 #if OPT_GRAPHICS
10017 init_Sres(screen.graph_termid);
10018 screen->graphics_termid = decodeTerminalID(TScreenOf(request)->graph_termid);
10019 switch (screen->graphics_termid) {
10020 case 125:
10021 case 240:
10022 case 241:
10023 case 330:
10024 case 340:
10025 case 382:
10026 break;
10027 default:
10028 screen->graphics_termid = 0;
10029 break;
10030 }
10031 TRACE(("graph_termid '%s' -> graphics_termid %d\n",
10032 screen->graph_termid,
10033 screen->graphics_termid));
10034
10035 init_Ires(screen.numcolorregisters);
10036 TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n",
10037 screen->numcolorregisters));
10038
10039 init_Bres(screen.privatecolorregisters); /* FIXME: should this be off unconditionally here? */
10040 TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n",
10041 BtoS(screen->privatecolorregisters)));
10042 #endif
10043
10044 #if OPT_GRAPHICS
10045 {
10046 int native_w, native_h;
10047
10048 switch (GraphicsTermId(screen)) {
10049 case 125:
10050 native_w = 768;
10051 native_h = 460;
10052 break;
10053 case 240:
10054 /* FALLTHRU */
10055 case 241:
10056 native_w = 800;
10057 native_h = 460;
10058 break;
10059 case 330:
10060 /* FALLTHRU */
10061 case 340:
10062 native_w = 800;
10063 native_h = 480;
10064 break;
10065 default:
10066 native_w = 800;
10067 native_h = 480;
10068 break;
10069 case 382:
10070 native_w = 960;
10071 native_h = 750;
10072 break;
10073 }
10074
10075 # if OPT_REGIS_GRAPHICS
10076 init_Sres(screen.graphics_regis_default_font);
10077 TRACE(("default ReGIS font: %s\n",
10078 screen->graphics_regis_default_font));
10079
10080 init_Sres(screen.graphics_regis_screensize);
10081 screen->graphics_regis_def_high = 1000;
10082 screen->graphics_regis_def_wide = 1000;
10083 if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) {
10084 TRACE(("setting default ReGIS screensize based on graphics_id %d\n",
10085 GraphicsTermId(screen)));
10086 screen->graphics_regis_def_high = (Dimension) native_h;
10087 screen->graphics_regis_def_wide = (Dimension) native_w;
10088 } else {
10089 int conf_high;
10090 int conf_wide;
10091 char ignore;
10092
10093 if (sscanf(screen->graphics_regis_screensize,
10094 "%dx%d%c",
10095 &conf_wide,
10096 &conf_high,
10097 &ignore) == 2) {
10098 if (conf_high > 0 && conf_wide > 0) {
10099 screen->graphics_regis_def_high =
10100 (Dimension) conf_high;
10101 screen->graphics_regis_def_wide =
10102 (Dimension) conf_wide;
10103 } else {
10104 TRACE(("ignoring invalid regisScreenSize %s\n",
10105 screen->graphics_regis_screensize));
10106 }
10107 } else {
10108 TRACE(("ignoring invalid regisScreenSize %s\n",
10109 screen->graphics_regis_screensize));
10110 }
10111 }
10112 TRACE(("default ReGIS graphics screensize %dx%d\n",
10113 (int) screen->graphics_regis_def_wide,
10114 (int) screen->graphics_regis_def_high));
10115 # endif
10116
10117 init_Sres(screen.graphics_max_size);
10118 screen->graphics_max_high = 1000;
10119 screen->graphics_max_wide = 1000;
10120 if (!x_strcasecmp(screen->graphics_max_size, "auto")) {
10121 TRACE(("setting max graphics screensize based on graphics_id %d\n",
10122 GraphicsTermId(screen)));
10123 screen->graphics_max_high = (Dimension) native_h;
10124 screen->graphics_max_wide = (Dimension) native_w;
10125 } else {
10126 int conf_high;
10127 int conf_wide;
10128 char ignore;
10129
10130 if (sscanf(screen->graphics_max_size,
10131 "%dx%d%c",
10132 &conf_wide,
10133 &conf_high,
10134 &ignore) == 2) {
10135 if (conf_high > 0 && conf_wide > 0) {
10136 screen->graphics_max_high = (Dimension) conf_high;
10137 screen->graphics_max_wide = (Dimension) conf_wide;
10138 } else {
10139 TRACE(("ignoring invalid maxGraphicSize %s\n",
10140 screen->graphics_max_size));
10141 }
10142 } else {
10143 TRACE(("ignoring invalid maxGraphicSize %s\n",
10144 screen->graphics_max_size));
10145 }
10146 }
10147 # if OPT_REGIS_GRAPHICS
10148 /* Make sure the max is large enough for the default ReGIS size. */
10149 if (screen->graphics_regis_def_high >
10150 screen->graphics_max_high) {
10151 screen->graphics_max_high =
10152 screen->graphics_regis_def_high;
10153 }
10154 if (screen->graphics_regis_def_wide >
10155 screen->graphics_max_wide) {
10156 screen->graphics_max_wide =
10157 screen->graphics_regis_def_wide;
10158 }
10159 # endif
10160 TRACE(("max graphics screensize %dx%d\n",
10161 (int) screen->graphics_max_wide,
10162 (int) screen->graphics_max_high));
10163 }
10164 #endif
10165
10166 #if OPT_SIXEL_GRAPHICS
10167 init_Bres(screen.sixel_scrolls_right);
10168 #endif
10169 #if OPT_PRINT_GRAPHICS
10170 init_Bres(screen.graphics_print_to_host);
10171 init_Bres(screen.graphics_expanded_print_mode);
10172 init_Bres(screen.graphics_print_color_mode);
10173 init_Bres(screen.graphics_print_color_syntax);
10174 init_Bres(screen.graphics_print_background_mode);
10175 init_Bres(screen.graphics_rotated_print_mode);
10176 #endif
10177
10178 /* look for focus related events on the shell, because we need
10179 * to care about the shell's border being part of our focus.
10180 */
10181 TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent));
10182 XtAddEventHandler(my_parent, EnterWindowMask, False,
10183 HandleEnterWindow, (Opaque) NULL);
10184 XtAddEventHandler(my_parent, LeaveWindowMask, False,
10185 HandleLeaveWindow, (Opaque) NULL);
10186 XtAddEventHandler(my_parent, FocusChangeMask, False,
10187 HandleFocusChange, (Opaque) NULL);
10188 XtAddEventHandler((Widget) wnew, 0L, True,
10189 VTNonMaskableEvent, (Opaque) NULL);
10190 XtAddEventHandler((Widget) wnew, PropertyChangeMask, False,
10191 HandleBellPropertyChange, (Opaque) NULL);
10192
10193 #if HANDLE_STRUCT_NOTIFY
10194 #if OPT_TOOLBAR
10195 wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar);
10196 init_Ires(VT100_TB_INFO(menu_height));
10197 #endif
10198 XtAddEventHandler(my_parent, MappingNotify | StructureNotifyMask, False,
10199 HandleStructNotify, (Opaque) 0);
10200 #endif /* HANDLE_STRUCT_NOTIFY */
10201
10202 screen->bellInProgress = False;
10203
10204 set_character_class(screen->charClass);
10205 #if OPT_REPORT_CCLASS
10206 if (resource.reportCClass)
10207 report_char_class(wnew);
10208 #endif
10209
10210 /* create it, but don't realize it */
10211 ScrollBarOn(wnew, True);
10212
10213 /* make sure that the resize gravity acceptable */
10214 if (!GravityIsNorthWest(wnew) &&
10215 !GravityIsSouthWest(wnew)) {
10216 char value[80];
10217 String temp[2];
10218 Cardinal nparams = 1;
10219
10220 sprintf(value, "%d", wnew->misc.resizeGravity);
10221 temp[0] = value;
10222 temp[1] = 0;
10223 XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
10224 "unsupported resizeGravity resource value (%s)",
10225 temp, &nparams);
10226 wnew->misc.resizeGravity = SouthWestGravity;
10227 }
10228 #ifndef NO_ACTIVE_ICON
10229 screen->whichVwin = &screen->fullVwin;
10230 #endif /* NO_ACTIVE_ICON */
10231
10232 init_Ires(screen.unparse_max);
10233 if ((int) screen->unparse_max < 256)
10234 screen->unparse_max = 256;
10235 screen->unparse_bfr = (IChar *) (void *) XtCalloc(screen->unparse_max,
10236 (Cardinal) sizeof(IChar));
10237
10238 if (screen->savelines < 0)
10239 screen->savelines = 0;
10240
10241 init_Bres(screen.awaitInput);
10242
10243 wnew->flags = 0;
10244 if (!screen->jumpscroll)
10245 wnew->flags |= SMOOTHSCROLL;
10246 if (wnew->misc.reverseWrap)
10247 wnew->flags |= REVERSEWRAP;
10248 if (wnew->misc.autoWrap)
10249 wnew->flags |= WRAPAROUND;
10250 if (wnew->misc.re_verse != wnew->misc.re_verse0)
10251 wnew->flags |= REVERSE_VIDEO;
10252 if (screen->c132)
10253 wnew->flags |= IN132COLUMNS;
10254
10255 wnew->initflags = wnew->flags;
10256
10257 init_Sres(keyboard.shift_escape_s);
10258 wnew->keyboard.shift_escape =
10259 extendedBoolean(wnew->keyboard.shift_escape_s, tblShift2S, ssLAST);
10260
10261 #if OPT_MOD_FKEYS
10262 init_Ires(keyboard.modify_1st.allow_keys);
10263 init_Ires(keyboard.modify_1st.cursor_keys);
10264 init_Ires(keyboard.modify_1st.function_keys);
10265 init_Ires(keyboard.modify_1st.keypad_keys);
10266 init_Ires(keyboard.modify_1st.other_keys);
10267 init_Ires(keyboard.modify_1st.string_keys);
10268 init_Ires(keyboard.format_keys);
10269 wnew->keyboard.modify_now = wnew->keyboard.modify_1st;
10270 #endif
10271
10272 init_Ires(misc.appcursorDefault);
10273 if (wnew->misc.appcursorDefault)
10274 wnew->keyboard.flags |= MODE_DECCKM;
10275
10276 init_Ires(misc.appkeypadDefault);
10277 if (wnew->misc.appkeypadDefault)
10278 wnew->keyboard.flags |= MODE_DECKPAM;
10279
10280 initLineData(wnew);
10281 #if OPT_WIDE_CHARS
10282 freeFontList(&(request->work.fonts.x11.list_n));
10283 #endif
10284 #if OPT_XRES_QUERY
10285 if (resource.reportXRes)
10286 reportResources(wnew);
10287 #endif
10288 xtermResetLocale(LC_NUMERIC, saveLocale);
10289 TRACE(("" TRACE_R " VTInitialize\n"));
10290 return;
10291 }
10292
10293 void
releaseCursorGCs(XtermWidget xw)10294 releaseCursorGCs(XtermWidget xw)
10295 {
10296 TScreen *screen = TScreenOf(xw);
10297 VTwin *win = WhichVWin(screen);
10298 int n;
10299
10300 for_each_curs_gc(n) {
10301 freeCgs(xw, win, (CgsEnum) n);
10302 }
10303 }
10304
10305 void
releaseWindowGCs(XtermWidget xw,VTwin * win)10306 releaseWindowGCs(XtermWidget xw, VTwin *win)
10307 {
10308 int n;
10309
10310 for_each_text_gc(n) {
10311 switch (n) {
10312 case gcBorder:
10313 case gcFiller:
10314 break;
10315 default:
10316 freeCgs(xw, win, (CgsEnum) n);
10317 break;
10318 }
10319 }
10320 }
10321
10322 #define TRACE_FREE_LEAK(name) \
10323 if (name) { \
10324 TRACE(("freed " #name ": %p\n", (const void *) name)); \
10325 FreeAndNull(name); \
10326 }
10327
10328 #define TRACE_FREE_GC(name,part) \
10329 if (part) { \
10330 TRACE(("freed %s " #part ": %p\n", name, (const void *) part)); \
10331 XFreeGC(dpy, part); \
10332 part = 0; \
10333 }
10334
10335 #if OPT_INPUT_METHOD
10336 static void
cleanupInputMethod(XtermWidget xw)10337 cleanupInputMethod(XtermWidget xw)
10338 {
10339 TInput *input = lookupTInput(xw, (Widget) xw);
10340
10341 if (input && input->xim) {
10342 XCloseIM(input->xim);
10343 input->xim = 0;
10344 TRACE(("freed screen->xim\n"));
10345 }
10346 }
10347 #else
10348 #define cleanupInputMethod(xw) /* nothing */
10349 #endif
10350
10351 #ifdef NO_LEAKS
10352 #define FREE_VT_WIN(name) freeVTwin(dpy, #name, &(screen->name))
10353 static void
freeVTwin(Display * dpy,const char * whichWin,VTwin * win)10354 freeVTwin(Display *dpy, const char *whichWin, VTwin *win)
10355 {
10356 (void) whichWin;
10357 TRACE_FREE_GC(whichWin, win->filler_gc);
10358 TRACE_FREE_GC(whichWin, win->border_gc);
10359 TRACE_FREE_GC(whichWin, win->marker_gc[0]);
10360 TRACE_FREE_GC(whichWin, win->marker_gc[1]);
10361 }
10362 #endif
10363
10364 static void
VTDestroy(Widget w GCC_UNUSED)10365 VTDestroy(Widget w GCC_UNUSED)
10366 {
10367 #ifdef NO_LEAKS
10368 XtermWidget xw = (XtermWidget) w;
10369 TScreen *screen = TScreenOf(xw);
10370 Display *dpy = screen->display;
10371 Cardinal n, k;
10372
10373 StopBlinking(xw);
10374
10375 if (screen->scrollWidget) {
10376 XtUninstallTranslations(screen->scrollWidget);
10377 XtDestroyWidget(screen->scrollWidget);
10378 }
10379
10380 while (screen->saved_fifo > 0) {
10381 deleteScrollback(screen);
10382 }
10383
10384 while (screen->save_title != 0) {
10385 SaveTitle *last = screen->save_title;
10386 screen->save_title = last->next;
10387 free(last->iconName);
10388 free(last->windowName);
10389 free(last);
10390 }
10391 #ifndef NO_ACTIVE_ICON
10392 TRACE_FREE_LEAK(xw->misc.active_icon_s);
10393 #endif
10394 #if OPT_ISO_COLORS
10395 TRACE_FREE_LEAK(screen->cmap_data);
10396 for (n = 0; n < MAXCOLORS; n++) {
10397 TRACE_FREE_LEAK(screen->Acolors[n].resource);
10398 }
10399 for (n = 0; n < MAX_SAVED_SGR; n++) {
10400 TRACE_FREE_LEAK(xw->saved_colors.palettes[n]);
10401 }
10402 #endif
10403 for (n = 0; n < NCOLORS; n++) {
10404 switch (n) {
10405 #if OPT_TEK4014
10406 case TEK_BG:
10407 /* FALLTHRU */
10408 case TEK_FG:
10409 /* FALLTHRU */
10410 case TEK_CURSOR:
10411 break;
10412 #endif
10413 default:
10414 TRACE_FREE_LEAK(screen->Tcolors[n].resource);
10415 break;
10416 }
10417 }
10418 FreeMarkGCs(xw);
10419 TRACE_FREE_LEAK(screen->unparse_bfr);
10420 TRACE_FREE_LEAK(screen->save_ptr);
10421 TRACE_FREE_LEAK(screen->saveBuf_data);
10422 TRACE_FREE_LEAK(screen->saveBuf_index);
10423 for (n = 0; n < 2; ++n) {
10424 TRACE_FREE_LEAK(screen->editBuf_data[n]);
10425 TRACE_FREE_LEAK(screen->editBuf_index[n]);
10426 }
10427 TRACE_FREE_LEAK(screen->keyboard_dialect);
10428 TRACE_FREE_LEAK(screen->cursor_font_name);
10429 TRACE_FREE_LEAK(screen->pointer_shape);
10430 TRACE_FREE_LEAK(screen->term_id);
10431 #if OPT_WIDE_CHARS
10432 TRACE_FREE_LEAK(screen->utf8_mode_s);
10433 TRACE_FREE_LEAK(screen->utf8_fonts_s);
10434 TRACE_FREE_LEAK(screen->utf8_title_s);
10435 #if OPT_LUIT_PROG
10436 TRACE_FREE_LEAK(xw->misc.locale_str);
10437 TRACE_FREE_LEAK(xw->misc.localefilter);
10438 #endif
10439 #endif
10440 TRACE_FREE_LEAK(xw->misc.T_geometry);
10441 TRACE_FREE_LEAK(xw->misc.geo_metry);
10442 #if OPT_INPUT_METHOD
10443 cleanupInputMethod(xw);
10444 TRACE_FREE_LEAK(xw->misc.f_x);
10445 TRACE_FREE_LEAK(xw->misc.input_method);
10446 TRACE_FREE_LEAK(xw->misc.preedit_type);
10447 #endif
10448 releaseCursorGCs(xw);
10449 releaseWindowGCs(xw, &(screen->fullVwin));
10450 #ifndef NO_ACTIVE_ICON
10451 XFreeFont(screen->display, getIconicFont(screen)->fs);
10452 releaseWindowGCs(xw, &(screen->iconVwin));
10453 #endif
10454 XtUninstallTranslations((Widget) xw);
10455 #if OPT_TOOLBAR
10456 XtUninstallTranslations((Widget) XtParent(xw));
10457 #endif
10458 XtUninstallTranslations((Widget) SHELL_OF(xw));
10459
10460 if (screen->hidden_cursor)
10461 XFreeCursor(screen->display, screen->hidden_cursor);
10462
10463 xtermCloseFonts(xw, screen->fnts);
10464 #if OPT_WIDE_ATTRS
10465 xtermCloseFonts(xw, screen->ifnts);
10466 #endif
10467 noleaks_cachedCgs(xw);
10468 free_termcap(xw);
10469
10470 FREE_VT_WIN(fullVwin);
10471 #ifndef NO_ACTIVE_ICON
10472 FREE_VT_WIN(iconVwin);
10473 #endif /* NO_ACTIVE_ICON */
10474
10475 TRACE_FREE_LEAK(screen->selection_targets_8bit);
10476 #if OPT_SELECT_REGEX
10477 for (n = 0; n < NSELECTUNITS; ++n) {
10478 if (screen->selectMap[n] == Select_REGEX) {
10479 TRACE_FREE_LEAK(screen->selectExpr[n]);
10480 }
10481 }
10482 #endif
10483
10484 #if OPT_RENDERFONT
10485 for (n = 0; n < NMENUFONTS; ++n) {
10486 int e;
10487 for (e = 0; e < fMAX; ++e) {
10488 xtermCloseXft(screen, getMyXftFont(xw, e, (int) n));
10489 }
10490 }
10491 discardRenderDraw(screen);
10492 {
10493 ListXftFonts *p;
10494 while ((p = screen->list_xft_fonts) != 0) {
10495 screen->list_xft_fonts = p->next;
10496 free(p);
10497 }
10498 }
10499 #endif
10500
10501 /* free things allocated via init_Sres or Init_Sres2 */
10502 #ifndef NO_ACTIVE_ICON
10503 TRACE_FREE_LEAK(screen->icon_fontname);
10504 #endif
10505 #ifdef ALLOWLOGGING
10506 TRACE_FREE_LEAK(screen->logfile);
10507 #endif
10508 TRACE_FREE_LEAK(screen->eight_bit_meta_s);
10509 TRACE_FREE_LEAK(screen->charClass);
10510 TRACE_FREE_LEAK(screen->answer_back);
10511 TRACE_FREE_LEAK(screen->printer_state.printer_command);
10512 TRACE_FREE_LEAK(screen->disallowedColorOps);
10513 TRACE_FREE_LEAK(screen->disallowedFontOps);
10514 TRACE_FREE_LEAK(screen->disallowedMouseOps);
10515 TRACE_FREE_LEAK(screen->disallowedPasteControls);
10516 TRACE_FREE_LEAK(screen->disallowedTcapOps);
10517 TRACE_FREE_LEAK(screen->disallowedWinOps);
10518 TRACE_FREE_LEAK(screen->default_string);
10519 TRACE_FREE_LEAK(screen->eightbit_select_types);
10520
10521 #if OPT_WIDE_CHARS
10522 TRACE_FREE_LEAK(screen->utf8_select_types);
10523 #endif
10524
10525 #if 0
10526 for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) {
10527 TRACE_FREE_LEAK(screen->MenuFontName(n));
10528 }
10529 #endif
10530
10531 TRACE_FREE_LEAK(screen->initial_font);
10532
10533 #if OPT_LUIT_PROG
10534 TRACE_FREE_LEAK(xw->misc.locale_str);
10535 TRACE_FREE_LEAK(xw->misc.localefilter);
10536 #endif
10537
10538 #if OPT_RENDERFONT
10539 TRACE_FREE_LEAK(xw->misc.default_xft.f_n);
10540 #if OPT_WIDE_CHARS
10541 TRACE_FREE_LEAK(xw->misc.default_xft.f_w);
10542 #endif
10543 TRACE_FREE_LEAK(xw->misc.render_font_s);
10544 #endif
10545
10546 TRACE_FREE_LEAK(xw->misc.default_font.f_n);
10547 TRACE_FREE_LEAK(xw->misc.default_font.f_b);
10548
10549 #if OPT_WIDE_CHARS
10550 TRACE_FREE_LEAK(xw->misc.default_font.f_w);
10551 TRACE_FREE_LEAK(xw->misc.default_font.f_wb);
10552 #endif
10553
10554 TRACE_FREE_LEAK(xw->work.wm_name);
10555 freeFontLists(&(xw->work.fonts.x11));
10556 #if OPT_RENDERFONT
10557 freeFontLists(&(xw->work.fonts.xft));
10558 #endif
10559
10560 xtermFontName(NULL);
10561 #if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS
10562 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n);
10563 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b);
10564 #if OPT_WIDE_CHARS
10565 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w);
10566 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb);
10567 #endif
10568 freeFontLists(&(screen->cacheVTFonts.fonts.x11));
10569 for (n = 0; n < NMENUFONTS; ++n) {
10570 for (k = 0; k < fMAX; ++k) {
10571 if (screen->menu_font_names[n][k] !=
10572 screen->cacheVTFonts.menu_font_names[n][k]) {
10573 if (screen->menu_font_names[n][k] != _Font_Selected_) {
10574 TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
10575 }
10576 TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]);
10577 } else {
10578 TRACE_FREE_LEAK(screen->menu_font_names[n][k]);
10579 }
10580 }
10581 }
10582 #endif
10583
10584 #if OPT_BLINK_CURS
10585 TRACE_FREE_LEAK(screen->cursor_blink_s);
10586 #endif
10587
10588 #if OPT_REGIS_GRAPHICS
10589 TRACE_FREE_LEAK(screen->graphics_regis_default_font);
10590 TRACE_FREE_LEAK(screen->graphics_regis_screensize);
10591 #endif
10592 #if OPT_GRAPHICS
10593 TRACE_FREE_LEAK(screen->graph_termid);
10594 TRACE_FREE_LEAK(screen->graphics_max_size);
10595 #endif
10596
10597 for (n = 0; n < NSELECTUNITS; ++n) {
10598 #if OPT_SELECT_REGEX
10599 TRACE_FREE_LEAK(screen->selectExpr[n]);
10600 #endif
10601 #if OPT_XRES_QUERY
10602 TRACE_FREE_LEAK(screen->onClick[n]);
10603 #endif
10604 }
10605
10606 XtFree((void *) (screen->selection_atoms));
10607
10608 for (n = 0; n < MAX_SELECTIONS; ++n) {
10609 free(screen->selected_cells[n].data_buffer);
10610 }
10611
10612 if (defaultTranslations != xtermClassRec.core_class.tm_table) {
10613 TRACE_FREE_LEAK(defaultTranslations);
10614 }
10615 TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table);
10616 TRACE_FREE_LEAK(xw->keyboard.shift_escape_s);
10617 TRACE_FREE_LEAK(xw->keyboard.extra_translations);
10618 TRACE_FREE_LEAK(xw->keyboard.shell_translations);
10619 TRACE_FREE_LEAK(xw->keyboard.xterm_translations);
10620 TRACE_FREE_LEAK(xw->keyboard.print_translations);
10621 UnmapSelections(xw);
10622
10623 XtFree((void *) (xw->visInfo));
10624
10625 #if OPT_WIDE_CHARS
10626 FreeTypedBuffer(XChar2b);
10627 FreeTypedBuffer(char);
10628 #endif
10629 #if OPT_RENDERFONT
10630 #if OPT_RENDERWIDE
10631 FreeTypedBuffer(XftCharSpec);
10632 #else
10633 FreeTypedBuffer(XftChar8);
10634 #endif
10635 #endif
10636
10637 TRACE_FREE_LEAK(myState.print_area);
10638 TRACE_FREE_LEAK(myState.string_area);
10639 memset(&myState, 0, sizeof(myState));
10640
10641 #endif /* defined(NO_LEAKS) */
10642 }
10643
10644 #ifndef NO_ACTIVE_ICON
10645 static void *
getProperty(Display * dpy,Window w,Atom req_type,const char * prop_name)10646 getProperty(Display *dpy,
10647 Window w,
10648 Atom req_type,
10649 const char *prop_name)
10650 {
10651 Atom property;
10652 Atom actual_return_type;
10653 int actual_format_return = 0;
10654 unsigned long nitems_return = 0;
10655 unsigned long bytes_after_return = 0;
10656 unsigned char *prop_return = 0;
10657 long long_length = 1024;
10658 size_t limit;
10659 char *result = 0;
10660
10661 TRACE(("getProperty %s(%s)\n", prop_name,
10662 req_type ? TraceAtomName(dpy, req_type) : "?"));
10663 property = XInternAtom(dpy, prop_name, False);
10664
10665 if (!xtermGetWinProp(dpy,
10666 w,
10667 property,
10668 0L,
10669 long_length,
10670 req_type,
10671 &actual_return_type,
10672 &actual_format_return,
10673 &nitems_return,
10674 &bytes_after_return,
10675 &prop_return)) {
10676 TRACE((".. Cannot get %s property.\n", prop_name));
10677 } else if (prop_return != 0) {
10678
10679 if (nitems_return != 0 &&
10680 actual_format_return != 0 &&
10681 actual_return_type == req_type) {
10682 /*
10683 * Null-terminate the result to make string handling easier.
10684 * The format==8 corresponds to strings, and the number of items
10685 * is the number of characters.
10686 */
10687 if (actual_format_return == 8) {
10688 limit = nitems_return;
10689 } else {
10690 /* manpage is misleading - X really uses 'long', not 32-bits */
10691 limit = sizeof(long) * nitems_return;
10692 }
10693 if ((result = malloc(limit + 1)) != 0) {
10694 memcpy(result, prop_return, limit);
10695 result[limit] = '\0';
10696 }
10697 TRACE(("... result %s\n", result ? ("ok") : "null"));
10698 }
10699 XFree(prop_return);
10700 } else {
10701 TRACE((".. no property returned\n"));
10702 }
10703 return (void *) result;
10704 }
10705
10706 /*
10707 * Active icons are supported by fvwm. This feature is not supported by
10708 * metacity (gnome) or kwin (kde). Both metacity and kwin support (in
10709 * incompatible ways, e.g., one uses the icon theme as a fallback for window
10710 * decorations but the other does not, etc, ...) an icon as part of the window
10711 * decoration (usually on the upper-left of the window).
10712 *
10713 * In either case, xterm's icon will only be shown in the window decorations if
10714 * xterm does not use the active icon feature.
10715 *
10716 * This function (tries to) determine the window manager's name, so that we can
10717 * provide a useful automatic default for active icons. It is based on reading
10718 * wmctrl, which covers most of EWMH and ICCM.
10719 */
10720 static char *
getWindowManagerName(XtermWidget xw)10721 getWindowManagerName(XtermWidget xw)
10722 {
10723 TScreen *screen = TScreenOf(xw);
10724 Display *dpy = screen->display;
10725 Window *sup_window = NULL;
10726 char *result = 0;
10727
10728 TRACE(("getWindowManagerName\n"));
10729 #define getWinProp(type, name) \
10730 (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name)
10731 if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == 0) {
10732 sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK");
10733 }
10734
10735 /*
10736 * If we found the supporting window, get the property containing the
10737 * window manager's name. EWMH defines _NET_WM_NAME, while ICCM defines
10738 * WM_CLASS. There is no standard for the names stored there;
10739 * conventionally it is mixed case. In practice, the former is more often
10740 * set; the latter is not given (or is a lowercased version of the former).
10741 */
10742 if (sup_window != 0) {
10743 #define getStringProp(type,name) \
10744 (char *)getProperty(dpy, *sup_window, type, name)
10745 if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == 0
10746 && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == 0
10747 && (result = getStringProp(XA_STRING, "WM_CLASS")) == 0) {
10748 TRACE(("... window manager does not tell its name\n"));
10749 }
10750 free(sup_window);
10751 } else {
10752 TRACE(("... Cannot get window manager info properties\n"));
10753 }
10754 if (result == 0)
10755 result = x_strdup("unknown");
10756 TRACE(("... window manager name is %s\n", result));
10757 return result;
10758 }
10759
10760 static Boolean
discount_frame_extents(XtermWidget xw,int * high,int * wide)10761 discount_frame_extents(XtermWidget xw, int *high, int *wide)
10762 {
10763 TScreen *screen = TScreenOf(xw);
10764 Display *dpy = screen->display;
10765
10766 Atom atom_supported = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False);
10767 Atom actual_type;
10768 int actual_format;
10769 long long_offset = 0;
10770 long long_length = 128; /* number of items to ask for at a time */
10771 unsigned long nitems;
10772 unsigned long bytes_after;
10773 unsigned char *args;
10774 Boolean rc;
10775
10776 rc = xtermGetWinProp(dpy,
10777 VShellWindow(xw),
10778 atom_supported,
10779 long_offset,
10780 long_length,
10781 XA_CARDINAL, /* req_type */
10782 &actual_type, /* actual_type_return */
10783 &actual_format, /* actual_format_return */
10784 &nitems, /* nitems_return */
10785 &bytes_after, /* bytes_after_return */
10786 &args /* prop_return */
10787 );
10788
10789 if (rc && args && (nitems == 4) && (actual_format == 32)) {
10790 long *extents = (long *) (void *) args;
10791
10792 TRACE(("_NET_FRAME_EXTENTS:\n"));
10793 TRACE((" left: %ld\n", extents[0]));
10794 TRACE((" right: %ld\n", extents[1]));
10795 TRACE((" top: %ld\n", extents[2]));
10796 TRACE((" bottom: %ld\n", extents[3]));
10797
10798 if (!x_strncasecmp(xw->work.wm_name, "gnome shell", 11)) {
10799 *wide -= (int) (extents[0] + extents[1]); /* -= (left+right) */
10800 *high -= (int) (extents[2] + extents[3]); /* -= (top+bottom) */
10801 TRACE(("...applied extents %d,%d\n", *high, *wide));
10802 } else if (!x_strncasecmp(xw->work.wm_name, "compiz", 6)) {
10803 /* Ubuntu 16.04 is really off-by-one */
10804 *wide -= (int) (extents[0] + extents[1] - 1);
10805 *high -= (int) (extents[2] + extents[3] - 1);
10806 TRACE(("...applied extents %d,%d\n", *high, *wide));
10807 } else if (!x_strncasecmp(xw->work.wm_name, "fvwm", 4)) {
10808 TRACE(("...skipping extents\n"));
10809 } else {
10810 TRACE(("...ignoring extents\n"));
10811 rc = False;
10812 }
10813 } else {
10814 rc = False;
10815 }
10816 return rc;
10817 }
10818 #endif /* !NO_ACTIVE_ICON */
10819
10820 void
initBorderGC(XtermWidget xw,VTwin * win)10821 initBorderGC(XtermWidget xw, VTwin *win)
10822 {
10823 TScreen *screen = TScreenOf(xw);
10824 Pixel filler;
10825
10826 TRACE(("initBorderGC(%s) core bg %#lx, bd %#lx text fg %#lx, bg %#lx %s\n",
10827 (win == &(screen->fullVwin)) ? "full" : "icon",
10828 xw->core.background_pixel,
10829 xw->core.border_pixel,
10830 T_COLOR(screen, TEXT_FG),
10831 T_COLOR(screen, TEXT_BG),
10832 xw->misc.re_verse ? "reverse" : "normal"));
10833 if (xw->misc.color_inner_border
10834 && (xw->core.background_pixel != xw->core.border_pixel)) {
10835 /*
10836 * By default, try to match the inner window's background.
10837 */
10838 if ((xw->core.background_pixel == T_COLOR(screen, TEXT_BG)) &&
10839 (xw->core.border_pixel == T_COLOR(screen, TEXT_FG))) {
10840 filler = T_COLOR(screen, TEXT_BG);
10841 } else {
10842 filler = xw->core.border_pixel;
10843 }
10844 TRACE((" border %#lx\n", filler));
10845 setCgsFore(xw, win, gcBorder, filler);
10846 setCgsBack(xw, win, gcBorder, filler);
10847 win->border_gc = getCgsGC(xw, win, gcBorder);
10848 }
10849 #if USE_DOUBLE_BUFFER
10850 else if (resource.buffered) {
10851 filler = T_COLOR(screen, TEXT_BG);
10852 TRACE((" border %#lx (buffered)\n", filler));
10853 setCgsFore(xw, win, gcBorder, filler);
10854 setCgsBack(xw, win, gcBorder, filler);
10855 win->border_gc = getCgsGC(xw, win, gcBorder);
10856 }
10857 #endif
10858 else {
10859 TRACE((" border unused\n"));
10860 win->border_gc = 0;
10861 }
10862
10863 /*
10864 * Initialize a GC for double-buffering, needed for XFillRectangle call
10865 * in xtermClear2(). When not double-buffering, the XClearArea call works,
10866 * without requiring a separate GC.
10867 */
10868 #if USE_DOUBLE_BUFFER
10869 if (resource.buffered) {
10870 filler = (((xw->flags & BG_COLOR) && (xw->cur_background >= 0))
10871 ? getXtermBG(xw, xw->flags, xw->cur_background)
10872 : T_COLOR(screen, TEXT_BG));
10873
10874 TRACE((" filler %#lx %s\n",
10875 filler,
10876 xw->misc.re_verse ? "reverse" : "normal"));
10877
10878 setCgsFore(xw, win, gcFiller, filler);
10879 setCgsBack(xw, win, gcFiller, filler);
10880
10881 win->filler_gc = getCgsGC(xw, win, gcFiller);
10882 }
10883 #endif
10884 }
10885 #if USE_DOUBLE_BUFFER
10886 static Boolean
allocateDbe(XtermWidget xw,VTwin * target)10887 allocateDbe(XtermWidget xw, VTwin *target)
10888 {
10889 TScreen *screen = TScreenOf(xw);
10890 Boolean result = False;
10891
10892 target->drawable = target->window;
10893
10894 if (resource.buffered) {
10895 Window win = target->window;
10896 Drawable d;
10897 int major, minor;
10898 if (XdbeQueryExtension(XtDisplay(xw), &major, &minor)) {
10899 d = XdbeAllocateBackBufferName(XtDisplay(xw), win,
10900 (XdbeSwapAction) XdbeCopied);
10901 if (d == None) {
10902 fprintf(stderr, "Couldn't allocate a back buffer!\n");
10903 exit(3);
10904 }
10905 target->drawable = d;
10906 screen->needSwap = 1;
10907 TRACE(("initialized double-buffering\n"));
10908 result = True;
10909 } else {
10910 resource.buffered = False;
10911 }
10912 }
10913 return result;
10914 }
10915 #endif /* USE_DOUBLE_BUFFER */
10916
10917 /*ARGSUSED*/
10918 static void
VTRealize(Widget w,XtValueMask * valuemask,XSetWindowAttributes * values)10919 VTRealize(Widget w,
10920 XtValueMask * valuemask,
10921 XSetWindowAttributes * values)
10922 {
10923 XtermWidget xw = (XtermWidget) w;
10924 TScreen *screen = TScreenOf(xw);
10925
10926 const VTFontNames *myfont;
10927 struct Xinerama_geometry pos;
10928 int pr;
10929 Atom pid_atom;
10930 int i;
10931
10932 TRACE(("VTRealize " TRACE_L "\n"));
10933
10934 TabReset(xw->tabs);
10935
10936 if (screen->menu_font_number == fontMenu_default) {
10937 myfont = defaultVTFontNames(xw);
10938 } else {
10939 myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number));
10940 }
10941 memset(screen->fnts, 0, sizeof(screen->fnts));
10942
10943 if (!xtermLoadFont(xw,
10944 myfont,
10945 False,
10946 screen->menu_font_number)) {
10947 if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) {
10948 char *use_font = x_strdup(DEFFONT);
10949 xtermWarning("unable to open font \"%s\", trying \"%s\"....\n",
10950 myfont->f_n, use_font);
10951 (void) xtermLoadFont(xw,
10952 xtermFontName(use_font),
10953 False,
10954 screen->menu_font_number);
10955 screen->MenuFontName(screen->menu_font_number) = use_font;
10956 }
10957 }
10958
10959 /* really screwed if we couldn't open default font */
10960 if (!GetNormalFont(screen, fNorm)->fs) {
10961 xtermWarning("unable to locate a suitable font\n");
10962 Exit(1);
10963 }
10964 #if OPT_WIDE_CHARS
10965 if (screen->utf8_mode) {
10966 TRACE(("check if this is a wide font, if not try again\n"));
10967 if (xtermLoadWideFonts(xw, False)) {
10968 SetVTFont(xw, screen->menu_font_number, True, NULL);
10969 /* we will not be able to switch to ISO-8859-1 */
10970 if (!screen->mergedVTFonts) {
10971 screen->utf8_fonts = uAlways;
10972 update_font_utf8_fonts();
10973 }
10974 }
10975 }
10976 #endif
10977
10978 xtermSetupPointer(xw, screen->pointer_shape);
10979
10980 /* set defaults */
10981 pos.x = 1;
10982 pos.y = 1;
10983 pos.w = 80;
10984 pos.h = 24;
10985
10986 TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry)));
10987 pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos);
10988 TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w));
10989
10990 set_max_col(screen, (int) (pos.w - 1)); /* units in character cells */
10991 set_max_row(screen, (int) (pos.h - 1)); /* units in character cells */
10992 xtermUpdateFontInfo(xw, False);
10993
10994 pos.w = screen->fullVwin.fullwidth;
10995 pos.h = screen->fullVwin.fullheight;
10996
10997 TRACE(("... BorderWidth: widget %d parent %d shell %d\n",
10998 BorderWidth(xw),
10999 BorderWidth(XtParent(xw)),
11000 BorderWidth(SHELL_OF(xw))));
11001
11002 if ((pr & XValue) && (XNegative & pr)) {
11003 pos.x = (Position) (pos.x + (pos.scr_w
11004 - (int) pos.w
11005 - (BorderWidth(XtParent(xw)) * 2)));
11006 }
11007 if ((pr & YValue) && (YNegative & pr)) {
11008 pos.y = (Position) (pos.y + (pos.scr_h
11009 - (int) pos.h
11010 - (BorderWidth(XtParent(xw)) * 2)));
11011 }
11012 pos.x = (Position) (pos.x + pos.scr_x);
11013 pos.y = (Position) (pos.y + pos.scr_y);
11014
11015 /* set up size hints for window manager; min 1 char by 1 char */
11016 getXtermSizeHints(xw);
11017 xtermSizeHints(xw, (xw->misc.scrollbar
11018 ? (screen->scrollWidget->core.width
11019 + BorderWidth(screen->scrollWidget))
11020 : 0));
11021
11022 xw->hints.x = pos.x;
11023 xw->hints.y = pos.y;
11024 #if OPT_MAXIMIZE
11025 /* assure single-increment resize for fullscreen */
11026 if (xw->work.ewmh[0].mode) {
11027 xw->hints.width_inc = 1;
11028 xw->hints.height_inc = 1;
11029 }
11030 #endif
11031 if ((XValue & pr) || (YValue & pr)) {
11032 xw->hints.flags |= USSize | USPosition;
11033 xw->hints.flags |= PWinGravity;
11034 switch (pr & (XNegative | YNegative)) {
11035 case 0:
11036 xw->hints.win_gravity = NorthWestGravity;
11037 break;
11038 case XNegative:
11039 xw->hints.win_gravity = NorthEastGravity;
11040 break;
11041 case YNegative:
11042 xw->hints.win_gravity = SouthWestGravity;
11043 break;
11044 default:
11045 xw->hints.win_gravity = SouthEastGravity;
11046 break;
11047 }
11048 } else {
11049 /* set a default size, but do *not* set position */
11050 xw->hints.flags |= PSize;
11051 }
11052 xw->hints.height = xw->hints.base_height
11053 + xw->hints.height_inc * MaxRows(screen);
11054 xw->hints.width = xw->hints.base_width
11055 + xw->hints.width_inc * MaxCols(screen);
11056
11057 if ((WidthValue & pr) || (HeightValue & pr))
11058 xw->hints.flags |= USSize;
11059 else
11060 xw->hints.flags |= PSize;
11061
11062 /*
11063 * Note that the size-hints are for the shell, while the resize-request
11064 * is for the vt100 widget. They are not the same size.
11065 */
11066 (void) REQ_RESIZE((Widget) xw,
11067 (Dimension) pos.w, (Dimension) pos.h,
11068 &xw->core.width, &xw->core.height);
11069
11070 /* XXX This is bogus. We are parsing geometries too late. This
11071 * is information that the shell widget ought to have before we get
11072 * realized, so that it can do the right thing.
11073 */
11074 if (xw->hints.flags & USPosition)
11075 XMoveWindow(XtDisplay(xw), VShellWindow(xw),
11076 xw->hints.x, xw->hints.y);
11077
11078 TRACE(("%s@%d -- ", __FILE__, __LINE__));
11079 TRACE_HINTS(&xw->hints);
11080 XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints);
11081 TRACE(("%s@%d -- ", __FILE__, __LINE__));
11082 TRACE_WM_HINTS(xw);
11083
11084 if ((pid_atom = XInternAtom(XtDisplay(xw), "_NET_WM_PID", False)) != None) {
11085 /* XChangeProperty format 32 really is "long" */
11086 unsigned long pid_l = (unsigned long) getpid();
11087 TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l));
11088 XChangeProperty(XtDisplay(xw), VShellWindow(xw),
11089 pid_atom, XA_CARDINAL, 32, PropModeReplace,
11090 (unsigned char *) &pid_l, 1);
11091 }
11092
11093 XFlush(XtDisplay(xw)); /* get it out to window manager */
11094
11095 /* use ForgetGravity instead of SouthWestGravity because translating
11096 the Expose events for ConfigureNotifys is too hard */
11097 values->bit_gravity = (GravityIsNorthWest(xw)
11098 ? NorthWestGravity
11099 : ForgetGravity);
11100 screen->fullVwin.window = XtWindow(xw) =
11101 XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)),
11102 xw->core.x, xw->core.y,
11103 xw->core.width, xw->core.height, BorderWidth(xw),
11104 (int) xw->core.depth,
11105 InputOutput, CopyFromParent,
11106 *valuemask | CWBitGravity, values);
11107 #if USE_DOUBLE_BUFFER
11108 if (allocateDbe(xw, &(screen->fullVwin))) {
11109 screen->needSwap = 1;
11110 TRACE(("initialized full double-buffering\n"));
11111 } else {
11112 resource.buffered = False;
11113 screen->fullVwin.drawable = screen->fullVwin.window;
11114 }
11115 #endif /* USE_DOUBLE_BUFFER */
11116 screen->event_mask = values->event_mask;
11117
11118 #ifndef NO_ACTIVE_ICON
11119 /*
11120 * Normally, the font-number for icon fonts does not correspond with any of
11121 * the menu-selectable fonts. If we cannot load the font given for the
11122 * iconFont resource, try with font1 aka "Unreadable".
11123 */
11124 screen->icon_fontnum = -1;
11125 if (getIconicFont(screen)->fs == 0) {
11126 getIconicFont(screen)->fs =
11127 xtermLoadQueryFont(xw, screen->MenuFontName(fontMenu_font1));
11128 ReportIcons(("%susing font1 '%s' as iconFont\n",
11129 (getIconicFont(screen)->fs
11130 ? ""
11131 : "NOT "),
11132 screen->MenuFontName(fontMenu_font1)));
11133 }
11134 #if OPT_RENDERFONT
11135 /*
11136 * If we still have no result from iconFont resource (perhaps because fonts
11137 * are missing) but are using Xft, try to use that instead. We prefer
11138 * bitmap fonts in any case, since scaled fonts are usually less readable,
11139 * particularly at small sizes.
11140 */
11141 if (UsingRenderFont(xw)
11142 && getIconicFont(screen)->fs == 0) {
11143 screen->icon_fontnum = fontMenu_default;
11144 getIconicFont(screen)->fs = GetNormalFont(screen, fNorm)->fs; /* need for next-if */
11145 ReportIcons(("using TrueType font as iconFont\n"));
11146 }
11147 #endif
11148 xw->work.wm_name = getWindowManagerName(xw);
11149 if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) {
11150 ReportIcons(("window manager name is %s\n", xw->work.wm_name));
11151 if (x_strncasecmp(xw->work.wm_name, "fvwm", 4) &&
11152 x_strncasecmp(xw->work.wm_name, "window maker", 12)) {
11153 xw->work.active_icon = eiFalse;
11154 TRACE(("... disable active_icon\n"));
11155 }
11156 }
11157 TRACE((".. if active_icon (%d), get its font\n", xw->work.active_icon));
11158 if (xw->work.active_icon && getIconicFont(screen)->fs) {
11159 int iconX = 0, iconY = 0;
11160 Widget shell = SHELL_OF(xw);
11161 VTwin *win = &(screen->iconVwin);
11162 int save_fontnum = screen->menu_font_number;
11163
11164 ReportIcons(("initializing active-icon %d\n", screen->icon_fontnum));
11165 screen->menu_font_number = screen->icon_fontnum;
11166 XtVaGetValues(shell,
11167 XtNiconX, &iconX,
11168 XtNiconY, &iconY,
11169 (XtPointer) 0);
11170 xtermComputeFontInfo(xw, &(screen->iconVwin),
11171 getIconicFont(screen)->fs, 0);
11172 screen->menu_font_number = save_fontnum;
11173
11174 /* since only one client is permitted to select for Button
11175 * events, we have to let the window manager get 'em...
11176 */
11177 values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask);
11178 values->border_pixel = xw->misc.icon_border_pixel;
11179
11180 screen->iconVwin.window =
11181 XCreateWindow(XtDisplay(xw),
11182 RootWindowOfScreen(XtScreen(shell)),
11183 iconX, iconY,
11184 screen->iconVwin.fullwidth,
11185 screen->iconVwin.fullheight,
11186 xw->misc.icon_border_width,
11187 (int) xw->core.depth,
11188 InputOutput, CopyFromParent,
11189 *valuemask | CWBitGravity | CWBorderPixel,
11190 values);
11191 #if USE_DOUBLE_BUFFER
11192 if (allocateDbe(xw, &(screen->iconVwin))) {
11193 TRACE(("initialized icon double-buffering\n"));
11194 } else {
11195 resource.buffered = False;
11196 screen->iconVwin.drawable = screen->iconVwin.window;
11197 screen->fullVwin.drawable = screen->fullVwin.window;
11198 }
11199 #endif /* USE_DOUBLE_BUFFER */
11200 XtVaSetValues(shell,
11201 XtNiconWindow, screen->iconVwin.window,
11202 (XtPointer) 0);
11203 XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w);
11204
11205 setCgsFont(xw, win, gcNorm, getIconicFont(screen));
11206 setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG));
11207 setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG));
11208
11209 copyCgs(xw, win, gcBold, gcNorm);
11210
11211 setCgsFont(xw, win, gcNormReverse, getIconicFont(screen));
11212 setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG));
11213 setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG));
11214
11215 copyCgs(xw, win, gcBoldReverse, gcNormReverse);
11216
11217 initBorderGC(xw, win);
11218
11219 #if OPT_TOOLBAR
11220 /*
11221 * Toolbar is initialized before we get here. Enable the menu item
11222 * and set it properly.
11223 */
11224 SetItemSensitivity(vtMenuEntries[vtMenu_activeicon].widget, True);
11225 update_activeicon();
11226 #endif
11227 } else {
11228 ReportIcons(("disabled active-icon\n"));
11229 xw->work.active_icon = eiFalse;
11230 }
11231 #endif /* NO_ACTIVE_ICON */
11232
11233 #if OPT_INPUT_METHOD
11234 VTInitI18N(xw);
11235 #endif
11236 #if OPT_NUM_LOCK
11237 VTInitModifiers(xw);
11238 #if OPT_EXTRA_PASTE
11239 if (xw->keyboard.extra_translations) {
11240 XtOverrideTranslations((Widget) xw,
11241 XtParseTranslationTable(xw->keyboard.extra_translations));
11242 }
11243 #endif
11244 #endif
11245
11246 set_cursor_gcs(xw);
11247 initBorderGC(xw, &(screen->fullVwin));
11248
11249 /* Reset variables used by ANSI emulation. */
11250
11251 resetCharsets(screen);
11252
11253 XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor);
11254
11255 set_cur_col(screen, 0);
11256 set_cur_row(screen, 0);
11257 set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1);
11258 set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1);
11259 resetMarginMode(xw);
11260
11261 memset(screen->sc, 0, sizeof(screen->sc));
11262
11263 /* Mark screen buffer as unallocated. We wait until the run loop so
11264 that the child process does not fork and exec with all the dynamic
11265 memory it will never use. If we were to do it here, the
11266 swap space for new process would be huge for huge savelines. */
11267 #if OPT_TEK4014
11268 if (!tekWidget) /* if not called after fork */
11269 #endif
11270 {
11271 screen->visbuf = NULL;
11272 screen->saveBuf_index = NULL;
11273 }
11274
11275 ResetWrap(screen);
11276 screen->scrolls = screen->incopy = 0;
11277 xtermSetCursorBox(screen);
11278
11279 screen->savedlines = 0;
11280
11281 for (i = 0; i < 2; ++i) {
11282 screen->whichBuf = !screen->whichBuf;
11283 CursorSave(xw);
11284 }
11285
11286 #ifndef NO_ACTIVE_ICON
11287 if (!xw->work.active_icon)
11288 #endif
11289 xtermLoadIcon(xw, resource.icon_hint);
11290
11291 /*
11292 * Do this last, since it may change the layout via a resize.
11293 */
11294 if (xw->misc.scrollbar) {
11295 screen->fullVwin.sb_info.width = 0;
11296 ScrollBarOn(xw, False);
11297 }
11298
11299 xtermSetWinSize(xw);
11300 TRACE(("" TRACE_R " VTRealize\n"));
11301 }
11302
11303 #if OPT_INPUT_METHOD
11304
11305 /* limit this feature to recent XFree86 since X11R6.x core dumps */
11306 #if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING)
11307 #define USE_XIM_INSTANTIATE_CB
11308
11309 static void
xim_instantiate_cb(Display * display,XPointer client_data GCC_UNUSED,XPointer call_data GCC_UNUSED)11310 xim_instantiate_cb(Display *display,
11311 XPointer client_data GCC_UNUSED,
11312 XPointer call_data GCC_UNUSED)
11313 {
11314 XtermWidget xw = term;
11315
11316 TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data));
11317
11318 if (display == XtDisplay(xw)) {
11319 VTInitI18N(xw);
11320 }
11321 }
11322
11323 static void
xim_destroy_cb(XIM im GCC_UNUSED,XPointer client_data GCC_UNUSED,XPointer call_data GCC_UNUSED)11324 xim_destroy_cb(XIM im GCC_UNUSED,
11325 XPointer client_data GCC_UNUSED,
11326 XPointer call_data GCC_UNUSED)
11327 {
11328 XtermWidget xw = term;
11329 TInput *input = lookupTInput(xw, (Widget) xw);
11330
11331 TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n",
11332 (long) im, client_data, call_data));
11333 if (input)
11334 input->xic = NULL;
11335 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
11336 xim_instantiate_cb, NULL);
11337 }
11338 #endif /* X11R6+ */
11339
11340 static Boolean
xim_create_fs(XtermWidget xw)11341 xim_create_fs(XtermWidget xw)
11342 {
11343 XFontStruct **fonts;
11344 char **font_name_list;
11345 char **missing_charset_list;
11346 char *def_string;
11347 int missing_charset_count;
11348 unsigned i, j;
11349
11350 if (xw->work.xim_fs == 0) {
11351 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
11352 xw->misc.f_x,
11353 &missing_charset_list,
11354 &missing_charset_count,
11355 &def_string);
11356 if (xw->work.xim_fs == NULL) {
11357 xtermWarning("Preparation of font set "
11358 "\"%s\" for XIM failed.\n", xw->misc.f_x);
11359 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw),
11360 DEFXIMFONT,
11361 &missing_charset_list,
11362 &missing_charset_count,
11363 &def_string);
11364 }
11365 }
11366 if (xw->work.xim_fs == NULL) {
11367 xtermWarning("Preparation of default font set "
11368 "\"%s\" for XIM failed.\n", DEFXIMFONT);
11369 cleanupInputMethod(xw);
11370 xw->work.cannot_im = True;
11371 } else {
11372 (void) XExtentsOfFontSet(xw->work.xim_fs);
11373 j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list);
11374 for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) {
11375 if (xw->work.xim_fs_ascent < (*fonts)->ascent)
11376 xw->work.xim_fs_ascent = (*fonts)->ascent;
11377 }
11378 }
11379 return (Boolean) !(xw->work.cannot_im);
11380 }
11381
11382 static void
xim_create_xic(XtermWidget xw,Widget theInput)11383 xim_create_xic(XtermWidget xw, Widget theInput)
11384 {
11385 Display *myDisplay = XtDisplay(theInput);
11386 Window myWindow = XtWindow(theInput);
11387 unsigned i, j;
11388 char *p = NULL, *s, *t, *ns, *end, buf[32];
11389 XIMStyles *xim_styles;
11390 XIMStyle input_style = 0;
11391 Bool found;
11392 static struct {
11393 const char *name;
11394 unsigned long code;
11395 } known_style[] = {
11396 {
11397 "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing)
11398 },
11399 {
11400 "OffTheSpot", (XIMPreeditArea | XIMStatusArea)
11401 },
11402 {
11403 "Root", (XIMPreeditNothing | XIMStatusNothing)
11404 },
11405 };
11406 TInput *input = lookupTInput(xw, theInput);
11407
11408 if (xw->work.cannot_im) {
11409 return;
11410 }
11411
11412 if (input == 0) {
11413 for (i = 0; i < NINPUTWIDGETS; ++i) {
11414 if (xw->work.inputs[i].w == 0) {
11415 input = xw->work.inputs + i;
11416 input->w = theInput;
11417 break;
11418 }
11419 }
11420 }
11421
11422 if (input == 0) {
11423 xtermWarning("attempted to add too many input widgets\n");
11424 return;
11425 }
11426
11427 TRACE(("xim_real_init\n"));
11428
11429 if (IsEmpty(xw->misc.input_method)) {
11430 if ((p = XSetLocaleModifiers("")) != NULL && *p) {
11431 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
11432 }
11433 } else {
11434 s = xw->misc.input_method;
11435 i = 5 + (unsigned) strlen(s);
11436
11437 t = (char *) MyStackAlloc(i, buf);
11438 if (t == NULL) {
11439 SysError(ERROR_VINIT);
11440 } else {
11441
11442 for (ns = s; ns && *s;) {
11443 while (*s && isspace(CharOf(*s)))
11444 s++;
11445 if (!*s)
11446 break;
11447 if ((ns = end = strchr(s, ',')) == 0)
11448 end = s + strlen(s);
11449 while ((end != s) && isspace(CharOf(end[-1])))
11450 end--;
11451
11452 if (end != s) {
11453 strcpy(t, "@im=");
11454 strncat(t, s, (size_t) (end - s));
11455
11456 if ((p = XSetLocaleModifiers(t)) != 0 && *p
11457 && (input->xim = XOpenIM(myDisplay,
11458 NULL,
11459 NULL,
11460 NULL)) != 0) {
11461 break;
11462 }
11463
11464 }
11465 s = ns + 1;
11466 }
11467 MyStackFree(t, buf);
11468 }
11469 }
11470
11471 if (input->xim == NULL
11472 && (p = XSetLocaleModifiers("@im=none")) != NULL
11473 && *p) {
11474 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL);
11475 }
11476
11477 if (!input->xim) {
11478 xtermWarning("Failed to open input method\n");
11479 return;
11480 }
11481 TRACE(("VTInitI18N opened input method:%s\n", NonNull(p)));
11482
11483 if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0)
11484 || !xim_styles
11485 || !xim_styles->count_styles) {
11486 xtermWarning("input method doesn't support any style\n");
11487 cleanupInputMethod(xw);
11488 xw->work.cannot_im = True;
11489 return;
11490 }
11491
11492 found = False;
11493 for (s = xw->misc.preedit_type; s && !found;) {
11494 while (*s && isspace(CharOf(*s)))
11495 s++;
11496 if (!*s)
11497 break;
11498 if ((ns = end = strchr(s, ',')) != 0)
11499 ns++;
11500 else
11501 end = s + strlen(s);
11502 while ((end != s) && isspace(CharOf(end[-1])))
11503 end--;
11504
11505 if (end != s) { /* just in case we have a spurious comma */
11506 TRACE(("looking for style '%.*s'\n", (int) (end - s), s));
11507 for (i = 0; i < XtNumber(known_style); i++) {
11508 if ((int) strlen(known_style[i].name) == (end - s)
11509 && !strncmp(s, known_style[i].name, (size_t) (end - s))) {
11510 input_style = known_style[i].code;
11511 for (j = 0; j < xim_styles->count_styles; j++) {
11512 if (input_style == xim_styles->supported_styles[j]) {
11513 found = True;
11514 break;
11515 }
11516 }
11517 if (found)
11518 break;
11519 }
11520 }
11521 }
11522
11523 s = ns;
11524 }
11525 XFree(xim_styles);
11526
11527 if (!found) {
11528 xtermWarning("input method doesn't support my preedit type (%s)\n",
11529 xw->misc.preedit_type);
11530 cleanupInputMethod(xw);
11531 xw->work.cannot_im = True;
11532 return;
11533 }
11534
11535 /*
11536 * Check for styles we do not yet support.
11537 */
11538 TRACE(("input_style %#lx\n", input_style));
11539 if (input_style == (XIMPreeditArea | XIMStatusArea)) {
11540 xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n");
11541 cleanupInputMethod(xw);
11542 xw->work.cannot_im = True;
11543 return;
11544 }
11545
11546 /*
11547 * For XIMPreeditPosition (or OverTheSpot), XIM client has to
11548 * prepare a font.
11549 * The font has to be locale-dependent XFontSet, whereas
11550 * XTerm use Unicode font. This leads a problem that the
11551 * same font cannot be used for XIM preedit.
11552 */
11553 if (input_style != (XIMPreeditNothing | XIMStatusNothing)) {
11554 XVaNestedList p_list;
11555 XPoint spot =
11556 {0, 0};
11557
11558 if (xim_create_fs(xw)) {
11559 p_list = XVaCreateNestedList(0,
11560 XNSpotLocation, &spot,
11561 XNFontSet, xw->work.xim_fs,
11562 (void *) 0);
11563 input->xic = XCreateIC(input->xim,
11564 XNInputStyle, input_style,
11565 XNClientWindow, myWindow,
11566 XNFocusWindow, myWindow,
11567 XNPreeditAttributes, p_list,
11568 (void *) 0);
11569 }
11570 } else {
11571 input->xic = XCreateIC(input->xim, XNInputStyle, input_style,
11572 XNClientWindow, myWindow,
11573 XNFocusWindow, myWindow,
11574 (void *) 0);
11575 }
11576
11577 if (!input->xic) {
11578 xtermWarning("Failed to create input context\n");
11579 cleanupInputMethod(xw);
11580 }
11581 #if defined(USE_XIM_INSTANTIATE_CB)
11582 else {
11583 XIMCallback destroy_cb;
11584
11585 destroy_cb.callback = xim_destroy_cb;
11586 destroy_cb.client_data = NULL;
11587 if (XSetIMValues(input->xim,
11588 XNDestroyCallback,
11589 &destroy_cb,
11590 (void *) 0)) {
11591 xtermWarning("Could not set destroy callback to IM\n");
11592 }
11593 }
11594 #endif
11595
11596 return;
11597 }
11598
11599 static void
xim_real_init(XtermWidget xw)11600 xim_real_init(XtermWidget xw)
11601 {
11602 xim_create_xic(xw, (Widget) xw);
11603 }
11604
11605 static void
VTInitI18N(XtermWidget xw)11606 VTInitI18N(XtermWidget xw)
11607 {
11608 if (xw->misc.open_im) {
11609 xim_real_init(xw);
11610
11611 #if defined(USE_XIM_INSTANTIATE_CB)
11612 if (lookupTInput(xw, (Widget) xw) == NULL
11613 && !xw->work.cannot_im
11614 && xw->misc.retry_im-- > 0) {
11615 sleep(3);
11616 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL,
11617 xim_instantiate_cb, NULL);
11618 }
11619 #endif
11620 }
11621 }
11622
11623 TInput *
lookupTInput(XtermWidget xw,Widget w)11624 lookupTInput(XtermWidget xw, Widget w)
11625 {
11626 TInput *result = 0;
11627 unsigned n;
11628
11629 for (n = 0; n < NINPUTWIDGETS; ++n) {
11630 if (xw->work.inputs[n].w == w) {
11631 result = xw->work.inputs + n;
11632 break;
11633 }
11634 }
11635
11636 return result;
11637 }
11638 #endif /* OPT_INPUT_METHOD */
11639
11640 static void
set_cursor_outline_gc(XtermWidget xw,Bool filled,Pixel fg,Pixel bg,Pixel cc)11641 set_cursor_outline_gc(XtermWidget xw,
11642 Bool filled,
11643 Pixel fg,
11644 Pixel bg,
11645 Pixel cc)
11646 {
11647 TScreen *screen = TScreenOf(xw);
11648 VTwin *win = WhichVWin(screen);
11649 CgsEnum cgsId = gcVTcursOutline;
11650
11651 if (cc == bg)
11652 cc = fg;
11653
11654 if (filled) {
11655 setCgsFore(xw, win, cgsId, bg);
11656 setCgsBack(xw, win, cgsId, cc);
11657 } else {
11658 setCgsFore(xw, win, cgsId, cc);
11659 setCgsBack(xw, win, cgsId, bg);
11660 }
11661 }
11662
11663 static Boolean
VTSetValues(Widget cur,Widget request GCC_UNUSED,Widget wnew,ArgList args GCC_UNUSED,Cardinal * num_args GCC_UNUSED)11664 VTSetValues(Widget cur,
11665 Widget request GCC_UNUSED,
11666 Widget wnew,
11667 ArgList args GCC_UNUSED,
11668 Cardinal *num_args GCC_UNUSED)
11669 {
11670 XtermWidget curvt = (XtermWidget) cur;
11671 XtermWidget newvt = (XtermWidget) wnew;
11672 Boolean refresh_needed = False;
11673 Boolean fonts_redone = False;
11674
11675 if ((T_COLOR(TScreenOf(curvt), TEXT_BG) !=
11676 T_COLOR(TScreenOf(newvt), TEXT_BG)) ||
11677 (T_COLOR(TScreenOf(curvt), TEXT_FG) !=
11678 T_COLOR(TScreenOf(newvt), TEXT_FG)) ||
11679 (TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) !=
11680 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) ||
11681 strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
11682 if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
11683 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt);
11684 }
11685 if (xtermLoadFont(newvt,
11686 xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)),
11687 True, TScreenOf(newvt)->menu_font_number)) {
11688 /* resizing does the redisplay, so don't ask for it here */
11689 refresh_needed = True;
11690 fonts_redone = True;
11691 } else if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) {
11692 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt);
11693 }
11694 }
11695 if (!fonts_redone
11696 && (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) !=
11697 T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) {
11698 if (set_cursor_gcs(newvt))
11699 refresh_needed = True;
11700 }
11701 if (curvt->misc.re_verse != newvt->misc.re_verse) {
11702 newvt->flags ^= REVERSE_VIDEO;
11703 ReverseVideo(newvt);
11704 /* ReverseVideo toggles */
11705 newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse);
11706 refresh_needed = True;
11707 }
11708 if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) !=
11709 T_COLOR(TScreenOf(newvt), MOUSE_FG)) ||
11710 (T_COLOR(TScreenOf(curvt), MOUSE_BG) !=
11711 T_COLOR(TScreenOf(newvt), MOUSE_BG))) {
11712 recolor_cursor(TScreenOf(newvt),
11713 TScreenOf(newvt)->pointer_cursor,
11714 T_COLOR(TScreenOf(newvt), MOUSE_FG),
11715 T_COLOR(TScreenOf(newvt), MOUSE_BG));
11716 refresh_needed = True;
11717 }
11718 if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
11719 ToggleScrollBar(newvt);
11720 }
11721
11722 return refresh_needed;
11723 }
11724
11725 /*
11726 * Given a font-slot and information about selection/reverse, find the
11727 * corresponding cached-GC slot.
11728 */
11729 #if OPT_WIDE_ATTRS
11730 static int
reverseCgs(XtermWidget xw,unsigned attr_flags,Bool hilite,int font)11731 reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font)
11732 {
11733 TScreen *screen = TScreenOf(xw);
11734 CgsEnum result = gcMAX;
11735
11736 (void) screen;
11737 if (ReverseOrHilite(screen, attr_flags, hilite)) {
11738 switch (font) {
11739 case fNorm:
11740 result = gcNormReverse;
11741 break;
11742 case fBold:
11743 result = gcBoldReverse;
11744 break;
11745 #if OPT_WIDE_ATTRS || OPT_RENDERWIDE
11746 case fItal:
11747 result = gcNormReverse; /* FIXME */
11748 break;
11749 #endif
11750 #if OPT_WIDE_CHARS
11751 case fWide:
11752 result = gcWideReverse;
11753 break;
11754 case fWBold:
11755 result = gcWBoldReverse;
11756 break;
11757 case fWItal:
11758 result = gcWideReverse; /* FIXME */
11759 break;
11760 #endif
11761 }
11762 } else {
11763 switch (font) {
11764 case fNorm:
11765 result = gcNorm;
11766 break;
11767 case fBold:
11768 result = gcBold;
11769 break;
11770 #if OPT_WIDE_ATTRS || OPT_RENDERWIDE
11771 case fItal:
11772 result = gcNorm; /* FIXME */
11773 break;
11774 #endif
11775 #if OPT_WIDE_CHARS
11776 case fWide:
11777 result = gcWide;
11778 break;
11779 case fWBold:
11780 result = gcWBold;
11781 break;
11782 case fWItal:
11783 result = gcWide; /* FIXME */
11784 break;
11785 #endif
11786 }
11787 }
11788 return (int) result;
11789 }
11790 #endif
11791
11792 #define setGC(code) set_at = __LINE__, currentCgs = code
11793
11794 #define OutsideSelection(screen,srow,scol) \
11795 ((srow) > (screen)->endH.row || \
11796 ((srow) == (screen)->endH.row && \
11797 (scol) >= (screen)->endH.col) || \
11798 (srow) < (screen)->startH.row || \
11799 ((srow) == (screen)->startH.row && \
11800 (scol) < (screen)->startH.col))
11801
11802 /*
11803 * Shows cursor at new cursor position in screen.
11804 */
11805 void
ShowCursor(XtermWidget xw)11806 ShowCursor(XtermWidget xw)
11807 {
11808 TScreen *screen = TScreenOf(xw);
11809 XTermDraw params;
11810 IChar base;
11811 unsigned flags;
11812 CellColor fg_bg = initCColor;
11813 GC currentGC;
11814 GC outlineGC;
11815 CgsEnum currentCgs = gcMAX;
11816 VTwin *currentWin = WhichVWin(screen);
11817 int set_at;
11818 Bool in_selection;
11819 Bool reversed;
11820 Bool filled;
11821 Pixel fg_pix;
11822 Pixel bg_pix;
11823 Pixel tmp;
11824 #if OPT_HIGHLIGHT_COLOR
11825 Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG);
11826 Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG);
11827 Boolean use_selbg;
11828 Boolean use_selfg;
11829 #endif
11830 #if OPT_WIDE_CHARS
11831 int my_col = 0;
11832 #endif
11833 int cursor_col;
11834 CLineData *ld = 0;
11835
11836 if (screen->cursor_state == BLINKED_OFF)
11837 return;
11838
11839 if (screen->eventMode != NORMAL)
11840 return;
11841
11842 if (INX2ROW(screen, screen->cur_row) > screen->max_row)
11843 return;
11844
11845 screen->cursorp.row = screen->cur_row;
11846 cursor_col = screen->cursorp.col = screen->cur_col;
11847 screen->cursor_moved = False;
11848
11849 #ifndef NO_ACTIVE_ICON
11850 if (IsIcon(screen)) {
11851 screen->cursor_state = ON;
11852 return;
11853 }
11854 #endif /* NO_ACTIVE_ICON */
11855
11856 ld = getLineData(screen, screen->cur_row);
11857
11858 base = ld->charData[cursor_col];
11859 flags = ld->attribs[cursor_col];
11860
11861 if_OPT_WIDE_CHARS(screen, {
11862 if (base == HIDDEN_CHAR && cursor_col > 0) {
11863 /* if cursor points to non-initial part of wide character,
11864 * back it up
11865 */
11866 --cursor_col;
11867 base = ld->charData[cursor_col];
11868 }
11869 my_col = cursor_col;
11870 if (base == 0)
11871 base = ' ';
11872 if (isWide((int) base))
11873 my_col += 1;
11874 });
11875
11876 if (base == 0) {
11877 base = ' ';
11878 }
11879 #if OPT_ISO_COLORS
11880 #ifdef EXP_BOGUS_FG
11881 /*
11882 * If the cursor happens to be on blanks, and we have not set both
11883 * foreground and background color, do not treat it as a colored cell.
11884 */
11885 if (base == ' ') {
11886 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
11887 TRACE(("ShowCursor - do not treat as a colored cell\n"));
11888 flags &= ~(FG_COLOR | BG_COLOR);
11889 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
11890 TRACE(("ShowCursor - should we treat as a colored cell?\n"));
11891 if (!(xw->flags & FG_COLOR)) {
11892 if (CheckBogusForeground(screen, "ShowCursor")) {
11893 flags &= ~(FG_COLOR | BG_COLOR);
11894 }
11895 }
11896 }
11897 }
11898 #else /* !EXP_BOGUS_FG */
11899 /*
11900 * If the cursor happens to be on blanks, and the foreground color is set
11901 * but not the background, do not treat it as a colored cell.
11902 */
11903 if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR
11904 && base == ' ') {
11905 flags &= ~TERM_COLOR_FLAGS(xw);
11906 }
11907 #endif
11908 #endif
11909
11910 /*
11911 * Compare the current cell to the last set of colors used for the
11912 * cursor and update the GC's if needed.
11913 */
11914 (void) fg_bg;
11915 if_OPT_ISO_COLORS(screen, {
11916 fg_bg = ld->color[cursor_col];
11917 });
11918
11919 fg_pix = getXtermFG(xw, flags, (int) extract_fg(xw, fg_bg, flags));
11920 bg_pix = getXtermBG(xw, flags, (int) extract_bg(xw, fg_bg, flags));
11921
11922 /*
11923 * If we happen to have the same foreground/background colors, choose
11924 * a workable foreground color from which we can obtain a visible cursor.
11925 */
11926 if (fg_pix == bg_pix) {
11927 long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG));
11928 long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG));
11929 if (bg_diff < 0)
11930 bg_diff = -bg_diff;
11931 if (fg_diff < 0)
11932 fg_diff = -fg_diff;
11933 if (bg_diff < fg_diff) {
11934 fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG);
11935 } else {
11936 fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG);
11937 }
11938 }
11939
11940 if (OutsideSelection(screen, screen->cur_row, screen->cur_col))
11941 in_selection = False;
11942 else
11943 in_selection = True;
11944
11945 reversed = ReverseOrHilite(screen, flags, in_selection);
11946
11947 /* This is like updatedXtermGC(), except that we have to worry about
11948 * whether the window has focus, since in that case we want just an
11949 * outline for the cursor.
11950 */
11951 filled = (screen->select || screen->always_highlight) && isCursorBlock(screen);
11952 #if OPT_HIGHLIGHT_COLOR
11953 use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix);
11954 use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix);
11955 #endif
11956 if (filled) {
11957 if (reversed) { /* text is reverse video */
11958 if (getCgsGC(xw, currentWin, gcVTcursNormal)) {
11959 setGC(gcVTcursNormal);
11960 } else {
11961 if (flags & BOLDATTR(screen)) {
11962 setGC(gcBold);
11963 } else {
11964 setGC(gcNorm);
11965 }
11966 }
11967 EXCHANGE(fg_pix, bg_pix, tmp);
11968 #if OPT_HIGHLIGHT_COLOR
11969 if (screen->hilite_reverse) {
11970 if (use_selbg && !use_selfg)
11971 fg_pix = bg_pix;
11972 if (use_selfg && !use_selbg)
11973 bg_pix = fg_pix;
11974 if (use_selbg)
11975 bg_pix = selbg_pix;
11976 if (use_selfg)
11977 fg_pix = selfg_pix;
11978 }
11979 #endif
11980 } else { /* normal video */
11981 if (getCgsGC(xw, currentWin, gcVTcursReverse)) {
11982 setGC(gcVTcursReverse);
11983 } else {
11984 if (flags & BOLDATTR(screen)) {
11985 setGC(gcBoldReverse);
11986 } else {
11987 setGC(gcNormReverse);
11988 }
11989 }
11990 }
11991
11992 #define CUR_XX T_COLOR(screen, TEXT_CURSOR)
11993 #define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
11994 #define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs))
11995
11996 #define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground))
11997 #define FIX_328 (CUR_XX == bg_pix)
11998 #define FIX_330 (FIX_328 && reversed && in_selection)
11999
12000 if (FIX_330 || FIX_311) {
12001 setCgsBack(xw, currentWin, currentCgs, fg_pix);
12002 }
12003 setCgsFore(xw, currentWin, currentCgs, bg_pix);
12004 } else { /* not selected */
12005 if (reversed) { /* text is reverse video */
12006 EXCHANGE(fg_pix, bg_pix, tmp);
12007 setGC(gcNormReverse);
12008 } else { /* normal video */
12009 setGC(gcNorm);
12010 }
12011 #if OPT_HIGHLIGHT_COLOR
12012 if (screen->hilite_reverse) {
12013 if (in_selection && !reversed) {
12014 /* EMPTY */
12015 /* really INVERSE ... */
12016 ;
12017 } else if (in_selection || reversed) {
12018 if (use_selbg) {
12019 if (use_selfg) {
12020 bg_pix = fg_pix;
12021 } else {
12022 fg_pix = bg_pix;
12023 bg_pix = selbg_pix;
12024 }
12025 }
12026 if (use_selfg) {
12027 fg_pix = selfg_pix;
12028 }
12029 }
12030 } else {
12031 if (in_selection) {
12032 if (use_selbg) {
12033 bg_pix = selbg_pix;
12034 }
12035 if (use_selfg) {
12036 fg_pix = selfg_pix;
12037 }
12038 }
12039 }
12040 #endif
12041 setCgsFore(xw, currentWin, currentCgs, fg_pix);
12042 setCgsBack(xw, currentWin, currentCgs, bg_pix);
12043 }
12044
12045 if (screen->cursor_busy == 0
12046 && (screen->cursor_state != ON || screen->cursor_GC != set_at)) {
12047 int x, y;
12048
12049 screen->cursor_GC = set_at;
12050 TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n",
12051 screen->cur_row, screen->cur_col,
12052 (filled ? "filled" : "outline"),
12053 (isCursorBlock(screen) ? "box" :
12054 isCursorUnderline(screen) ? "underline" : "bar"),
12055 set_at));
12056
12057 currentGC = getCgsGC(xw, currentWin, currentCgs);
12058 x = LineCursorX(screen, ld, cursor_col);
12059 y = CursorY(screen, screen->cur_row);
12060
12061 if (!isCursorBlock(screen)) {
12062 /*
12063 * Overriding the combination of filled, reversed, in_selection is
12064 * too complicated since the underline or bar and the text-cell use
12065 * different rules. Just redraw the text-cell, and draw the
12066 * underline or bar on top of it.
12067 */
12068 HideCursor(xw);
12069
12070 /*
12071 * Our current-GC is likely to have been modified in HideCursor().
12072 * Set up a new request.
12073 */
12074 if (filled) {
12075 if (FIX_330 || FIX_311) {
12076 setCgsBack(xw, currentWin, currentCgs, fg_pix);
12077 }
12078 setCgsFore(xw, currentWin, currentCgs, bg_pix);
12079 } else {
12080 setCgsFore(xw, currentWin, currentCgs, fg_pix);
12081 setCgsBack(xw, currentWin, currentCgs, bg_pix);
12082 }
12083 }
12084
12085 /*
12086 * Update the outline-gc, to keep the cursor color distinct from the
12087 * background color.
12088 */
12089 set_cursor_outline_gc(xw,
12090 filled,
12091 fg_pix,
12092 bg_pix,
12093 T_COLOR(screen, TEXT_CURSOR));
12094
12095 outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline);
12096 if (outlineGC == 0)
12097 outlineGC = currentGC;
12098
12099 if (isCursorUnderline(screen)) {
12100
12101 /*
12102 * Finally, draw the underline.
12103 */
12104 screen->box->x = (short) x;
12105 screen->box->y = (short) (y + FontHeight(screen) - 2);
12106 XDrawLines(screen->display, VDrawable(screen), outlineGC,
12107 screen->box, NBOX, CoordModePrevious);
12108 } else if (isCursorBar(screen)) {
12109
12110 /*
12111 * Or draw the bar.
12112 */
12113 screen->box->x = (short) x;
12114 screen->box->y = (short) y;
12115 XDrawLines(screen->display, VDrawable(screen), outlineGC,
12116 screen->box, NBOX, CoordModePrevious);
12117 } else {
12118 #if OPT_WIDE_ATTRS
12119 int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0);
12120 int italics_off = ((xw->flags & ATR_ITALIC) != 0);
12121 int fix_italics = (italics_on != italics_off);
12122 int which_font = ((xw->flags & BOLD) ? fBold : fNorm);
12123 MyGetFont getter = italics_on ? getItalicFont : getNormalFont;
12124
12125 if_OPT_WIDE_CHARS(screen, {
12126 if (isWide((int) base)) {
12127 which_font = ((xw->flags & BOLD) ? fWBold : fWide);
12128 }
12129 });
12130
12131 if (fix_italics && UseItalicFont(screen)) {
12132 xtermLoadItalics(xw);
12133 setCgsFont(xw, currentWin, currentCgs,
12134 getter(screen, which_font));
12135 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen))
12136 ? getItalicFont
12137 : getNormalFont);
12138 }
12139 currentGC = getCgsGC(xw, currentWin, currentCgs);
12140 #endif /* OPT_WIDE_ATTRS */
12141
12142 /* *INDENT-EQLS* */
12143 params.xw = xw;
12144 params.attr_flags = (flags & DRAWX_MASK);
12145 params.draw_flags = 0;
12146 params.this_chrset = LineCharSet(screen, ld);
12147 params.real_chrset = CSET_SWL;
12148 params.on_wide = 0;
12149
12150 drawXtermText(¶ms,
12151 currentGC, x, y,
12152 &base, 1);
12153
12154 #if OPT_WIDE_CHARS
12155 if_OPT_WIDE_CHARS(screen, {
12156 size_t off;
12157
12158 /* *INDENT-EQLS* */
12159 params.draw_flags = NOBACKGROUND;
12160 params.on_wide = isWide((int) base);
12161
12162 for_each_combData(off, ld) {
12163 if (!(ld->combData[off][my_col]))
12164 break;
12165 drawXtermText(¶ms,
12166 currentGC, x, y,
12167 ld->combData[off] + my_col, 1);
12168 }
12169 });
12170 #endif
12171
12172 if (!filled) {
12173 screen->box->x = (short) x;
12174 screen->box->y = (short) y;
12175 XDrawLines(screen->display, VDrawable(screen), outlineGC,
12176 screen->box, NBOX, CoordModePrevious);
12177 }
12178 #if OPT_WIDE_ATTRS
12179 if (fix_italics && UseItalicFont(screen)) {
12180 setCgsFont(xw, currentWin, currentCgs,
12181 getter(screen, which_font));
12182 }
12183 #endif
12184 }
12185 }
12186 screen->cursor_state = ON;
12187
12188 return;
12189 }
12190
12191 /*
12192 * hide cursor at previous cursor position in screen.
12193 */
12194 void
HideCursor(XtermWidget xw)12195 HideCursor(XtermWidget xw)
12196 {
12197 TScreen *screen = TScreenOf(xw);
12198 XTermDraw params;
12199 GC currentGC;
12200 int x, y;
12201 IChar base;
12202 unsigned flags;
12203 CellColor fg_bg = initCColor;
12204 Bool in_selection;
12205 #if OPT_WIDE_CHARS
12206 int my_col = 0;
12207 #endif
12208 int cursor_col;
12209 CLineData *ld = 0;
12210 #if OPT_WIDE_ATTRS
12211 int which_Cgs = gcMAX;
12212 unsigned attr_flags;
12213 int which_font = fNorm;
12214 MyGetFont getter = getNormalFont;
12215 #endif
12216
12217 if (screen->cursor_state == OFF)
12218 return;
12219 if (INX2ROW(screen, screen->cursorp.row) > screen->max_row)
12220 return;
12221
12222 cursor_col = screen->cursorp.col;
12223
12224 #ifndef NO_ACTIVE_ICON
12225 if (IsIcon(screen)) {
12226 screen->cursor_state = OFF;
12227 return;
12228 }
12229 #endif /* NO_ACTIVE_ICON */
12230
12231 ld = getLineData(screen, screen->cursorp.row);
12232
12233 base = ld->charData[cursor_col];
12234 flags = ld->attribs[cursor_col];
12235
12236 if_OPT_WIDE_CHARS(screen, {
12237 if (base == HIDDEN_CHAR && cursor_col > 0) {
12238 /* if cursor points to non-initial part of wide character,
12239 * back it up
12240 */
12241 --cursor_col;
12242 base = ld->charData[cursor_col];
12243 }
12244 my_col = cursor_col;
12245 if (base == 0)
12246 base = ' ';
12247 if (isWide((int) base))
12248 my_col += 1;
12249 });
12250
12251 if (base == 0) {
12252 base = ' ';
12253 }
12254 #ifdef EXP_BOGUS_FG
12255 /*
12256 * If the cursor happens to be on blanks, and we have not set both
12257 * foreground and background color, do not treat it as a colored cell.
12258 */
12259 #if OPT_ISO_COLORS
12260 if (base == ' ') {
12261 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) {
12262 TRACE(("HideCursor - do not treat as a colored cell\n"));
12263 flags &= ~(FG_COLOR | BG_COLOR);
12264 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) {
12265 TRACE(("HideCursor - should we treat as a colored cell?\n"));
12266 if (!(xw->flags & FG_COLOR))
12267 if (CheckBogusForeground(screen, "HideCursor"))
12268 flags &= ~(FG_COLOR | BG_COLOR);
12269 }
12270 }
12271 #endif
12272 #endif
12273
12274 /*
12275 * Compare the current cell to the last set of colors used for the
12276 * cursor and update the GC's if needed.
12277 */
12278 if_OPT_ISO_COLORS(screen, {
12279 fg_bg = ld->color[cursor_col];
12280 });
12281
12282 if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col))
12283 in_selection = False;
12284 else
12285 in_selection = True;
12286
12287 #if OPT_WIDE_ATTRS
12288 attr_flags = ld->attribs[cursor_col];
12289 if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) {
12290 which_font = ((attr_flags & BOLD) ? fBold : fNorm);
12291 if ((attr_flags & ATR_ITALIC) && UseItalicFont(screen))
12292 getter = getItalicFont;
12293
12294 if_OPT_WIDE_CHARS(screen, {
12295 if (isWide((int) base)) {
12296 which_font = ((attr_flags & BOLD) ? fWBold : fWide);
12297 }
12298 });
12299
12300 which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font);
12301 if (which_Cgs != gcMAX) {
12302 setCgsFont(xw, WhichVWin(screen),
12303 (CgsEnum) which_Cgs,
12304 getter(screen, which_font));
12305 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen))
12306 ? getItalicFont
12307 : getNormalFont);
12308 }
12309 }
12310 #endif
12311
12312 currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection);
12313
12314 TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n",
12315 screen->cursorp.row, screen->cursorp.col));
12316
12317 x = LineCursorX(screen, ld, cursor_col);
12318 y = CursorY(screen, screen->cursorp.row);
12319
12320 /* *INDENT-EQLS* */
12321 params.xw = xw;
12322 params.attr_flags = (flags & DRAWX_MASK);
12323 params.draw_flags = 0;
12324 params.this_chrset = LineCharSet(screen, ld);
12325 params.real_chrset = CSET_SWL;
12326 params.on_wide = 0;
12327
12328 drawXtermText(¶ms,
12329 currentGC, x, y,
12330 &base, 1);
12331
12332 #if OPT_WIDE_CHARS
12333 if_OPT_WIDE_CHARS(screen, {
12334 size_t off;
12335
12336 /* *INDENT-EQLS* */
12337 params.draw_flags = NOBACKGROUND;
12338 params.on_wide = isWide((int) base);
12339
12340 for_each_combData(off, ld) {
12341 if (!(ld->combData[off][my_col]))
12342 break;
12343 drawXtermText(¶ms,
12344 currentGC, x, y,
12345 ld->combData[off] + my_col, 1);
12346 }
12347 });
12348 #endif
12349 screen->cursor_state = OFF;
12350
12351 #if OPT_WIDE_ATTRS
12352 if (which_Cgs != gcMAX) {
12353 setCgsFont(xw, WhichVWin(screen),
12354 (CgsEnum) which_Cgs,
12355 getter(screen, which_font));
12356 }
12357 #endif
12358 resetXtermGC(xw, flags, in_selection);
12359
12360 refresh_displayed_graphics(xw,
12361 screen->cursorp.col,
12362 screen->cursorp.row,
12363 1, 1);
12364
12365 return;
12366 }
12367
12368 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
12369 static void
StartBlinking(XtermWidget xw)12370 StartBlinking(XtermWidget xw)
12371 {
12372 TScreen *screen = TScreenOf(xw);
12373
12374 if (screen->blink_timer == 0) {
12375 unsigned long interval = (unsigned long) ((screen->cursor_state == ON)
12376 ? screen->blink_on
12377 : screen->blink_off);
12378 if (interval == 0) /* wow! */
12379 interval = 1; /* let's humor him anyway */
12380 screen->blink_timer = XtAppAddTimeOut(app_con,
12381 interval,
12382 HandleBlinking,
12383 xw);
12384 }
12385 }
12386
12387 static void
StopBlinking(XtermWidget xw)12388 StopBlinking(XtermWidget xw)
12389 {
12390 TScreen *screen = TScreenOf(xw);
12391
12392 if (screen->blink_timer) {
12393 XtRemoveTimeOut(screen->blink_timer);
12394 screen->blink_timer = 0;
12395 reallyStopBlinking(xw);
12396 } else {
12397 screen->blink_timer = 0;
12398 }
12399 }
12400
12401 #if OPT_BLINK_TEXT
12402 Bool
LineHasBlinking(TScreen * screen,CLineData * ld)12403 LineHasBlinking(TScreen *screen, CLineData *ld)
12404 {
12405 Bool result = False;
12406 if (ld != 0) {
12407 int col;
12408
12409 for (col = 0; col < MaxCols(screen); ++col) {
12410 if (ld->attribs[col] & BLINK) {
12411 result = True;
12412 break;
12413 }
12414 }
12415 }
12416 return result;
12417 }
12418 #endif
12419
12420 /*
12421 * Blink the cursor by alternately showing/hiding cursor. We leave the timer
12422 * running all the time (even though that's a little inefficient) to make the
12423 * logic simple.
12424 */
12425 static void
HandleBlinking(XtPointer closure,XtIntervalId * id GCC_UNUSED)12426 HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED)
12427 {
12428 XtermWidget xw = (XtermWidget) closure;
12429 TScreen *screen = TScreenOf(xw);
12430 Bool resume = False;
12431
12432 screen->blink_timer = 0;
12433 screen->blink_state = !screen->blink_state;
12434
12435 #if OPT_BLINK_CURS
12436 if (DoStartBlinking(screen)) {
12437 if (screen->cursor_state == ON) {
12438 if (screen->select || screen->always_highlight) {
12439 HideCursor(xw);
12440 if (screen->cursor_state == OFF)
12441 screen->cursor_state = BLINKED_OFF;
12442 }
12443 } else if (screen->cursor_state == BLINKED_OFF) {
12444 screen->cursor_state = OFF;
12445 ShowCursor(xw);
12446 if (screen->cursor_state == OFF)
12447 screen->cursor_state = BLINKED_OFF;
12448 }
12449 resume = True;
12450 }
12451 #endif
12452
12453 #if OPT_BLINK_TEXT
12454 /*
12455 * Inspect the lines on the current screen to see if any have the BLINK flag
12456 * associated with them. Prune off any that have had the corresponding
12457 * cells reset. If any are left, repaint those lines with ScrnRefresh().
12458 */
12459 if (!(screen->blink_as_bold)) {
12460 int row;
12461 int first_row = screen->max_row;
12462 int last_row = -1;
12463
12464 for (row = screen->max_row; row >= 0; row--) {
12465 LineData *ld = getLineData(screen, ROW2INX(screen, row));
12466
12467 if (ld != 0 && LineTstBlinked(ld)) {
12468 if (LineHasBlinking(screen, ld)) {
12469 resume = True;
12470 if (row > last_row)
12471 last_row = row;
12472 if (row < first_row)
12473 first_row = row;
12474 } else {
12475 LineClrBlinked(ld);
12476 }
12477 }
12478 }
12479 /*
12480 * FIXME: this could be a little more efficient, e.g,. by limiting the
12481 * columns which are updated.
12482 */
12483 if (first_row <= last_row) {
12484 ScrnRefresh(xw,
12485 first_row,
12486 0,
12487 last_row + 1 - first_row,
12488 MaxCols(screen),
12489 True);
12490 }
12491 }
12492 #endif
12493
12494 /*
12495 * If either the cursor or text is blinking, restart the timer.
12496 */
12497 if (resume)
12498 StartBlinking(xw);
12499 }
12500 #endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */
12501
12502 void
RestartBlinking(XtermWidget xw)12503 RestartBlinking(XtermWidget xw)
12504 {
12505 #if OPT_BLINK_CURS || OPT_BLINK_TEXT
12506 TScreen *screen = TScreenOf(xw);
12507
12508 if (screen->blink_timer == 0) {
12509 Bool resume = False;
12510
12511 #if OPT_BLINK_CURS
12512 if (DoStartBlinking(screen)) {
12513 resume = True;
12514 }
12515 #endif
12516 #if OPT_BLINK_TEXT
12517 if (!resume) {
12518 int row;
12519
12520 for (row = screen->max_row; row >= 0; row--) {
12521 CLineData *ld = getLineData(screen, ROW2INX(screen, row));
12522
12523 if (ld != 0 && LineTstBlinked(ld)) {
12524 if (LineHasBlinking(screen, ld)) {
12525 resume = True;
12526 break;
12527 }
12528 }
12529 }
12530 }
12531 #endif
12532 if (resume)
12533 StartBlinking(xw);
12534 }
12535 #else
12536 (void) xw;
12537 #endif
12538 }
12539
12540 /*
12541 * Implement soft or hard (full) reset of the VTxxx emulation. There are a
12542 * couple of differences from real DEC VTxxx terminals (to avoid breaking
12543 * applications which have come to rely on xterm doing this):
12544 *
12545 * + autowrap mode should be reset (instead it's reset to the resource
12546 * default).
12547 * + the popup menu offers a choice of resetting the savedLines, or not.
12548 * (but the control sequence does this anyway).
12549 */
12550 static void
ReallyReset(XtermWidget xw,Bool full,Bool saved)12551 ReallyReset(XtermWidget xw, Bool full, Bool saved)
12552 {
12553 TScreen *screen = TScreenOf(xw);
12554 IFlags saveflags = xw->flags;
12555
12556 TRACE(("ReallyReset %s, %s\n",
12557 full ? "hard" : "soft",
12558 saved ? "clear savedLines" : "keep savedLines"));
12559
12560 if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) {
12561 Bell(xw, XkbBI_MinorError, 0);
12562 return;
12563 }
12564
12565 if (saved) {
12566 screen->savedlines = 0;
12567 ScrollBarDrawThumb(xw, 0);
12568 }
12569
12570 /* make cursor visible */
12571 screen->cursor_set = ON;
12572 InitCursorShape(screen, screen);
12573 xtermSetCursorBox(screen);
12574 #if OPT_BLINK_CURS
12575 screen->cursor_blink = screen->cursor_blink_i;
12576 screen->cursor_blink_esc = 0;
12577 TRACE(("cursor_shape:%d blinks:%d\n",
12578 screen->cursor_shape,
12579 screen->cursor_blink));
12580 #endif
12581
12582 /* reset scrolling region */
12583 resetMarginMode(xw);
12584
12585 bitclr(&xw->flags, ORIGIN);
12586
12587 if_OPT_ISO_COLORS(screen, {
12588 static char empty[1];
12589 reset_SGR_Colors(xw);
12590 if (ResetAnsiColorRequest(xw, empty, 0))
12591 xtermRepaint(xw);
12592 });
12593
12594 /* Reset character-sets to initial state */
12595 resetCharsets(screen);
12596
12597 #if OPT_MOD_FKEYS
12598 /* Reset modifier-resources to initial state */
12599 xw->keyboard.modify_now = xw->keyboard.modify_1st;
12600 #endif
12601 #if OPT_DEC_RECTOPS
12602 screen->checksum_ext = screen->checksum_ext0;
12603 #endif
12604
12605 /* Reset DECSCA */
12606 bitclr(&xw->flags, PROTECTED);
12607 screen->protected_mode = OFF_PROTECT;
12608
12609 if (full) { /* RIS */
12610 if (screen->bellOnReset)
12611 Bell(xw, XkbBI_TerminalBell, 0);
12612
12613 reset_displayed_graphics(screen);
12614
12615 /* reset the mouse mode */
12616 screen->send_mouse_pos = MOUSE_OFF;
12617 screen->send_focus_pos = OFF;
12618 screen->extend_coords = 0;
12619 screen->waitingForTrackInfo = False;
12620 screen->eventMode = NORMAL;
12621
12622 xtermShowPointer(xw, True);
12623
12624 TabReset(xw->tabs);
12625 xw->keyboard.flags = MODE_SRM;
12626
12627 guard_keyboard_type = False;
12628 screen->old_fkeys = screen->old_fkeys0;
12629 decode_keyboard_type(xw, &resource);
12630 update_keyboard_type();
12631
12632 #if OPT_INITIAL_ERASE
12633 if (xw->keyboard.reset_DECBKM == 1)
12634 xw->keyboard.flags |= MODE_DECBKM;
12635 else if (xw->keyboard.reset_DECBKM == 2)
12636 #endif
12637 if (TScreenOf(xw)->backarrow_key)
12638 xw->keyboard.flags |= MODE_DECBKM;
12639 TRACE(("full reset DECBKM %s\n",
12640 BtoS(xw->keyboard.flags & MODE_DECBKM)));
12641
12642 #if OPT_SCROLL_LOCK
12643 xtermClearLEDs(screen);
12644 #endif
12645 screen->title_modes = screen->title_modes0;
12646 screen->pointer_mode = screen->pointer_mode0;
12647 #if OPT_SIXEL_GRAPHICS
12648 if (TScreenOf(xw)->sixel_scrolling)
12649 xw->keyboard.flags |= MODE_DECSDM;
12650 TRACE(("full reset DECSDM to %s (resource default is %s)\n",
12651 BtoS(xw->keyboard.flags & MODE_DECSDM),
12652 BtoS(TScreenOf(xw)->sixel_scrolling)));
12653 #endif
12654
12655 #if OPT_GRAPHICS
12656 screen->privatecolorregisters = TScreenOf(xw)->privatecolorregisters;
12657 TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n",
12658 BtoS(screen->privatecolorregisters),
12659 BtoS(TScreenOf(xw)->privatecolorregisters)));
12660 #endif
12661
12662 #if OPT_SIXEL_GRAPHICS
12663 screen->sixel_scrolls_right = TScreenOf(xw)->sixel_scrolls_right;
12664 TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n",
12665 BtoS(screen->sixel_scrolls_right),
12666 BtoS(TScreenOf(xw)->sixel_scrolls_right)));
12667 #endif
12668
12669 update_appcursor();
12670 update_appkeypad();
12671 update_decbkm();
12672 update_decsdm();
12673 show_8bit_control(False);
12674 reset_decudk(xw);
12675
12676 FromAlternate(xw);
12677 ClearScreen(xw);
12678 screen->cursor_state = OFF;
12679
12680 if (xw->flags & REVERSE_VIDEO)
12681 ReverseVideo(xw);
12682 ResetItalics(xw);
12683 xw->flags = xw->initflags;
12684
12685 update_reversevideo();
12686 update_autowrap();
12687 update_reversewrap();
12688 update_autolinefeed();
12689
12690 screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL));
12691 update_jumpscroll();
12692
12693 #if OPT_DEC_RECTOPS
12694 screen->cur_decsace = 0;
12695 #endif
12696 #if OPT_PASTE64 || OPT_READLINE
12697 screen->paste_brackets = OFF;
12698 #endif
12699 #if OPT_READLINE
12700 screen->click1_moves = OFF;
12701 screen->paste_moves = OFF;
12702 screen->dclick3_deletes = OFF;
12703 screen->paste_quotes = OFF;
12704 screen->paste_literal_nl = OFF;
12705 #endif /* OPT_READLINE */
12706
12707 if (screen->c132 && (saveflags & IN132COLUMNS)) {
12708 TRACE(("Making resize-request to restore 80-columns %dx%d\n",
12709 MaxRows(screen), MaxCols(screen)));
12710 RequestResize(xw, MaxRows(screen), 80, True);
12711 repairSizeHints();
12712 XSync(screen->display, False); /* synchronize */
12713 if (xtermAppPending())
12714 xevents(xw);
12715 }
12716
12717 CursorSet(screen, 0, 0, xw->flags);
12718 CursorSave(xw);
12719 } else { /* DECSTR */
12720 /*
12721 * There's a tiny difference, to accommodate usage of xterm.
12722 * We reset autowrap to the resource values rather than turning
12723 * it off.
12724 */
12725 UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM));
12726 bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP);
12727 bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE);
12728 ResetItalics(xw);
12729 if_OPT_ISO_COLORS(screen, {
12730 reset_SGR_Colors(xw);
12731 });
12732 update_appcursor();
12733 update_autowrap();
12734 update_reversewrap();
12735
12736 CursorSave(xw);
12737 screen->sc[screen->whichBuf].row =
12738 screen->sc[screen->whichBuf].col = 0;
12739 }
12740 }
12741
12742 void
VTReset(XtermWidget xw,Bool full,Bool saved)12743 VTReset(XtermWidget xw, Bool full, Bool saved)
12744 {
12745 ReallyReset(xw, full, saved);
12746
12747 FreeAndNull(myState.string_area);
12748 FreeAndNull(myState.print_area);
12749
12750 longjmp(vtjmpbuf, 1); /* force ground state in parser */
12751 }
12752
12753 typedef enum {
12754 ccLO,
12755 ccDASH,
12756 ccHI,
12757 ccCOLON,
12758 ccID,
12759 ccCOMMA
12760 } CCLASS;
12761
12762 /*
12763 * set_character_class - takes a string of the form
12764 *
12765 * low[-high][:id][,low[-high][:id][...]]
12766 *
12767 * and sets the indicated ranges to the indicated values.
12768 */
12769 static int
set_character_class(char * s)12770 set_character_class(char *s)
12771 {
12772 #define FMT "%s in range string \"%s\" (position %d)\n"
12773
12774 TRACE(("set_character_class(%s) " TRACE_L "\n", NonNull(s)));
12775 if (IsEmpty(s)) {
12776 TRACE((TRACE_R " ERR set_character_class\n"));
12777 return -1;
12778 } else {
12779 CCLASS state = ccLO;
12780 int arg[3];
12781 int i;
12782 int len = (int) strlen(s);
12783
12784 arg[0] =
12785 arg[1] =
12786 arg[2] = -1;
12787
12788 for (i = 0; i < len; ++i) {
12789 int ch = CharOf(s[i]);
12790 char *t = 0;
12791 long value = 0;
12792
12793 if (isspace(ch))
12794 continue;
12795
12796 switch (state) {
12797 case ccLO:
12798 case ccHI:
12799 case ccID:
12800 if (!isdigit(ch)) {
12801 xtermWarning(FMT, "missing number", s, i);
12802 TRACE((TRACE_R " ERR set_character_class\n"));
12803 return (-1);
12804 }
12805 value = strtol(s + i, &t, 0);
12806 i = (int) (t - s - 1);
12807 break;
12808 case ccDASH:
12809 case ccCOLON:
12810 case ccCOMMA:
12811 break;
12812 }
12813
12814 switch (state) {
12815 case ccLO:
12816 arg[0] =
12817 arg[1] = (int) value;
12818 arg[2] = -1;
12819 state = ccDASH;
12820 break;
12821
12822 case ccDASH:
12823 if (ch == '-') {
12824 state = ccHI;
12825 } else {
12826 goto parse_class;
12827 }
12828 break;
12829
12830 case ccHI:
12831 arg[1] = (int) value;
12832 state = ccCOLON;
12833 break;
12834
12835 parse_class:
12836 case ccCOLON:
12837 if (ch == ':') {
12838 state = ccID;
12839 } else if (ch == ',') {
12840 goto apply_class;
12841 } else {
12842 xtermWarning(FMT, "unexpected character", s, i);
12843 TRACE((TRACE_R " ERR set_character_class\n"));
12844 return (-1);
12845 }
12846 break;
12847
12848 case ccID:
12849 arg[2] = (int) value;
12850 state = ccCOMMA;
12851 break;
12852
12853 apply_class:
12854 case ccCOMMA:
12855 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
12856 xtermWarning(FMT, "bad range", s, i);
12857 TRACE((TRACE_R " ERR set_character_class\n"));
12858 return -1;
12859 }
12860 state = ccLO;
12861 break;
12862 }
12863 }
12864 if (state >= ccDASH) {
12865 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) {
12866 xtermWarning(FMT, "bad range", s, i);
12867 TRACE((TRACE_R " ERR set_character_class\n"));
12868 return -1;
12869 }
12870 }
12871 }
12872
12873 TRACE((TRACE_R " OK set_character_class\n"));
12874 return (0);
12875 #undef FMT
12876 }
12877
12878 void
getKeymapResources(Widget w,const char * mapName,const char * mapClass,const char * type,void * result,size_t size)12879 getKeymapResources(Widget w,
12880 const char *mapName,
12881 const char *mapClass,
12882 const char *type,
12883 void *result,
12884 size_t size)
12885 {
12886 XtResource key_resources[1];
12887 key_resources[0].resource_name = XtNtranslations;
12888 key_resources[0].resource_class = XtCTranslations;
12889 key_resources[0].resource_type = (char *) type;
12890 key_resources[0].resource_size = (Cardinal) size;
12891 key_resources[0].resource_offset = 0;
12892 key_resources[0].default_type = key_resources[0].resource_type;
12893 key_resources[0].default_addr = 0;
12894 XtGetSubresources(w, (XtPointer) result, mapName, mapClass,
12895 key_resources, (Cardinal) 1, NULL, (Cardinal) 0);
12896 }
12897
12898 /* ARGSUSED */
12899 static void
HandleKeymapChange(Widget w,XEvent * event GCC_UNUSED,String * params,Cardinal * param_count)12900 HandleKeymapChange(Widget w,
12901 XEvent *event GCC_UNUSED,
12902 String *params,
12903 Cardinal *param_count)
12904 {
12905 static XtTranslations keymap, original;
12906
12907 TRACE(("HandleKeymapChange(%#lx, %s)\n",
12908 (unsigned long) w,
12909 (*param_count
12910 ? params[0]
12911 : "missing")));
12912
12913 if (*param_count != 1)
12914 return;
12915
12916 if (original == NULL) {
12917 TRACE(("...saving original keymap-translations\n"));
12918 original = w->core.tm.translations;
12919 }
12920
12921 if (strcmp(params[0], "None") == 0) {
12922 TRACE(("...restoring original keymap-translations\n"));
12923 XtOverrideTranslations(w, original);
12924 } else {
12925 char mapName[1000];
12926 char mapClass[1000];
12927 char *pmapName;
12928 char *pmapClass;
12929 size_t len;
12930
12931 len = strlen(params[0]) + 7;
12932
12933 pmapName = (char *) MyStackAlloc(len, mapName);
12934 pmapClass = (char *) MyStackAlloc(len, mapClass);
12935 if (pmapName == NULL
12936 || pmapClass == NULL) {
12937 SysError(ERROR_KMMALLOC1);
12938 } else {
12939
12940 (void) sprintf(pmapName, "%sKeymap", params[0]);
12941 (void) strcpy(pmapClass, pmapName);
12942 if (islower(CharOf(pmapClass[0])))
12943 pmapClass[0] = x_toupper(pmapClass[0]);
12944 getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable,
12945 &keymap, sizeof(keymap));
12946 if (keymap != NULL) {
12947 TRACE(("...applying keymap \"%s\"\n", pmapName));
12948 XtOverrideTranslations(w, keymap);
12949 } else {
12950 TRACE(("...found no match for keymap \"%s\"\n", pmapName));
12951 }
12952
12953 MyStackFree(pmapName, mapName);
12954 MyStackFree(pmapClass, mapClass);
12955 }
12956 }
12957 }
12958
12959 /* ARGSUSED */
12960 static void
HandleBell(Widget w GCC_UNUSED,XEvent * event GCC_UNUSED,String * params,Cardinal * param_count)12961 HandleBell(Widget w GCC_UNUSED,
12962 XEvent *event GCC_UNUSED,
12963 String *params, /* [0] = volume */
12964 Cardinal *param_count) /* 0 or 1 */
12965 {
12966 int percent = (*param_count) ? atoi(params[0]) : 0;
12967
12968 Bell(term, XkbBI_TerminalBell, percent);
12969 }
12970
12971 /* ARGSUSED */
12972 static void
HandleVisualBell(Widget w GCC_UNUSED,XEvent * event GCC_UNUSED,String * params GCC_UNUSED,Cardinal * param_count GCC_UNUSED)12973 HandleVisualBell(Widget w GCC_UNUSED,
12974 XEvent *event GCC_UNUSED,
12975 String *params GCC_UNUSED,
12976 Cardinal *param_count GCC_UNUSED)
12977 {
12978 VisualBell();
12979 }
12980
12981 /* ARGSUSED */
12982 static void
HandleIgnore(Widget w,XEvent * event,String * params GCC_UNUSED,Cardinal * param_count GCC_UNUSED)12983 HandleIgnore(Widget w,
12984 XEvent *event,
12985 String *params GCC_UNUSED,
12986 Cardinal *param_count GCC_UNUSED)
12987 {
12988 XtermWidget xw;
12989
12990 TRACE(("Handle ignore for %p %s\n",
12991 (void *) w, visibleEventType(event->type)));
12992 if ((xw = getXtermWidget(w)) != 0) {
12993 /* do nothing, but check for funny escape sequences */
12994 switch (event->type) {
12995 case ButtonPress:
12996 case ButtonRelease:
12997 case MotionNotify:
12998 (void) SendMousePosition(xw, event);
12999 break;
13000 }
13001 }
13002 }
13003
13004 /* ARGSUSED */
13005 static void
DoSetSelectedFont(Widget w,XtPointer client_data GCC_UNUSED,Atom * selection GCC_UNUSED,Atom * type,XtPointer value,unsigned long * length,int * format)13006 DoSetSelectedFont(Widget w,
13007 XtPointer client_data GCC_UNUSED,
13008 Atom *selection GCC_UNUSED,
13009 Atom *type,
13010 XtPointer value,
13011 unsigned long *length,
13012 int *format)
13013 {
13014 XtermWidget xw = getXtermWidget(w);
13015
13016 if (xw == 0) {
13017 xtermWarning("unexpected widget in DoSetSelectedFont\n");
13018 } else if (*type != XA_STRING || *format != 8) {
13019 Bell(xw, XkbBI_MinorError, 0);
13020 } else {
13021 Boolean failed = False;
13022 int oldFont = TScreenOf(xw)->menu_font_number;
13023 char *save = TScreenOf(xw)->SelectFontName();
13024 char *val;
13025 char *test;
13026 unsigned len = (unsigned) *length;
13027 unsigned tst;
13028
13029 /*
13030 * Some versions of X deliver null-terminated selections, some do not.
13031 */
13032 for (tst = 0; tst < len; ++tst) {
13033 if (((char *) value)[tst] == '\0') {
13034 len = tst;
13035 break;
13036 }
13037 }
13038
13039 if (len > 0 && (val = TypeMallocN(char, len + 1)) != 0) {
13040 char *used;
13041
13042 memcpy(val, value, (size_t) len);
13043 val[len] = '\0';
13044 used = x_strtrim(val);
13045 TRACE(("DoSetSelectedFont(%s)\n", used));
13046 /* Do some sanity checking to avoid sending a long selection
13047 back to the server in an OpenFont that is unlikely to succeed.
13048 XLFD allows up to 255 characters and no control characters;
13049 we are a little more liberal here. */
13050 if (len < 1000
13051 && used != 0
13052 && !strchr(used, '\n')
13053 && (test = x_strdup(used)) != 0) {
13054 TScreenOf(xw)->SelectFontName() = test;
13055 if (!xtermLoadFont(xw,
13056 xtermFontName(used),
13057 True,
13058 fontMenu_fontsel)) {
13059 failed = True;
13060 free(test);
13061 TScreenOf(xw)->SelectFontName() = save;
13062 }
13063 } else {
13064 failed = True;
13065 }
13066 if (failed) {
13067 (void) xtermLoadFont(xw,
13068 xtermFontName(TScreenOf(xw)->MenuFontName(oldFont)),
13069 True,
13070 oldFont);
13071 Bell(xw, XkbBI_MinorError, 0);
13072 }
13073 free(used);
13074 free(val);
13075 }
13076 }
13077 }
13078
13079 void
FindFontSelection(XtermWidget xw,const char * atom_name,Bool justprobe)13080 FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe)
13081 {
13082 TScreen *screen = TScreenOf(xw);
13083 static AtomPtr *atoms;
13084 static unsigned int atomCount = 0;
13085 AtomPtr *pAtom;
13086 unsigned a;
13087 Atom target;
13088
13089 if (!atom_name)
13090 atom_name = ((screen->mappedSelect && atomCount)
13091 ? screen->mappedSelect[0]
13092 : "PRIMARY");
13093 TRACE(("FindFontSelection(%s)\n", atom_name));
13094
13095 for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
13096 if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) {
13097 TRACE(("...found atom %d:%s\n", a + 1, atom_name));
13098 break;
13099 }
13100 }
13101 if (!a) {
13102 atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1);
13103 *(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name);
13104 ++atomCount;
13105 TRACE(("...added atom %d:%s\n", atomCount, atom_name));
13106 }
13107
13108 target = XmuInternAtom(XtDisplay(xw), *pAtom);
13109 if (justprobe) {
13110 screen->SelectFontName() =
13111 XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : 0;
13112 TRACE(("...selected fontname '%s'\n",
13113 NonNull(screen->SelectFontName())));
13114 } else {
13115 XtGetSelectionValue((Widget) xw, target, XA_STRING,
13116 DoSetSelectedFont, NULL,
13117 XtLastTimestampProcessed(XtDisplay(xw)));
13118 }
13119 return;
13120 }
13121
13122 Bool
set_cursor_gcs(XtermWidget xw)13123 set_cursor_gcs(XtermWidget xw)
13124 {
13125 TScreen *screen = TScreenOf(xw);
13126 VTwin *win = WhichVWin(screen);
13127
13128 Pixel cc = T_COLOR(screen, TEXT_CURSOR);
13129 Pixel fg = T_COLOR(screen, TEXT_FG);
13130 Pixel bg = T_COLOR(screen, TEXT_BG);
13131 Bool changed = False;
13132
13133 /*
13134 * Let's see, there are three things that have "color":
13135 *
13136 * background
13137 * text
13138 * cursorblock
13139 *
13140 * And, there are four situations when drawing a cursor, if we decide
13141 * that we like have a solid block of cursor color with the letter
13142 * that it is highlighting shown in the background color to make it
13143 * stand out:
13144 *
13145 * selected window, normal video - background on cursor
13146 * selected window, reverse video - foreground on cursor
13147 * unselected window, normal video - foreground on background
13148 * unselected window, reverse video - background on foreground
13149 *
13150 * Since the last two are really just normalGC and reverseGC, we only
13151 * need two new GC's. Under monochrome, we get the same effect as
13152 * above by setting cursor color to foreground.
13153 */
13154
13155 TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg));
13156 if (win != 0 && (cc != bg)) {
13157 Pixel xx = ((fg == cc) ? bg : cc);
13158
13159 /* set the fonts to the current one */
13160 setCgsFont(xw, win, gcVTcursNormal, 0);
13161 setCgsFont(xw, win, gcVTcursFilled, 0);
13162 setCgsFont(xw, win, gcVTcursReverse, 0);
13163 setCgsFont(xw, win, gcVTcursOutline, 0);
13164
13165 /* we have a colored cursor */
13166 setCgsFore(xw, win, gcVTcursNormal, fg);
13167 setCgsBack(xw, win, gcVTcursNormal, xx);
13168
13169 setCgsFore(xw, win, gcVTcursFilled, xx);
13170 setCgsBack(xw, win, gcVTcursFilled, fg);
13171
13172 if (screen->always_highlight) {
13173 /* both GC's use the same color */
13174 setCgsFore(xw, win, gcVTcursReverse, bg);
13175 setCgsBack(xw, win, gcVTcursReverse, cc);
13176 } else {
13177 setCgsFore(xw, win, gcVTcursReverse, bg);
13178 setCgsBack(xw, win, gcVTcursReverse, cc);
13179 }
13180 set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc);
13181 changed = True;
13182 FreeMarkGCs(xw);
13183 }
13184
13185 if (changed) {
13186 TRACE(("...set_cursor_gcs - done\n"));
13187 }
13188 return changed;
13189 }
13190
13191 /*
13192 * Build up the default translations string, allowing the user to suppress
13193 * some of the features.
13194 */
13195 void
VTInitTranslations(void)13196 VTInitTranslations(void)
13197 {
13198 /* *INDENT-OFF* */
13199 static struct {
13200 Boolean wanted;
13201 const char *name;
13202 const char *value;
13203 } table[] = {
13204 #define DATA(name,value) { False, name, value }
13205 DATA("select",
13206 "\
13207 Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\
13208 Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\
13209 "
13210 ),
13211 #if OPT_MAXIMIZE
13212 DATA("fullscreen",
13213 "\
13214 Alt <Key>Return:fullscreen() \n\
13215 "
13216 ),
13217 #endif
13218 #if OPT_SCROLL_LOCK
13219 DATA("scroll-lock",
13220 "\
13221 <KeyRelease> Scroll_Lock:scroll-lock() \n\
13222 "
13223 ),
13224 #endif
13225 #if OPT_SHIFT_FONTS
13226 DATA("shift-fonts",
13227 "\
13228 Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\
13229 Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\
13230 Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\
13231 "
13232 ),
13233 #endif
13234 DATA("paging",
13235 "\
13236 Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
13237 Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
13238 "
13239 ),
13240 /* This must be the last set mentioning "KeyPress" */
13241 DATA("keypress",
13242 "\
13243 ~Meta <KeyPress>:insert-seven-bit() \n\
13244 Meta <KeyPress>:insert-eight-bit() \n\
13245 "
13246 ),
13247 DATA("popup-menu",
13248 "\
13249 !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
13250 !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
13251 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\
13252 ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
13253 !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
13254 !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
13255 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\
13256 ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
13257 !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
13258 !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
13259 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\
13260 ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
13261 "
13262 ),
13263 /* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */
13264 DATA("reset",
13265 "\
13266 Meta <Btn2Down>:clear-saved-lines() \n\
13267 "
13268 ),
13269 DATA("select",
13270 "\
13271 ~Meta <Btn1Down>:select-start() \n\
13272 ~Meta <Btn1Motion>:select-extend() \n\
13273 ~Ctrl ~Meta <Btn2Down>:ignore() \n\
13274 ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\
13275 ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
13276 ~Meta <Btn3Motion>:select-extend() \n\
13277 <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\
13278 "
13279 ),
13280 DATA("wheel-mouse",
13281 "\
13282 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
13283 Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
13284 Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
13285 @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\
13286 <Btn4Down>:scroll-back(5,line,m) \n\
13287 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
13288 Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
13289 Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
13290 @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\
13291 <Btn5Down>:scroll-forw(5,line,m) \n\
13292 "
13293 ),
13294 DATA("pointer",
13295 "\
13296 <BtnMotion>:pointer-motion() \n\
13297 <BtnDown>:pointer-button() \n\
13298 <BtnUp>:pointer-button() \n\
13299 "
13300 ),
13301 DATA("default",
13302 "\
13303 <BtnUp>:ignore() \n\
13304 "
13305 )
13306 };
13307 #undef DATA
13308 /* *INDENT-ON* */
13309
13310 char *result = 0;
13311
13312 int pass;
13313 Cardinal item;
13314
13315 TRACE(("VTInitTranslations\n"));
13316 for (item = 0; item < XtNumber(table); ++item) {
13317 table[item].wanted = True;
13318 }
13319 #if OPT_MAXIMIZE
13320 /*
13321 * As a special case, allow for disabling the alt-enter translation if
13322 * the resource settings prevent fullscreen from being used. We would
13323 * do the same for scroll-lock and shift-fonts if they were application
13324 * resources too, rather than in the widget.
13325 */
13326 if (resource.fullscreen == esNever) {
13327 for (item = 0; item < XtNumber(table); ++item) {
13328 if (!strcmp(table[item].name, "fullscreen")) {
13329 table[item].wanted = False;
13330 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
13331 }
13332 }
13333 }
13334 #endif
13335 if (!IsEmpty(resource.omitTranslation)) {
13336 char *value;
13337 const char *source = resource.omitTranslation;
13338
13339 while (*source != '\0' && (value = ParseList(&source)) != 0) {
13340 size_t len = strlen(value);
13341
13342 TRACE(("parsed:%s\n", value));
13343 for (item = 0; item < XtNumber(table); ++item) {
13344 if (strlen(table[item].name) >= len
13345 && x_strncasecmp(table[item].name,
13346 value,
13347 (unsigned) len) == 0) {
13348 table[item].wanted = False;
13349 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value));
13350 /* continue: "select", for instance is two chunks */
13351 }
13352 }
13353 free(value);
13354 }
13355 }
13356
13357 for (pass = 0; pass < 2; ++pass) {
13358 size_t needed = 0;
13359 for (item = 0; item < XtNumber(table); ++item) {
13360 if (table[item].wanted) {
13361 if (pass) {
13362 strcat(result, table[item].value);
13363 } else {
13364 needed += strlen(table[item].value) + 1;
13365 }
13366 }
13367 }
13368 if (!pass) {
13369 result = XtMalloc((Cardinal) needed);
13370 *result = '\0';
13371 }
13372 }
13373
13374 TRACE(("result:\n%s\n", result));
13375
13376 defaultTranslations = result;
13377 free((void *) xtermClassRec.core_class.tm_table);
13378 xtermClassRec.core_class.tm_table = result;
13379 }
13380
13381 #ifdef NO_LEAKS
13382 void
noleaks_charproc(void)13383 noleaks_charproc(void)
13384 {
13385 free(v_buffer);
13386 }
13387 #endif
13388