charproc.c revision 5104ee6e
1/* $XTermId: charproc.c,v 1.2060 2025/01/05 20:45:50 tom Exp $ */ 2 3/* 4 * Copyright 1999-2024,2025 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#include <graphics_sixel.h> 137 138#ifdef NO_LEAKS 139#include <xtermcap.h> 140#endif 141 142typedef int (*BitFunc) (unsigned * /* p */ , 143 unsigned /* mask */ ); 144 145static IChar doinput(XtermWidget /* xw */ ); 146static int set_character_class(char * /*s */ ); 147static void FromAlternate(XtermWidget /* xw */ , 148 Bool /* clearFirst */ ); 149static void ReallyReset(XtermWidget /* xw */ , 150 Bool /* full */ , 151 Bool /* saved */ ); 152static void RequestResize(XtermWidget /* xw */ , 153 int /* rows */ , 154 int /* cols */ , 155 Bool /* text */ ); 156static void SwitchBufs(XtermWidget /* xw */ , 157 int /* toBuf */ , 158 Bool /* clearFirst */ ); 159static void ToAlternate(XtermWidget /* xw */ , 160 Bool /* clearFirst */ ); 161static void ansi_modes(XtermWidget /* xw */ , 162 BitFunc /* func */ ); 163static int bitclr(unsigned *p, unsigned mask); 164static int bitcpy(unsigned *p, unsigned q, unsigned mask); 165static int bitset(unsigned *p, unsigned mask); 166static void dpmodes(XtermWidget /* xw */ , 167 BitFunc /* func */ ); 168static void restoremodes(XtermWidget /* xw */ ); 169static void savemodes(XtermWidget /* xw */ ); 170static void window_ops(XtermWidget /* xw */ ); 171 172#if OPT_BLINK_CURS || OPT_BLINK_TEXT 173#define SettableCursorBlink(screen) \ 174 (((screen)->cursor_blink != cbAlways) && \ 175 ((screen)->cursor_blink != cbNever)) 176#define UpdateCursorBlink(xw) \ 177 SetCursorBlink(xw, TScreenOf(xw)->cursor_blink) 178static void SetCursorBlink(XtermWidget /* xw */ , 179 BlinkOps /* enable */ ); 180static void HandleBlinking(XtPointer /* closure */ , 181 XtIntervalId * /* id */ ); 182static void StartBlinking(XtermWidget /* xw */ ); 183static void StopBlinking(XtermWidget /* xw */ ); 184#else 185#define StartBlinking(xw) /* nothing */ 186#define StopBlinking(xw) /* nothing */ 187#endif 188 189#ifndef NO_ACTIVE_ICON 190static Boolean discount_frame_extents(XtermWidget /* xw */ , 191 int * /* height */ , 192 int * /* width */ ); 193#else 194#define discount_frame_extents(xw, height, width) False 195#endif 196 197#if OPT_INPUT_METHOD 198static void PreeditPosition(XtermWidget /* xw */ ); 199#endif 200 201#define DEFAULT -1 202#define BELLSUPPRESSMSEC 200 203 204static ANSI reply; 205static PARAMS parms; 206 207#define nparam parms.count 208 209#define InitParams() init_params() 210#define GetParam(n) parms.params[(n)] 211#define SetParam(n,v) parms.params[(n)] = v 212#define ParamPair(n) nparam - (n), parms.params + (n) 213 214static jmp_buf vtjmpbuf; 215 216/* event handlers */ 217static void HandleBell PROTO_XT_ACTIONS_ARGS; 218static void HandleIgnore PROTO_XT_ACTIONS_ARGS; 219static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS; 220static void HandleVisualBell PROTO_XT_ACTIONS_ARGS; 221#if HANDLE_STRUCT_NOTIFY 222static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS; 223#endif 224 225/* 226 * NOTE: VTInitialize zeros out the entire ".screen" component of the 227 * XtermWidget, so make sure to add an assignment statement in VTInitialize() 228 * for each new ".screen" field added to this resource list. 229 */ 230 231/* Defaults */ 232#if OPT_ISO_COLORS 233 234/* 235 * If we default to colorMode enabled, compile-in defaults for the ANSI colors. 236 */ 237#if DFT_COLORMODE 238#define DFT_COLOR(name) name 239#else 240#define DFT_COLOR(name) XtDefaultForeground 241#endif 242#endif 243 244static char _Font_Selected_[] = "yes"; /* string is arbitrary */ 245 246static const char *defaultTranslations; 247/* *INDENT-OFF* */ 248static XtActionsRec actionsList[] = { 249 { "allow-bold-fonts", HandleAllowBoldFonts }, 250 { "allow-send-events", HandleAllowSends }, 251 { "bell", HandleBell }, 252 { "clear-saved-lines", HandleClearSavedLines }, 253 { "copy-selection", HandleCopySelection }, 254 { "create-menu", HandleCreateMenu }, 255 { "delete-is-del", HandleDeleteIsDEL }, 256 { "dired-button", DiredButton }, 257 { "hard-reset", HandleHardReset }, 258 { "ignore", HandleIgnore }, 259 { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */ 260 { "insert-eight-bit", HandleEightBitKeyPressed }, 261 { "insert-selection", HandleInsertSelection }, 262 { "insert-seven-bit", HandleKeyPressed }, 263 { "interpret", HandleInterpret }, 264 { "keymap", HandleKeymapChange }, 265 { "pointer-motion", HandlePointerMotion }, 266 { "pointer-button", HandlePointerButton }, 267 { "popup-menu", HandlePopupMenu }, 268 { "print", HandlePrintScreen }, 269 { "print-everything", HandlePrintEverything }, 270 { "print-redir", HandlePrintControlMode }, 271 { "quit", HandleQuit }, 272 { "redraw", HandleRedraw }, 273 { "scroll-back", HandleScrollBack }, 274 { "scroll-forw", HandleScrollForward }, 275 { "scroll-to", HandleScrollTo }, 276 { "secure", HandleSecure }, 277 { "select-cursor-end", HandleKeyboardSelectEnd }, 278 { "select-cursor-extend", HandleKeyboardSelectExtend }, 279 { "select-cursor-start", HandleKeyboardSelectStart }, 280 { "select-end", HandleSelectEnd }, 281 { "select-extend", HandleSelectExtend }, 282 { "select-set", HandleSelectSet }, 283 { "select-start", HandleSelectStart }, 284 { "send-signal", HandleSendSignal }, 285 { "set-8-bit-control", Handle8BitControl }, 286 { "set-allow132", HandleAllow132 }, 287 { "set-altscreen", HandleAltScreen }, 288 { "set-appcursor", HandleAppCursor }, 289 { "set-appkeypad", HandleAppKeypad }, 290 { "set-autolinefeed", HandleAutoLineFeed }, 291 { "set-autowrap", HandleAutoWrap }, 292 { "set-backarrow", HandleBackarrow }, 293 { "set-bellIsUrgent", HandleBellIsUrgent }, 294 { "set-cursesemul", HandleCursesEmul }, 295 { "set-jumpscroll", HandleJumpscroll }, 296 { "set-keep-clipboard", HandleKeepClipboard }, 297 { "set-keep-selection", HandleKeepSelection }, 298 { "set-marginbell", HandleMarginBell }, 299 { "set-old-function-keys", HandleOldFunctionKeys }, 300 { "set-pop-on-bell", HandleSetPopOnBell }, 301 { "set-reverse-video", HandleReverseVideo }, 302 { "set-reversewrap", HandleReverseWrap }, 303 { "set-scroll-on-key", HandleScrollKey }, 304 { "set-scroll-on-tty-output", HandleScrollTtyOutput }, 305 { "set-scrollbar", HandleScrollbar }, 306 { "set-select", HandleSetSelect }, 307 { "set-sun-keyboard", HandleSunKeyboard }, 308 { "set-titeInhibit", HandleTiteInhibit }, 309 { "set-visual-bell", HandleSetVisualBell }, 310 { "set-vt-font", HandleSetFont }, 311 { "soft-reset", HandleSoftReset }, 312 { "start-cursor-extend", HandleKeyboardStartExtend }, 313 { "start-extend", HandleStartExtend }, 314 { "string", HandleStringEvent }, 315 { "vi-button", ViButton }, 316 { "visual-bell", HandleVisualBell }, 317#ifdef ALLOWLOGGING 318 { "set-logging", HandleLogging }, 319#endif 320#if OPT_ALLOW_XXX_OPS 321 { "allow-color-ops", HandleAllowColorOps }, 322 { "allow-font-ops", HandleAllowFontOps }, 323 { "allow-mouse-ops", HandleAllowMouseOps }, 324 { "allow-tcap-ops", HandleAllowTcapOps }, 325 { "allow-title-ops", HandleAllowTitleOps }, 326 { "allow-window-ops", HandleAllowWindowOps }, 327#endif 328#if OPT_BLINK_CURS 329 { "set-cursorblink", HandleCursorBlink }, 330#endif 331#if OPT_BOX_CHARS 332 { "set-font-linedrawing", HandleFontBoxChars }, 333 { "set-font-packed", HandleFontPacked }, 334#endif 335#if OPT_DABBREV 336 { "dabbrev-expand", HandleDabbrevExpand }, 337#endif 338#if OPT_DEC_CHRSET 339 { "set-font-doublesize", HandleFontDoublesize }, 340#endif 341#if OPT_DEC_SOFTFONT 342 { "set-font-loading", HandleFontLoading }, 343#endif 344#if OPT_EXEC_XTERM 345 { "spawn-new-terminal", HandleSpawnTerminal }, 346#endif 347#if OPT_GRAPHICS 348 { "set-private-colors", HandleSetPrivateColorRegisters }, 349#endif 350#if OPT_HP_FUNC_KEYS 351 { "set-hp-function-keys", HandleHpFunctionKeys }, 352#endif 353#if OPT_LOAD_VTFONTS 354 { "load-vt-fonts", HandleLoadVTFonts }, 355#endif 356#if OPT_MAXIMIZE 357 { "deiconify", HandleDeIconify }, 358 { "fullscreen", HandleFullscreen }, 359 { "iconify", HandleIconify }, 360 { "maximize", HandleMaximize }, 361 { "restore", HandleRestoreSize }, 362#endif 363#if OPT_NUM_LOCK 364 { "alt-sends-escape", HandleAltEsc }, 365 { "meta-sends-escape", HandleMetaEsc }, 366 { "set-num-lock", HandleNumLock }, 367#endif 368#if OPT_PRINT_ON_EXIT 369 { "print-immediate", HandlePrintImmediate }, 370 { "print-on-error", HandlePrintOnError }, 371#endif 372#if OPT_READLINE 373 { "readline-button", ReadLineButton }, 374#endif 375#if OPT_RENDERFONT 376 { "set-render-font", HandleRenderFont }, 377#endif 378#if OPT_SCO_FUNC_KEYS 379 { "set-sco-function-keys", HandleScoFunctionKeys }, 380#endif 381#if OPT_SCREEN_DUMPS 382 { "dump-html", HandleDumpHtml }, 383 { "dump-svg", HandleDumpSvg }, 384#endif 385#if OPT_SCROLL_LOCK 386 { "scroll-lock", HandleScrollLock }, 387#endif 388#if OPT_SELECTION_OPS 389#if OPT_EXEC_SELECTION 390 { "exec-formatted", HandleExecFormatted }, 391 { "exec-selectable", HandleExecSelectable }, 392#endif 393 { "insert-formatted", HandleInsertFormatted }, 394 { "insert-selectable", HandleInsertSelectable }, 395#endif 396#if OPT_SHIFT_FONTS 397 { "larger-vt-font", HandleLargerFont }, 398 { "smaller-vt-font", HandleSmallerFont }, 399#endif 400#if OPT_SIXEL_GRAPHICS 401 { "set-sixel-scrolling", HandleSixelScrolling }, 402#endif 403#if OPT_SUN_FUNC_KEYS 404 { "set-sun-function-keys", HandleSunFunctionKeys }, 405#endif 406#if OPT_TEK4014 407 { "set-terminal-type", HandleSetTerminalType }, 408 { "set-visibility", HandleVisibility }, 409 { "set-tek-text", HandleSetTekText }, 410 { "tek-page", HandleTekPage }, 411 { "tek-reset", HandleTekReset }, 412 { "tek-copy", HandleTekCopy }, 413#endif 414#if OPT_TOOLBAR 415 { "set-toolbar", HandleToolbar }, 416#endif 417#if OPT_WIDE_CHARS 418 { "set-utf8-mode", HandleUTF8Mode }, 419 { "set-utf8-fonts", HandleUTF8Fonts }, 420 { "set-utf8-title", HandleUTF8Title }, 421#endif 422}; 423/* *INDENT-ON* */ 424 425#define SPS screen.printer_state 426 427static XtResource xterm_resources[] = 428{ 429 Bres(XtNallowPasteControls, XtCAllowPasteControls, 430 screen.allowPasteControl0, False), 431 Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False), 432 Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR), 433 Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT), 434 Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE), 435 Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP), 436 Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE), 437 Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW), 438 Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False), 439 Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC), 440 Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True), 441 Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False), 442 Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False), 443 Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False), 444 Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False), 445 Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False), 446 Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True), 447 Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False), 448 Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False), 449 Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS), 450 Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False), 451 Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True), 452 Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True), 453 Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False), 454 Bres(XtNc132, XtCC132, screen.c132, False), 455 Sres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll_s, DEF_CD_XTRA_SCROLL), 456 Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False), 457 Bres(XtNcurses, XtCCurses, screen.curses, False), 458 Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True), 459 Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, 460 screen.cutToBeginningOfLine, True), 461 Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL), 462 Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True), 463 Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False), 464 Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True), 465 Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True), 466 Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True), 467 Bres(XtNhighlightSelection, XtCHighlightSelection, 468 screen.highlight_selection, False), 469 Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False), 470 Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False), 471 Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True), 472 Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, True), 473 Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True), 474 Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False), 475 Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True), 476 Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False), 477 Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False), 478 Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC), 479 Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False), 480 Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False), 481 Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False), 482 Bres(XtNpreferLatin1, XtCPreferLatin1, screen.prefer_latin1, True), 483 Bres(XtNprintRawChars, XtCPrintRawChars, screen.print_rawchars, False), 484 Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False), 485 Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False), 486 Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False), 487 Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True), 488 Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False), 489 Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False), 490 Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False), 491 Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False), 492 Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False), 493 Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False), 494 Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True), 495 Bres(XtNselectToClipboard, XtCSelectToClipboard, 496 screen.selectToClipboard, False), 497 Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False), 498 Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False), 499 Sres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll_s, DEF_TI_XTRA_SCROLL), 500 Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False), 501 Bres(XtNunderLine, XtCUnderLine, screen.underline, True), 502 Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False), 503 Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False), 504 505 Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"), 506 507 Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC), 508 Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource), 509 Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER), 510 Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1), 511 Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE), 512 Ires(XtNmaxStringParse, XtCMaxStringParse, screen.strings_max, DEF_STRINGS_MAX), 513 Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME), 514 Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL), 515 Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE), 516 Ires(XtNprinterControlMode, XtCPrinterControlMode, 517 SPS.printer_controlmode, 0), 518 Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES), 519 Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1), 520 Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100), 521 Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES), 522 Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1), 523 Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES), 524 525 Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL), 526 Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL), 527 Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL), 528 Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL), 529 Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL), 530 Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL), 531 Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL), 532 Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL), 533 534 Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""), 535 Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT), 536 Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL), 537 Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID), 538 Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"), 539 Sres(XtNdisallowedColorOps, XtCDisallowedColorOps, 540 screen.disallowedColorOps, DEF_DISALLOWED_COLOR), 541 Sres(XtNdisallowedFontOps, XtCDisallowedFontOps, 542 screen.disallowedFontOps, DEF_DISALLOWED_FONT), 543 Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps, 544 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE), 545 Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls, 546 screen.disallowedPasteOps, DEF_DISALLOWED_PASTE_CONTROLS), 547 Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps, 548 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP), 549 Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps, 550 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW), 551 Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META), 552 Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes, 553 screen.eightbit_select_types, NULL), 554 Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT), 555 Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL), 556 Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT), 557 Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""), 558 Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL), 559 Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL), 560 561 Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground), 562 Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground), 563 Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground), 564 Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground), 565 Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground), 566 567 {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity), 568 XtOffsetOf(XtermWidgetRec, misc.resizeGravity), 569 XtRImmediate, (XtPointer) SouthWestGravity}, 570 571 Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"), 572 573#ifdef ALLOWLOGGING 574 Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False), 575 Bres(XtNlogging, XtCLogging, misc.log_on, False), 576 Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL), 577#endif 578 579#ifndef NO_ACTIVE_ICON 580 Sres(XtNactiveIcon, XtCActiveIcon, misc.active_icon_s, "default"), 581 Ires(XtNiconBorderWidth, XtCBorderWidth, misc.icon_border_width, 2), 582 Sres(XtNiconFont, XtCIconFont, screen.icon_fontname, "nil2"), 583 Cres(XtNiconBorderColor, XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground), 584#endif /* NO_ACTIVE_ICON */ 585 586#if OPT_BLINK_CURS 587 Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True), 588 Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"), 589#endif 590 Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False), 591 Bres(XtNcursorBar, XtCCursorBar, screen.cursor_bar, False), 592 593#if OPT_BLINK_TEXT 594 Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD), 595#endif 596 597#if OPT_BLINK_CURS || OPT_BLINK_TEXT 598 Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600), 599 Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300), 600#endif 601 602#if OPT_BOX_CHARS 603 Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False), 604 Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True), 605 Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True), 606#endif 607#if OPT_BOX_CHARS || OPT_WIDE_CHARS 608 Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, True), 609#endif 610 611#if OPT_BROKEN_OSC 612 Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True), 613#endif 614 615#if OPT_BROKEN_ST 616 Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False), 617#endif 618 619#if OPT_C1_PRINT 620 Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False), 621#endif 622 623#if OPT_CLIP_BOLD 624 Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True), 625 Bres(XtNuseBorderClipping, XtCUseBorderClipping, 626 screen.use_border_clipping, False), 627#endif 628 629#if OPT_DEC_CHRSET 630 Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True), 631 Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET), 632#endif 633 634#if OPT_DEC_RECTOPS 635 Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC), 636#endif 637 638#if OPT_HIGHLIGHT_COLOR 639 Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground), 640 Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground), 641 Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True), 642 Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe), 643#endif /* OPT_HIGHLIGHT_COLOR */ 644 645#if OPT_INPUT_METHOD 646 Bres(XtNopenIm, XtCOpenIm, misc.open_im, True), 647 Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL), 648 Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type, 649 "OverTheSpot,Root"), 650 Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3), 651#endif 652 653#if OPT_ISO_COLORS 654 Bres(XtNboldColors, XtCColorMode, screen.boldColors, True), 655 Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0), 656 Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE), 657 658 Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False), 659 Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False), 660 Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False), 661 Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False), 662 Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False), 663 Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False), 664#if OPT_WIDE_ATTRS 665 Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False), 666#endif 667#if OPT_DIRECT_COLOR 668 Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True), 669#endif 670 671 COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")), 672 COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")), 673 COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")), 674 COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")), 675 COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)), 676 COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")), 677 COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")), 678 COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")), 679 COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")), 680 COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")), 681 COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")), 682 COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")), 683 COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)), 684 COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")), 685 COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")), 686 COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")), 687 COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)), 688 COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)), 689 COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)), 690 COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)), 691 692#if OPT_WIDE_ATTRS 693 COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)), 694#endif 695 696#endif /* OPT_ISO_COLORS */ 697 698 CLICK_RES("2", screen.onClick[1], "word"), 699 CLICK_RES("3", screen.onClick[2], "line"), 700 CLICK_RES("4", screen.onClick[3], 0), 701 CLICK_RES("5", screen.onClick[4], 0), 702 703 Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"), 704 705#if OPT_MOD_FKEYS 706 Ires(XtNmodifyKeyboard, XtCModifyKeyboard, 707 keyboard.modify_1st.allow_keys, 0), 708 Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys, 709 keyboard.modify_1st.cursor_keys, 2), 710 Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys, 711 keyboard.modify_1st.function_keys, 2), 712 Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys, 713 keyboard.modify_1st.keypad_keys, 0), 714 Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys, 715 keyboard.modify_1st.other_keys, 0), 716 Ires(XtNmodifyStringKeys, XtCModifyStringKeys, 717 keyboard.modify_1st.string_keys, 0), 718 Ires(XtNformatOtherKeys, XtCFormatOtherKeys, 719 keyboard.format_keys, 0), 720#endif 721 722#if OPT_NUM_LOCK 723 Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False), 724 Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True), 725#endif 726 727#if OPT_PRINT_COLORS 728 Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1), 729#endif 730 731#if OPT_REGIS_GRAPHICS 732 Sres(XtNregisDefaultFont, XtCRegisDefaultFont, 733 screen.graphics_regis_default_font, ""), 734 Sres(XtNregisScreenSize, XtCRegisScreenSize, 735 screen.graphics_regis_screensize, "auto"), 736#endif 737 738#if OPT_GRAPHICS 739 Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID), 740 Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size, 741 "1000x1000"), 742#endif 743 744#if OPT_ISO_COLORS && OPT_WIDE_ATTRS && OPT_SGR2_HASH 745 Bres(XtNfaintIsRelative, XtCFaintIsRelative, screen.faint_relative, False), 746#endif 747 748#if OPT_SHIFT_FONTS 749 Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True), 750#endif 751 752#if OPT_SIXEL_GRAPHICS 753 Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, True), 754 Bres(XtNsixelScrollsRight, XtCSixelScrollsRight, 755 screen.sixel_scrolls_right, False), 756#endif 757 758#if OPT_GRAPHICS 759 Ires(XtNnumColorRegisters, XtCNumColorRegisters, 760 screen.numcolorregisters, 0), 761 Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters, 762 screen.privatecolorregisters, True), 763 Bres(XtNincrementalGraphics, XtCIncrementalGraphics, 764 screen.incremental_graphics, False), 765#endif 766 767#if OPT_STATUS_LINE 768 Sres(XtNindicatorFormat, XtCIndicatorFormat, screen.status_fmt, DEF_SL_FORMAT), 769#endif 770 771#if OPT_SUNPC_KBD 772 Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10), 773#endif 774 775#if OPT_TEK4014 776 Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False), 777 Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False), 778 Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False), 779#endif 780 781#if OPT_TOOLBAR 782 Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0), 783 Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25), 784#endif 785 786#if OPT_WIDE_CHARS 787 Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False), 788 Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False), 789 Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True), 790 Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False), 791 Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False), 792 Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True), 793 Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False), 794 Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2), 795 Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655), 796 Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536), 797 Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"), 798 Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"), 799 Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"), 800 Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT), 801 Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT), 802 Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL), 803#endif 804 805#if OPT_LUIT_PROG 806 Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"), 807 Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER), 808#endif 809 810#if OPT_INPUT_METHOD 811 Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT), 812#endif 813 814#if OPT_SCROLL_LOCK 815 Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False), 816 Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False), 817#endif 818 819 /* these are used only for testing ncurses, not in the manual page */ 820#if OPT_XMC_GLITCH 821 Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False), 822 Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True), 823 Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1), 824 Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0), 825#endif 826 827#ifdef SCROLLBAR_RIGHT 828 Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False), 829#endif 830 831#if OPT_RENDERFONT 832 Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False), 833 Ires(XtNxftMaxGlyphMemory, XtCXftMaxGlyphMemory, 834 screen.xft_max_glyph_memory, 0), 835 Ires(XtNxftMaxUnrefFonts, XtCXftMaxUnrefFonts, 836 screen.xft_max_unref_fonts, 0), 837 Bres(XtNxftTrackMemUsage, XtCXftTrackMemUsage, 838 screen.xft_track_mem_usage, DEF_TRACK_USAGE), 839#define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0") 840 RES_FACESIZE(1), 841 RES_FACESIZE(2), 842 RES_FACESIZE(3), 843 RES_FACESIZE(4), 844 RES_FACESIZE(5), 845 RES_FACESIZE(6), 846 RES_FACESIZE(7), 847 Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE), 848 Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME), 849 Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"), 850 Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE), 851 Ires(XtNlimitFontHeight, XtCLimitFontHeight, misc.limit_fontheight, 10), 852 Ires(XtNlimitFontWidth, XtCLimitFontWidth, misc.limit_fontwidth, 10), 853#if OPT_RENDERWIDE 854 Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME), 855#endif 856#endif 857}; 858 859static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg, 860 ArgList args, Cardinal *num_args); 861static void VTClassInit(void); 862static void VTDestroy(Widget w); 863static void VTExpose(Widget w, XEvent *event, Region region); 864static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args, 865 Cardinal *num_args); 866static void VTRealize(Widget w, XtValueMask * valuemask, 867 XSetWindowAttributes * values); 868static void VTResize(Widget w); 869 870#if OPT_INPUT_METHOD 871static void VTInitI18N(XtermWidget); 872#endif 873 874static 875WidgetClassRec xtermClassRec = 876{ 877 { 878 /* core_class fields */ 879 (WidgetClass) & widgetClassRec, /* superclass */ 880 "VT100", /* class_name */ 881 sizeof(XtermWidgetRec), /* widget_size */ 882 VTClassInit, /* class_initialize */ 883 NULL, /* class_part_initialize */ 884 False, /* class_inited */ 885 VTInitialize, /* initialize */ 886 NULL, /* initialize_hook */ 887 VTRealize, /* realize */ 888 actionsList, /* actions */ 889 XtNumber(actionsList), /* num_actions */ 890 xterm_resources, /* resources */ 891 XtNumber(xterm_resources), /* num_resources */ 892 NULLQUARK, /* xrm_class */ 893 True, /* compress_motion */ 894 False, /* compress_exposure */ 895 True, /* compress_enterleave */ 896 False, /* visible_interest */ 897 VTDestroy, /* destroy */ 898 VTResize, /* resize */ 899 VTExpose, /* expose */ 900 VTSetValues, /* set_values */ 901 NULL, /* set_values_hook */ 902 XtInheritSetValuesAlmost, /* set_values_almost */ 903 NULL, /* get_values_hook */ 904 NULL, /* accept_focus */ 905 XtVersion, /* version */ 906 NULL, /* callback_offsets */ 907 NULL, /* tm_table */ 908 XtInheritQueryGeometry, /* query_geometry */ 909 XtInheritDisplayAccelerator, /* display_accelerator */ 910 NULL /* extension */ 911 } 912}; 913 914WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec; 915 916/* 917 * Add input-actions for widgets that are overlooked (scrollbar and toolbar): 918 * 919 * a) Sometimes the scrollbar passes through translations, sometimes it 920 * doesn't. We add the KeyPress translations here, just to be sure. 921 * b) In the normal (non-toolbar) configuration, the xterm widget covers 922 * almost all of the window. With a toolbar, there's a relatively 923 * large area that the user would expect to enter keystrokes since the 924 * program can get the focus. 925 */ 926void 927xtermAddInput(Widget w) 928{ 929 /* *INDENT-OFF* */ 930 XtActionsRec input_actions[] = { 931 { "insert", HandleKeyPressed }, /* alias */ 932 { "insert-eight-bit", HandleEightBitKeyPressed }, 933 { "insert-seven-bit", HandleKeyPressed }, 934 { "pointer-motion", HandlePointerMotion }, 935 { "pointer-button", HandlePointerButton }, 936 { "secure", HandleSecure }, 937 { "string", HandleStringEvent }, 938 { "scroll-back", HandleScrollBack }, 939 { "scroll-forw", HandleScrollForward }, 940 { "scroll-to", HandleScrollTo }, 941 { "select-cursor-end", HandleKeyboardSelectEnd }, 942 { "select-cursor-extend", HandleKeyboardSelectExtend }, 943 { "select-cursor-start", HandleKeyboardSelectStart }, 944 { "insert-selection", HandleInsertSelection }, 945 { "select-start", HandleSelectStart }, 946 { "select-extend", HandleSelectExtend }, 947 { "start-extend", HandleStartExtend }, 948 { "select-end", HandleSelectEnd }, 949 { "clear-saved-lines", HandleClearSavedLines }, 950 { "popup-menu", HandlePopupMenu }, 951 { "bell", HandleBell }, 952 { "ignore", HandleIgnore }, 953#if OPT_DABBREV 954 { "dabbrev-expand", HandleDabbrevExpand }, 955#endif 956#if OPT_MAXIMIZE 957 { "fullscreen", HandleFullscreen }, 958#endif 959#if OPT_SCROLL_LOCK 960 { "scroll-lock", HandleScrollLock }, 961#endif 962#if OPT_SHIFT_FONTS 963 { "larger-vt-font", HandleLargerFont }, 964 { "smaller-vt-font", HandleSmallerFont }, 965#endif 966 }; 967 /* *INDENT-ON* */ 968 969 TRACE_TRANS("BEFORE", w); 970 XtAppAddActions(app_con, input_actions, XtNumber(input_actions)); 971 XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations)); 972 TRACE_TRANS("AFTER:", w); 973 974#if OPT_EXTRA_PASTE 975 if (term && term->keyboard.extra_translations) 976 XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations)); 977#endif 978} 979 980#if OPT_ISO_COLORS 981#ifdef EXP_BOGUS_FG 982static Bool 983CheckBogusForeground(TScreen *screen, const char *tag) 984{ 985 int row = -1, col = -1, pass; 986 Bool isClear = True; 987 988 (void) tag; 989 for (pass = 0; pass < 2; ++pass) { 990 row = screen->cur_row; 991 for (; isClear && (row <= screen->max_row); ++row) { 992 CLineData *ld = getLineData(screen, row); 993 994 if (ld != 0) { 995 IAttr *attribs = ld->attribs; 996 997 col = (row == screen->cur_row) ? screen->cur_col : 0; 998 for (; isClear && (col <= screen->max_col); ++col) { 999 unsigned flags = attribs[col]; 1000 if (pass) { 1001 flags &= ~FG_COLOR; 1002 attribs[col] = (IAttr) flags; 1003 } else if ((flags & BG_COLOR)) { 1004 isClear = False; 1005 } else if ((flags & FG_COLOR)) { 1006 unsigned ch = ld->charData[col]; 1007 isClear = ((ch == ' ') || (ch == 0)); 1008 } else { 1009 isClear = False; 1010 } 1011 } 1012 } 1013 } 1014 } 1015 TRACE(("%s checked %d,%d to %d,%d %s pass %d\n", 1016 tag, screen->cur_row, screen->cur_col, 1017 row, col, 1018 isClear && pass ? "cleared" : "unchanged", 1019 pass)); 1020 1021 return isClear; 1022} 1023#endif 1024 1025/* 1026 * The terminal's foreground and background colors are set via two mechanisms: 1027 * text (cur_foreground, cur_background values that are passed down to 1028 * XDrawImageString and XDrawString) 1029 * area (X11 graphics context used in XClearArea and XFillRectangle) 1030 */ 1031void 1032SGR_Foreground(XtermWidget xw, int color) 1033{ 1034 TScreen *screen = TScreenOf(xw); 1035 Pixel fg; 1036 1037 if (color >= 0) { 1038 UIntSet(xw->flags, FG_COLOR); 1039 } else { 1040 UIntClr(xw->flags, FG_COLOR); 1041 } 1042 fg = getXtermFG(xw, xw->flags, color); 1043 xw->cur_foreground = color; 1044 1045 setCgsFore(xw, WhichVWin(screen), gcNorm, fg); 1046 setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg); 1047 1048 setCgsFore(xw, WhichVWin(screen), gcBold, fg); 1049 setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg); 1050 1051#ifdef EXP_BOGUS_FG 1052 /* 1053 * If we've just turned off the foreground color, check for blank cells 1054 * which have no background color, but do have foreground color. This 1055 * could happen due to setting the foreground color just before scrolling. 1056 * 1057 * Those cells look uncolored, but will confuse ShowCursor(), which looks 1058 * for the colors in the current cell, and will see the foreground color. 1059 * In that case, remove the foreground color from the blank cells. 1060 */ 1061 if (color < 0) { 1062 CheckBogusForeground(screen, "SGR_Foreground"); 1063 } 1064#endif 1065} 1066 1067void 1068SGR_Background(XtermWidget xw, int color) 1069{ 1070 TScreen *screen = TScreenOf(xw); 1071 Pixel bg; 1072 1073 /* 1074 * An indexing operation may have set screen->scroll_amt, which would 1075 * normally result in calling FlushScroll() in WriteText(). However, 1076 * if we're changing the background color now, then the new value 1077 * should not apply to the pending blank lines. 1078 */ 1079 if (screen->scroll_amt && (color != xw->cur_background)) 1080 FlushScroll(xw); 1081 1082 if (color >= 0) { 1083 UIntSet(xw->flags, BG_COLOR); 1084 } else { 1085 UIntClr(xw->flags, BG_COLOR); 1086 } 1087 bg = getXtermBG(xw, xw->flags, color); 1088 xw->cur_background = color; 1089 1090 setCgsBack(xw, WhichVWin(screen), gcNorm, bg); 1091 setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg); 1092 1093 setCgsBack(xw, WhichVWin(screen), gcBold, bg); 1094 setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg); 1095} 1096 1097/* Invoked after updating bold/underline flags, computes the extended color 1098 * index to use for foreground. (See also 'extract_fg()'). 1099 */ 1100static void 1101setExtendedFG(XtermWidget xw) 1102{ 1103 int fg = xw->sgr_foreground; 1104 1105 if (TScreenOf(xw)->colorAttrMode 1106 || (fg < 0)) { 1107 fg = MapToColorMode(fg, TScreenOf(xw), xw->flags); 1108 } 1109 1110 /* This implements the IBM PC-style convention of 8-colors, with one 1111 * bit for bold, thus mapping the 0-7 codes to 8-15. It won't make 1112 * much sense for 16-color applications, but we keep it to retain 1113 * compatibility with ANSI-color applications. 1114 */ 1115#if OPT_PC_COLORS /* XXXJTL should be settable at runtime (resource or OSC?) */ 1116 if (TScreenOf(xw)->boldColors 1117 && (!xw->sgr_38_xcolors) 1118 && (fg >= 0) 1119 && (fg < 8) 1120 && (xw->flags & BOLD)) 1121 fg |= 8; 1122#endif 1123 1124 SGR_Foreground(xw, fg); 1125} 1126 1127/* Invoked after updating inverse flag, computes the extended color 1128 * index to use for background. (See also 'extract_bg()'). 1129 */ 1130static void 1131setExtendedBG(XtermWidget xw) 1132{ 1133 int bg = xw->sgr_background; 1134 1135 if (TScreenOf(xw)->colorAttrMode 1136 || (bg < 0)) { 1137 if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE)) 1138 bg = COLOR_RV; 1139 } 1140 1141 SGR_Background(xw, bg); 1142} 1143 1144void 1145setExtendedColors(XtermWidget xw) 1146{ 1147 setExtendedFG(xw); 1148 setExtendedBG(xw); 1149} 1150 1151static void 1152reset_SGR_Foreground(XtermWidget xw) 1153{ 1154 xw->sgr_foreground = -1; 1155 xw->sgr_38_xcolors = False; 1156 clrDirectFG(xw->flags); 1157 setExtendedFG(xw); 1158} 1159 1160static void 1161reset_SGR_Background(XtermWidget xw) 1162{ 1163 xw->sgr_background = -1; 1164 clrDirectBG(xw->flags); 1165 setExtendedBG(xw); 1166} 1167 1168static void 1169reset_SGR_Colors(XtermWidget xw) 1170{ 1171 reset_SGR_Foreground(xw); 1172 reset_SGR_Background(xw); 1173} 1174#endif /* OPT_ISO_COLORS */ 1175 1176#if OPT_WIDE_ATTRS 1177/* 1178 * Call this before changing the state of ATR_ITALIC, to update the GC fonts. 1179 */ 1180static void 1181setItalicFont(XtermWidget xw, Bool enable) 1182{ 1183 if (enable) { 1184 if ((xw->flags & ATR_ITALIC) == 0) { 1185 xtermLoadItalics(xw); 1186 TRACE(("setItalicFont: enabling Italics\n")); 1187 xtermUpdateFontGCs(xw, getItalicFont); 1188 } 1189 } else if ((xw->flags & ATR_ITALIC) != 0) { 1190 TRACE(("setItalicFont: disabling Italics\n")); 1191 xtermUpdateFontGCs(xw, getNormalFont); 1192 } 1193} 1194 1195static void 1196ResetItalics(XtermWidget xw) 1197{ 1198 setItalicFont(xw, False); 1199 UIntClr(xw->flags, ATR_ITALIC); 1200} 1201 1202#else 1203#define ResetItalics(xw) /* nothing */ 1204#endif 1205 1206static void 1207initCharset(TScreen *screen, int which, DECNRCM_codes code) 1208{ 1209 screen->gsets[which] = code; 1210} 1211 1212void 1213saveCharsets(TScreen *screen, DECNRCM_codes * target) 1214{ 1215 int g; 1216 for (g = 0; g < NUM_GSETS2; ++g) { 1217 target[g] = screen->gsets[g]; 1218 } 1219} 1220 1221void 1222restoreCharsets(TScreen *screen, const DECNRCM_codes * source) 1223{ 1224 int g; 1225 for (g = 0; g < NUM_GSETS2; ++g) { 1226 screen->gsets[g] = source[g]; 1227 } 1228} 1229 1230void 1231resetCharsets(TScreen *screen) 1232{ 1233 int dft_upss = ((screen->ansi_level >= 2) 1234 ? PreferredUPSS(screen) 1235 : nrc_ASCII); 1236 1237#if OPT_WIDE_CHARS 1238 /* 1239 * User-preferred selection set makes a choice between ISO-8859-1 and 1240 * a precursor to it. Those are both single-byte encodings. Because the 1241 * multibyte UTF-8 equates to ISO-8859-1, the default (DEC Supplemental) 1242 * cannot be used as a default in UTF-8 mode. But we cannot use ISO-8859-1 1243 * either, because that would break the special case in decodeUtf8() that 1244 * checks if NRCS is being used, passing 8-bit characters as is. 1245 * 1246 * In short, UPSS is not available with UTF-8, but DECRQUPSS will say that 1247 * ISO-Latin1 is selected. 1248 */ 1249 if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) { 1250 dft_upss = nrc_ASCII; 1251 } 1252#endif 1253 1254 TRACE(("resetCharsets: UPSS=%s\n", visibleScsCode(dft_upss))); 1255 1256 /* 1257 * The assignments for G2/G3 to ASCII differ from the documented DEC 1258 * terminal, because xterm also checks GR to decide whether or not to 1259 * handle non-Unicode character sets, e.g., NRCS. 1260 */ 1261 initCharset(screen, 0, nrc_ASCII); 1262 initCharset(screen, 1, nrc_ASCII); 1263 initCharset(screen, 2, dft_upss); 1264 initCharset(screen, 3, dft_upss); 1265 initCharset(screen, 4, dft_upss); /* gsets_upss */ 1266 1267 screen->curgl = 0; /* G0 => GL. */ 1268 screen->curgr = 2; /* G2 => GR. */ 1269 screen->curss = 0; /* No single shift. */ 1270 1271#if OPT_VT52_MODE 1272 if (screen->vtXX_level == 0) 1273 initCharset(screen, 1, nrc_DEC_Spec_Graphic); /* Graphics */ 1274#endif 1275} 1276 1277static void 1278modified_DECNRCM(XtermWidget xw) 1279{ 1280#if OPT_WIDE_CHARS 1281 TScreen *screen = TScreenOf(xw); 1282 if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) { 1283 int enabled = ((xw->flags & NATIONAL) != 0); 1284 int modefix; 1285 EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix); 1286 switchPtyData(screen, !enabled); 1287 TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF")); 1288 } 1289#else 1290 (void) xw; 1291#endif 1292} 1293 1294/* 1295 * VT300 and up support three ANSI conformance levels, defined according to 1296 * ECMA-43 (originally dpANSI X3.134.1). 1297 * 1298 * VSRM - Documented Exceptions EL-00070-D 1299 */ 1300static void 1301set_ansi_conformance(TScreen *screen, int level) 1302{ 1303 TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n", 1304 level, 1305 screen->vtXX_level * 100, 1306 screen->terminal_id, 1307 screen->ansi_level)); 1308 if (screen->vtXX_level >= 3) { 1309 screen->ansi_level = level; 1310 } 1311} 1312 1313static void 1314set_vtXX_level(TScreen *screen, int level) 1315{ 1316 screen->vtXX_level = level; 1317 screen->ansi_level = (level > 1) ? 3 : 1; 1318} 1319 1320/* 1321 * Set scrolling margins. VTxxx terminals require that the top/bottom are 1322 * different, so we have at least two lines in the scrolling region. 1323 */ 1324static void 1325set_tb_margins(TScreen *screen, int top, int bottom) 1326{ 1327 TRACE(("set_tb_margins %d..%d, prior %d..%d\n", 1328 top, bottom, 1329 screen->top_marg, 1330 screen->bot_marg)); 1331 if (bottom > top) { 1332 screen->top_marg = top; 1333 screen->bot_marg = bottom; 1334 } 1335 if (screen->top_marg > screen->max_row) 1336 screen->top_marg = screen->max_row; 1337 if (screen->bot_marg > screen->max_row) 1338 screen->bot_marg = screen->max_row; 1339} 1340 1341static void 1342set_lr_margins(TScreen *screen, int left, int right) 1343{ 1344 TRACE(("set_lr_margins %d..%d, prior %d..%d\n", 1345 left, right, 1346 screen->lft_marg, 1347 screen->rgt_marg)); 1348 if (right > left) { 1349 screen->lft_marg = left; 1350 screen->rgt_marg = right; 1351 } 1352 if (screen->lft_marg > screen->max_col) 1353 screen->lft_marg = screen->max_col; 1354 if (screen->rgt_marg > screen->max_col) 1355 screen->rgt_marg = screen->max_col; 1356} 1357 1358#define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row) 1359#define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col) 1360 1361void 1362resetMargins(XtermWidget xw) 1363{ 1364 TScreen *screen = TScreenOf(xw); 1365 1366 reset_tb_margins(screen); 1367 reset_lr_margins(screen); 1368} 1369 1370static void 1371resetMarginMode(XtermWidget xw) 1372{ 1373 UIntClr(xw->flags, LEFT_RIGHT); 1374 resetMargins(xw); 1375} 1376 1377static void 1378resetRendition(XtermWidget xw) 1379{ 1380 TScreen *screen = TScreenOf(xw); 1381 (void) screen; 1382 ResetItalics(xw); 1383 UIntClr(xw->flags, 1384 (SGR_MASK | SGR_MASK2 | INVISIBLE)); 1385} 1386 1387void 1388set_max_col(TScreen *screen, int cols) 1389{ 1390 TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col)); 1391 if (cols < 0) 1392 cols = 0; 1393 screen->max_col = cols; 1394} 1395 1396void 1397set_max_row(TScreen *screen, int rows) 1398{ 1399 TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row)); 1400 if (rows < 0) 1401 rows = 0; 1402 screen->max_row = rows; 1403} 1404 1405#if OPT_TRACE 1406#define DATA(name) { name, #name } 1407static const struct { 1408 const PARSE_T *table; 1409 const char *name; 1410} all_tables[] = { 1411 1412 DATA(ansi_table) 1413 ,DATA(cigtable) 1414 ,DATA(csi2_table) 1415 ,DATA(csi_ex_table) 1416 ,DATA(csi_amp_table) 1417 ,DATA(csi_quo_table) 1418 ,DATA(csi_table) 1419 ,DATA(dec2_table) 1420 ,DATA(dec3_table) 1421 ,DATA(dec_table) 1422 ,DATA(eigtable) 1423 ,DATA(esc_sp_table) 1424 ,DATA(esc_table) 1425 ,DATA(scrtable) 1426 ,DATA(scs96table) 1427 ,DATA(scstable) 1428 ,DATA(sos_table) 1429#if OPT_BLINK_CURS 1430 ,DATA(csi_sp_table) 1431#endif 1432#if OPT_DEC_LOCATOR 1433 ,DATA(csi_tick_table) 1434#endif 1435#if OPT_DEC_RECTOPS 1436 ,DATA(csi_dollar_table) 1437 ,DATA(csi_star_table) 1438 ,DATA(csi_dec_dollar_table) 1439#endif 1440#if OPT_VT52_MODE 1441 ,DATA(vt52_table) 1442 ,DATA(vt52_esc_table) 1443 ,DATA(vt52_ignore_table) 1444#endif 1445#if OPT_VT525_COLORS 1446 ,DATA(csi_comma_table) 1447#endif 1448#if OPT_WIDE_CHARS 1449 ,DATA(esc_pct_table) 1450 ,DATA(scs_amp_table) 1451 ,DATA(scs_pct_table) 1452 ,DATA(scs_2qt_table) 1453#endif 1454#if OPT_XTERM_SGR 1455 ,DATA(csi_hash_table) 1456#endif 1457#undef DATA 1458}; 1459 1460#define WHICH_TABLE(name) if (table == name) result = #name 1461static const char * 1462which_table(const PARSE_T * table) 1463{ 1464 const char *result = "?"; 1465 Cardinal n; 1466 for (n = 0; n < XtNumber(all_tables); ++n) { 1467 if (table == all_tables[n].table) { 1468 result = all_tables[n].name; 1469 break; 1470 } 1471 } 1472 1473 return result; 1474} 1475 1476static void 1477check_tables(void) 1478{ 1479 Cardinal n; 1480 int ch; 1481 int total_codes = 0; 1482 int total_ground = 0; 1483 int total_ignored = 0; 1484 1485 TRACE(("** check_tables\n")); 1486 for (n = 0; n < XtNumber(all_tables); ++n) { 1487 const PARSE_T *table = all_tables[n].table; 1488 TRACE(("*** %s\n", all_tables[n].name)); 1489 /* 1490 * Most of the tables should use the same codes in 0..31, 128..159 1491 * as the "ansi" table. 1492 */ 1493 if (strncmp(all_tables[n].name, "ansi", 4) && 1494 strncmp(all_tables[n].name, "sos_", 4) && 1495 strncmp(all_tables[n].name, "vt52", 4)) { 1496 for (ch = 0; ch < 32; ++ch) { 1497 int c1 = ch + 128; 1498 PARSE_T st_l = table[ch]; 1499 PARSE_T st_r = table[c1]; 1500 if (st_l != ansi_table[ch]) { 1501 TRACE((" %3d: %d vs %d\n", ch, st_l, ansi_table[ch])); 1502 } 1503 if (st_r != ansi_table[c1]) { 1504 TRACE((" %3d: %d vs %d\n", c1, st_r, ansi_table[c1])); 1505 } 1506 } 1507 } 1508 /* 1509 * All of the tables should have their GL/GR parts encoded the same. 1510 * 1511 * Originally reported by Paul Williams (patch #171), this is a 1512 * standard feature of DEC's terminals, documented in DEC 070 section 1513 * 3.5.4.5 "GR Graphic Characters Within Control Strings". 1514 */ 1515 for (ch = 32; ch < 127; ++ch) { 1516 PARSE_T st_l = table[ch]; 1517 PARSE_T st_r = table[ch + 128]; 1518 if (st_l != st_r) { 1519 if (st_r == CASE_IGNORE && 1520 !strncmp(all_tables[n].name, "vt52", 4)) { 1521 ; 1522 } else { 1523 TRACE((" %3d: %d vs %d\n", ch, st_l, st_r)); 1524 } 1525 } 1526 } 1527 /* 1528 * Just for amusement, show how sparse the encoding tables are. 1529 */ 1530 for (ch = 0; ch < 256; ++ch) { 1531 ++total_codes; 1532 switch (table[ch]) { 1533 case CASE_GROUND_STATE: 1534 total_ground++; 1535 break; 1536 case CASE_ESC_IGNORE: 1537 /* FALLTHRU */ 1538 case CASE_IGNORE: 1539 /* FALLTHRU */ 1540 case CASE_VT52_IGNORE: 1541 total_ignored++; 1542 break; 1543 } 1544 } 1545 } 1546 TRACE(("VTPrsTbl:\n")); 1547 TRACE(("%d total codes\n", total_codes)); 1548 TRACE(("%d total ignored\n", total_ignored)); 1549 TRACE(("%d total reset/ground\n", total_ground)); 1550} 1551 1552static void 1553check_bitmasks(void) 1554{ 1555#define dMSK 0x100 1556#define DATA(mode,name) { mode, name, #name } 1557#define DMSK(what) (dMSK | (what)) 1558#define DGRP(offs) (1 << ((offs) - 1)) 1559 static struct { 1560 int mode; 1561 int code; 1562 const char *name; 1563 } table[] = { 1564 DATA(DGRP(1), INVERSE), 1565 DATA(DGRP(1), UNDERLINE), 1566 DATA(DGRP(1), BOLD), 1567 DATA(DGRP(1), BLINK), 1568 DATA(DMSK(DGRP(1)), SGR_MASK), 1569 DATA(DGRP(2), BG_COLOR), 1570 DATA(DGRP(2), FG_COLOR), 1571 DATA(DGRP(2), PROTECTED), 1572 DATA(DGRP(4), CHARDRAWN), 1573 DATA(DGRP(2), INVISIBLE), 1574#if OPT_WIDE_ATTRS 1575 DATA(DGRP(2), ATR_FAINT), 1576 DATA(DGRP(2), ATR_ITALIC), 1577 DATA(DGRP(2), ATR_STRIKEOUT), 1578 DATA(DGRP(2), ATR_DBL_UNDER), 1579 DATA(DGRP(2), ATR_DIRECT_FG), 1580 DATA(DGRP(2), ATR_DIRECT_BG), 1581#endif 1582 DATA(DMSK(DGRP(2)), SGR_MASK2), 1583 DATA(DMSK(DGRP(3)), ATTRIBUTES), 1584 DATA(DGRP(3), REVERSE_VIDEO), 1585 DATA(DGRP(3), WRAPAROUND), 1586 DATA(DGRP(3), REVERSEWRAP), 1587 DATA(DGRP(3), REVERSEWRAP2), 1588 DATA(DGRP(3), LINEFEED), 1589 DATA(DGRP(3), ORIGIN), 1590 DATA(DGRP(3), INSERT), 1591 DATA(DGRP(3), SMOOTHSCROLL), 1592 DATA(DGRP(3), IN132COLUMNS), 1593 DATA(DGRP(5), NATIONAL), 1594 DATA(DGRP(5), LEFT_RIGHT), 1595 DATA(DGRP(5), NOCLEAR_COLM), 1596 DATA(DGRP(4), NOBACKGROUND), 1597 DATA(DGRP(4), NOTRANSLATION), 1598 DATA(DGRP(4), DOUBLEWFONT), 1599 DATA(DGRP(4), DOUBLEHFONT), 1600 DATA(DGRP(4), CHARBYCHAR), 1601 DATA(DGRP(4), NORESOLUTION), 1602 DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK), 1603 DATA(-1, EOF) 1604 }; 1605#undef DATA 1606 int j, k; 1607 TRACE(("** check_bitmasks:\n")); 1608 for (j = 0; table[j].mode >= 0; ++j) { 1609 TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name)); 1610 if (table[j].mode & dMSK) { 1611 int mask = dMSK; 1612 for (k = 0; table[k].mode >= 0; ++k) { 1613 if (j == k) 1614 continue; 1615 if (table[k].mode & dMSK) 1616 continue; 1617 if ((table[j].mode & table[k].mode) != 0) 1618 mask |= table[k].mode; 1619 } 1620 if (mask != table[j].mode) { 1621 TRACE(("...expected %08X\n", mask)); 1622 } 1623 } else { 1624 for (k = 0; table[k].mode >= 0; ++k) { 1625 if (j == k) 1626 continue; 1627 if (table[k].mode & dMSK) 1628 continue; 1629 if ((table[j].code & table[k].code) != 0) { 1630 TRACE(("...same bits %s\n", table[k].name)); 1631 } 1632 } 1633 } 1634 } 1635} 1636#endif 1637 1638static int 1639init_params(void) 1640{ 1641 while (parms.count-- > 0) { 1642 parms.is_sub[parms.count] = 0; 1643 parms.params[parms.count] = 0; 1644 } 1645 parms.count = 0; 1646 parms.has_subparams = 0; 1647 return 0; 1648} 1649 1650#if OPT_TRACE > 0 1651static void 1652dump_params(void) 1653{ 1654 int n; 1655 int arg; 1656 TRACE(("params %d (%d)\n", nparam, parms.has_subparams)); 1657 for (arg = 1, n = 0; n < nparam; ++n) { 1658 TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n])); 1659 if (!parms.is_sub[n]) 1660 ++arg; 1661 } 1662} 1663#define DumpParams() dump_params() 1664#else 1665#define DumpParams() /* nothing */ 1666#endif 1667 1668 /* allocate larger buffer if needed/possible */ 1669#define SafeAlloc(type, area, used, size) \ 1670 type *new_string = area; \ 1671 size_t new_length = size; \ 1672 if (new_length == 0) { \ 1673 new_length = 1024; \ 1674 new_string = TypeMallocN(type, new_length); \ 1675 } else if (used+1 >= new_length) { \ 1676 new_length = size * 2; \ 1677 new_string = TypeMallocN(type, new_length); \ 1678 if (new_string != NULL \ 1679 && area != NULL \ 1680 && used != 0) { \ 1681 memcpy(new_string, area, used * sizeof(type)); \ 1682 } \ 1683 } 1684#define SafeFree(area, size) \ 1685 if (area != new_string) { \ 1686 free(area); \ 1687 area = new_string; \ 1688 } \ 1689 size = new_length 1690 1691#define WriteNow() { \ 1692 unsigned single = 0; \ 1693 \ 1694 if (screen->curss) { \ 1695 if (sp->print_area != NULL) { \ 1696 dotext(xw, \ 1697 screen->gsets[(int) (screen->curss)], \ 1698 sp->print_area, \ 1699 (Cardinal) 1); \ 1700 single++; \ 1701 } \ 1702 screen->curss = 0; \ 1703 } \ 1704 if (sp->print_used > single) { \ 1705 if (sp->print_area != NULL) { \ 1706 dotext(xw, \ 1707 screen->gsets[(int) (screen->curgl)], \ 1708 sp->print_area + single, \ 1709 (Cardinal) (sp->print_used - single)); \ 1710 } \ 1711 } \ 1712 sp->print_used = 0; \ 1713 } \ 1714 1715typedef enum { 1716 sa_INIT 1717 ,sa_LAST 1718 ,sa_REGIS 1719 ,sa_SIXEL 1720} StringArgs; 1721 1722struct ParseState { 1723 unsigned check_recur; 1724#if OPT_VT52_MODE 1725 Bool vt52_cup; 1726#endif 1727 const PARSE_T *groundtable; 1728 const PARSE_T *parsestate; 1729 int scstype; 1730 int scssize; 1731 Bool private_function; /* distinguish private-mode from standard */ 1732 int string_mode; /* nonzero iff we're processing a string */ 1733 StringArgs string_args; /* parse-state within string processing */ 1734 Bool string_skip; /* true if we will ignore the string */ 1735 int lastchar; /* positive iff we had a graphic character */ 1736 int nextstate; 1737#if OPT_WIDE_CHARS 1738 int last_was_wide; 1739#endif 1740 /* Buffer for processing printable text */ 1741 IChar *print_area; 1742 size_t print_size; 1743 size_t print_used; 1744 /* Buffer for processing strings (e.g., OSC ... ST) */ 1745 Char *string_area; 1746 size_t string_size; 1747 size_t string_used; 1748 /* Buffer for deferring input */ 1749 Char *defer_area; 1750 size_t defer_size; 1751 size_t defer_used; 1752}; 1753 1754static struct ParseState myState; 1755 1756static void 1757init_groundtable(TScreen *screen, struct ParseState *sp) 1758{ 1759 (void) screen; 1760 1761#if OPT_VT52_MODE 1762 if (!(screen->vtXX_level)) { 1763 sp->groundtable = vt52_table; 1764 } else if (screen->terminal_id >= 100) 1765#endif 1766 { 1767 sp->groundtable = ansi_table; 1768 } 1769} 1770 1771static void 1772select_charset(struct ParseState *sp, int type, int size) 1773{ 1774 TRACE(("select_charset G%d size %d -> G%d size %d\n", 1775 sp->scstype, sp->scssize, 1776 type, size)); 1777 1778 sp->scstype = type; 1779 sp->scssize = size; 1780 if (size == 94) { 1781 sp->parsestate = scstable; 1782 } else { 1783 sp->parsestate = scs96table; 1784 } 1785} 1786/* *INDENT-OFF* */ 1787static const struct { 1788 DECNRCM_codes result; 1789 int prefix; 1790 int suffix; 1791 int min_level; 1792 int max_level; 1793 int need_nrc; 1794 int sized_96; 1795} scs_table[] = { 1796 { nrc_ASCII, 0, 'B', 1, 9, 0, 0 }, 1797 { nrc_British, 0, 'A', 1, 9, 0, 0 }, 1798 { nrc_DEC_Spec_Graphic, 0, '0', 1, 9, 0, 0 }, 1799 { nrc_DEC_Alt_Chars, 0, '1', 1, 1, 0, 0 }, 1800 { nrc_DEC_Alt_Graphics, 0, '2', 1, 1, 0, 0 }, 1801 /* VT2xx */ 1802 { nrc_DEC_Supp, 0, '<', 2, 2, 0, 0 }, 1803 { nrc_Dutch, 0, '4', 2, 9, 1, 0 }, 1804 { nrc_Finnish, 0, '5', 2, 9, 1, 0 }, 1805 { nrc_Finnish2, 0, 'C', 2, 9, 1, 0 }, 1806 { nrc_French, 0, 'R', 2, 9, 1, 0 }, 1807 { nrc_French2, 0, 'f', 2, 9, 1, 0 }, 1808 { nrc_French_Canadian, 0, 'Q', 2, 9, 1, 0 }, 1809 { nrc_German, 0, 'K', 2, 9, 1, 0 }, 1810 { nrc_Italian, 0, 'Y', 2, 9, 1, 0 }, 1811 { nrc_Norwegian_Danish2, 0, 'E', 2, 9, 1, 0 }, 1812 { nrc_Norwegian_Danish3, 0, '6', 2, 9, 1, 0 }, 1813 { nrc_Spanish, 0, 'Z', 2, 9, 1, 0 }, 1814 { nrc_Swedish, 0, '7', 2, 9, 1, 0 }, 1815 { nrc_Swedish2, 0, 'H', 2, 9, 1, 0 }, 1816 { nrc_Swiss, 0, '=', 2, 9, 1, 0 }, 1817 /* VT3xx */ 1818 { nrc_DEC_UPSS, 0, '<', 3, 9, 0, 1 }, 1819 { nrc_British_Latin_1, 0, 'A', 3, 9, 1, 0 }, 1820 { nrc_DEC_Supp_Graphic, '%', '5', 3, 9, 0, 0 }, 1821 { nrc_DEC_Technical, 0, '>', 3, 9, 0, 0 }, 1822 { nrc_French_Canadian2, 0, '9', 3, 9, 1, 0 }, 1823 { nrc_Norwegian_Danish, 0, '`', 3, 9, 1, 0 }, 1824 { nrc_Portugese, '%', '6', 3, 9, 1, 0 }, 1825 { nrc_ISO_Latin_1_Supp, 0, 'A', 3, 9, 0, 1 }, 1826 { nrc_JIS_Katakana, 0, 'I', 3, 3, 0, 0 }, 1827 { nrc_JIS_Roman, 0, 'J', 3, 3, 0, 0 }, 1828 /* VT5xx */ 1829 { nrc_Greek, '"', '>', 5, 9, 1, 0 }, 1830 { nrc_Hebrew, '%', '=', 5, 9, 1, 0 }, 1831 { nrc_Russian, '&', '5', 5, 9, 1, 0 }, 1832 { nrc_SCS_NRCS, '%', '3', 5, 9, 1, 0 }, 1833 { nrc_Turkish, '%', '2', 5, 9, 1, 0 }, 1834 { nrc_DEC_Cyrillic, '&', '4', 5, 9, 0, 0 }, 1835 { nrc_DEC_Greek_Supp, '"', '?', 5, 9, 0, 0 }, 1836 { nrc_DEC_Hebrew_Supp, '"', '4', 5, 9, 0, 0 }, 1837 { nrc_DEC_Turkish_Supp, '%', '0', 5, 9, 0, 0 }, 1838 { nrc_ISO_Greek_Supp, 0, 'F', 5, 9, 0, 1 }, 1839 { nrc_ISO_Hebrew_Supp, 0, 'H', 5, 9, 0, 1 }, 1840 { nrc_ISO_Latin_2_Supp, 0, 'B', 5, 9, 0, 1 }, 1841 { nrc_ISO_Latin_5_Supp, 0, 'M', 5, 9, 0, 1 }, 1842 { nrc_ISO_Latin_Cyrillic,0, 'L', 5, 9, 0, 1 }, 1843}; 1844/* *INDENT-ON* */ 1845 1846#if OPT_DEC_RECTOPS 1847static char * 1848encode_scs(DECNRCM_codes value, int *psize) 1849{ 1850 static char buffer[3]; 1851 Cardinal n; 1852 char *result = buffer; 1853 1854 for (n = 0; n < XtNumber(scs_table); ++n) { 1855 if (scs_table[n].result == value) { 1856 if (scs_table[n].prefix) 1857 *result++ = (char) scs_table[n].prefix; 1858 if (scs_table[n].suffix) 1859 *result++ = (char) scs_table[n].suffix; 1860 *psize = scs_table[n].sized_96; 1861 break; 1862 } 1863 } 1864 *result = '\0'; 1865 return buffer; 1866} 1867 1868static int 1869is_96charset(DECNRCM_codes value) 1870{ 1871 Cardinal n; 1872 int result = 0; 1873 1874 for (n = 0; n < XtNumber(scs_table); ++n) { 1875 if (scs_table[n].result == value) { 1876 result = scs_table[n].sized_96 ? 1 : 0; 1877 break; 1878 } 1879 } 1880 return result; 1881} 1882#endif 1883 1884void 1885xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix) 1886{ 1887 TScreen *screen = TScreenOf(xw); 1888 Cardinal n; 1889 DECNRCM_codes result = nrc_Unknown; 1890 1891 prefix = AsciiOf(prefix); 1892 suffix = AsciiOf(suffix); 1893 for (n = 0; n < XtNumber(scs_table); ++n) { 1894 if (prefix == scs_table[n].prefix 1895 && suffix == scs_table[n].suffix 1896 && sgroup <= scs_table[n].min_level 1897 && screen->vtXX_level >= scs_table[n].min_level 1898 && screen->vtXX_level <= scs_table[n].max_level 1899 && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) { 1900 result = scs_table[n].result; 1901 break; 1902 } 1903 } 1904 if (result != nrc_Unknown) { 1905 initCharset(screen, which, result); 1906 TRACE(("setting G%d to table #%d %s", 1907 which, n, visibleScsCode((int) result))); 1908 } else { 1909 TRACE(("...unknown GSET")); 1910 initCharset(screen, which, nrc_ASCII); 1911 } 1912#if OPT_TRACE 1913 TRACE((" (")); 1914 if (prefix) 1915 TRACE(("prefix='%c', ", prefix)); 1916 TRACE(("suffix='%c', sgroup=%d", suffix, sgroup)); 1917 TRACE((")\n")); 1918#endif 1919} 1920 1921/* 1922 * Given a parameter number, and subparameter (starting in each case from zero) 1923 * return the corresponding index into the parameter array. If the combination 1924 * is not found, return -1. 1925 */ 1926static int 1927subparam_index(int p, int s) 1928{ 1929 int result = -1; 1930 int j, p2, s2; 1931 1932 for (j = p2 = 0; j < nparam; ++j, ++p2) { 1933 if (parms.is_sub[j]) { 1934 s2 = 0; 1935 1936 do { 1937 if ((p == p2) && (s == s2)) { 1938 result = j; 1939 break; 1940 } 1941 ++s2; 1942 } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])); 1943 1944 if (result >= 0) 1945 break; 1946 1947 --j; /* undo the last "while" */ 1948 } else if (p == p2) { 1949 if (s == 0) { 1950 result = j; 1951 } 1952 break; 1953 } 1954 } 1955 TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result)); 1956 return result; 1957} 1958 1959/* 1960 * Given an index into the parameter array, return the corresponding parameter 1961 * number (starting from zero). 1962 */ 1963static int 1964param_number(int item) 1965{ 1966 int result = -1; 1967 int j, p; 1968 1969 for (j = p = 0; j < nparam; ++j, ++p) { 1970 if (j >= item) { 1971 result = p; 1972 break; 1973 } 1974 if (parms.is_sub[j]) { 1975 while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) { 1976 /* EMPTY */ 1977 } 1978 --j; 1979 } 1980 } 1981 1982 TRACE2(("...param_number(%d) = %d\n", item, result)); 1983 return result; 1984} 1985 1986/* 1987 * Check if the given index in the parameter array has subparameters. 1988 * If so, return the number of subparameters to use as a loop limit, etc. 1989 */ 1990static int 1991param_has_subparams(int item) 1992{ 1993 int result = 0; 1994 if (parms.has_subparams) { 1995 int p = param_number(item); 1996 int n = subparam_index(p, 0); 1997 if (n >= 0 && parms.is_sub[n]) { 1998 while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) { 1999 result++; 2000 } 2001 } 2002 } 2003 TRACE(("...param_has_subparams(%d) ->%d\n", item, result)); 2004 return result; 2005} 2006 2007#if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS 2008 2009static int 2010get_subparam(int p, int s) 2011{ 2012 int item = subparam_index(p, s); 2013 int result = (item >= 0) ? parms.params[item] : DEFAULT; 2014 TRACE(("...get_subparam[%d] = %d\n", item, result)); 2015 return result; 2016} 2017 2018/* 2019 * Some background - 2020 * 2021 * Todd Larason provided the initial changes to support 256-colors in July 1999. 2022 * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and 2023 * was unsure if there would be some standard using those codes. His response 2024 * was that this was documented (it turns out, in equally vague terms) in ITU 2025 * T.416 2026 * 2027 * Discussing this with Todd Larason in mid-1999, my point was that given the 2028 * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going 2029 * to be effective (more than $100 then, more than $200 in 2012) 2030 * 2031 * We overlooked the detail about ":" as a subparameter delimiter (documented 2032 * in 5.4.2 in ECMA-48). Some discussion in KDE in mid-2006 led Lars Doelle 2033 * to discuss the issue with me. Lars' initial concern dealt with the fact 2034 * that a sequence such as 2035 * CSI 38 ; 5 ; 1 m 2036 * violated the principle that SGR parameters could be used in any order. 2037 * Further discussion (see KDE #107487) resolved that the standard expected 2038 * that the sequence would look like 2039 * CSI 38 ; 5 : 1 m 2040 * which still violates that principle, since the "5:1" parameter has to 2041 * follow the "38" to be useful. 2042 * 2043 * This function accepts either format (per request by Paul Leonerd Evans). 2044 * It also accepts 2045 * CSI 38 : 5 : 1 m 2046 * according to Lars' original assumption. While implementing that, I added 2047 * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value. 2048 * ISO-8613-6 documents that as "direct color". 2049 * 2050 * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's 2051 * quirk in the description of direct color: it mentions a color space 2052 * identifier parameter which should follow the "2" (as parameter 1). In the 2053 * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as 2054 * well as parameters 7 and 8. Like parameter 1, parameters 7 and 8 are not 2055 * defined clearly in the standard, and a close reading indicates they are 2056 * optional, saying they "may be used". This implementation ignores parameters 2057 * 6 (and above), and provides for the color space identifier by checking the 2058 * number of parameters: 2059 * 3 after "2" (no color space identifier) 2060 * 4 or more after "2" (color space identifier) 2061 * 2062 * By the way - all of the parameters are decimal integers, and missing 2063 * parameters represent a default value. ISO-8613-6 is clear about that. 2064 * 2065 * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter. 2066 * ECMA-48 says only: 2067 * 2068 * 5.4.2 Parameter string format 2069 * 2070 * A parameter string which does not start with a bit combination in the 2071 * range 03/12 to 03/15 shall have the following format: 2072 * 2073 * a) A parameter string consists of one or more parameter 2074 * sub-strings, each of which represents a number in decimal 2075 * notation. 2076 * 2077 * b) Each parameter sub-string consists of one or more bit 2078 * combinations from 03/00 to 03/10; the bit combinations from 2079 * 03/00 to 03/09 represent the digits ZERO to NINE; bit 2080 * combination 03/10 may be used as a separator in a parameter 2081 * sub-string, for example, to separate the fractional part of a 2082 * decimal number from the integer part of that number. 2083 * 2084 * That is, there is no mention in ECMA-48 of the possibility that a parameter 2085 * string might be a list of parameters, as done in ISO-8613-3 (nor does 2086 * ECMA-48 provide an example where the ":" separator might be used). Because 2087 * of this, xterm treats other cases than those needed for ISO-8613-3 as an 2088 * error, and stops interpreting the sequence. 2089 */ 2090#define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0)) 2091static Boolean 2092parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended) 2093{ 2094 Boolean result = False; 2095 int item = *itemp; 2096 int next = item; 2097 int base = param_number(item); 2098 int code = -1; 2099 int values[3]; /* maximum number of subparameters */ 2100 int need = 0; /* number of subparameters needed */ 2101 int have; 2102 int n; 2103 2104 /* 2105 * On entry, 'item' points to the 38/48 code in the parameter array. 2106 * If that has subparameters, we will expect all of the values to 2107 * be subparameters of that item. 2108 */ 2109 if ((have = param_has_subparams(item)) != 0) { 2110 /* accept CSI 38 : 5 : 1 m */ 2111 /* accept CSI 38 : 2 : 1 : 2 : 3 m */ 2112 code = get_subparam(base, 1); 2113 need = extended_colors_limit(code); 2114 next = item + have; 2115 for (n = 0; n < need && n < 3; ++n) { 2116 values[n] = get_subparam(base, 2 + n + (have > 4)); 2117 } 2118 } else if (++item < nparam) { 2119 ++base; 2120 if ((have = param_has_subparams(item)) != 0) { 2121 /* accept CSI 38 ; 5 : 1 m */ 2122 /* accept CSI 38 ; 2 : 1 : 2 : 3 m */ 2123 code = get_subparam(base, 0); 2124 need = extended_colors_limit(code); 2125 next = base + have; 2126 for (n = 0; n < need && n < 3; ++n) { 2127 values[n] = get_subparam(base, 1 + n + (have > 3)); 2128 } 2129 } else { 2130 /* accept CSI 38 ; 5 ; 1 m */ 2131 /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */ 2132 code = GetParam(item); 2133 need = extended_colors_limit(code); 2134 next = item + need; 2135 for (n = 0; n < need && n < 3; ++n) { 2136 values[n] = GetParam(item + 1 + n); 2137 } 2138 } 2139 } 2140 item = next; 2141 2142 *extended = False; 2143 switch (code) { 2144 case 2: 2145 /* direct color in rgb space */ 2146 if ((values[0] >= 0 && values[0] < 256) && 2147 (values[1] >= 0 && values[1] < 256) && 2148 (values[2] >= 0 && values[2] < 256)) { 2149#if OPT_DIRECT_COLOR 2150 if (TScreenOf(xw)->direct_color && xw->has_rgb) { 2151 *colorp = getDirectColor(xw, values[0], values[1], values[2]); 2152 result = True; 2153 *extended = True; 2154 } else 2155#endif 2156 { 2157 *colorp = xtermClosestColor(xw, values[0], values[1], values[2]); 2158 result = okIndexedColor(*colorp); 2159 } 2160 } else { 2161 *colorp = -1; 2162 } 2163 break; 2164 case 5: 2165 /* indexed color */ 2166 *colorp = values[0]; 2167 result = okIndexedColor(*colorp); 2168 break; 2169 default: 2170 *colorp = -1; 2171 break; 2172 } 2173 2174 TRACE(("...resulting color %d/%d %s\n", 2175 *colorp, NUM_ANSI_COLORS, 2176 result ? "OK" : "ERR")); 2177 2178 *itemp = item; 2179 return result; 2180} 2181#endif /* ...extended_colors */ 2182 2183static int 2184optional_param(int which) 2185{ 2186 return (nparam > which) ? GetParam(which) : DEFAULT; 2187} 2188 2189static int 2190only_default(void) 2191{ 2192 return (nparam <= 1) && (GetParam(0) == DEFAULT); 2193} 2194 2195static int 2196use_default_value(int which, int default_value) 2197{ 2198 int result = (nparam > which) ? GetParam(which) : default_value; 2199 if (result <= 0) 2200 result = default_value; 2201 return result; 2202} 2203 2204#define zero_if_default(which) use_default_value(which, 0) 2205 2206#define one_if_default(which) use_default_value(which, 1) 2207 2208#define BeginString(mode) \ 2209 do { \ 2210 sp->string_mode = mode; \ 2211 sp->string_args = sa_LAST; \ 2212 sp->parsestate = sos_table; \ 2213 } while (0) 2214 2215#define BeginString2(mode) \ 2216 do { \ 2217 sp->string_mode = mode; \ 2218 sp->string_args = sa_INIT; \ 2219 sp->parsestate = sos_table; \ 2220 } while (0) 2221 2222static void 2223begin_sixel(XtermWidget xw, struct ParseState *sp) 2224{ 2225 TScreen *screen = TScreenOf(xw); 2226 2227 sp->string_args = sa_LAST; 2228 if (optSixelGraphics(screen)) { 2229#if OPT_SIXEL_GRAPHICS 2230 ANSI params; 2231 const char *cp; 2232 2233 cp = (const char *) sp->string_area; 2234 sp->string_area[sp->string_used] = '\0'; 2235 parse_ansi_params(¶ms, &cp); 2236 parse_sixel_init(xw, ¶ms); 2237 sp->string_args = sa_SIXEL; 2238 sp->string_used = 0; 2239#else 2240 (void) screen; 2241 TRACE(("ignoring sixel graphic (compilation flag not enabled)\n")); 2242#endif 2243 } 2244} 2245 2246/* 2247 * Color palette changes using the OSC controls require a repaint of the 2248 * screen - but not immediately. Do the repaint as soon as we detect a 2249 * state which will not lead to another color palette change. 2250 */ 2251static void 2252repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp) 2253{ 2254 Boolean ignore = False; 2255 2256 switch (sp->nextstate) { 2257 case CASE_ESC: 2258 ignore = ((sp->parsestate == ansi_table) || 2259 (sp->parsestate == sos_table)); 2260#if USE_DOUBLE_BUFFER 2261 if (resource.buffered && TScreenOf(xw)->needSwap) { 2262 ignore = False; 2263 } 2264#endif 2265 break; 2266 case CASE_OSC: 2267 ignore = ((sp->parsestate == ansi_table) || 2268 (sp->parsestate == esc_table)); 2269 break; 2270 case CASE_IGNORE: 2271 ignore = (sp->parsestate == sos_table); 2272 break; 2273 case CASE_ST: 2274 ignore = ((sp->parsestate == esc_table) || 2275 (sp->parsestate == sos_table)); 2276 break; 2277 case CASE_ESC_DIGIT: 2278 ignore = (sp->parsestate == csi_table); 2279 break; 2280 case CASE_ESC_SEMI: 2281 ignore = (sp->parsestate == csi2_table); 2282 break; 2283 } 2284 2285 if (!ignore) { 2286 TRACE(("repaintWhenPaletteChanged\n")); 2287 xw->work.palette_changed = False; 2288 xtermRepaint(xw); 2289 xtermFlushDbe(xw); 2290 } 2291} 2292 2293#if OPT_C1_PRINT || OPT_WIDE_CHARS 2294#define ParseSOS(screen) ((screen)->c1_printable == 0) 2295#else 2296#define ParseSOS(screen) 0 2297#endif 2298 2299#define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable 2300 2301static void 2302illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp) 2303{ 2304 ResetState(sp); 2305 sp->nextstate = sp->parsestate[c]; 2306 Bell(xw, XkbBI_MinorError, 0); 2307} 2308 2309static void 2310init_parser(XtermWidget xw, struct ParseState *sp) 2311{ 2312 TScreen *screen = TScreenOf(xw); 2313 2314 free(sp->defer_area); 2315 free(sp->print_area); 2316 free(sp->string_area); 2317 memset(sp, 0, sizeof(*sp)); 2318 sp->scssize = 94; /* number of printable/nonspace ASCII */ 2319 sp->lastchar = -1; /* not a legal IChar */ 2320 sp->nextstate = -1; /* not a legal state */ 2321 2322 init_groundtable(screen, sp); 2323 ResetState(sp); 2324} 2325 2326static void 2327init_reply(unsigned type) 2328{ 2329 memset(&reply, 0, sizeof(reply)); 2330 reply.a_type = (Char) type; 2331} 2332 2333static void 2334deferparsing(unsigned c, struct ParseState *sp) 2335{ 2336 SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size); 2337 if (new_string == NULL) { 2338 xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n", 2339 (unsigned long) new_length, c); 2340 return; 2341 } 2342 SafeFree(sp->defer_area, sp->defer_size); 2343 sp->defer_area[(sp->defer_used)++] = CharOf(c); 2344} 2345 2346#if OPT_MOD_FKEYS 2347static void 2348set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled) 2349{ 2350#define SET_MOD_FKEYS(field) \ 2351 xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \ 2352 ? xw->keyboard.modify_1st.field \ 2353 : what; \ 2354 TRACE(("set modify_now.%s to %d\n", #field, \ 2355 xw->keyboard.modify_now.field)); 2356 2357 switch (which) { 2358 case 0: 2359 SET_MOD_FKEYS(allow_keys); 2360 break; 2361 case 1: 2362 SET_MOD_FKEYS(cursor_keys); 2363 break; 2364 case 2: 2365 SET_MOD_FKEYS(function_keys); 2366 break; 2367 case 3: 2368 SET_MOD_FKEYS(keypad_keys); 2369 break; 2370 case 4: 2371 SET_MOD_FKEYS(other_keys); 2372 break; 2373 case 5: 2374 SET_MOD_FKEYS(string_keys); 2375 break; 2376 } 2377} 2378 2379static void 2380report_mod_fkeys(XtermWidget xw, int which) /* XTQMODKEYS */ 2381{ 2382#define GET_MOD_FKEYS(field) \ 2383 reply.a_param[1] = (ParmType) xw->keyboard.modify_now.field 2384 2385 init_reply(ANSI_CSI); 2386 reply.a_pintro = '>'; /* replies look like a set-mode */ 2387 reply.a_nparam = 2; 2388 reply.a_final = 'm'; 2389 2390 reply.a_param[1] = DEFAULT; 2391 switch (reply.a_param[0] = (ParmType) which) { 2392 case 0: 2393 GET_MOD_FKEYS(allow_keys); 2394 break; 2395 case 1: 2396 GET_MOD_FKEYS(cursor_keys); 2397 break; 2398 case 2: 2399 GET_MOD_FKEYS(function_keys); 2400 break; 2401 case 3: 2402 GET_MOD_FKEYS(keypad_keys); 2403 break; 2404 case 4: 2405 GET_MOD_FKEYS(other_keys); 2406 break; 2407 case 5: 2408 GET_MOD_FKEYS(string_keys); 2409 break; 2410 } 2411 unparseseq(xw, &reply); 2412} 2413#endif /* OPT_MOD_FKEYS */ 2414 2415#if OPT_STATUS_LINE 2416typedef enum { 2417 SLnone = 0, /* no status-line timer needed */ 2418 SLclock = 1, /* status-line updates once/second */ 2419 SLcoords = 2, /* status-line shows cursor-position */ 2420 SLwritten = 3 /* status-line may need asynchronous repainting */ 2421} SL_MODE; 2422 2423#define SL_BUFSIZ 80 2424 2425#if OPT_TRACE 2426static const char * 2427visibleStatusType(int code) 2428{ 2429 const char *result = "?"; 2430 switch (code) { 2431 case 0: 2432 result = "none"; 2433 break; 2434 case 1: 2435 result = "indicator"; 2436 break; 2437 case 2: 2438 result = "writable"; 2439 break; 2440 } 2441 return result; 2442} 2443 2444static void 2445trace_status_line(XtermWidget xw, int lineno, const char *tag) 2446{ 2447 TScreen *screen = TScreenOf(xw); 2448 2449 TRACE(("@%d, %s (%s, %s)%s%s @ (%d,%d) vs %d\n", 2450 lineno, 2451 tag, 2452 screen->status_active ? "active" : "inactive", 2453 visibleStatusType(screen->status_type), 2454 ((screen->status_type != screen->status_shown) 2455 ? " vs " 2456 : ""), 2457 ((screen->status_type != screen->status_shown) 2458 ? visibleStatusType(screen->status_shown) 2459 : ""), 2460 screen->cur_row, 2461 screen->cur_col, 2462 LastRowNumber(screen))); 2463} 2464 2465#define TRACE_SL(tag) trace_status_line(xw, __LINE__, tag) 2466#else 2467#define TRACE_SL(tag) /* nothing */ 2468#endif 2469 2470static SL_MODE 2471find_SL_MODE(XtermWidget xw) 2472{ 2473 TScreen *screen = TScreenOf(xw); 2474 SL_MODE result = SLnone; 2475 const char *parse; 2476 2477 for (parse = screen->status_fmt; *parse != '\0'; ++parse) { 2478 const char *found = parse; 2479 if (*parse == '%') { 2480 if (*++parse == L_CURL) { 2481 const char *check = strchr(parse, '%'); 2482 size_t length = 0; 2483 2484 if (check != NULL && check[1] == R_CURL) { 2485 length = (size_t) (2 + check - found); 2486 } else { 2487 length = strlen(found); 2488 } 2489 2490 if (!strncmp(found, "%{unixtime%}", length)) { 2491 if (result == SLnone) 2492 result = SLclock; 2493 } else if (!strncmp(found, "%{position%}", length)) { 2494 result = SLcoords; 2495 } 2496 parse = found + length - 1; 2497 } 2498#if defined(HAVE_STRFTIME) 2499 else if (*parse != '\0') { 2500 if (result == SLnone && strchr("cEgOrsSTX+", *parse) != NULL) { 2501 result = SLclock; 2502 } 2503 } 2504#endif 2505 } 2506 } 2507 return result; 2508} 2509 2510static long 2511find_SL_Timeout(XtermWidget xw) 2512{ 2513 long result = 0; 2514 switch (find_SL_MODE(xw)) { 2515 case SLnone: 2516 case SLwritten: 2517 break; 2518 case SLclock: 2519 result = DEF_SL_CLOCK; 2520 break; 2521 case SLcoords: 2522 result = DEF_SL_COORDS; 2523 break; 2524 } 2525 return result; 2526} 2527 2528static void 2529StatusInit(SavedCursor * data) 2530{ 2531 memset(data, 0, sizeof(*data)); 2532 data->sgr_foreground = -1; 2533 data->sgr_background = -1; 2534} 2535 2536#define SL_SAVE(n) \ 2537 do { \ 2538 TRACE(("@%d saving %s to %d,%d\n", __LINE__, \ 2539 (n) ? "status" : "main", \ 2540 screen->cur_row, \ 2541 screen->cur_col)); \ 2542 CursorSave2(xw, &screen->status_data[n]); \ 2543 } while (0) 2544#define SL_RESTORE(n) \ 2545 do { \ 2546 CursorRestore2(xw, &screen->status_data[n]); \ 2547 TRACE(("@%d restored %s to %d,%d\n", __LINE__, \ 2548 (n) ? "status" : "main", \ 2549 screen->status_data[n].row, \ 2550 screen->status_data[n].col)); \ 2551 } while (0) 2552 2553/* save the status-line position, restore main display */ 2554#define SL_SAVE2() \ 2555 do { \ 2556 SL_SAVE(1); \ 2557 SL_RESTORE(0); \ 2558 } while (0) 2559 2560/* save the main-display position, restore status-line */ 2561#define SL_RESTORE2() \ 2562 do { \ 2563 SL_SAVE(0); \ 2564 SL_RESTORE(1); \ 2565 screen->cur_row = FirstRowNumber(screen); \ 2566 } while (0) 2567 2568static void 2569StatusPutChars(XtermWidget xw, const char *value, int length) 2570{ 2571 TScreen *screen = TScreenOf(xw); 2572 2573 if (length < 0) 2574 length = (int) strlen(value); 2575 2576 while (length > 0) { 2577 IChar buffer[SL_BUFSIZ + 1]; 2578 Cardinal n; 2579 for (n = 0; n < SL_BUFSIZ && length > 0 && *value != '\0'; ++n) { 2580 buffer[n] = CharOf(*value++); 2581 if (buffer[n] < 32 || buffer[n] > 126) 2582 buffer[n] = ' '; /* FIXME - provide for UTF-8 */ 2583 --length; 2584 } 2585 buffer[n] = 0; 2586 dotext(xw, 2587 screen->gsets[(int) (screen->curgl)], 2588 buffer, n); 2589 } 2590} 2591 2592static void 2593show_indicator_status(XtPointer closure, XtIntervalId * id GCC_UNUSED) 2594{ 2595 XtermWidget xw = (XtermWidget) closure; 2596 TScreen *screen = TScreenOf(xw); 2597 int right_margin; 2598 2599 time_t now; 2600 const char *parse; 2601 char buffer[SL_BUFSIZ + 1]; 2602 long interval; 2603 2604 if (screen->status_type != 1) { 2605 screen->status_timeout = False; 2606 return; 2607 } 2608 if (screen->status_active && (screen->status_type == screen->status_shown)) { 2609 return; 2610 } 2611 2612 screen->status_active = True; 2613 2614 if (screen->status_shown <= 1) { 2615 SL_SAVE(0); 2616 } 2617 screen->cur_row = FirstRowNumber(screen); 2618 screen->cur_col = 0; 2619 2620 xw->flags |= INVERSE; 2621 xw->flags &= (IFlags) (~WRAPAROUND); 2622 2623 now = time((time_t *) 0); 2624 2625 for (parse = screen->status_fmt; *parse != '\0'; ++parse) { 2626 const char *found = parse; 2627 if (*parse == '%') { 2628 if (*++parse == L_CURL) { 2629 const char *check = strchr(parse, '%'); 2630 size_t length = 0; 2631 2632 if (check != NULL && check[1] == R_CURL) { 2633 length = (size_t) (2 + check - found); 2634 } else { 2635 length = strlen(found); 2636 } 2637 2638 if (!strncmp(found, "%{version%}", length)) { 2639 StatusPutChars(xw, xtermVersion(), -1); 2640 } else if (!strncmp(found, "%{unixtime%}", length)) { 2641 char *t = x_strtrim(ctime(&now)); 2642 if (t != NULL) { 2643 StatusPutChars(xw, t, -1); 2644 free(t); 2645 } 2646 } else if (!strncmp(found, "%{position%}", length)) { 2647 sprintf(buffer, "(%02d,%03d)", 2648 screen->status_data[0].row + 1, 2649 screen->status_data[0].col + 1); 2650 StatusPutChars(xw, buffer, -1); 2651 } else { 2652 StatusPutChars(xw, found, (int) length); 2653 } 2654 parse = found + length - 1; 2655 } 2656#if defined(HAVE_STRFTIME) 2657 else if (*parse != '\0') { 2658 char format[3]; 2659 struct tm *tm = localtime(&now); 2660 2661 format[0] = '%'; 2662 format[1] = *parse; 2663 format[2] = '\0'; 2664 if (strftime(buffer, sizeof(buffer) - 1, format, tm) != 0) { 2665 StatusPutChars(xw, buffer, -1); 2666 } else { 2667 StatusPutChars(xw, "?", 1); 2668 StatusPutChars(xw, parse - 1, 2); 2669 } 2670 } 2671#endif 2672 } else { 2673 StatusPutChars(xw, parse, 1); 2674 } 2675 } 2676 right_margin = ScrnRightMargin(xw); 2677 memset(buffer, ' ', (size_t) SL_BUFSIZ); 2678 while (screen->cur_col < right_margin) { 2679 int chunk = Min(SL_BUFSIZ, (right_margin - screen->cur_col)); 2680 StatusPutChars(xw, buffer, chunk); 2681 } 2682 2683 ScrnRefresh(xw, FirstRowNumber(screen), 0, 1, right_margin, True); 2684 screen->status_active = False; 2685 2686 SL_RESTORE(0); 2687 2688 /* if we processed a position or date/time, repeat */ 2689 interval = find_SL_Timeout(xw); 2690 if (interval > 0) { 2691 (void) XtAppAddTimeOut(app_con, 2692 (unsigned long) interval, 2693 show_indicator_status, xw); 2694 } 2695 screen->status_timeout = True; 2696} 2697 2698static void 2699clear_status_line(XtermWidget xw) 2700{ 2701 TScreen *screen = TScreenOf(xw); 2702 SavedCursor save_me; 2703 SavedCursor clearit; 2704 int save_type = screen->status_type; 2705 2706 TRACE_SL("clear_status_line"); 2707 StatusInit(&clearit); 2708 CursorSave2(xw, &save_me); 2709 CursorRestore2(xw, &clearit); 2710 2711 screen->status_type = 2; 2712 set_cur_row(screen, LastRowNumber(screen)); 2713#if 1 2714 ClearLine(xw); 2715#else 2716 if (getLineData(screen, screen->cur_row) != NULL) { 2717 int n; 2718 char buffer[SL_BUFSIZ + 1]; 2719 CLineData *ld = getLineData(screen, screen->cur_row); 2720 int right_margin = ScrnRightMargin(xw); 2721 2722 TRACE(("...text[%d:%d]:%s\n", 2723 screen->cur_row, 2724 LastRowNumber(screen), 2725 visibleIChars(ld->charData, ld->lineSize))); 2726 2727 memset(buffer, '#', SL_BUFSIZ); 2728 for (n = 0; n < screen->max_col; n += SL_BUFSIZ) { 2729 StatusPutChars(xw, buffer, right_margin - n); 2730 } 2731 } 2732#endif 2733 CursorRestore2(xw, &save_me); 2734 screen->status_type = save_type; 2735 TRACE_SL("clear_status_line (done)"); 2736} 2737 2738static void 2739show_writable_status(XtermWidget xw) 2740{ 2741 TScreen *screen = TScreenOf(xw); 2742 2743 TRACE(("show_writable_status (%d:%d) max=%d\n", 2744 FirstRowNumber(screen), 2745 LastRowNumber(screen), 2746 MaxRows(screen))); 2747 screen->cur_row = FirstRowNumber(screen); 2748} 2749 2750/* 2751 * Depending the status-type, make the window grow or shrink by one row to 2752 * show or hide the status-line. Keep the rest of the window from scrolling 2753 * by overriding the resize-gravity. 2754 */ 2755static void 2756resize_status_line(XtermWidget xw) 2757{ 2758 TScreen *screen = TScreenOf(xw); 2759 XtGravity savedGravity = xw->misc.resizeGravity; 2760 2761 TRACE_SL(screen->status_type 2762 ? "...resize to show status-line" 2763 : "...resize to hide status-line"); 2764 2765 xw->misc.resizeGravity = NorthWestGravity; 2766 2767 RequestResize(xw, MaxRows(screen), MaxCols(screen), True); 2768 2769 xw->misc.resizeGravity = savedGravity; 2770} 2771 2772/* 2773 * DEC STD 070, chapter 14 "VSRM - Status Display Extension" 2774 */ 2775static void 2776update_status_line(XtermWidget xw, int new_active, int new_type) 2777{ 2778 /* *INDENT-EQLS* */ 2779 TScreen *screen = TScreenOf(xw); 2780 int old_active = screen->status_active; 2781 int old_type = screen->status_type; 2782 int old_shown = screen->status_shown; 2783 2784 TRACE_SL("update_status_line"); 2785 2786 if (new_active >= 0 && new_active <= 1) { 2787 screen->status_active = new_active; 2788 if (old_active == new_active) { 2789 goto finish; 2790 } 2791 if (old_type < 2) { 2792 goto finish; 2793 } 2794 if (new_active && !old_active) { 2795 SL_SAVE(0); 2796 } 2797 } else if (new_type >= 0 && new_type <= 2) { 2798 screen->status_type = new_type; 2799 } else { 2800 goto finish; 2801 } 2802 2803 if (screen->status_type == 1) { 2804 int next_shown = screen->status_type; 2805 if (screen->status_type != screen->status_shown) { 2806 if (screen->status_shown == 0) { 2807 resize_status_line(xw); 2808 } else { 2809 clear_status_line(xw); 2810 } 2811 } 2812 show_indicator_status(xw, NULL); 2813 if (screen->status_shown != next_shown) { 2814 screen->status_shown = next_shown; 2815 TRACE_SL("...updating shown"); 2816 } 2817 if (old_shown == 2) { 2818 SL_RESTORE(0); 2819 } 2820 } else if (screen->status_active) { 2821 if (screen->status_type != screen->status_shown) { 2822 Boolean do_resize = False; 2823 2824 if (screen->status_type == 0) { 2825 if (screen->status_shown >= 2) { 2826 SL_SAVE2(); 2827 } 2828 do_resize = True; /* shrink... */ 2829 clear_status_line(xw); 2830 StatusInit(&screen->status_data[1]); 2831 } else if (screen->status_shown == 0) { 2832 if (screen->status_type >= 2) { 2833 SL_RESTORE2(); 2834 } 2835 do_resize = True; /* grow... */ 2836 } else { 2837 clear_status_line(xw); 2838 } 2839 if (do_resize) { 2840 resize_status_line(xw); 2841 } 2842 screen->status_shown = screen->status_type; 2843 TRACE_SL("...updating shown"); 2844 } 2845 show_writable_status(xw); 2846 } else { 2847 if (screen->status_shown) { 2848 if (screen->status_type != 0 && 2849 screen->status_type != screen->status_shown) { 2850 clear_status_line(xw); 2851 } 2852 if (screen->status_shown >= 2) { 2853 SL_SAVE2(); 2854 } 2855 if (screen->status_type == 0) { 2856 screen->status_timeout = False; 2857 clear_status_line(xw); 2858 StatusInit(&screen->status_data[1]); 2859 resize_status_line(xw); /* shrink... */ 2860 } 2861 screen->status_shown = screen->status_type; 2862 TRACE_SL("...updating shown"); 2863 } 2864 } 2865 finish: 2866 TRACE_SL("update_status_line (done)"); 2867 return; 2868} 2869 2870/* 2871 * If the status-type is "2", we can switch the active status display back and 2872 * forth between the main-display and the status-line without clearing the 2873 * status-line (unless the status-line was not shown before). 2874 * 2875 * This has no effect if the status-line displays an indicator (type==1), 2876 * or if no status-line type was selected (type==0). 2877 */ 2878static void 2879handle_DECSASD(XtermWidget xw, int value) 2880{ 2881 TRACE(("CASE_DECSASD - select active status display: %s (currently %s)\n", 2882 BtoS(value), 2883 BtoS(TScreenOf(xw)->status_active))); 2884 2885 update_status_line(xw, value, -1); 2886} 2887 2888/* 2889 * If the status-line is inactive (i.e., only the main-display is used), 2890 * changing the status-type between none/writable has no immediate effect. 2891 * 2892 * But if the status-line is active, setting the status-type reinitializes the 2893 * status-line. 2894 * 2895 * Setting the status-type to indicator overrides the DECSASD active-display 2896 * mode. 2897 */ 2898static void 2899handle_DECSSDT(XtermWidget xw, int value) 2900{ 2901 TRACE(("CASE_DECSSDT - select type of status display: %d (currently %d)\n", 2902 value, 2903 TScreenOf(xw)->status_type)); 2904 2905 update_status_line(xw, -1, value); 2906} 2907 2908#else 2909#define clear_status_line(xw) /* nothing */ 2910#endif /* OPT_STATUS_LINE */ 2911 2912#if OPT_VT52_MODE 2913static void 2914update_vt52_vt100_settings(void) 2915{ 2916 update_autowrap(); 2917 update_reversewrap(); 2918 update_autolinefeed(); 2919 update_appcursor(); 2920 update_appkeypad(); 2921 update_allow132(); 2922} 2923#endif 2924 2925#define TRACE_GSETS(name) TRACE(("CASE_GSETS%s(%d) = '%c'\n", name, sp->scstype, AsciiOf(c))) 2926 2927static Boolean 2928doparsing(XtermWidget xw, unsigned c, struct ParseState *sp) 2929{ 2930 TScreen *screen = TScreenOf(xw); 2931 int item; 2932 int count; 2933 int value; 2934 int laststate; 2935 int thischar = -1; 2936 XTermRect myRect; 2937#if OPT_DEC_RECTOPS 2938 int thispage = 1; 2939#endif 2940 2941 if (sp->check_recur) { 2942 /* Defer parsing when parser is already running as the parser is not 2943 * safe to reenter. 2944 */ 2945 deferparsing(c, sp); 2946 return True; 2947 } 2948 sp->check_recur++; 2949 2950 do { 2951#if OPT_WIDE_CHARS 2952 int this_is_wide = 0; 2953 int is_formatter = 0; 2954 2955 /* 2956 * Handle zero-width combining characters. Make it faster by noting 2957 * that according to the Unicode charts, the majority of Western 2958 * character sets do not use this feature. There are some unassigned 2959 * codes at 0x242, but no zero-width characters until past 0x300. 2960 */ 2961 if (c >= 0x300 2962 && screen->wide_chars 2963 && CharWidth(screen, c) == 0 2964 && !(is_formatter = (CharacterClass((int) c) == CNTRL))) { 2965 int prev, test; 2966 Boolean used = True; 2967 int use_row; 2968 int use_col; 2969 2970 WriteNow(); 2971 use_row = (screen->char_was_written 2972 ? screen->last_written_row 2973 : screen->cur_row); 2974 use_col = (screen->char_was_written 2975 ? screen->last_written_col 2976 : screen->cur_col); 2977 2978 /* 2979 * Check if the latest data can be added to the base character. 2980 * If there is already a combining character stored for the cell, 2981 * we cannot, since that would change the order. 2982 */ 2983 if (screen->normalized_c 2984 && !IsCellCombined(screen, use_row, use_col)) { 2985 prev = (int) XTERM_CELL(use_row, use_col); 2986 test = do_precomposition(prev, (int) c); 2987 TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n", 2988 prev, CharWidth(screen, prev), 2989 (int) c, CharWidth(screen, c), 2990 test, CharWidth(screen, test))); 2991 } else { 2992 prev = -1; 2993 test = -1; 2994 } 2995 2996 /* substitute combined character with precomposed character 2997 * only if it does not change the width of the base character 2998 */ 2999 if (test != -1 3000 && CharWidth(screen, test) == CharWidth(screen, prev)) { 3001 putXtermCell(screen, use_row, use_col, test); 3002 } else if (screen->char_was_written 3003 || getXtermCell(screen, use_row, use_col) >= ' ') { 3004 addXtermCombining(screen, use_row, use_col, c); 3005 } else { 3006 /* 3007 * none of the above... we will add the combining character as 3008 * a base character. 3009 */ 3010 used = False; 3011 } 3012 3013 if (used) { 3014 if (!screen->scroll_amt) 3015 ScrnUpdate(xw, use_row, use_col, 1, 1, 1); 3016 break; 3017 } 3018 } 3019#endif 3020 3021 /* Intercept characters for printer controller mode */ 3022 if (PrinterOf(screen).printer_controlmode == 2) { 3023 if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0) 3024 break; 3025 } 3026 3027 /* 3028 * VT52 is a little ugly in the one place it has a parameterized 3029 * control sequence, since the parameter falls after the character 3030 * that denotes the type of sequence. 3031 */ 3032#if OPT_VT52_MODE 3033 if (sp->vt52_cup) { 3034 int row, col; 3035 if (nparam < NPARAM - 1) { 3036 SetParam(nparam++, (int) AsciiOf(c) - 32); 3037 parms.is_sub[nparam] = 0; 3038 } 3039 if (nparam < 2) 3040 break; 3041 sp->vt52_cup = False; 3042 /* 3043 * According to EK-VT5X-OP-001 DECscope User's Guide, if the row 3044 * is out of range, no vertical movement occurs, while if the 3045 * column is out of range, it is set to the rightmost column. 3046 * 3047 * However, DEC 070 (VSRM - VT52 Emulation EL-00070-0A, page A-28) 3048 * differs from that, updating the column only when the parameter 3049 * is in range, i.e., not mentioning the rightmost column. 3050 */ 3051 if ((row = GetParam(0)) > screen->max_row) 3052 row = screen->cur_row; 3053 if ((col = GetParam(1)) > screen->max_col) 3054 col = ((screen->terminal_id < 100) 3055 ? screen->max_col /* real VT52 */ 3056 : screen->cur_col); /* emulated VT52 */ 3057 CursorSet(screen, row, col, xw->flags); 3058 sp->parsestate = vt52_table; 3059 SetParam(0, 0); 3060 SetParam(1, 0); 3061 break; 3062 } 3063#endif 3064 3065 laststate = sp->nextstate; 3066 if (c == ANSI_DEL 3067 && sp->parsestate == sp->groundtable 3068 && sp->scssize == 96 3069 && sp->scstype != 0) { 3070 /* 3071 * Handle special case of shifts for 96-character sets by checking 3072 * if we have a DEL. The other special case for SPACE will always 3073 * be printable. 3074 */ 3075 sp->nextstate = CASE_PRINT; 3076 } else 3077#if OPT_WIDE_CHARS 3078 if (c > 255) { 3079 /* 3080 * The parsing tables all have 256 entries. If we're supporting 3081 * wide characters, we handle them by treating them the same as 3082 * printing characters. 3083 */ 3084 if (sp->parsestate == sp->groundtable) { 3085 sp->nextstate = is_formatter ? CASE_IGNORE : CASE_PRINT; 3086 } else if (sp->parsestate == sos_table) { 3087 if ((c & WIDEST_ICHAR) > 255) { 3088 TRACE(("Found code > 255 while in SOS state: %04X\n", c)); 3089 c = BAD_ASCII; 3090 } 3091 } else { 3092 sp->nextstate = CASE_GROUND_STATE; 3093 } 3094 } else 3095#endif 3096 sp->nextstate = sp->parsestate[c]; 3097 3098#if OPT_BROKEN_OSC 3099 /* 3100 * Linux console palette escape sequences start with an OSC, but do 3101 * not terminate correctly. Some scripts do not check before writing 3102 * them, making xterm appear to hang (it's awaiting a valid string 3103 * terminator). Just ignore these if we see them - there's no point 3104 * in emulating bad code. 3105 */ 3106 if (screen->brokenLinuxOSC 3107 && sp->parsestate == sos_table) { 3108 if (sp->string_used && sp->string_area) { 3109 switch (sp->string_area[0]) { 3110 case 'P': 3111 if (sp->string_used <= 7) 3112 break; 3113 /* FALLTHRU */ 3114 case 'R': 3115 illegal_parse(xw, c, sp); 3116 TRACE(("Reset to ground state (brokenLinuxOSC)\n")); 3117 break; 3118 } 3119 } 3120 } 3121#endif 3122 3123#if OPT_BROKEN_ST 3124 /* 3125 * Before patch #171, carriage control embedded within an OSC string 3126 * would terminate it. Some (buggy, of course) applications rely on 3127 * this behavior. Accommodate them by allowing one to compile xterm 3128 * and emulate the old behavior. 3129 */ 3130 if (screen->brokenStringTerm 3131 && sp->parsestate == sos_table 3132 && c < 32) { 3133 switch (c) { 3134 case ANSI_EOT: /* FALLTHRU */ 3135 case ANSI_BS: /* FALLTHRU */ 3136 case ANSI_HT: /* FALLTHRU */ 3137 case ANSI_LF: /* FALLTHRU */ 3138 case ANSI_VT: /* FALLTHRU */ 3139 case ANSI_FF: /* FALLTHRU */ 3140 case ANSI_CR: /* FALLTHRU */ 3141 case ANSI_SO: /* FALLTHRU */ 3142 case ANSI_SI: /* FALLTHRU */ 3143 case ANSI_XON: /* FALLTHRU */ 3144 case ANSI_CAN: 3145 illegal_parse(xw, c, sp); 3146 TRACE(("Reset to ground state (brokenStringTerm)\n")); 3147 break; 3148 } 3149 } 3150#endif 3151 3152#if OPT_C1_PRINT 3153 /* 3154 * This is not completely foolproof, but will allow an application 3155 * with values in the C1 range to use them as printable characters, 3156 * provided that they are not intermixed with an escape sequence. 3157 */ 3158#if OPT_WIDE_CHARS 3159 if (!screen->wide_chars) 3160#endif 3161 if (screen->c1_printable 3162 && (c >= 128 && c < 256)) { 3163 sp->nextstate = (sp->parsestate == esc_table 3164 ? CASE_ESC_IGNORE 3165 : sp->parsestate[160]); 3166 TRACE(("allowC1Printable %04X %s ->%s\n", 3167 c, which_table(sp->parsestate), 3168 visibleVTparse(sp->nextstate))); 3169 } 3170#endif 3171 3172#if OPT_WIDE_CHARS 3173 /* 3174 * If we have a C1 code and the c1_printable flag is not set, simply 3175 * ignore it when it was translated from UTF-8, unless the parse-state 3176 * tells us that a C1 would be legal. 3177 */ 3178#if OPT_C1_PRINT 3179 if (!screen->c1_printable) 3180#endif 3181 if (screen->wide_chars 3182 && (c >= 128 && c < 160)) { 3183 if (sp->parsestate != ansi_table) 3184 sp->nextstate = CASE_IGNORE; 3185 } 3186 3187 /* 3188 * If this character is a different width than the last one, put the 3189 * previous text into the buffer and draw it now. 3190 */ 3191 this_is_wide = isWide((int) c); 3192 if (this_is_wide != sp->last_was_wide) { 3193 WriteNow(); 3194 } 3195#endif 3196 3197 /* 3198 * Accumulate string for printable text. This may be 8/16-bit 3199 * characters. 3200 */ 3201 if (sp->nextstate == CASE_PRINT) { 3202 SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size); 3203 if (new_string == NULL) { 3204 xtermWarning("Cannot allocate %lu bytes for printable text\n", 3205 (unsigned long) new_length); 3206 break; 3207 } 3208 SafeFree(sp->print_area, sp->print_size); 3209#if OPT_VT52_MODE 3210 /* 3211 * Strip output text to 7-bits for VT52. We should do this for 3212 * VT100 also (which is a 7-bit device), but xterm has been 3213 * doing this for so long we shouldn't change this behavior. 3214 */ 3215 if (screen->vtXX_level < 1) 3216 c = AsciiOf(c); 3217#endif 3218 sp->print_area[sp->print_used++] = (IChar) c; 3219 sp->lastchar = thischar = (int) c; 3220#if OPT_WIDE_CHARS 3221 sp->last_was_wide = this_is_wide; 3222#endif 3223 if (morePtyData(screen, VTbuffer)) { 3224 break; 3225 } 3226 } 3227 3228 if (sp->nextstate == CASE_PRINT 3229 || (laststate == CASE_PRINT && sp->print_used)) { 3230 WriteNow(); 3231 } 3232 3233 /* 3234 * Accumulate string for DCS, OSC controls 3235 * The string content should always be 8-bit characters. 3236 * 3237 * APC, PM and SOS are ignored; xterm currently does not use those. 3238 */ 3239 if (sp->parsestate == sos_table) { 3240#if OPT_WIDE_CHARS 3241 /* 3242 * We cannot display codes above 255, but let's try to 3243 * accommodate the application a little by not aborting the 3244 * string. 3245 */ 3246 if ((c & WIDEST_ICHAR) > 255) { 3247 sp->nextstate = CASE_PRINT; 3248 c = BAD_ASCII; 3249 } 3250#endif 3251 if (sp->string_mode == ANSI_APC || 3252 sp->string_mode == ANSI_PM || 3253 sp->string_mode == ANSI_SOS) { 3254 /* EMPTY */ 3255 } 3256#if OPT_SIXEL_GRAPHICS 3257 else if (sp->string_args == sa_SIXEL) { 3258 /* avoid adding the string-terminator */ 3259 if (sos_table[CharOf(c)] == CASE_IGNORE) 3260 parse_sixel_char(AsciiOf(c)); 3261 } 3262#endif 3263 else if (sp->string_skip) { 3264 sp->string_used++; 3265 } else if (sp->string_used > screen->strings_max) { 3266 sp->string_skip = True; 3267 sp->string_used++; 3268 FreeAndNull(sp->string_area); 3269 sp->string_size = 0; 3270 } else { 3271 Boolean utf8Title; 3272 3273 SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size); 3274 if (new_string == NULL) { 3275 xtermWarning("Cannot allocate %lu bytes for string mode %#02x\n", 3276 (unsigned long) new_length, sp->string_mode); 3277 break; 3278 } 3279 SafeFree(sp->string_area, sp->string_size); 3280 3281 /* 3282 * Provide for special case where xterm allows an OSC string to 3283 * contain 8-bit data. Otherwise, ECMA-48 section 9 recommends 3284 * parsing controls with a 7-bit table, precluding the use of 3285 * 8-bit data. 3286 */ 3287#if OPT_WIDE_CHARS 3288 utf8Title = (sp->string_mode == ANSI_OSC 3289 && IsSetUtf8Title(xw) 3290 && (sp->string_used >= 2) 3291 && (sp->string_area[0] == '0' 3292 || sp->string_area[0] == '2') 3293 && sp->string_area[1] == ';'); 3294#else 3295 utf8Title = False; 3296#endif 3297 3298 /* 3299 * ReGIS and SIXEL data can be detected by skipping over (only) 3300 * parameters to the first non-parameter character and 3301 * inspecting it. Since both are DCS, we can also ignore OSC. 3302 */ 3303 sp->string_area[(sp->string_used)++] = (utf8Title 3304 ? CharOf(c) 3305 : AsciiOf(c)); 3306 if (sp->string_args < sa_LAST) { 3307 switch (c) { 3308 case ':': 3309 case ';': 3310 case '0': 3311 case '1': 3312 case '2': 3313 case '3': 3314 case '4': 3315 case '5': 3316 case '6': 3317 case '7': 3318 case '8': 3319 case '9': 3320 break; 3321 case 'p': 3322 sp->string_args = sa_REGIS; 3323 break; 3324 case 'q': 3325 begin_sixel(xw, sp); 3326 break; 3327 default: 3328 sp->string_args = sa_LAST; 3329 break; 3330 } 3331 } 3332 } 3333 } else if (sp->parsestate != esc_table) { 3334 /* if we were accumulating, we're not any more */ 3335 sp->string_mode = 0; 3336 sp->string_used = 0; 3337 } 3338 3339 DumpParams(); 3340 TRACE(("parse %04X -> %s %s (used=%lu)\n", 3341 c, visibleVTparse(sp->nextstate), 3342 which_table(sp->parsestate), 3343 (unsigned long) sp->string_used)); 3344 3345 /* 3346 * If the parameter list has subparameters (tokens separated by ":") 3347 * reject any controls that do not accept subparameters. 3348 */ 3349 if (parms.has_subparams) { 3350 switch (sp->nextstate) { 3351 case CASE_GROUND_STATE: 3352 case CASE_CSI_IGNORE: 3353 case CASE_SUB: 3354 /* FALLTHRU */ 3355 3356 case CASE_ESC_DIGIT: 3357 case CASE_ESC_SEMI: 3358 case CASE_ESC_COLON: 3359 /* these states are required to parse parameter lists */ 3360 break; 3361 3362 case CASE_SGR: 3363 TRACE(("...possible subparam usage\n")); 3364 break; 3365 3366 case CASE_CSI_DEC_DOLLAR_STATE: 3367 case CASE_CSI_DOLLAR_STATE: 3368 case CASE_CSI_HASH_STATE: 3369 case CASE_CSI_EX_STATE: 3370 case CASE_CSI_QUOTE_STATE: 3371 case CASE_CSI_SPACE_STATE: 3372 case CASE_CSI_STAR_STATE: 3373 case CASE_CSI_TICK_STATE: 3374 case CASE_DEC2_STATE: 3375 case CASE_DEC3_STATE: 3376 case CASE_DEC_STATE: 3377 /* use this branch when we do not yet have the final character */ 3378 TRACE(("...unexpected subparam usage\n")); 3379 InitParams(); 3380 sp->nextstate = CASE_CSI_IGNORE; 3381 break; 3382 3383 default: 3384 /* use this branch for cases where we have the final character 3385 * in the table that processed the parameter list. 3386 */ 3387 TRACE(("...unexpected subparam usage\n")); 3388 ResetState(sp); 3389 break; 3390 } 3391 } 3392 3393 if (xw->work.palette_changed) { 3394 repaintWhenPaletteChanged(xw, sp); 3395 } 3396#if OPT_STATUS_LINE 3397 /* 3398 * If we are currently writing to the status-line, ignore controls that 3399 * apply only to the full screen, or which use features which we will 3400 * not support in the status-line. 3401 */ 3402 if (IsStatusShown(screen) && (screen)->status_active) { 3403 switch (sp->nextstate) { 3404 case CASE_DECDHL: 3405 case CASE_DECSWL: 3406 case CASE_DECDWL: 3407 case CASE_CUU: 3408 case CASE_CUD: 3409 case CASE_VPA: 3410 case CASE_VPR: 3411 case CASE_ED: 3412 case CASE_TRACK_MOUSE: 3413 case CASE_DECSTBM: 3414 case CASE_DECALN: 3415 case CASE_GRAPHICS_ATTRIBUTES: 3416 case CASE_SUB: 3417 case CASE_SPA: 3418 case CASE_EPA: 3419 case CASE_SU: 3420 case CASE_IND: 3421 case CASE_CPL: 3422 case CASE_CNL: 3423 case CASE_NEL: 3424 case CASE_RI: 3425#if OPT_DEC_LOCATOR 3426 case CASE_DECEFR: 3427 case CASE_DECELR: 3428 case CASE_DECSLE: 3429 case CASE_DECRQLP: 3430#endif 3431#if OPT_DEC_RECTOPS 3432 case CASE_DECRQCRA: 3433 case CASE_DECCRA: 3434 case CASE_DECERA: 3435 case CASE_DECFRA: 3436 case CASE_DECSERA: 3437 case CASE_DECSACE: 3438 case CASE_DECCARA: 3439 case CASE_DECRARA: 3440#endif 3441 ResetState(sp); 3442 sp->nextstate = -1; /* not a legal state */ 3443 break; 3444 } 3445 } 3446#endif 3447 3448 switch (sp->nextstate) { 3449 case CASE_PRINT: 3450 TRACE(("CASE_PRINT - printable characters\n")); 3451 break; 3452 3453 case CASE_GROUND_STATE: 3454 TRACE(("CASE_GROUND_STATE - exit ignore mode\n")); 3455 ResetState(sp); 3456 break; 3457 3458 case CASE_IGNORE: 3459 TRACE(("CASE_IGNORE - Ignore character %02X\n", c)); 3460 break; 3461 3462 case CASE_SUB: 3463 TRACE(("CASE_SUB - substitute/show error\n")); 3464 /* 3465 * ECMA-48 5th edition (June 1991) documents SUB without describing 3466 * its effect. Earlier editions do not mention it. 3467 * 3468 * DEC's VT100 user guide documents SUB as having the same effect 3469 * as CAN (cancel). The VT220 reference adds a visible effect 3470 * (display as a reverse "?"), as well as mentioning that device 3471 * control sequences also are cancelled. DEC 070 comments that a 3472 * "half-tone blotch" is used with VT100, etc. 3473 * 3474 * None of that applies to VT52. 3475 */ 3476 if (screen->terminal_id >= 100) { 3477 IChar effect = ( 3478#if OPT_WIDE_CHARS 3479 (screen->terminal_id > 200) ? 0x2426 : 0x2592 3480#else 3481 2 3482#endif 3483 ); 3484 dotext(xw, 3485 screen->gsets[(int) (screen->curgl)], 3486 &effect, 1); 3487 } 3488 ResetState(sp); 3489 break; 3490 3491 case CASE_ENQ: 3492 TRACE(("CASE_ENQ - answerback\n")); 3493 if (((xw->keyboard.flags & MODE_SRM) == 0) 3494 ? (sp->check_recur == 0) 3495 : (sp->check_recur <= 1)) { 3496 for (count = 0; screen->answer_back[count] != 0; count++) 3497 unparseputc(xw, screen->answer_back[count]); 3498 unparse_end(xw); 3499 } 3500 break; 3501 3502 case CASE_BELL: 3503 TRACE(("CASE_BELL - bell\n")); 3504 if (sp->string_mode == ANSI_OSC) { 3505 if (sp->string_area) { 3506 if (sp->string_used) 3507 sp->string_area[--(sp->string_used)] = '\0'; 3508 if (sp->check_recur <= 1) 3509 do_osc(xw, sp->string_area, sp->string_used, (int) c); 3510 } 3511 ResetState(sp); 3512 } else { 3513 /* bell */ 3514 Bell(xw, XkbBI_TerminalBell, 0); 3515 } 3516 break; 3517 3518 case CASE_BS: 3519 TRACE(("CASE_BS - backspace\n")); 3520 CursorBack(xw, 1); 3521 break; 3522 3523 case CASE_CR: 3524 TRACE(("CASE_CR\n")); 3525 CarriageReturn(xw); 3526 break; 3527 3528 case CASE_ESC: 3529 if_OPT_VT52_MODE(screen, { 3530 sp->parsestate = vt52_esc_table; 3531 break; 3532 }); 3533 sp->parsestate = esc_table; 3534 break; 3535 3536#if OPT_VT52_MODE 3537 case CASE_VT52_CUP: 3538 TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n")); 3539 sp->vt52_cup = True; 3540 ResetState(sp); 3541 break; 3542 3543 case CASE_VT52_IGNORE: 3544 TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n")); 3545 sp->parsestate = vt52_ignore_table; 3546 break; 3547#endif 3548 3549 case CASE_VMOT: 3550 TRACE(("CASE_VMOT\n")); 3551 /* 3552 * form feed, line feed, vertical tab 3553 */ 3554 xtermAutoPrint(xw, c); 3555 xtermIndex(xw, 1); 3556 if (xw->flags & LINEFEED) 3557 CarriageReturn(xw); 3558 else if (screen->jumpscroll && !screen->fastscroll) 3559 do_xevents(xw); 3560 break; 3561 3562 case CASE_CBT: 3563 TRACE(("CASE_CBT\n")); 3564 /* cursor backward tabulation */ 3565 count = one_if_default(0); 3566 while ((count-- > 0) 3567 && (TabToPrevStop(xw))) ; 3568 ResetState(sp); 3569 break; 3570 3571 case CASE_CHT: 3572 TRACE(("CASE_CHT\n")); 3573 /* cursor forward tabulation */ 3574 count = one_if_default(0); 3575 while ((count-- > 0) 3576 && (TabToNextStop(xw))) ; 3577 ResetState(sp); 3578 break; 3579 3580 case CASE_TAB: 3581 /* tab */ 3582 TabToNextStop(xw); 3583 break; 3584 3585 case CASE_SI: 3586 screen->curgl = 0; 3587 if_OPT_VT52_MODE(screen, { 3588 ResetState(sp); 3589 }); 3590 break; 3591 3592 case CASE_SO: 3593 screen->curgl = 1; 3594 if_OPT_VT52_MODE(screen, { 3595 ResetState(sp); 3596 }); 3597 break; 3598 3599 case CASE_DECDHL: 3600 TRACE(("CASE_DECDHL - double-height line: %s\n", 3601 (AsciiOf(c) == '3') ? "top" : "bottom")); 3602 xterm_DECDHL(xw, AsciiOf(c) == '3'); 3603 ResetState(sp); 3604 break; 3605 3606 case CASE_DECSWL: 3607 TRACE(("CASE_DECSWL - single-width line\n")); 3608 xterm_DECSWL(xw); 3609 ResetState(sp); 3610 break; 3611 3612 case CASE_DECDWL: 3613 TRACE(("CASE_DECDWL - double-width line\n")); 3614 xterm_DECDWL(xw); 3615 ResetState(sp); 3616 break; 3617 3618 case CASE_SCR_STATE: 3619 /* enter scr state */ 3620 sp->parsestate = scrtable; 3621 break; 3622 3623 case CASE_SCS0_STATE: 3624 /* enter scs state 0 */ 3625 select_charset(sp, 0, 94); 3626 break; 3627 3628 case CASE_SCS1_STATE: 3629 /* enter scs state 1 */ 3630 select_charset(sp, 1, 94); 3631 break; 3632 3633 case CASE_SCS2_STATE: 3634 /* enter scs state 2 */ 3635 select_charset(sp, 2, 94); 3636 break; 3637 3638 case CASE_SCS3_STATE: 3639 /* enter scs state 3 */ 3640 select_charset(sp, 3, 94); 3641 break; 3642 3643 case CASE_SCS1A_STATE: 3644 /* enter scs state 1 */ 3645 select_charset(sp, 1, 96); 3646 break; 3647 3648 case CASE_SCS2A_STATE: 3649 /* enter scs state 2 */ 3650 select_charset(sp, 2, 96); 3651 break; 3652 3653 case CASE_SCS3A_STATE: 3654 /* enter scs state 3 */ 3655 select_charset(sp, 3, 96); 3656 break; 3657 3658 case CASE_ESC_IGNORE: 3659 /* unknown escape sequence */ 3660 sp->parsestate = eigtable; 3661 break; 3662 3663 case CASE_ESC_DIGIT: 3664 /* digit in csi or dec mode */ 3665 if (nparam > 0) { 3666 value = zero_if_default(nparam - 1); 3667 SetParam(nparam - 1, (10 * value) + (int) (AsciiOf(c) - '0')); 3668 if (GetParam(nparam - 1) > MAX_I_PARAM) 3669 SetParam(nparam - 1, MAX_I_PARAM); 3670 if (sp->parsestate == csi_table) 3671 sp->parsestate = csi2_table; 3672 } 3673 break; 3674 3675 case CASE_ESC_SEMI: 3676 /* semicolon in csi or dec mode */ 3677 if (nparam < NPARAM) { 3678 parms.is_sub[nparam] = 0; 3679 SetParam(nparam++, DEFAULT); 3680 } 3681 if (sp->parsestate == csi_table) 3682 sp->parsestate = csi2_table; 3683 break; 3684 3685 /* 3686 * A _few_ commands accept colon-separated subparameters. 3687 * Mark the parameter list so that we can exclude (most) bogus 3688 * commands with simple/fast checks. 3689 */ 3690 case CASE_ESC_COLON: 3691 if (nparam < NPARAM) { 3692 parms.has_subparams = 1; 3693 if (nparam == 0) { 3694 parms.is_sub[nparam] = 1; 3695 SetParam(nparam++, DEFAULT); 3696 } else if (parms.is_sub[nparam - 1] == 0) { 3697 parms.is_sub[nparam - 1] = 1; 3698 parms.is_sub[nparam] = 2; 3699 parms.params[nparam] = 0; 3700 ++nparam; 3701 } else { 3702 parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1]; 3703 parms.params[nparam] = 0; 3704 ++nparam; 3705 } 3706 } 3707 break; 3708 3709 case CASE_DEC_STATE: 3710 /* enter dec mode */ 3711 sp->parsestate = dec_table; 3712 break; 3713 3714 case CASE_DEC2_STATE: 3715 /* enter dec2 mode */ 3716 sp->parsestate = dec2_table; 3717 break; 3718 3719 case CASE_DEC3_STATE: 3720 /* enter dec3 mode */ 3721 sp->parsestate = dec3_table; 3722 break; 3723 3724 case CASE_ICH: 3725 TRACE(("CASE_ICH - insert char\n")); 3726 InsertChar(xw, (unsigned) one_if_default(0)); 3727 ResetState(sp); 3728 break; 3729 3730 case CASE_CUU: 3731 TRACE(("CASE_CUU - cursor up\n")); 3732 CursorUp(screen, one_if_default(0)); 3733 ResetState(sp); 3734 break; 3735 3736 case CASE_CUD: 3737 TRACE(("CASE_CUD - cursor down\n")); 3738 CursorDown(screen, one_if_default(0)); 3739 ResetState(sp); 3740 break; 3741 3742 case CASE_CUF: 3743 TRACE(("CASE_CUF - cursor forward\n")); 3744 CursorForward(xw, one_if_default(0)); 3745 ResetState(sp); 3746 break; 3747 3748 case CASE_CUB: 3749 TRACE(("CASE_CUB - cursor backward\n")); 3750 CursorBack(xw, one_if_default(0)); 3751 ResetState(sp); 3752 break; 3753 3754 case CASE_CUP: 3755 TRACE(("CASE_CUP - cursor position\n")); 3756 if_OPT_XMC_GLITCH(screen, { 3757 Jump_XMC(xw); 3758 }); 3759 CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags); 3760 ResetState(sp); 3761 break; 3762 3763 case CASE_VPA: 3764 TRACE(("CASE_VPA - vertical position absolute\n")); 3765 CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags); 3766 ResetState(sp); 3767 break; 3768 3769 case CASE_HPA: 3770 TRACE(("CASE_HPA - horizontal position absolute\n")); 3771 CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags); 3772 ResetState(sp); 3773 break; 3774 3775 case CASE_VPR: 3776 TRACE(("CASE_VPR - vertical position relative\n")); 3777 CursorSet(screen, 3778 CursorRow(xw) + one_if_default(0), 3779 CursorCol(xw), 3780 xw->flags); 3781 ResetState(sp); 3782 break; 3783 3784 case CASE_HPR: 3785 TRACE(("CASE_HPR - horizontal position relative\n")); 3786 CursorSet(screen, 3787 CursorRow(xw), 3788 CursorCol(xw) + one_if_default(0), 3789 xw->flags); 3790 ResetState(sp); 3791 break; 3792 3793 case CASE_HP_BUGGY_LL: 3794 TRACE(("CASE_HP_BUGGY_LL\n")); 3795 /* Some HP-UX applications have the bug that they 3796 assume ESC F goes to the lower left corner of 3797 the screen, regardless of what terminfo says. */ 3798 if (screen->hp_ll_bc) 3799 CursorSet(screen, screen->max_row, 0, xw->flags); 3800 ResetState(sp); 3801 break; 3802 3803 case CASE_ED: 3804 TRACE(("CASE_ED - erase display\n")); 3805 do_cd_xtra_scroll(xw, zero_if_default(0)); 3806 do_erase_display(xw, zero_if_default(0), OFF_PROTECT); 3807 ResetState(sp); 3808 break; 3809 3810 case CASE_EL: 3811 TRACE(("CASE_EL - erase line\n")); 3812 do_erase_line(xw, zero_if_default(0), OFF_PROTECT); 3813 ResetState(sp); 3814 break; 3815 3816 case CASE_ECH: 3817 TRACE(("CASE_ECH - erase char\n")); 3818 /* ECH */ 3819 do_erase_char(xw, one_if_default(0), OFF_PROTECT); 3820 ResetState(sp); 3821 break; 3822 3823 case CASE_IL: 3824 TRACE(("CASE_IL - insert line\n")); 3825 InsertLine(xw, one_if_default(0)); 3826 ResetState(sp); 3827 break; 3828 3829 case CASE_DL: 3830 TRACE(("CASE_DL - delete line\n")); 3831 DeleteLine(xw, one_if_default(0), True); 3832 ResetState(sp); 3833 break; 3834 3835 case CASE_DCH: 3836 TRACE(("CASE_DCH - delete char\n")); 3837 DeleteChar(xw, (unsigned) one_if_default(0)); 3838 ResetState(sp); 3839 break; 3840 3841 case CASE_TRACK_MOUSE: 3842 /* 3843 * A single parameter other than zero is always scroll-down. 3844 * A zero-parameter is used to reset the mouse mode, and is 3845 * not useful for scrolling anyway. 3846 */ 3847 if (nparam > 1 || GetParam(0) == 0) { 3848 CELL start; 3849 3850 TRACE(("CASE_TRACK_MOUSE\n")); 3851 /* Track mouse as long as in window and between 3852 * specified rows 3853 */ 3854 start.row = one_if_default(2) - 1; 3855 start.col = GetParam(1) - 1; 3856 TrackMouse(xw, 3857 GetParam(0), 3858 &start, 3859 GetParam(3) - 1, GetParam(4) - 2); 3860 } else { 3861 TRACE(("CASE_SD - scroll down\n")); 3862 /* SD */ 3863 RevScroll(xw, one_if_default(0)); 3864 do_xevents(xw); 3865 } 3866 ResetState(sp); 3867 break; 3868 3869 case CASE_SD: 3870 /* 3871 * Cater to ECMA-48's typographical error... 3872 */ 3873 TRACE(("CASE_SD - scroll down\n")); 3874 RevScroll(xw, one_if_default(0)); 3875 do_xevents(xw); 3876 ResetState(sp); 3877 break; 3878 3879 case CASE_DECID: 3880 TRACE(("CASE_DECID\n")); 3881 if_OPT_VT52_MODE(screen, { 3882 /* 3883 * If xterm's started in VT52 mode, it's not emulating VT52 3884 * within VT100, etc., so the terminal identifies differently. 3885 */ 3886 switch (screen->terminal_id) { 3887 case 50: 3888 value = 'A'; 3889 break; 3890 case 52: 3891 value = 'K'; 3892 break; 3893 case 55: 3894 value = 'C'; 3895 break; 3896 default: 3897 value = 'Z'; 3898 break; 3899 } 3900 unparseputc(xw, ANSI_ESC); 3901 unparseputc(xw, '/'); 3902 unparseputc(xw, value); 3903 unparse_end(xw); 3904 ResetState(sp); 3905 break; 3906 }); 3907 SetParam(0, DEFAULT); /* Default ID parameter */ 3908 /* FALLTHRU */ 3909 case CASE_DA1: 3910 TRACE(("CASE_DA1\n")); 3911 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 3912 count = 0; 3913 init_reply(ANSI_CSI); 3914 reply.a_pintro = '?'; 3915 3916 /* 3917 * The first parameter corresponds to the highest operating 3918 * level (i.e., service level) of the emulation. A DEC 3919 * terminal can be setup to respond with a different DA 3920 * response, but there's no control sequence that modifies 3921 * this. We set it via a resource. 3922 */ 3923 if (screen->display_da1 < 200) { 3924 switch (screen->display_da1) { 3925 case 132: 3926 reply.a_param[count++] = 4; /* VT132 */ 3927#if OPT_REGIS_GRAPHICS 3928 reply.a_param[count++] = 6; /* no STP, AVO, GPO (ReGIS) */ 3929#else 3930 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */ 3931#endif 3932 break; 3933 case 131: 3934 reply.a_param[count++] = 7; /* VT131 */ 3935 break; 3936 case 125: 3937 reply.a_param[count++] = 12; /* VT125 */ 3938#if OPT_REGIS_GRAPHICS 3939 reply.a_param[count++] = 0 | 2 | 1; /* no STP, AVO, GPO (ReGIS) */ 3940#else 3941 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */ 3942#endif 3943 reply.a_param[count++] = 0; /* no printer */ 3944 reply.a_param[count++] = XTERM_PATCH; /* ROM version */ 3945 break; 3946 case 102: 3947 reply.a_param[count++] = 6; /* VT102 */ 3948 break; 3949 case 101: 3950 reply.a_param[count++] = 1; /* VT101 */ 3951 reply.a_param[count++] = 0; /* no options */ 3952 break; 3953 default: /* VT100 */ 3954 reply.a_param[count++] = 1; /* VT100 */ 3955 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */ 3956 break; 3957 } 3958 } else { 3959 reply.a_param[count++] = (ParmType) (60 3960 + screen->display_da1 3961 / 100); 3962 reply.a_param[count++] = 1; /* 132-columns */ 3963 reply.a_param[count++] = 2; /* printer */ 3964#if OPT_REGIS_GRAPHICS 3965 if (optRegisGraphics(screen)) { 3966 reply.a_param[count++] = 3; /* ReGIS graphics */ 3967 } 3968#endif 3969#if OPT_SIXEL_GRAPHICS 3970 if (optSixelGraphics(screen)) { 3971 reply.a_param[count++] = 4; /* sixel graphics */ 3972 } 3973#endif 3974 reply.a_param[count++] = 6; /* selective-erase */ 3975#if OPT_SUNPC_KBD 3976 if (xw->keyboard.type == keyboardIsVT220) 3977#endif 3978 reply.a_param[count++] = 8; /* user-defined-keys */ 3979 reply.a_param[count++] = 9; /* national replacement charsets */ 3980 reply.a_param[count++] = 15; /* technical characters */ 3981 reply.a_param[count++] = 16; /* locator port */ 3982 if (screen->display_da1 >= 400) { 3983 reply.a_param[count++] = 17; /* terminal state interrogation */ 3984 reply.a_param[count++] = 18; /* windowing extension */ 3985 reply.a_param[count++] = 21; /* horizontal scrolling */ 3986 } 3987 if_OPT_ISO_COLORS(screen, { 3988 reply.a_param[count++] = 22; /* ANSI color, VT525 */ 3989 }); 3990 reply.a_param[count++] = 28; /* rectangular editing */ 3991#if OPT_DEC_LOCATOR 3992 reply.a_param[count++] = 29; /* ANSI text locator */ 3993#endif 3994 } 3995 reply.a_nparam = (ParmType) count; 3996 reply.a_final = 'c'; 3997 unparseseq(xw, &reply); 3998 } 3999 ResetState(sp); 4000 break; 4001 4002 case CASE_DA2: 4003 TRACE(("CASE_DA2\n")); 4004 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 4005 count = 0; 4006 init_reply(ANSI_CSI); 4007 reply.a_pintro = '>'; 4008 4009 if (screen->terminal_id >= 200) { 4010 switch (screen->terminal_id) { 4011 case 220: 4012 default: 4013 reply.a_param[count++] = 1; /* VT220 */ 4014 break; 4015 case 240: 4016 case 241: 4017 /* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */ 4018 reply.a_param[count++] = 2; /* VT240 */ 4019 break; 4020 case 320: 4021 /* http://www.vt100.net/docs/vt320-uu/appendixe.html */ 4022 reply.a_param[count++] = 24; /* VT320 */ 4023 break; 4024 case 330: 4025 reply.a_param[count++] = 18; /* VT330 */ 4026 break; 4027 case 340: 4028 reply.a_param[count++] = 19; /* VT340 */ 4029 break; 4030 case 382: 4031 reply.a_param[count++] = 32; /* VT382 */ 4032 break; 4033 case 420: 4034 reply.a_param[count++] = 41; /* VT420 */ 4035 break; 4036 case 510: 4037 /* http://www.vt100.net/docs/vt510-rm/DA2 */ 4038 reply.a_param[count++] = 61; /* VT510 */ 4039 break; 4040 case 520: 4041 reply.a_param[count++] = 64; /* VT520 */ 4042 break; 4043 case 525: 4044 reply.a_param[count++] = 65; /* VT525 */ 4045 break; 4046 } 4047 } else { 4048 reply.a_param[count++] = 0; /* VT100 (nonstandard) */ 4049 } 4050 reply.a_param[count++] = XTERM_PATCH; /* Version */ 4051 reply.a_param[count++] = 0; /* options (none) */ 4052 reply.a_nparam = (ParmType) count; 4053 reply.a_final = 'c'; 4054 unparseseq(xw, &reply); 4055 } 4056 ResetState(sp); 4057 break; 4058 4059 case CASE_DECRPTUI: 4060 TRACE(("CASE_DECRPTUI\n")); 4061 if ((screen->vtXX_level >= 4) 4062 && (GetParam(0) <= 0)) { /* less than means DEFAULT */ 4063 unparseputc1(xw, ANSI_DCS); 4064 unparseputc(xw, '!'); 4065 unparseputc(xw, '|'); 4066 /* report the "terminal unit id" as 4 pairs of hexadecimal 4067 * digits -- meaningless for a terminal emulator, but some 4068 * host may care about the format. 4069 */ 4070 for (count = 0; count < 8; ++count) { 4071 unparseputc(xw, '0'); 4072 } 4073 unparseputc1(xw, ANSI_ST); 4074 unparse_end(xw); 4075 } 4076 ResetState(sp); 4077 break; 4078 4079 case CASE_TBC: 4080 TRACE(("CASE_TBC - tab clear\n")); 4081 if ((value = GetParam(0)) <= 0) /* less than means default */ 4082 TabClear(xw->tabs, screen->cur_col); 4083 else if (value == 3) 4084 TabZonk(xw->tabs); 4085 ResetState(sp); 4086 break; 4087 4088 case CASE_SET: 4089 TRACE(("CASE_SET - set mode\n")); 4090 ansi_modes(xw, bitset); 4091 ResetState(sp); 4092 break; 4093 4094 case CASE_RST: 4095 TRACE(("CASE_RST - reset mode\n")); 4096 ansi_modes(xw, bitclr); 4097 ResetState(sp); 4098 break; 4099 4100 case CASE_SGR: 4101 for (item = 0; item < nparam; ++item) { 4102 int op = GetParam(item); 4103 int skip; 4104 4105 if_OPT_XMC_GLITCH(screen, { 4106 Mark_XMC(xw, op); 4107 }); 4108 TRACE(("CASE_SGR %d\n", op)); 4109 4110 /* 4111 * Only SGR 38/48 accept subparameters, and in those cases 4112 * the values will not be seen at this point. 4113 */ 4114 if ((skip = param_has_subparams(item)) != 0) { 4115 switch (op) { 4116 case 38: 4117 /* FALLTHRU */ 4118 case 48: 4119 if_OPT_ISO_COLORS(screen, { 4120 break; 4121 }); 4122 /* FALLTHRU */ 4123 default: 4124 TRACE(("...unexpected subparameter in SGR\n")); 4125 item += skip; /* ignore this */ 4126 op = 9999; /* will never use this, anyway */ 4127 break; 4128 } 4129 } 4130 4131 switch (op) { 4132 case DEFAULT: 4133 /* FALLTHRU */ 4134 case 0: 4135 resetRendition(xw); 4136 if_OPT_ISO_COLORS(screen, { 4137 reset_SGR_Colors(xw); 4138 }); 4139 break; 4140 case 1: /* Bold */ 4141 UIntSet(xw->flags, BOLD); 4142 if_OPT_ISO_COLORS(screen, { 4143 setExtendedFG(xw); 4144 }); 4145 break; 4146#if OPT_WIDE_ATTRS 4147 case 2: /* faint, decreased intensity or second colour */ 4148 UIntSet(xw->flags, ATR_FAINT); 4149 if_OPT_ISO_COLORS(screen, { 4150 setExtendedFG(xw); 4151 }); 4152 break; 4153 case 3: /* italicized */ 4154 setItalicFont(xw, UseItalicFont(screen)); 4155 UIntSet(xw->flags, ATR_ITALIC); 4156 if_OPT_ISO_COLORS(screen, { 4157 setExtendedFG(xw); 4158 }); 4159 break; 4160#endif 4161 case 4: /* Underscore */ 4162 UIntSet(xw->flags, UNDERLINE); 4163 if_OPT_ISO_COLORS(screen, { 4164 setExtendedFG(xw); 4165 }); 4166 break; 4167 case 5: /* Blink (less than 150 per minute) */ 4168 /* FALLTHRU */ 4169 case 6: /* Blink (150 per minute, or more) */ 4170 UIntSet(xw->flags, BLINK); 4171 StartBlinking(xw); 4172 if_OPT_ISO_COLORS(screen, { 4173 setExtendedFG(xw); 4174 }); 4175 break; 4176 case 7: 4177 UIntSet(xw->flags, INVERSE); 4178 if_OPT_ISO_COLORS(screen, { 4179 setExtendedBG(xw); 4180 }); 4181 break; 4182 case 8: 4183 UIntSet(xw->flags, INVISIBLE); 4184 break; 4185#if OPT_WIDE_ATTRS 4186 case 9: /* crossed-out characters */ 4187 UIntSet(xw->flags, ATR_STRIKEOUT); 4188 break; 4189#endif 4190#if OPT_WIDE_ATTRS 4191 case 21: /* doubly-underlined */ 4192 UIntSet(xw->flags, ATR_DBL_UNDER); 4193 break; 4194#endif 4195 case 22: /* reset 'bold' */ 4196 UIntClr(xw->flags, BOLD); 4197#if OPT_WIDE_ATTRS 4198 UIntClr(xw->flags, ATR_FAINT); 4199#endif 4200 if_OPT_ISO_COLORS(screen, { 4201 setExtendedFG(xw); 4202 }); 4203 break; 4204#if OPT_WIDE_ATTRS 4205 case 23: /* not italicized */ 4206 ResetItalics(xw); 4207 if_OPT_ISO_COLORS(screen, { 4208 setExtendedFG(xw); 4209 }); 4210 break; 4211#endif 4212 case 24: 4213 UIntClr(xw->flags, UNDERLINE); 4214#if OPT_WIDE_ATTRS 4215 UIntClr(xw->flags, ATR_DBL_UNDER); 4216#endif 4217 if_OPT_ISO_COLORS(screen, { 4218 setExtendedFG(xw); 4219 }); 4220 break; 4221 case 25: /* reset 'blink' */ 4222 UIntClr(xw->flags, BLINK); 4223 if_OPT_ISO_COLORS(screen, { 4224 setExtendedFG(xw); 4225 }); 4226 break; 4227 case 27: 4228 UIntClr(xw->flags, INVERSE); 4229 if_OPT_ISO_COLORS(screen, { 4230 setExtendedBG(xw); 4231 }); 4232 break; 4233 case 28: 4234 UIntClr(xw->flags, INVISIBLE); 4235 break; 4236#if OPT_WIDE_ATTRS 4237 case 29: /* not crossed out */ 4238 UIntClr(xw->flags, ATR_STRIKEOUT); 4239 break; 4240#endif 4241 case 30: 4242 /* FALLTHRU */ 4243 case 31: 4244 /* FALLTHRU */ 4245 case 32: 4246 /* FALLTHRU */ 4247 case 33: 4248 /* FALLTHRU */ 4249 case 34: 4250 /* FALLTHRU */ 4251 case 35: 4252 /* FALLTHRU */ 4253 case 36: 4254 /* FALLTHRU */ 4255 case 37: 4256 if_OPT_ISO_COLORS(screen, { 4257 xw->sgr_foreground = (op - 30); 4258 xw->sgr_38_xcolors = False; 4259 clrDirectFG(xw->flags); 4260 setExtendedFG(xw); 4261 }); 4262 break; 4263 case 38: 4264 /* This is more complicated than I'd like, but it should 4265 * properly eat all the parameters for unsupported modes. 4266 */ 4267 if_OPT_ISO_COLORS(screen, { 4268 Boolean extended; 4269 if (parse_extended_colors(xw, &value, &item, 4270 &extended)) { 4271 xw->sgr_foreground = value; 4272 xw->sgr_38_xcolors = True; 4273 setDirectFG(xw->flags, extended); 4274 setExtendedFG(xw); 4275 } 4276 }); 4277 break; 4278 case 39: 4279 if_OPT_ISO_COLORS(screen, { 4280 reset_SGR_Foreground(xw); 4281 }); 4282 break; 4283 case 40: 4284 /* FALLTHRU */ 4285 case 41: 4286 /* FALLTHRU */ 4287 case 42: 4288 /* FALLTHRU */ 4289 case 43: 4290 /* FALLTHRU */ 4291 case 44: 4292 /* FALLTHRU */ 4293 case 45: 4294 /* FALLTHRU */ 4295 case 46: 4296 /* FALLTHRU */ 4297 case 47: 4298 if_OPT_ISO_COLORS(screen, { 4299 xw->sgr_background = (op - 40); 4300 clrDirectBG(xw->flags); 4301 setExtendedBG(xw); 4302 }); 4303 break; 4304 case 48: 4305 if_OPT_ISO_COLORS(screen, { 4306 Boolean extended; 4307 if (parse_extended_colors(xw, &value, &item, 4308 &extended)) { 4309 xw->sgr_background = value; 4310 setDirectBG(xw->flags, extended); 4311 setExtendedBG(xw); 4312 } 4313 }); 4314 break; 4315 case 49: 4316 if_OPT_ISO_COLORS(screen, { 4317 reset_SGR_Background(xw); 4318 }); 4319 break; 4320 case 90: 4321 /* FALLTHRU */ 4322 case 91: 4323 /* FALLTHRU */ 4324 case 92: 4325 /* FALLTHRU */ 4326 case 93: 4327 /* FALLTHRU */ 4328 case 94: 4329 /* FALLTHRU */ 4330 case 95: 4331 /* FALLTHRU */ 4332 case 96: 4333 /* FALLTHRU */ 4334 case 97: 4335 if_OPT_AIX_COLORS(screen, { 4336 xw->sgr_foreground = (op - 90 + 8); 4337 clrDirectFG(xw->flags); 4338 setExtendedFG(xw); 4339 }); 4340 break; 4341 case 100: 4342#if !OPT_AIX_COLORS 4343 if_OPT_ISO_COLORS(screen, { 4344 reset_SGR_Foreground(xw); 4345 reset_SGR_Background(xw); 4346 }); 4347 break; 4348#endif 4349 case 101: 4350 /* FALLTHRU */ 4351 case 102: 4352 /* FALLTHRU */ 4353 case 103: 4354 /* FALLTHRU */ 4355 case 104: 4356 /* FALLTHRU */ 4357 case 105: 4358 /* FALLTHRU */ 4359 case 106: 4360 /* FALLTHRU */ 4361 case 107: 4362 if_OPT_AIX_COLORS(screen, { 4363 xw->sgr_background = (op - 100 + 8); 4364 clrDirectBG(xw->flags); 4365 setExtendedBG(xw); 4366 }); 4367 break; 4368 default: 4369 /* later: skip += NPARAM; */ 4370 break; 4371 } 4372 } 4373 ResetState(sp); 4374 break; 4375 4376 /* DSR (except for the '?') is a superset of CPR */ 4377 case CASE_DSR: 4378 sp->private_function = True; 4379 4380 /* FALLTHRU */ 4381 case CASE_CPR: 4382 TRACE(("CASE_DSR - device status report\n")); 4383 count = 0; 4384 init_reply(ANSI_CSI); 4385 reply.a_pintro = CharOf(sp->private_function ? '?' : 0); 4386 reply.a_final = 'n'; 4387 4388 switch (GetParam(0)) { 4389 case 5: 4390 TRACE(("...request operating status\n")); 4391 /* operating status */ 4392 reply.a_param[count++] = 0; /* (no malfunction ;-) */ 4393 break; 4394 case 6: 4395 TRACE(("...request %s\n", 4396 (sp->private_function 4397 ? "DECXCPR" 4398 : "CPR"))); 4399 /* CPR */ 4400 /* DECXCPR (with page=1) */ 4401 value = screen->cur_row; 4402 if ((xw->flags & ORIGIN) != 0) { 4403 value -= screen->top_marg; 4404 } 4405 if_STATUS_LINE(screen, { 4406 if ((value -= LastRowNumber(screen)) < 0) 4407 value = 0; 4408 }); 4409 reply.a_param[count++] = (ParmType) (value + 1); 4410 4411 value = (screen->cur_col + 1); 4412 if ((xw->flags & ORIGIN) != 0) { 4413 value -= screen->lft_marg; 4414 } 4415 reply.a_param[count++] = (ParmType) value; 4416 4417 if (sp->private_function && 4418 (screen->vtXX_level >= 4 || 4419 (screen->terminal_id >= 330 && 4420 screen->vtXX_level >= 3))) { 4421 /* VT330 (not VT320) and VT420 */ 4422 reply.a_param[count++] = 1; 4423 } 4424 reply.a_final = 'R'; 4425 break; 4426 case 15: 4427 TRACE(("...request printer status\n")); 4428 if (sp->private_function 4429 && screen->vtXX_level >= 2) { /* VT220 */ 4430 reply.a_param[count++] = 13; /* no printer detected */ 4431 } 4432 break; 4433 case 25: 4434 TRACE(("...request UDK status\n")); 4435 if (sp->private_function 4436 && screen->vtXX_level >= 2) { /* VT220 */ 4437 reply.a_param[count++] = 20; /* UDK always unlocked */ 4438 } 4439 break; 4440 case 26: 4441 TRACE(("...request keyboard status\n")); 4442 if (sp->private_function 4443 && screen->vtXX_level >= 2) { /* VT220 */ 4444 reply.a_param[count++] = 27; 4445 reply.a_param[count++] = 1; /* North American */ 4446 if (screen->vtXX_level >= 3) { /* VT320 */ 4447 reply.a_param[count++] = 0; /* ready */ 4448 } 4449 if (screen->vtXX_level >= 4) { /* VT420 */ 4450 reply.a_param[count++] = 0; /* LK201 */ 4451 } 4452 } 4453 break; 4454 case 55: /* according to the VT330/VT340 Text Programming Manual */ 4455 TRACE(("...request locator status\n")); 4456 if (sp->private_function 4457 && screen->vtXX_level >= 3) { /* VT330 */ 4458#if OPT_DEC_LOCATOR 4459 reply.a_param[count++] = 50; /* locator ready */ 4460#else 4461 reply.a_param[count++] = 53; /* no locator */ 4462#endif 4463 } 4464 break; 4465 case 56: 4466 TRACE(("...request locator type\n")); 4467 if (sp->private_function 4468 && screen->vtXX_level >= 3) { /* VT330 */ 4469 reply.a_param[count++] = 57; 4470#if OPT_DEC_LOCATOR 4471 reply.a_param[count++] = 1; /* mouse */ 4472#else 4473 reply.a_param[count++] = 0; /* unknown */ 4474#endif 4475 } 4476 break; 4477 case 62: 4478 TRACE(("...request DECMSR - macro space\n")); 4479 if (sp->private_function 4480 && screen->vtXX_level >= 4) { /* VT420 */ 4481 reply.a_pintro = 0; 4482 reply.a_radix[count] = 16; /* no data */ 4483 reply.a_param[count++] = 0; /* no space for macros */ 4484 reply.a_inters = '*'; 4485 reply.a_final = L_CURL; 4486 } 4487 break; 4488 case 63: 4489 TRACE(("...request DECCKSR - memory checksum\n")); 4490 /* DECCKSR - Memory checksum */ 4491 if (sp->private_function 4492 && screen->vtXX_level >= 4) { /* VT420 */ 4493 init_reply(ANSI_DCS); 4494 reply.a_param[count++] = (ParmType) GetParam(1); /* PID */ 4495 reply.a_delim = "!~"; /* delimiter */ 4496 reply.a_radix[count] = 16; /* use hex */ 4497 reply.a_param[count++] = 0; /* no data */ 4498 } 4499 break; 4500 case 75: 4501 TRACE(("...request data integrity\n")); 4502 if (sp->private_function 4503 && screen->vtXX_level >= 4) { /* VT420 */ 4504 reply.a_param[count++] = 70; /* no errors */ 4505 } 4506 break; 4507 case 85: 4508 TRACE(("...request multi-session configuration\n")); 4509 if (sp->private_function 4510 && screen->vtXX_level >= 4) { /* VT420 */ 4511 reply.a_param[count++] = 83; /* not configured */ 4512 } 4513 break; 4514 default: 4515 break; 4516 } 4517 4518 if ((reply.a_nparam = (ParmType) count) != 0) 4519 unparseseq(xw, &reply); 4520 4521 ResetState(sp); 4522 sp->private_function = False; 4523 break; 4524 4525 case CASE_MC: 4526 TRACE(("CASE_MC - media control\n")); 4527 xtermMediaControl(xw, GetParam(0), False); 4528 ResetState(sp); 4529 break; 4530 4531 case CASE_DEC_MC: 4532 TRACE(("CASE_DEC_MC - DEC media control\n")); 4533 xtermMediaControl(xw, GetParam(0), True); 4534 ResetState(sp); 4535 break; 4536 4537 case CASE_HP_MEM_LOCK: 4538 /* FALLTHRU */ 4539 case CASE_HP_MEM_UNLOCK: 4540 TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK) 4541 ? "CASE_HP_MEM_LOCK" 4542 : "CASE_HP_MEM_UNLOCK"))); 4543 if (screen->scroll_amt) 4544 FlushScroll(xw); 4545 if (sp->parsestate[c] == CASE_HP_MEM_LOCK) 4546 set_tb_margins(screen, screen->cur_row, screen->bot_marg); 4547 else 4548 set_tb_margins(screen, 0, screen->bot_marg); 4549 ResetState(sp); 4550 break; 4551 4552 case CASE_DECSTBM: 4553 TRACE(("CASE_DECSTBM - set scrolling region\n")); 4554 { 4555 int top; 4556 int bot; 4557 top = one_if_default(0); 4558 if (nparam < 2 || (bot = GetParam(1)) == DEFAULT 4559 || bot > MaxRows(screen) 4560 || bot == 0) 4561 bot = MaxRows(screen); 4562 if (bot > top) { 4563 if (screen->scroll_amt) 4564 FlushScroll(xw); 4565 set_tb_margins(screen, top - 1, bot - 1); 4566 CursorSet(screen, 0, 0, xw->flags); 4567 } 4568 ResetState(sp); 4569 } 4570 break; 4571 4572 case CASE_DECREQTPARM: 4573 TRACE(("CASE_DECREQTPARM\n")); 4574 if (screen->terminal_id < 200) { /* VT102 */ 4575 value = zero_if_default(0); 4576 if (value == 0 || value == 1) { 4577 init_reply(ANSI_CSI); 4578 reply.a_nparam = 7; 4579 reply.a_param[0] = (ParmType) (value + 2); 4580 reply.a_param[1] = 1; /* no parity */ 4581 reply.a_param[2] = 1; /* eight bits */ 4582 reply.a_param[3] = 128; /* transmit 38.4k baud */ 4583 reply.a_param[4] = 128; /* receive 38.4k baud */ 4584 reply.a_param[5] = 1; /* clock multiplier ? */ 4585 reply.a_param[6] = 0; /* STP flags ? */ 4586 reply.a_final = 'x'; 4587 unparseseq(xw, &reply); 4588 } 4589 } 4590 ResetState(sp); 4591 break; 4592 4593 case CASE_DECSET: 4594 /* DECSET */ 4595#if OPT_VT52_MODE 4596 if (screen->vtXX_level != 0) 4597#endif 4598 dpmodes(xw, bitset); 4599 ResetState(sp); 4600#if OPT_TEK4014 4601 if (TEK4014_ACTIVE(xw)) { 4602 TRACE(("Tek4014 is now active...\n")); 4603 if (sp->check_recur) 4604 sp->check_recur--; 4605 return False; 4606 } 4607#endif 4608 break; 4609 4610 case CASE_DECRST: 4611 /* DECRST */ 4612 dpmodes(xw, bitclr); 4613 init_groundtable(screen, sp); 4614 ResetState(sp); 4615 break; 4616 4617 case CASE_DECALN: 4618 TRACE(("CASE_DECALN - alignment test\n")); 4619 if (screen->cursor_state) 4620 HideCursor(xw); 4621 /* 4622 * DEC STD 070 (see pages D-19 to D-20) does not mention left/right 4623 * margins. The section is dated March 1985, not updated for the 4624 * VT420 (introduced in 1990). 4625 */ 4626 UIntClr(xw->flags, ORIGIN); 4627 screen->do_wrap = False; 4628 resetRendition(xw); 4629 resetMargins(xw); 4630 xterm_ResetDouble(xw); 4631 CursorSet(screen, 0, 0, xw->flags); 4632 xtermParseRect(xw, 0, NULL, &myRect); 4633 ScrnFillRectangle(xw, &myRect, 'E', 0, False); 4634 ResetState(sp); 4635 break; 4636 4637 case CASE_GSETS5: 4638 if (screen->vtXX_level >= 5) { 4639 TRACE_GSETS("5"); 4640 xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c); 4641 } 4642 ResetState(sp); 4643 break; 4644 4645 case CASE_GSETS3: 4646 if (screen->vtXX_level >= 3) { 4647 TRACE_GSETS("3"); 4648 xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c); 4649 } 4650 ResetState(sp); 4651 break; 4652 4653 case CASE_GSETS: 4654 if (strchr("012AB", AsciiOf(c)) != NULL) { 4655 TRACE_GSETS(""); 4656 xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c); 4657 } else if (screen->vtXX_level >= 2) { 4658 TRACE_GSETS(""); 4659 xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c); 4660 } 4661 ResetState(sp); 4662 break; 4663 4664 case CASE_ANSI_SC: 4665 if (IsLeftRightMode(xw)) { 4666 int left; 4667 int right; 4668 4669 TRACE(("CASE_DECSLRM - set left and right margin\n")); 4670 left = one_if_default(0); 4671 if (nparam < 2 || (right = GetParam(1)) == DEFAULT 4672 || right > MaxCols(screen) 4673 || right == 0) 4674 right = MaxCols(screen); 4675 if (right > left) { 4676 set_lr_margins(screen, left - 1, right - 1); 4677 CursorSet(screen, 0, 0, xw->flags); 4678 } 4679 } else if (only_default()) { 4680 TRACE(("CASE_ANSI_SC - save cursor\n")); 4681 CursorSave(xw); 4682 } 4683 ResetState(sp); 4684 break; 4685 4686 case CASE_DECSC: 4687 TRACE(("CASE_DECSC - save cursor\n")); 4688 CursorSave(xw); 4689 ResetState(sp); 4690 break; 4691 4692 case CASE_ANSI_RC: 4693 if (!only_default()) 4694 break; 4695 /* FALLTHRU */ 4696 case CASE_DECRC: 4697 TRACE(("CASE_%sRC - restore cursor\n", 4698 (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_")); 4699 CursorRestore(xw); 4700 if_OPT_ISO_COLORS(screen, { 4701 setExtendedFG(xw); 4702 }); 4703 ResetState(sp); 4704 break; 4705 4706 case CASE_DECKPAM: 4707 TRACE(("CASE_DECKPAM\n")); 4708 xw->keyboard.flags |= MODE_DECKPAM; 4709 update_appkeypad(); 4710 ResetState(sp); 4711 break; 4712 4713 case CASE_DECKPNM: 4714 TRACE(("CASE_DECKPNM\n")); 4715 UIntClr(xw->keyboard.flags, MODE_DECKPAM); 4716 update_appkeypad(); 4717 ResetState(sp); 4718 break; 4719 4720 case CASE_CSI_QUOTE_STATE: 4721 sp->parsestate = csi_quo_table; 4722 break; 4723 4724#if OPT_BLINK_CURS 4725 case CASE_CSI_SPACE_STATE: 4726 sp->parsestate = csi_sp_table; 4727 break; 4728 4729 case CASE_DECSCUSR: 4730 TRACE(("CASE_DECSCUSR\n")); 4731 { 4732 Boolean change; 4733 int blinks = screen->cursor_blink_esc; 4734 XtCursorShape shapes = screen->cursor_shape; 4735 4736 HideCursor(xw); 4737 4738 switch (GetParam(0)) { 4739 case DEFAULT: 4740 /* FALLTHRU */ 4741 case DEFAULT_STYLE: 4742 /* FALLTHRU */ 4743 case BLINK_BLOCK: 4744 blinks = True; 4745 screen->cursor_shape = CURSOR_BLOCK; 4746 break; 4747 case STEADY_BLOCK: 4748 blinks = False; 4749 screen->cursor_shape = CURSOR_BLOCK; 4750 break; 4751 case BLINK_UNDERLINE: 4752 blinks = True; 4753 screen->cursor_shape = CURSOR_UNDERLINE; 4754 break; 4755 case STEADY_UNDERLINE: 4756 blinks = False; 4757 screen->cursor_shape = CURSOR_UNDERLINE; 4758 break; 4759 case BLINK_BAR: 4760 blinks = True; 4761 screen->cursor_shape = CURSOR_BAR; 4762 break; 4763 case STEADY_BAR: 4764 blinks = False; 4765 screen->cursor_shape = CURSOR_BAR; 4766 break; 4767 } 4768 change = (blinks != screen->cursor_blink_esc || 4769 shapes != screen->cursor_shape); 4770 TRACE(("cursor_shape:%d blinks:%d%s\n", 4771 screen->cursor_shape, blinks, 4772 change ? " (changed)" : "")); 4773 if (change) { 4774 xtermSetCursorBox(screen); 4775 if (SettableCursorBlink(screen)) { 4776 screen->cursor_blink_esc = blinks; 4777 UpdateCursorBlink(xw); 4778 } 4779 } 4780 } 4781 ResetState(sp); 4782 break; 4783#endif 4784 4785#if OPT_SCROLL_LOCK 4786 case CASE_DECLL: 4787 TRACE(("CASE_DECLL\n")); 4788 if (nparam > 0) { 4789 for (count = 0; count < nparam; ++count) { 4790 int op = zero_if_default(count); 4791 switch (op) { 4792 case 0: 4793 case DEFAULT: 4794 xtermClearLEDs(screen); 4795 break; 4796 case 1: 4797 /* FALLTHRU */ 4798 case 2: 4799 /* FALLTHRU */ 4800 case 3: 4801 xtermShowLED(screen, 4802 (Cardinal) op, 4803 True); 4804 break; 4805 case 21: 4806 /* FALLTHRU */ 4807 case 22: 4808 /* FALLTHRU */ 4809 case 23: 4810 xtermShowLED(screen, 4811 (Cardinal) (op - 20), 4812 True); 4813 break; 4814 } 4815 } 4816 } else { 4817 xtermClearLEDs(screen); 4818 } 4819 ResetState(sp); 4820 break; 4821#endif 4822 4823#if OPT_VT52_MODE 4824 case CASE_VT52_FINISH: 4825 TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n", 4826 screen->terminal_id, 4827 screen->vtXX_level)); 4828 if (screen->terminal_id >= 100 4829 && screen->vtXX_level == 0) { 4830 sp->groundtable = 4831 sp->parsestate = ansi_table; 4832 /* 4833 * On restore, the terminal does not recognize DECRQSS for 4834 * DECSCL (per vttest). 4835 */ 4836 set_vtXX_level(screen, 1); 4837 xw->flags = screen->vt52_save_flags; 4838 screen->curgl = screen->vt52_save_curgl; 4839 screen->curgr = screen->vt52_save_curgr; 4840 screen->curss = screen->vt52_save_curss; 4841 restoreCharsets(screen, screen->vt52_save_gsets); 4842 update_vt52_vt100_settings(); 4843 } 4844 break; 4845#endif 4846 4847 case CASE_ANSI_LEVEL_1: 4848 TRACE(("CASE_ANSI_LEVEL_1\n")); 4849 set_ansi_conformance(screen, 1); 4850 ResetState(sp); 4851 break; 4852 4853 case CASE_ANSI_LEVEL_2: 4854 TRACE(("CASE_ANSI_LEVEL_2\n")); 4855 set_ansi_conformance(screen, 2); 4856 ResetState(sp); 4857 break; 4858 4859 case CASE_ANSI_LEVEL_3: 4860 TRACE(("CASE_ANSI_LEVEL_3\n")); 4861 set_ansi_conformance(screen, 3); 4862 ResetState(sp); 4863 break; 4864 4865 case CASE_DECSCL: 4866 TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1))); 4867 /* 4868 * This changes the emulation level, and is not recognized by 4869 * VT100s. However, a VT220 or above can be set to conformance 4870 * level 1 to act like a VT100. 4871 */ 4872 if (screen->terminal_id >= 200) { 4873 /* 4874 * Disallow unrecognized parameters, as well as attempts to set 4875 * the operating level higher than the given terminal-id. 4876 */ 4877 if (GetParam(0) >= 61 4878 && GetParam(0) <= 60 + (screen->terminal_id / 100)) { 4879 int new_vtXX_level = GetParam(0) - 60; 4880 int case_value = zero_if_default(1); 4881 /* 4882 * Note: 4883 * 4884 * The VT300, VT420, VT520 manuals claim that DECSCL does a 4885 * hard reset (RIS). 4886 * 4887 * Both the VT220 manual and DEC STD 070 (which documents 4888 * levels 1-4 in detail) state that it is a soft reset. 4889 * 4890 * Perhaps both sets of manuals are right (unlikely). 4891 * Kermit says it's soft. 4892 */ 4893 ReallyReset(xw, False, False); 4894 init_parser(xw, sp); 4895 set_vtXX_level(screen, new_vtXX_level); 4896 if (new_vtXX_level > 1) { 4897 switch (case_value) { 4898 case 1: 4899 show_8bit_control(False); 4900 break; 4901 case 0: 4902 case 2: 4903 show_8bit_control(True); 4904 break; 4905 } 4906 } 4907 } 4908 } 4909 ResetState(sp); 4910 break; 4911 4912 case CASE_DECSCA: 4913 TRACE(("CASE_DECSCA\n")); 4914 screen->protected_mode = DEC_PROTECT; 4915 if (GetParam(0) <= 0 || GetParam(0) == 2) { 4916 UIntClr(xw->flags, PROTECTED); 4917 TRACE(("...clear PROTECTED\n")); 4918 } else if (GetParam(0) == 1) { 4919 xw->flags |= PROTECTED; 4920 TRACE(("...set PROTECTED\n")); 4921 } 4922 ResetState(sp); 4923 break; 4924 4925 case CASE_DECSED: 4926 TRACE(("CASE_DECSED\n")); 4927 do_erase_display(xw, zero_if_default(0), DEC_PROTECT); 4928 ResetState(sp); 4929 break; 4930 4931 case CASE_DECSEL: 4932 TRACE(("CASE_DECSEL\n")); 4933 do_erase_line(xw, zero_if_default(0), DEC_PROTECT); 4934 ResetState(sp); 4935 break; 4936 4937 case CASE_GRAPHICS_ATTRIBUTES: 4938#if OPT_GRAPHICS 4939 TRACE(("CASE_GRAPHICS_ATTRIBUTES\n")); 4940 { 4941 /* request: item, action, value */ 4942 /* reply: item, status, value */ 4943 if (nparam != 3) { 4944 TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam)); 4945 } else { 4946 int status = 3; /* assume failure */ 4947 int result = 0; 4948 int result2 = 0; 4949 4950 TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n", 4951 GetParam(0), GetParam(1), GetParam(2))); 4952 switch (GetParam(0)) { 4953 case 1: /* color register count */ 4954 switch (GetParam(1)) { 4955 case 1: /* read */ 4956 status = 0; /* success */ 4957 result = (int) get_color_register_count(screen); 4958 break; 4959 case 2: /* reset */ 4960 screen->numcolorregisters = 0; 4961 status = 0; /* success */ 4962 result = (int) get_color_register_count(screen); 4963 break; 4964 case 3: /* set */ 4965 if (GetParam(2) > 1 && 4966 (unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) { 4967 screen->numcolorregisters = GetParam(2); 4968 status = 0; /* success */ 4969 result = (int) get_color_register_count(screen); 4970 } 4971 break; 4972 case 4: /* read maximum */ 4973 status = 0; /* success */ 4974 result = MAX_COLOR_REGISTERS; 4975 break; 4976 default: 4977 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n", 4978 GetParam(1))); 4979 status = 2; /* error in Pa */ 4980 break; 4981 } 4982 if (status == 0 && !(optSixelGraphics(screen) 4983 || optRegisGraphics(screen))) 4984 status = 3; 4985 break; 4986# if OPT_SIXEL_GRAPHICS 4987 case 2: /* graphics geometry */ 4988 switch (GetParam(1)) { 4989 case 1: /* read */ 4990 TRACE(("Get sixel graphics geometry\n")); 4991 status = 0; /* success */ 4992 result = Min(Width(screen), (int) screen->graphics_max_wide); 4993 result2 = Min(Height(screen), (int) screen->graphics_max_high); 4994 break; 4995 case 2: /* reset */ 4996 /* FALLTHRU */ 4997 case 3: /* set */ 4998 break; 4999 case 4: /* read maximum */ 5000 status = 0; /* success */ 5001 result = screen->graphics_max_wide; 5002 result2 = screen->graphics_max_high; 5003 break; 5004 default: 5005 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n", 5006 GetParam(1))); 5007 status = 2; /* error in Pa */ 5008 break; 5009 } 5010 if (status == 0 && !optSixelGraphics(screen)) 5011 status = 3; 5012 break; 5013#endif 5014# if OPT_REGIS_GRAPHICS 5015 case 3: /* ReGIS geometry */ 5016 switch (GetParam(1)) { 5017 case 1: /* read */ 5018 status = 0; /* success */ 5019 result = screen->graphics_regis_def_wide; 5020 result2 = screen->graphics_regis_def_high; 5021 break; 5022 case 2: /* reset */ 5023 /* FALLTHRU */ 5024 case 3: /* set */ 5025 /* FALLTHRU */ 5026 case 4: /* read maximum */ 5027 /* not implemented */ 5028 break; 5029 default: 5030 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n", 5031 GetParam(1))); 5032 status = 2; /* error in Pa */ 5033 break; 5034 } 5035 if (status == 0 && !optRegisGraphics(screen)) 5036 status = 3; 5037 break; 5038#endif 5039 default: 5040 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n", 5041 GetParam(0))); 5042 status = 1; 5043 break; 5044 } 5045 5046 init_reply(ANSI_CSI); 5047 reply.a_pintro = '?'; 5048 count = 0; 5049 reply.a_param[count++] = (ParmType) GetParam(0); 5050 reply.a_param[count++] = (ParmType) status; 5051 if (status == 0) { 5052 reply.a_param[count++] = (ParmType) result; 5053 if (GetParam(0) >= 2) 5054 reply.a_param[count++] = (ParmType) result2; 5055 } 5056 reply.a_nparam = (ParmType) count; 5057 reply.a_final = 'S'; 5058 unparseseq(xw, &reply); 5059 } 5060 } 5061#endif 5062 ResetState(sp); 5063 break; 5064 5065 case CASE_ST: 5066 TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n", 5067 (unsigned long) sp->string_used, 5068 sp->string_mode)); 5069 ResetState(sp); 5070 if (!sp->string_used && !sp->string_args) 5071 break; 5072 if (sp->string_skip) { 5073 xtermWarning("Ignoring too-long string (%lu) for mode %#02x\n", 5074 (unsigned long) sp->string_used, 5075 sp->string_mode); 5076 sp->string_skip = False; 5077 sp->string_used = 0; 5078 } else { 5079 if (sp->string_used) 5080 sp->string_area[--(sp->string_used)] = '\0'; 5081 if (sp->check_recur <= 1) { 5082 switch (sp->string_mode) { 5083 case ANSI_APC: 5084 /* ignored */ 5085 break; 5086 case ANSI_DCS: 5087#if OPT_SIXEL_GRAPHICS 5088 if (sp->string_args == sa_SIXEL) { 5089 parse_sixel_finished(); 5090 TRACE(("DONE parsed sixel data\n")); 5091 } else 5092#endif 5093 do_dcs(xw, sp->string_area, sp->string_used); 5094 break; 5095 case ANSI_OSC: 5096 do_osc(xw, sp->string_area, sp->string_used, ANSI_ST); 5097 break; 5098 case ANSI_PM: 5099 /* ignored */ 5100 break; 5101 case ANSI_SOS: 5102 /* ignored */ 5103 break; 5104 default: 5105 TRACE(("unknown mode\n")); 5106 break; 5107 } 5108 } 5109 } 5110 break; 5111 5112 case CASE_SOS: 5113 TRACE(("CASE_SOS: Start of String\n")); 5114 if (ParseSOS(screen)) { 5115 BeginString(ANSI_SOS); 5116 } else { 5117 illegal_parse(xw, c, sp); 5118 } 5119 break; 5120 5121 case CASE_PM: 5122 TRACE(("CASE_PM: Privacy Message\n")); 5123 if (ParseSOS(screen)) { 5124 BeginString(ANSI_PM); 5125 } else { 5126 illegal_parse(xw, c, sp); 5127 } 5128 break; 5129 5130 case CASE_DCS: 5131 TRACE(("CASE_DCS: Device Control String\n")); 5132 BeginString2(ANSI_DCS); 5133 break; 5134 5135 case CASE_APC: 5136 TRACE(("CASE_APC: Application Program Command\n")); 5137 if (ParseSOS(screen)) { 5138 BeginString(ANSI_APC); 5139 } else { 5140 illegal_parse(xw, c, sp); 5141 } 5142 break; 5143 5144 case CASE_SPA: 5145 TRACE(("CASE_SPA - start protected area\n")); 5146 screen->protected_mode = ISO_PROTECT; 5147 xw->flags |= PROTECTED; 5148 ResetState(sp); 5149 break; 5150 5151 case CASE_EPA: 5152 TRACE(("CASE_EPA - end protected area\n")); 5153 UIntClr(xw->flags, PROTECTED); 5154 ResetState(sp); 5155 break; 5156 5157 case CASE_SU: 5158 TRACE(("CASE_SU - scroll up\n")); 5159 xtermScroll(xw, one_if_default(0)); 5160 ResetState(sp); 5161 break; 5162 5163 case CASE_SL: /* ISO 6429, non-DEC */ 5164 TRACE(("CASE_SL - scroll left\n")); 5165 xtermScrollLR(xw, one_if_default(0), True); 5166 ResetState(sp); 5167 break; 5168 5169 case CASE_SR: /* ISO 6429, non-DEC */ 5170 TRACE(("CASE_SR - scroll right\n")); 5171 xtermScrollLR(xw, one_if_default(0), False); 5172 ResetState(sp); 5173 break; 5174 5175 case CASE_DECDC: 5176 TRACE(("CASE_DC - delete column\n")); 5177 if (screen->vtXX_level >= 4) { 5178 xtermColScroll(xw, one_if_default(0), True, screen->cur_col); 5179 } 5180 ResetState(sp); 5181 break; 5182 5183 case CASE_DECIC: 5184 TRACE(("CASE_IC - insert column\n")); 5185 if (screen->vtXX_level >= 4) { 5186 xtermColScroll(xw, one_if_default(0), False, screen->cur_col); 5187 } 5188 ResetState(sp); 5189 break; 5190 5191 case CASE_DECBI: 5192 TRACE(("CASE_BI - back index\n")); 5193 if (screen->vtXX_level >= 4) { 5194 xtermColIndex(xw, True); 5195 } 5196 ResetState(sp); 5197 break; 5198 5199 case CASE_DECFI: 5200 TRACE(("CASE_FI - forward index\n")); 5201 if (screen->vtXX_level >= 4) { 5202 xtermColIndex(xw, False); 5203 } 5204 ResetState(sp); 5205 break; 5206 5207 case CASE_IND: 5208 TRACE(("CASE_IND - index\n")); 5209 xtermIndex(xw, 1); 5210 do_xevents(xw); 5211 ResetState(sp); 5212 break; 5213 5214 case CASE_CPL: 5215 TRACE(("CASE_CPL - cursor prev line\n")); 5216 CursorPrevLine(xw, one_if_default(0)); 5217 ResetState(sp); 5218 break; 5219 5220 case CASE_CNL: 5221 TRACE(("CASE_CNL - cursor next line\n")); 5222 CursorNextLine(xw, one_if_default(0)); 5223 ResetState(sp); 5224 break; 5225 5226 case CASE_NEL: 5227 TRACE(("CASE_NEL\n")); 5228 xtermIndex(xw, 1); 5229 CarriageReturn(xw); 5230 ResetState(sp); 5231 break; 5232 5233 case CASE_HTS: 5234 TRACE(("CASE_HTS - horizontal tab set\n")); 5235 TabSet(xw->tabs, screen->cur_col); 5236 ResetState(sp); 5237 break; 5238 5239 case CASE_REPORT_VERSION: 5240 TRACE(("CASE_REPORT_VERSION - report terminal version\n")); 5241 if (GetParam(0) <= 0) { 5242 unparseputc1(xw, ANSI_DCS); 5243 unparseputc(xw, '>'); 5244 unparseputc(xw, '|'); 5245 unparseputs(xw, xtermVersion()); 5246 unparseputc1(xw, ANSI_ST); 5247 unparse_end(xw); 5248 } 5249 ResetState(sp); 5250 break; 5251 5252 case CASE_RI: 5253 TRACE(("CASE_RI - reverse index\n")); 5254 RevIndex(xw, 1); 5255 ResetState(sp); 5256 break; 5257 5258 case CASE_SS2: 5259 TRACE(("CASE_SS2\n")); 5260 if (screen->vtXX_level > 1) 5261 screen->curss = 2; 5262 ResetState(sp); 5263 break; 5264 5265 case CASE_SS3: 5266 TRACE(("CASE_SS3\n")); 5267 if (screen->vtXX_level > 1) 5268 screen->curss = 3; 5269 ResetState(sp); 5270 break; 5271 5272 case CASE_CSI_STATE: 5273 /* enter csi state */ 5274 InitParams(); 5275 SetParam(nparam++, DEFAULT); 5276 sp->parsestate = csi_table; 5277 break; 5278 5279 case CASE_ESC_SP_STATE: 5280 /* esc space */ 5281 sp->parsestate = esc_sp_table; 5282 break; 5283 5284 case CASE_CSI_EX_STATE: 5285 /* csi exclamation */ 5286 sp->parsestate = csi_ex_table; 5287 break; 5288 5289 case CASE_CSI_TICK_STATE: 5290 /* csi tick (') */ 5291 sp->parsestate = csi_tick_table; 5292 break; 5293 5294#if OPT_DEC_LOCATOR 5295 case CASE_DECEFR: 5296 TRACE(("CASE_DECEFR - Enable Filter Rectangle\n")); 5297 if (okSendMousePos(xw) == DEC_LOCATOR) { 5298 MotionOff(screen, xw); 5299 if ((screen->loc_filter_top = GetParam(0)) < 1) 5300 screen->loc_filter_top = LOC_FILTER_POS; 5301 if (nparam < 2 5302 || (screen->loc_filter_left = GetParam(1)) < 1) 5303 screen->loc_filter_left = LOC_FILTER_POS; 5304 if (nparam < 3 5305 || (screen->loc_filter_bottom = GetParam(2)) < 1) 5306 screen->loc_filter_bottom = LOC_FILTER_POS; 5307 if (nparam < 4 5308 || (screen->loc_filter_right = GetParam(3)) < 1) 5309 screen->loc_filter_right = LOC_FILTER_POS; 5310 InitLocatorFilter(xw); 5311 } 5312 ResetState(sp); 5313 break; 5314 5315 case CASE_DECELR: 5316 MotionOff(screen, xw); 5317 if (GetParam(0) <= 0 || GetParam(0) > 2) { 5318 screen->send_mouse_pos = MOUSE_OFF; 5319 TRACE(("DECELR - Disable Locator Reports\n")); 5320 } else { 5321 TRACE(("DECELR - Enable Locator Reports\n")); 5322 screen->send_mouse_pos = DEC_LOCATOR; 5323 xtermShowPointer(xw, True); 5324 if (GetParam(0) == 2) { 5325 screen->locator_reset = True; 5326 } else { 5327 screen->locator_reset = False; 5328 } 5329 if (nparam < 2 || GetParam(1) != 1) { 5330 screen->locator_pixels = False; 5331 } else { 5332 screen->locator_pixels = True; 5333 } 5334 screen->loc_filter = False; 5335 } 5336 ResetState(sp); 5337 break; 5338 5339 case CASE_DECSLE: 5340 TRACE(("DECSLE - Select Locator Events\n")); 5341 for (count = 0; count < nparam; ++count) { 5342 switch (zero_if_default(count)) { 5343 case 0: 5344 MotionOff(screen, xw); 5345 screen->loc_filter = False; 5346 screen->locator_events = 0; 5347 break; 5348 case 1: 5349 screen->locator_events |= LOC_BTNS_DN; 5350 break; 5351 case 2: 5352 UIntClr(screen->locator_events, LOC_BTNS_DN); 5353 break; 5354 case 3: 5355 screen->locator_events |= LOC_BTNS_UP; 5356 break; 5357 case 4: 5358 UIntClr(screen->locator_events, LOC_BTNS_UP); 5359 break; 5360 } 5361 } 5362 ResetState(sp); 5363 break; 5364 5365 case CASE_DECRQLP: 5366 TRACE(("DECRQLP - Request Locator Position\n")); 5367 if (GetParam(0) < 2) { 5368 /* Issue DECLRP Locator Position Report */ 5369 GetLocatorPosition(xw); 5370 } 5371 ResetState(sp); 5372 break; 5373#endif /* OPT_DEC_LOCATOR */ 5374 5375 case CASE_CSI_AMP_STATE: 5376 TRACE(("CASE_CSI_AMP_STATE\n")); 5377 /* csi ampersand (&) */ 5378 if (screen->vtXX_level >= 3) 5379 sp->parsestate = csi_amp_table; 5380 else 5381 sp->parsestate = eigtable; 5382 break; 5383 5384#if OPT_DEC_RECTOPS 5385 case CASE_CSI_DOLLAR_STATE: 5386 TRACE(("CASE_CSI_DOLLAR_STATE\n")); 5387 /* csi dollar ($) */ 5388 if (screen->vtXX_level >= 3) 5389 sp->parsestate = csi_dollar_table; 5390 else 5391 sp->parsestate = eigtable; 5392 break; 5393 5394 case CASE_CSI_STAR_STATE: 5395 TRACE(("CASE_CSI_STAR_STATE\n")); 5396 /* csi star (*) */ 5397 if (screen->vtXX_level >= 4) 5398 sp->parsestate = csi_star_table; 5399 else 5400 sp->parsestate = eigtable; 5401 break; 5402 5403 case CASE_DECRQCRA: 5404 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) { 5405 int checksum; 5406 int pid; 5407 5408 TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n")); 5409 xtermCheckRect(xw, ParamPair(0), &checksum); 5410 init_reply(ANSI_DCS); 5411 count = 0; 5412 checksum &= 0xffff; 5413 pid = GetParam(0); 5414 reply.a_param[count++] = (ParmType) pid; 5415 reply.a_delim = "!~"; /* delimiter */ 5416 reply.a_radix[count] = 16; 5417 reply.a_param[count++] = (ParmType) checksum; 5418 reply.a_nparam = (ParmType) count; 5419 TRACE(("...checksum(%d) = %04X\n", pid, checksum)); 5420 unparseseq(xw, &reply); 5421 } 5422 ResetState(sp); 5423 break; 5424 5425 case CASE_DECCRA: 5426 if (screen->vtXX_level >= 4) { 5427 TRACE(("CASE_DECCRA - Copy rectangular area\n")); 5428 xtermParseRect(xw, ParamPair(0), &myRect); 5429 ScrnCopyRectangle(xw, &myRect, ParamPair(5)); 5430 } 5431 ResetState(sp); 5432 break; 5433 5434 case CASE_DECERA: 5435 if (screen->vtXX_level >= 4) { 5436 TRACE(("CASE_DECERA - Erase rectangular area\n")); 5437 xtermParseRect(xw, ParamPair(0), &myRect); 5438 ScrnFillRectangle(xw, &myRect, ' ', xw->flags, True); 5439 } 5440 ResetState(sp); 5441 break; 5442 5443 case CASE_DECFRA: 5444 if (screen->vtXX_level >= 4) { 5445 value = use_default_value(0, ' '); 5446 5447 TRACE(("CASE_DECFRA - Fill rectangular area\n")); 5448 /* DEC 070, page 5-170 says the fill-character is either 5449 * ASCII or Latin1; xterm allows printable Unicode values. 5450 */ 5451 if (nparam > 0 5452 && ((value >= 256 && CharWidth(screen, value) > 0) 5453 || IsLatin1(value))) { 5454 xtermParseRect(xw, ParamPair(1), &myRect); 5455 ScrnFillRectangle(xw, &myRect, value, xw->flags, True); 5456 } 5457 } 5458 ResetState(sp); 5459 break; 5460 5461 case CASE_DECSERA: 5462 if (screen->vtXX_level >= 4) { 5463 TRACE(("CASE_DECSERA - Selective erase rectangular area\n")); 5464 xtermParseRect(xw, ParamPair(0), &myRect); 5465 ScrnWipeRectangle(xw, &myRect); 5466 } 5467 ResetState(sp); 5468 break; 5469 5470 case CASE_DECSACE: 5471 TRACE(("CASE_DECSACE - Select attribute change extent\n")); 5472 screen->cur_decsace = zero_if_default(0); 5473 ResetState(sp); 5474 break; 5475 5476 case CASE_DECCARA: 5477 if (screen->vtXX_level >= 4) { 5478 TRACE(("CASE_DECCARA - Change attributes in rectangular area\n")); 5479 xtermParseRect(xw, ParamPair(0), &myRect); 5480 ScrnMarkRectangle(xw, &myRect, False, ParamPair(4)); 5481 } 5482 ResetState(sp); 5483 break; 5484 5485 case CASE_DECRARA: 5486 if (screen->vtXX_level >= 4) { 5487 TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n")); 5488 xtermParseRect(xw, ParamPair(0), &myRect); 5489 ScrnMarkRectangle(xw, &myRect, True, ParamPair(4)); 5490 } 5491 ResetState(sp); 5492 break; 5493 5494 case CASE_DECSCPP: 5495 if (screen->vtXX_level >= 3) { 5496 TRACE(("CASE_DECSCPP\n")); 5497 /* default and 0 are "80", with "132" as the other legal choice */ 5498 switch (zero_if_default(0)) { 5499 case 0: 5500 case 80: 5501 value = 80; 5502 break; 5503 case 132: 5504 value = 132; 5505 break; 5506 default: 5507 value = -1; 5508 break; 5509 } 5510 if (value > 0) { 5511 if (screen->cur_col + 1 > value) 5512 CursorSet(screen, screen->cur_row, value - 1, xw->flags); 5513 UIntClr(xw->flags, IN132COLUMNS); 5514 if (value == 132) 5515 UIntSet(xw->flags, IN132COLUMNS); 5516 RequestResize(xw, -1, value, True); 5517 } 5518 } 5519 ResetState(sp); 5520 break; 5521 5522 case CASE_DECSNLS: 5523 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetWinLines)) { 5524 TRACE(("CASE_DECSNLS\n")); 5525 value = zero_if_default(0); 5526 if (value >= 1 && value <= 255) { 5527 RequestResize(xw, value, -1, True); 5528 } 5529 } 5530 ResetState(sp); 5531 break; 5532 5533 case CASE_DECRQDE: 5534 if (screen->vtXX_level >= 3) { 5535 init_reply(ANSI_CSI); 5536 count = 0; 5537 reply.a_param[count++] = (ParmType) MaxRows(screen); /* number of lines */ 5538 reply.a_param[count++] = (ParmType) MaxCols(screen); /* number of columns */ 5539 reply.a_param[count++] = 1; /* current page column */ 5540 reply.a_param[count++] = 1; /* current page line */ 5541 reply.a_param[count++] = 1; /* current page */ 5542 reply.a_inters = '"'; 5543 reply.a_final = 'w'; 5544 reply.a_nparam = (ParmType) count; 5545 unparseseq(xw, &reply); 5546 } 5547 ResetState(sp); 5548 break; 5549 5550 case CASE_DECRQPSR: 5551#define reply_char(n,c) do { reply.a_radix[(n)] = 1; reply.a_param[(n)++] = (ParmType)(c); } while (0) 5552#define reply_bit(n,c) ((n) ? (c) : 0) 5553 if (screen->vtXX_level >= 3) { 5554 TRACE(("CASE_DECRQPSR\n")); 5555 switch (GetParam(0)) { 5556 case 1: 5557 TRACE(("...DECCIR\n")); 5558 init_reply(ANSI_DCS); 5559 count = 0; 5560 reply_char(count, '1'); 5561 reply_char(count, '$'); 5562 reply_char(count, 'u'); 5563 reply.a_param[count++] = (ParmType) (screen->cur_row + 1); 5564 reply.a_param[count++] = (ParmType) (screen->cur_col + 1); 5565 reply.a_param[count++] = (ParmType) thispage; 5566 reply_char(count, ';'); 5567 reply_char(count, (0x40 5568 | reply_bit(xw->flags & INVERSE, 8) 5569 | reply_bit(xw->flags & BLINK, 4) 5570 | reply_bit(xw->flags & UNDERLINE, 2) 5571 | reply_bit(xw->flags & BOLD, 1) 5572 )); 5573 reply_char(count, ';'); 5574 reply_char(count, 0x40 | 5575 reply_bit(screen->protected_mode & 5576 DEC_PROTECT, 1) 5577 ); 5578 reply_char(count, ';'); 5579 reply_char(count, (0x40 5580 | reply_bit(screen->do_wrap, 8) 5581 | reply_bit((screen->curss == 3), 4) 5582 | reply_bit((screen->curss == 2), 2) 5583 | reply_bit(xw->flags & ORIGIN, 1) 5584 )); 5585 reply_char(count, ';'); 5586 reply.a_param[count++] = screen->curgl; 5587 reply.a_param[count++] = screen->curgr; 5588 reply_char(count, ';'); 5589 value = 0x40; 5590 for (item = 0; item < NUM_GSETS; ++item) { 5591 value |= (is_96charset(screen->gsets[item]) << item); 5592 } 5593 reply_char(count, value); /* encoded charset sizes */ 5594 reply_char(count, ';'); 5595 for (item = 0; item < NUM_GSETS; ++item) { 5596 int ps; 5597 char *temp = encode_scs(screen->gsets[item], &ps); 5598 while (*temp != '\0') { 5599 reply_char(count, *temp++); 5600 } 5601 } 5602 reply.a_nparam = (ParmType) count; 5603 unparseseq(xw, &reply); 5604 break; 5605 case 2: 5606 TRACE(("...DECTABSR\n")); 5607 init_reply(ANSI_DCS); 5608 reply.a_delim = "/"; 5609 count = 0; 5610 reply_char(count, '2'); 5611 reply_char(count, '$'); 5612 reply_char(count, 'u'); 5613 for (item = 0; item < MAX_TABS; ++item) { 5614 if (count + 1 >= NPARAM) 5615 break; 5616 if (item > screen->max_col) 5617 break; 5618 if (TabIsSet(xw->tabs, item)) 5619 reply.a_param[count++] = (ParmType) (item + 1); 5620 } 5621 reply.a_nparam = (ParmType) count; 5622 unparseseq(xw, &reply); 5623 break; 5624 } 5625 } 5626 ResetState(sp); 5627 break; 5628 5629 case CASE_DECRQUPSS: 5630 TRACE(("CASE_DECRQUPSS\n")); 5631 if (screen->vtXX_level >= 3) { 5632 int psize = 0; 5633 char *encoded = encode_scs(screen->gsets_upss, &psize); 5634 init_reply(ANSI_DCS); 5635 count = 0; 5636 reply_char(count, psize ? '1' : '0'); 5637 reply_char(count, '!'); 5638 reply_char(count, 'u'); 5639 reply_char(count, *encoded++); 5640 if (*encoded) 5641 reply_char(count, *encoded); 5642 reply.a_nparam = (ParmType) count; 5643 unparseseq(xw, &reply); 5644 } 5645 break; 5646 5647 case CASE_RQM: 5648 TRACE(("CASE_RQM\n")); 5649 do_ansi_rqm(xw, ParamPair(0)); 5650 ResetState(sp); 5651 break; 5652 5653 case CASE_DECRQM: 5654 TRACE(("CASE_DECRQM\n")); 5655 do_dec_rqm(xw, ParamPair(0)); 5656 ResetState(sp); 5657 break; 5658 5659 case CASE_CSI_DEC_DOLLAR_STATE: 5660 TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n")); 5661 /* csi ? dollar ($) */ 5662 sp->parsestate = csi_dec_dollar_table; 5663 break; 5664 5665 case CASE_DECST8C: 5666 TRACE(("CASE_DECST8C\n")); 5667 if (screen->vtXX_level >= 5 5668 && (GetParam(0) == 5 || GetParam(0) <= 0)) { 5669 TabZonk(xw->tabs); 5670 for (count = 0; count < MAX_TABS; ++count) { 5671 item = (count + 1) * 8; 5672 if (item > screen->max_col) 5673 break; 5674 TabSet(xw->tabs, item); 5675 } 5676 } 5677 ResetState(sp); 5678 break; 5679#else 5680 case CASE_CSI_DOLLAR_STATE: 5681 /* csi dollar ($) */ 5682 sp->parsestate = eigtable; 5683 break; 5684 5685 case CASE_CSI_STAR_STATE: 5686 /* csi dollar (*) */ 5687 sp->parsestate = eigtable; 5688 break; 5689 5690 case CASE_CSI_DEC_DOLLAR_STATE: 5691 /* csi ? dollar ($) */ 5692 sp->parsestate = eigtable; 5693 break; 5694 5695 case CASE_DECST8C: 5696 /* csi ? 5 W */ 5697 ResetState(sp); 5698 break; 5699#endif /* OPT_DEC_RECTOPS */ 5700 5701#if OPT_VT525_COLORS 5702 case CASE_CSI_COMMA_STATE: 5703 TRACE(("CASE_CSI_COMMA_STATE\n")); 5704 /* csi comma (,) */ 5705 if (screen->vtXX_level >= 5) 5706 sp->parsestate = csi_comma_table; 5707 else 5708 sp->parsestate = eigtable; 5709 break; 5710 5711 case CASE_DECAC: 5712 TRACE(("CASE_DECAC\n")); 5713#if OPT_ISO_COLORS 5714 if (screen->terminal_id >= 525) { 5715 int fg, bg; 5716 5717 switch (GetParam(0)) { 5718 case 1: 5719 fg = GetParam(1); 5720 bg = GetParam(2); 5721 if (fg >= 0 && fg < 16 && bg >= 0 && bg < 16) { 5722 Boolean repaint = False; 5723 5724 if (AssignFgColor(xw, 5725 GET_COLOR_RES(xw, screen->Acolors[fg]))) 5726 repaint = True; 5727 if (AssignBgColor(xw, 5728 GET_COLOR_RES(xw, screen->Acolors[bg]))) 5729 repaint = True; 5730 if (repaint) 5731 xtermRepaint(xw); 5732 screen->assigned_fg = fg; 5733 screen->assigned_bg = bg; 5734 } 5735 break; 5736 case 2: 5737 /* window frames: not implemented */ 5738 break; 5739 } 5740 } 5741#endif 5742 ResetState(sp); 5743 break; 5744 5745 case CASE_DECATC: 5746#if OPT_ISO_COLORS 5747 TRACE(("CASE_DECATC\n")); 5748 if (screen->terminal_id >= 525) { 5749 int ps = GetParam(0); 5750 int fg = GetParam(1); 5751 int bg = GetParam(2); 5752 if (ps >= 0 && ps < 16 5753 && fg >= 0 && fg < 16 5754 && bg >= 0 && bg < 16) { 5755 screen->alt_colors[ps].fg = fg; 5756 screen->alt_colors[ps].bg = bg; 5757 } 5758 } 5759#endif 5760 ResetState(sp); 5761 break; 5762 5763 case CASE_DECTID: 5764 TRACE(("CASE_DECTID\n")); 5765 switch (GetParam(0)) { 5766 case 0: 5767 screen->display_da1 = 100; 5768 break; 5769 case 1: 5770 screen->display_da1 = 101; 5771 break; 5772 case 2: 5773 screen->display_da1 = 102; 5774 break; 5775 case 5: 5776 screen->display_da1 = 220; 5777 break; 5778 case 7: 5779 screen->display_da1 = 320; 5780 break; 5781 case 9: 5782 screen->display_da1 = 420; 5783 break; 5784 case 10: 5785 screen->display_da1 = 520; 5786 break; 5787 } 5788 ResetState(sp); 5789 break; 5790#else 5791 case CASE_CSI_COMMA_STATE: 5792 sp->parsestate = eigtable; 5793 break; 5794#endif 5795 5796 case CASE_DECSASD: 5797#if OPT_STATUS_LINE 5798 if (screen->vtXX_level >= 2) { 5799 handle_DECSASD(xw, zero_if_default(0)); 5800 } 5801#endif 5802 ResetState(sp); 5803 break; 5804 5805 case CASE_DECSSDT: 5806#if OPT_STATUS_LINE 5807 if (screen->vtXX_level >= 2) { 5808 handle_DECSSDT(xw, zero_if_default(0)); 5809 } 5810#endif 5811 ResetState(sp); 5812 break; 5813 5814#if OPT_XTERM_SGR /* most are related, all use csi_hash_table[] */ 5815 case CASE_CSI_HASH_STATE: 5816 TRACE(("CASE_CSI_HASH_STATE\n")); 5817 /* csi hash (#) */ 5818 sp->parsestate = csi_hash_table; 5819 break; 5820 5821 case CASE_XTERM_CHECKSUM: 5822#if OPT_DEC_RECTOPS 5823 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) { 5824 TRACE(("CASE_XTERM_CHECKSUM\n")); 5825 screen->checksum_ext = zero_if_default(0); 5826 } 5827#endif 5828 ResetState(sp); 5829 break; 5830 5831 case CASE_XTERM_PUSH_SGR: 5832 TRACE(("CASE_XTERM_PUSH_SGR\n")); 5833 value = 0; 5834 if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) { 5835 value = DEFAULT; 5836 } else if (nparam > 0) { 5837 for (count = 0; count < nparam; ++count) { 5838 item = zero_if_default(count); 5839 /* deprecated - for compatibility */ 5840#if OPT_ISO_COLORS 5841 if (item == psFG_COLOR_obs) { 5842 item = psFG_COLOR; 5843 } else if (item == psBG_COLOR_obs) { 5844 item = psBG_COLOR; 5845 } 5846#endif 5847 if (item > 0 && item < MAX_PUSH_SGR) { 5848 value |= (1 << (item - 1)); 5849 } 5850 } 5851 } 5852 xtermPushSGR(xw, value); 5853 ResetState(sp); 5854 break; 5855 5856 case CASE_XTERM_REPORT_SGR: 5857 TRACE(("CASE_XTERM_REPORT_SGR\n")); 5858 xtermParseRect(xw, ParamPair(0), &myRect); 5859 xtermReportSGR(xw, &myRect); 5860 ResetState(sp); 5861 break; 5862 5863 case CASE_XTERM_POP_SGR: 5864 TRACE(("CASE_XTERM_POP_SGR\n")); 5865 xtermPopSGR(xw); 5866 ResetState(sp); 5867 break; 5868 5869 case CASE_XTERM_PUSH_COLORS: 5870 TRACE(("CASE_XTERM_PUSH_COLORS\n")); 5871 if (nparam == 0) { 5872 xtermPushColors(xw, DEFAULT); 5873 } else { 5874 for (count = 0; count < nparam; ++count) { 5875 xtermPushColors(xw, GetParam(count)); 5876 } 5877 } 5878 ResetState(sp); 5879 break; 5880 5881 case CASE_XTERM_POP_COLORS: 5882 TRACE(("CASE_XTERM_POP_COLORS\n")); 5883 if (nparam == 0) { 5884 xtermPopColors(xw, DEFAULT); 5885 } else { 5886 for (count = 0; count < nparam; ++count) { 5887 xtermPopColors(xw, GetParam(count)); 5888 } 5889 } 5890 ResetState(sp); 5891 break; 5892 5893 case CASE_XTERM_REPORT_COLORS: 5894 TRACE(("CASE_XTERM_REPORT_COLORS\n")); 5895 xtermReportColors(xw); 5896 ResetState(sp); 5897 break; 5898 5899 case CASE_XTERM_TITLE_STACK: 5900 xtermReportTitleStack(xw); 5901 ResetState(sp); 5902 break; 5903#endif 5904 5905 case CASE_S7C1T: 5906 TRACE(("CASE_S7C1T\n")); 5907 if (screen->vtXX_level >= 2) { 5908 show_8bit_control(False); 5909 ResetState(sp); 5910 } 5911 break; 5912 5913 case CASE_S8C1T: 5914 TRACE(("CASE_S8C1T\n")); 5915 if (screen->vtXX_level >= 2) { 5916 show_8bit_control(True); 5917 ResetState(sp); 5918 } 5919 break; 5920 5921 case CASE_OSC: 5922 TRACE(("CASE_OSC: Operating System Command\n")); 5923 BeginString(ANSI_OSC); 5924 break; 5925 5926 case CASE_RIS: 5927 TRACE(("CASE_RIS\n")); 5928 VTReset(xw, True, True); 5929 /* NOTREACHED */ 5930 5931 case CASE_DECSTR: 5932 TRACE(("CASE_DECSTR\n")); 5933 VTReset(xw, False, False); 5934 /* NOTREACHED */ 5935 5936 case CASE_REP: 5937 TRACE(("CASE_REP\n")); 5938 if (CharWidth(screen, sp->lastchar) > 0) { 5939 IChar repeated[2]; 5940 count = one_if_default(0); 5941 repeated[0] = (IChar) sp->lastchar; 5942 while (count-- > 0) { 5943 dotext(xw, 5944 screen->gsets[(int) (screen->curgl)], 5945 repeated, 1); 5946 } 5947 } 5948 ResetState(sp); 5949 break; 5950 5951 case CASE_LS2: 5952 TRACE(("CASE_LS2\n")); 5953 if (screen->ansi_level > 2) 5954 screen->curgl = 2; 5955 ResetState(sp); 5956 break; 5957 5958 case CASE_LS3: 5959 TRACE(("CASE_LS3\n")); 5960 if (screen->ansi_level > 2) 5961 screen->curgl = 3; 5962 ResetState(sp); 5963 break; 5964 5965 case CASE_LS3R: 5966 TRACE(("CASE_LS3R\n")); 5967 if (screen->ansi_level > 2) 5968 screen->curgr = 3; 5969 ResetState(sp); 5970 break; 5971 5972 case CASE_LS2R: 5973 TRACE(("CASE_LS2R\n")); 5974 if (screen->ansi_level > 2) 5975 screen->curgr = 2; 5976 ResetState(sp); 5977 break; 5978 5979 case CASE_LS1R: 5980 TRACE(("CASE_LS1R\n")); 5981 if (screen->ansi_level > 2) 5982 screen->curgr = 1; 5983 ResetState(sp); 5984 break; 5985 5986 case CASE_XTERM_SAVE: 5987 savemodes(xw); 5988 ResetState(sp); 5989 break; 5990 5991 case CASE_XTERM_RESTORE: 5992 restoremodes(xw); 5993 ResetState(sp); 5994 break; 5995 5996 case CASE_XTERM_WINOPS: 5997 TRACE(("CASE_XTERM_WINOPS\n")); 5998 window_ops(xw); 5999 ResetState(sp); 6000 break; 6001#if OPT_WIDE_CHARS 6002 case CASE_ESC_PERCENT: 6003 TRACE(("CASE_ESC_PERCENT\n")); 6004 sp->parsestate = esc_pct_table; 6005 break; 6006 6007 case CASE_UTF8: 6008 /* If we did not set UTF-8 mode from resource or the 6009 * command-line, allow it to be enabled/disabled by 6010 * control sequence. 6011 */ 6012 TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n", 6013 screen->wide_chars, 6014 screen->utf8_mode, 6015 BtoS(AsciiOf(c) == 'G'))); 6016 if ((!screen->wide_chars) && (AsciiOf(c) == 'G')) { 6017 WriteNow(); 6018 ChangeToWide(xw); 6019 } 6020 if (screen->wide_chars 6021 && !screen->utf8_always) { 6022 switchPtyData(screen, AsciiOf(c) == 'G'); 6023 TRACE(("UTF8 mode %s\n", 6024 BtoS(screen->utf8_mode))); 6025 } else { 6026 TRACE(("UTF8 mode NOT turned %s (%s)\n", 6027 BtoS(AsciiOf(c) == 'G'), 6028 (screen->utf8_mode == uAlways) 6029 ? "UTF-8 mode set from command-line" 6030 : "wideChars resource was not set")); 6031 } 6032 ResetState(sp); 6033 break; 6034 6035 case CASE_SCS_DQUOTE: 6036 TRACE(("CASE_SCS_DQUOTE\n")); 6037 sp->parsestate = scs_2qt_table; 6038 break; 6039 6040 case CASE_GSETS_DQUOTE: 6041 if (screen->vtXX_level >= 5) { 6042 TRACE_GSETS("_DQUOTE"); 6043 xtermDecodeSCS(xw, sp->scstype, 5, '"', (int) c); 6044 } 6045 ResetState(sp); 6046 break; 6047 6048 case CASE_SCS_AMPRSND: 6049 TRACE(("CASE_SCS_AMPRSND\n")); 6050 sp->parsestate = scs_amp_table; 6051 break; 6052 6053 case CASE_GSETS_AMPRSND: 6054 if (screen->vtXX_level >= 5) { 6055 TRACE_GSETS("_AMPRSND"); 6056 xtermDecodeSCS(xw, sp->scstype, 5, '&', (int) c); 6057 } 6058 ResetState(sp); 6059 break; 6060 6061 case CASE_SCS_PERCENT: 6062 TRACE(("CASE_SCS_PERCENT\n")); 6063 sp->parsestate = scs_pct_table; 6064 break; 6065 6066 case CASE_GSETS_PERCENT: 6067 if (screen->vtXX_level >= 3) { 6068 TRACE_GSETS("_PERCENT"); 6069 switch (AsciiOf(c)) { 6070 case '0': /* DEC Turkish */ 6071 case '2': /* Turkish */ 6072 case '=': /* Hebrew */ 6073 value = 5; 6074 break; 6075 case '5': /* DEC Supplemental Graphics */ 6076 case '6': /* Portuguese */ 6077 default: 6078 value = 3; 6079 break; 6080 } 6081 xtermDecodeSCS(xw, sp->scstype, value, '%', (int) c); 6082 } 6083 ResetState(sp); 6084 break; 6085#endif 6086 case CASE_XTERM_SHIFT_ESCAPE: 6087 TRACE(("CASE_XTERM_SHIFT_ESCAPE\n")); 6088 value = ((nparam == 0) 6089 ? 0 6090 : one_if_default(0)); 6091 if (value >= 0 && value <= 1) 6092 xw->keyboard.shift_escape = value; 6093 ResetState(sp); 6094 break; 6095 6096#if OPT_MOD_FKEYS 6097 case CASE_SET_MOD_FKEYS: 6098 TRACE(("CASE_SET_MOD_FKEYS\n")); 6099 if (nparam >= 1) { 6100 set_mod_fkeys(xw, 6101 GetParam(0), 6102 ((nparam > 1) 6103 ? GetParam(1) 6104 : DEFAULT), 6105 True); 6106 } else { 6107 for (value = 1; value <= 5; ++value) 6108 set_mod_fkeys(xw, value, DEFAULT, True); 6109 } 6110 ResetState(sp); 6111 break; 6112 6113 case CASE_SET_MOD_FKEYS0: 6114 TRACE(("CASE_SET_MOD_FKEYS0\n")); 6115 if (nparam >= 1 && GetParam(0) != DEFAULT) { 6116 set_mod_fkeys(xw, GetParam(0), -1, False); 6117 } else { 6118 xw->keyboard.modify_now.function_keys = -1; 6119 } 6120 ResetState(sp); 6121 break; 6122 6123 case CASE_XTERM_REPORT_MOD_FKEYS: 6124 TRACE(("CASE_XTERM_REPORT_MOD_FKEYS\n")); 6125 for (value = 0; value < nparam; ++value) { 6126 report_mod_fkeys(xw, GetParam(value)); 6127 } 6128 ResetState(sp); 6129 break; 6130#endif 6131 case CASE_HIDE_POINTER: 6132 TRACE(("CASE_HIDE_POINTER\n")); 6133 if (nparam >= 1 && GetParam(0) != DEFAULT) { 6134 screen->pointer_mode = GetParam(0); 6135 } else { 6136 screen->pointer_mode = DEF_POINTER_MODE; 6137 } 6138 ResetState(sp); 6139 break; 6140 6141 case CASE_XTERM_SM_TITLE: 6142 TRACE(("CASE_XTERM_SM_TITLE\n")); 6143 if (nparam >= 1) { 6144 for (count = 0; count < nparam; ++count) { 6145 value = GetParam(count); 6146 if (ValidTitleMode(value)) 6147 screen->title_modes |= xBIT(value); 6148 } 6149 } else { 6150 screen->title_modes = DEF_TITLE_MODES; 6151 } 6152 TRACE(("...title_modes %#x\n", screen->title_modes)); 6153 ResetState(sp); 6154 break; 6155 6156 case CASE_XTERM_RM_TITLE: 6157 TRACE(("CASE_XTERM_RM_TITLE\n")); 6158 if (nparam >= 1) { 6159 for (count = 0; count < nparam; ++count) { 6160 value = GetParam(count); 6161 if (ValidTitleMode(value)) 6162 screen->title_modes &= ~xBIT(value); 6163 } 6164 } else { 6165 screen->title_modes = DEF_TITLE_MODES; 6166 } 6167 TRACE(("...title_modes %#x\n", screen->title_modes)); 6168 ResetState(sp); 6169 break; 6170 6171 case CASE_CSI_IGNORE: 6172 sp->parsestate = cigtable; 6173 break; 6174 6175 case CASE_DECSWBV: 6176 TRACE(("CASE_DECSWBV\n")); 6177 switch (zero_if_default(0)) { 6178 case 2: 6179 /* FALLTHRU */ 6180 case 3: 6181 /* FALLTHRU */ 6182 case 4: 6183 screen->warningVolume = bvLow; 6184 break; 6185 case 5: 6186 /* FALLTHRU */ 6187 case 6: 6188 /* FALLTHRU */ 6189 case 7: 6190 /* FALLTHRU */ 6191 case 8: 6192 screen->warningVolume = bvHigh; 6193 break; 6194 default: 6195 screen->warningVolume = bvOff; 6196 break; 6197 } 6198 TRACE(("...warningVolume %d\n", screen->warningVolume)); 6199 ResetState(sp); 6200 break; 6201 6202 case CASE_DECSMBV: 6203 TRACE(("CASE_DECSMBV\n")); 6204 switch (zero_if_default(0)) { 6205 case 2: 6206 /* FALLTHRU */ 6207 case 3: 6208 /* FALLTHRU */ 6209 case 4: 6210 screen->marginVolume = bvLow; 6211 break; 6212 case 0: 6213 /* FALLTHRU */ 6214 case 5: 6215 /* FALLTHRU */ 6216 case 6: 6217 /* FALLTHRU */ 6218 case 7: 6219 /* FALLTHRU */ 6220 case 8: 6221 screen->marginVolume = bvHigh; 6222 break; 6223 default: 6224 screen->marginVolume = bvOff; 6225 break; 6226 } 6227 TRACE(("...marginVolume %d\n", screen->marginVolume)); 6228 ResetState(sp); 6229 break; 6230 } 6231 if (sp->parsestate == sp->groundtable) 6232 sp->lastchar = thischar; 6233 } while (0); 6234 6235#if OPT_WIDE_CHARS 6236 screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse) 6237 && (sp->parsestate != sos_table)); 6238#endif 6239 6240 if (sp->check_recur) 6241 sp->check_recur--; 6242 return True; 6243} 6244 6245static void 6246VTparse(XtermWidget xw) 6247{ 6248 Boolean keep_running; 6249 6250 /* We longjmp back to this point in VTReset() */ 6251 (void) setjmp(vtjmpbuf); 6252 init_parser(xw, &myState); 6253 6254 do { 6255 keep_running = doparsing(xw, doinput(xw), &myState); 6256 if (myState.check_recur == 0 && myState.defer_used != 0) { 6257 while (myState.defer_used) { 6258 Char *deferred = myState.defer_area; 6259 size_t len = myState.defer_used; 6260 size_t i; 6261 myState.defer_area = NULL; 6262 myState.defer_size = 0; 6263 myState.defer_used = 0; 6264 for (i = 0; i < len; i++) { 6265 (void) doparsing(xw, deferred[i], &myState); 6266 } 6267 free(deferred); 6268 } 6269 } else { 6270 free(myState.defer_area); 6271 } 6272 myState.defer_area = NULL; 6273 myState.defer_size = 0; 6274 myState.defer_used = 0; 6275 } while (keep_running); 6276} 6277 6278static Char *v_buffer; /* pointer to physical buffer */ 6279static Char *v_bufstr = NULL; /* beginning of area to write */ 6280static Char *v_bufptr; /* end of area to write */ 6281static Char *v_bufend; /* end of physical buffer */ 6282 6283/* Write data to the pty as typed by the user, pasted with the mouse, 6284 or generated by us in response to a query ESC sequence. */ 6285 6286void 6287v_write(int f, const Char *data, size_t len) 6288{ 6289 TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len))); 6290 if (v_bufstr == NULL) { 6291 if (len > 0) { 6292 v_buffer = (Char *) XtMalloc((Cardinal) len); 6293 v_bufstr = v_buffer; 6294 v_bufptr = v_buffer; 6295 v_bufend = v_buffer + len; 6296 } 6297 if (v_bufstr == NULL) { 6298 return; 6299 } 6300 } 6301 if_DEBUG({ 6302 fprintf(stderr, "v_write called with %lu bytes (%lu left over)", 6303 (unsigned long) len, 6304 (unsigned long) (v_bufptr - v_bufstr)); 6305 if (len > 1 && len < 10) 6306 fprintf(stderr, " \"%.*s\"", (int) len, (const char *) data); 6307 fprintf(stderr, "\n"); 6308 }); 6309 6310 if (!FD_ISSET(f, &pty_mask)) { 6311 IGNORE_RC(write(f, (const char *) data, (size_t) len)); 6312 return; 6313 } 6314 6315 /* 6316 * Append to the block we already have. 6317 * Always doing this simplifies the code, and 6318 * isn't too bad, either. If this is a short 6319 * block, it isn't too expensive, and if this is 6320 * a long block, we won't be able to write it all 6321 * anyway. 6322 */ 6323 6324 if (len > 0) { 6325#if OPT_DABBREV 6326 TScreenOf(term)->dabbrev_working = False; /* break dabbrev sequence */ 6327#endif 6328 if (v_bufend < v_bufptr + len) { /* we've run out of room */ 6329 if (v_bufstr != v_buffer) { 6330 /* there is unused space, move everything down */ 6331 /* possibly overlapping memmove here */ 6332 if_DEBUG({ 6333 fprintf(stderr, "moving data down %ld\n", 6334 (long) (v_bufstr - v_buffer)); 6335 }); 6336 memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr)); 6337 v_bufptr -= v_bufstr - v_buffer; 6338 v_bufstr = v_buffer; 6339 } 6340 if (v_bufend < v_bufptr + len) { 6341 /* still won't fit: get more space */ 6342 /* Don't use XtRealloc because an error is not fatal. */ 6343 size_t size = (size_t) (v_bufptr - v_buffer); 6344 v_buffer = TypeRealloc(Char, size + len, v_buffer); 6345 if (v_buffer) { 6346 if_DEBUG({ 6347 fprintf(stderr, "expanded buffer to %lu\n", 6348 (unsigned long) (size + len)); 6349 }); 6350 v_bufstr = v_buffer; 6351 v_bufptr = v_buffer + size; 6352 v_bufend = v_bufptr + len; 6353 } else { 6354 /* no memory: ignore entire write request */ 6355 xtermWarning("cannot allocate buffer space\n"); 6356 v_buffer = v_bufstr; /* restore clobbered pointer */ 6357 } 6358 } 6359 } 6360 if (v_bufend >= v_bufptr + len) { 6361 /* new stuff will fit */ 6362 memmove(v_bufptr, data, (size_t) len); 6363 v_bufptr += len; 6364 } 6365 } 6366 6367 /* 6368 * Write out as much of the buffer as we can. 6369 * Be careful not to overflow the pty's input silo. 6370 * We are conservative here and only write 6371 * a small amount at a time. 6372 * 6373 * If we can't push all the data into the pty yet, we expect write 6374 * to return a non-negative number less than the length requested 6375 * (if some data written) or -1 and set errno to EAGAIN, 6376 * EWOULDBLOCK, or EINTR (if no data written). 6377 * 6378 * (Not all systems do this, sigh, so the code is actually 6379 * a little more forgiving.) 6380 */ 6381 6382#define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */ 6383 6384 if (v_bufptr > v_bufstr) { 6385 int riten; 6386 6387 riten = (int) write(f, v_bufstr, 6388 (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE) 6389 ? v_bufptr - v_bufstr 6390 : MAX_PTY_WRITE)); 6391 if (riten < 0) { 6392 if_DEBUG({ 6393 perror("write"); 6394 }); 6395 riten = 0; 6396 } 6397 if_DEBUG({ 6398 fprintf(stderr, "write called with %ld, wrote %d\n", 6399 ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE) 6400 ? (long) (v_bufptr - v_bufstr) 6401 : MAX_PTY_WRITE), 6402 riten); 6403 }); 6404 v_bufstr += riten; 6405 if (v_bufstr >= v_bufptr) /* we wrote it all */ 6406 v_bufstr = v_bufptr = v_buffer; 6407 } 6408 6409 /* 6410 * If we have lots of unused memory allocated, return it 6411 */ 6412 if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */ 6413 /* save pointers across realloc */ 6414 size_t start = (size_t) (v_bufstr - v_buffer); 6415 size_t size = (size_t) (v_bufptr - v_buffer); 6416 size_t allocsize = (size ? size : 1); 6417 6418 v_buffer = TypeRealloc(Char, allocsize, v_buffer); 6419 if (v_buffer) { 6420 v_bufstr = v_buffer + start; 6421 v_bufptr = v_buffer + size; 6422 v_bufend = v_buffer + allocsize; 6423 if_DEBUG({ 6424 fprintf(stderr, "shrunk buffer to %lu\n", (unsigned long) allocsize); 6425 }); 6426 } else { 6427 /* should we print a warning if couldn't return memory? */ 6428 v_buffer = v_bufstr - start; /* restore clobbered pointer */ 6429 } 6430 } 6431} 6432 6433static void 6434updateCursor(XtermWidget xw) 6435{ 6436 TScreen *screen = TScreenOf(xw); 6437 6438 if (screen->cursor_set != screen->cursor_state) { 6439 if (screen->cursor_set) 6440 ShowCursor(xw); 6441 else 6442 HideCursor(xw); 6443 } 6444} 6445 6446#if OPT_BLINK_CURS || OPT_BLINK_TEXT 6447static void 6448reallyStopBlinking(XtermWidget xw) 6449{ 6450 TScreen *screen = TScreenOf(xw); 6451 6452 if (screen->cursor_state == BLINKED_OFF) { 6453 /* force cursor to display if it is enabled */ 6454 screen->cursor_state = !screen->cursor_set; 6455 updateCursor(xw); 6456 xevents(xw); 6457 } 6458} 6459#endif 6460 6461static void 6462update_the_screen(XtermWidget xw) 6463{ 6464 TScreen *screen = TScreenOf(xw); 6465 Boolean moved; 6466 6467 if (screen->scroll_amt) 6468 FlushScroll(xw); 6469 moved = CursorMoved(screen); 6470 if (screen->cursor_set && moved) { 6471 if (screen->cursor_state) 6472 HideCursor(xw); 6473 ShowCursor(xw); 6474#if OPT_INPUT_METHOD 6475 PreeditPosition(xw); 6476#endif 6477 } else { 6478#if OPT_INPUT_METHOD 6479 if (moved) 6480 PreeditPosition(xw); 6481#endif 6482 updateCursor(xw); 6483 } 6484} 6485 6486static void 6487init_timeval(struct timeval *target, long usecs) 6488{ 6489 target->tv_sec = 0; 6490 target->tv_usec = usecs; 6491 while (target->tv_usec > 1000000) { 6492 target->tv_usec -= 1000000; 6493 target->tv_sec++; 6494 } 6495} 6496 6497static Boolean 6498better_timeout(struct timeval *check, struct timeval *against) 6499{ 6500 Boolean result = False; 6501 if (against->tv_sec == 0 && against->tv_usec == 0) { 6502 result = True; 6503 } else if (check->tv_sec == against->tv_sec) { 6504 if (check->tv_usec < against->tv_usec) { 6505 result = True; 6506 } 6507 } else if (check->tv_sec < against->tv_sec) { 6508 result = True; 6509 } 6510 return result; 6511} 6512 6513#if OPT_BLINK_CURS 6514static long 6515smaller_timeout(long value) 6516{ 6517 /* 1000 for msec/usec, 8 for "much" smaller */ 6518 value *= (1000 / 8); 6519 if (value < 1) 6520 value = 1; 6521 return value; 6522} 6523#endif 6524 6525static void 6526in_put(XtermWidget xw) 6527{ 6528 static PtySelect select_mask; 6529 static PtySelect write_mask; 6530 6531 TScreen *screen = TScreenOf(xw); 6532 int i; 6533 int update = VTbuffer->update; 6534#if USE_DOUBLE_BUFFER 6535 int should_wait = 1; 6536#endif 6537 struct timeval my_timeout; 6538 6539 for (;;) { 6540 int size; 6541 int time_select; 6542 6543 if (screen->eventMode == NORMAL 6544 && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) { 6545 if (screen->scrollWidget 6546 && screen->scrollttyoutput 6547 && screen->topline < 0) 6548 WindowScroll(xw, 0, False); /* Scroll to bottom */ 6549 /* stop speed reading at some point to look for X stuff */ 6550 TRACE(("VTbuffer uses %ld/%d\n", 6551 (long) (VTbuffer->last - VTbuffer->buffer), 6552 BUF_SIZE)); 6553 if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) { 6554 FD_CLR(screen->respond, &select_mask); 6555 break; 6556 } 6557#if USE_DOUBLE_BUFFER 6558 if (resource.buffered && should_wait) { 6559 /* wait for potential extra data (avoids some flickering) */ 6560 usleep((unsigned) DbeMsecs(xw)); 6561 should_wait = 0; 6562 } 6563#endif 6564#if defined(HAVE_SCHED_YIELD) 6565 /* 6566 * If we've read a full (small/fragment) buffer, let the operating 6567 * system have a turn, and we'll resume reading until we've either 6568 * read only a fragment of the buffer, or we've filled the large 6569 * buffer (see above). Doing this helps keep up with large bursts 6570 * of output. 6571 */ 6572 if (size == FRG_SIZE) { 6573 init_timeval(&my_timeout, 0L); 6574 i = Select(max_plus1, &select_mask, &write_mask, 0, &my_timeout); 6575 if (i > 0 && FD_ISSET(screen->respond, &select_mask)) { 6576 sched_yield(); 6577 } else 6578 break; 6579 } else { 6580 break; 6581 } 6582#else 6583 (void) size; /* unused in this branch */ 6584 break; 6585#endif 6586 } 6587 update_the_screen(xw); 6588 6589 XFlush(screen->display); /* always flush writes before waiting */ 6590 6591 /* Update the masks and, unless X events are already in the queue, 6592 wait for I/O to be possible. */ 6593 XFD_COPYSET(&Select_mask, &select_mask); 6594 /* in selection mode xterm does not read pty */ 6595 if (screen->eventMode != NORMAL) 6596 FD_CLR(screen->respond, &select_mask); 6597 6598 if (v_bufptr > v_bufstr) { 6599 XFD_COPYSET(&pty_mask, &write_mask); 6600 } else 6601 FD_ZERO(&write_mask); 6602 init_timeval(&my_timeout, 0L); 6603 time_select = 0; 6604 6605 /* 6606 * if there's either an XEvent or an XtTimeout pending, just take 6607 * a quick peek, i.e. timeout from the select() immediately. If 6608 * there's nothing pending, let select() block a little while, but 6609 * for a shorter interval than the arrow-style scrollbar timeout. 6610 * The blocking is optional, because it tends to increase the load 6611 * on the host. 6612 */ 6613 if (xtermAppPending()) { 6614 time_select = 1; 6615 } else { 6616#define ImproveTimeout(usecs) \ 6617 struct timeval try_timeout; \ 6618 init_timeval(&try_timeout, usecs); \ 6619 if (better_timeout(&try_timeout, &my_timeout)) { \ 6620 my_timeout = try_timeout; \ 6621 } 6622#if OPT_STATUS_LINE 6623 if ((screen->status_type == 1) && screen->status_timeout) { 6624 ImproveTimeout(find_SL_Timeout(xw) * 1000L); 6625 time_select = 1; 6626 } 6627#endif 6628 if (screen->awaitInput) { 6629 ImproveTimeout(50000L); 6630 time_select = 1; 6631 } 6632#if OPT_BLINK_CURS 6633 if ((screen->blink_timer != 0 && 6634 ((screen->select & FOCUS) || screen->always_highlight)) || 6635 (screen->cursor_state == BLINKED_OFF)) { 6636 /* 6637 * Compute the timeout for the blinking cursor to be much 6638 * smaller than the "on" or "off" interval. 6639 */ 6640 long tick = smaller_timeout((long) ((screen->blink_on < screen->blink_off) 6641 ? screen->blink_on 6642 : screen->blink_off)); 6643 ImproveTimeout(tick); 6644 time_select = 1; 6645 } 6646#endif 6647 } 6648#if OPT_SESSION_MGT 6649 if (resource.sessionMgt && (ice_fd >= 0)) { 6650 FD_SET(ice_fd, &select_mask); 6651 } 6652#endif 6653 if (need_cleanup) 6654 NormalExit(); 6655 xtermFlushDbe(xw); 6656 i = Select(max_plus1, &select_mask, &write_mask, 0, 6657 (time_select ? &my_timeout : NULL)); 6658 if (i < 0) { 6659 if (errno != EINTR) 6660 SysError(ERROR_SELECT); 6661 continue; 6662 } 6663 6664 /* if there is room to write more data to the pty, go write more */ 6665 if (FD_ISSET(screen->respond, &write_mask)) { 6666 v_write(screen->respond, (Char *) 0, (size_t) 0); /* flush buffer */ 6667 } 6668 6669 /* if there are X events already in our queue, it 6670 counts as being readable */ 6671 if (xtermAppPending() || 6672 FD_ISSET(ConnectionNumber(screen->display), &select_mask)) { 6673 xevents(xw); 6674 if (VTbuffer->update != update) /* HandleInterpret */ 6675 break; 6676 } 6677 6678 } 6679} 6680 6681static IChar 6682doinput(XtermWidget xw) 6683{ 6684 TScreen *screen = TScreenOf(xw); 6685 6686 while (!morePtyData(screen, VTbuffer)) 6687 in_put(xw); 6688 return nextPtyData(screen, VTbuffer); 6689} 6690 6691#if OPT_INPUT_METHOD 6692/* 6693 * For OverTheSpot, client has to inform the position for XIM preedit. 6694 */ 6695static void 6696PreeditPosition(XtermWidget xw) 6697{ 6698 TInput *input = lookupTInput(xw, (Widget) xw); 6699 TScreen *screen = TScreenOf(xw); 6700 CLineData *ld; 6701 XPoint spot; 6702 XVaNestedList list; 6703 6704 if (input && input->xic 6705 && (ld = getLineData(screen, screen->cur_row)) != NULL) { 6706 spot.x = (short) LineCursorX(screen, ld, screen->cur_col); 6707 spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent); 6708 list = XVaCreateNestedList(0, 6709 XNSpotLocation, &spot, 6710 XNForeground, T_COLOR(screen, TEXT_FG), 6711 XNBackground, T_COLOR(screen, TEXT_BG), 6712 (void *) 0); 6713 XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0); 6714 XFree(list); 6715 } 6716} 6717#endif 6718 6719static void 6720WrapLine(XtermWidget xw) 6721{ 6722 TScreen *screen = TScreenOf(xw); 6723 LineData *ld = getLineData(screen, screen->cur_row); 6724 6725 if (ld != NULL) { 6726 /* mark that we had to wrap this line */ 6727 LineSetFlag(ld, LINEWRAPPED); 6728 ShowWrapMarks(xw, screen->cur_row, ld); 6729 xtermAutoPrint(xw, '\n'); 6730 xtermIndex(xw, 1); 6731 set_cur_col(screen, ScrnLeftMargin(xw)); 6732 } 6733} 6734 6735/* 6736 * Process a string of characters according to the character set indicated by 6737 * charset. Worry about end of line conditions (wraparound if selected). 6738 * 6739 * It is possible to use CUP, etc., to move outside margins. In that case, the 6740 * right-margin is ineffective until the text (may) wrap and get within the 6741 * margins. 6742 */ 6743void 6744dotext(XtermWidget xw, 6745 DECNRCM_codes charset, 6746 IChar *buf, /* start of characters to process */ 6747 Cardinal len) /* end */ 6748{ 6749 TScreen *screen = TScreenOf(xw); 6750#if OPT_WIDE_CHARS 6751 Cardinal chars_chomped = 1; 6752 int next_col = screen->cur_col; 6753#else 6754 int next_col, this_col; /* must be signed */ 6755#endif 6756 Cardinal offset; 6757 int rmargin = ScrnRightMargin(xw); 6758 6759 xw->work.write_text = buf; 6760#if OPT_DEC_RECTOPS 6761 xw->work.write_sums = NULL; 6762#endif 6763#if OPT_WIDE_CHARS 6764 if (screen->vt100_graphics) 6765#endif 6766 { 6767 DECNRCM_codes rightset = screen->gsets[(int) (screen->curgr)]; 6768 if (charset != nrc_ASCII || rightset != nrc_ASCII) { 6769 len = xtermCharSetOut(xw, len, charset); 6770 if (len == 0) 6771 return; 6772 } 6773 } 6774 6775 if_OPT_XMC_GLITCH(screen, { 6776 Cardinal n; 6777 if (charset != '?') { 6778 for (n = 0; n < len; n++) { 6779 if (buf[n] == XMC_GLITCH) 6780 buf[n] = XMC_GLITCH + 1; 6781 } 6782 } 6783 }); 6784 6785#if OPT_WIDE_CHARS 6786 for (offset = 0; 6787 offset < len && (chars_chomped > 0 || screen->do_wrap); 6788 offset += chars_chomped) { 6789#if OPT_DEC_CHRSET 6790 CLineData *ld = getLineData(screen, screen->cur_row); 6791 int real_rmargin = (CSET_DOUBLE(GetLineDblCS(ld)) 6792 ? (rmargin / 2) 6793 : rmargin); 6794#else 6795 int real_rmargin = rmargin; 6796#endif 6797 int last_col = LineMaxCol(screen, ld); 6798 int width_here = 0; 6799 int last_chomp = 0; 6800 Boolean force_wrap; 6801 6802 chars_chomped = 0; 6803 do { 6804 int right = ((screen->cur_col > real_rmargin) 6805 ? last_col 6806 : real_rmargin); 6807 int width_available = right + 1 - screen->cur_col; 6808 Boolean need_wrap = False; 6809 Boolean did_wrap = False; 6810 6811 force_wrap = False; 6812 6813 if (screen->do_wrap) { 6814 screen->do_wrap = False; 6815 if ((xw->flags & WRAPAROUND)) { 6816 WrapLine(xw); 6817 right = ((screen->cur_col > real_rmargin) 6818 ? last_col 6819 : real_rmargin); 6820 width_available = right + 1 - screen->cur_col; 6821 next_col = screen->cur_col; 6822 did_wrap = True; 6823 } 6824 } 6825 6826 /* 6827 * This can happen with left/right margins... 6828 */ 6829 if (width_available <= 0) { 6830 break; 6831 } 6832 6833 /* 6834 * Regarding the soft-hyphen aberration, see 6835 * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html 6836 */ 6837 while (width_here <= width_available 6838 && chars_chomped < (len - offset)) { 6839 Cardinal n = chars_chomped + offset; 6840 if (!screen->utf8_mode 6841 || (screen->vt100_graphics && charset == '0')) { 6842 last_chomp = 1; 6843 } else if (screen->c1_printable && 6844 buf[n] >= 0x80 && 6845 buf[n] <= 0xa0) { 6846 last_chomp = 1; 6847 } else { 6848 last_chomp = CharWidth(screen, buf[n]); 6849 if (last_chomp <= 0) { 6850 IChar ch = buf[n]; 6851 Bool eat_it = !screen->utf8_mode && (ch > 127); 6852 if (ch == 0xad) { 6853 /* 6854 * Only display soft-hyphen if it happens to be at 6855 * the right-margin. While that means that only 6856 * the displayed character could be selected for 6857 * pasting, a well-behaved application would never 6858 * send this, anyway... 6859 */ 6860 if (width_here < width_available - 1) { 6861 eat_it = True; 6862 } else { 6863 last_chomp = 1; 6864 eat_it = False; 6865 } 6866 TRACE(("...will%s display soft-hyphen\n", 6867 eat_it ? " not" : "")); 6868 } 6869 /* 6870 * Supposedly we dealt with combining characters and 6871 * control characters in doparse(). Anything left over 6872 * is junk that we will not attempt to display. 6873 */ 6874 if (eat_it) { 6875 TRACE(("...will not display U+%04X\n", ch)); 6876 --len; 6877 while (n < len) { 6878 buf[n] = buf[n + 1]; 6879 ++n; 6880 } 6881 last_chomp = 0; 6882 chars_chomped--; 6883 } 6884 } 6885 } 6886 width_here += last_chomp; 6887 chars_chomped++; 6888 } 6889 6890 if (width_here > width_available) { 6891 if (last_chomp > right + 1) { 6892 break; /* give up - it is too big */ 6893 } else if (chars_chomped-- == 0) { 6894 /* This can happen with left/right margins... */ 6895 break; 6896 } 6897 width_here -= last_chomp; 6898 if (chars_chomped > 0) { 6899 if (!(xw->flags & WRAPAROUND)) { 6900 buf[chars_chomped + offset - 1] = buf[len - 1]; 6901 } else { 6902 need_wrap = True; 6903 } 6904 } 6905 } else if (width_here == width_available) { 6906 need_wrap = True; 6907 } else if (chars_chomped != (len - offset)) { 6908 need_wrap = True; 6909 } 6910 6911 if (chars_chomped != 0 && next_col <= last_col) { 6912 WriteText(xw, offset, chars_chomped); 6913 } else if (!did_wrap 6914 && len > 0 6915 && (xw->flags & WRAPAROUND) 6916 && screen->cur_col > ScrnLeftMargin(xw)) { 6917 force_wrap = True; 6918 need_wrap = True; 6919 } 6920 next_col += width_here; 6921 screen->do_wrap = need_wrap; 6922 } while (force_wrap); 6923 } 6924 6925 /* 6926 * Remember that we wrote something to the screen, for use as a base of 6927 * combining characters. The logic above may have called cursor-forward 6928 * or carriage-return operations which resets this flag, so we set it at 6929 * the very end. 6930 */ 6931 screen->char_was_written = True; 6932#else /* ! OPT_WIDE_CHARS */ 6933 6934 for (offset = 0; offset < len; offset += (Cardinal) this_col) { 6935#if OPT_DEC_CHRSET 6936 CLineData *ld = getLineData(screen, screen->cur_row); 6937#endif 6938 int right = ((screen->cur_col > rmargin) 6939 ? screen->max_col 6940 : rmargin); 6941 6942 int last_col = LineMaxCol(screen, ld); 6943 if (last_col > right) 6944 last_col = right; 6945 this_col = last_col - screen->cur_col + 1; 6946 if (screen->do_wrap) { 6947 screen->do_wrap = False; 6948 if ((xw->flags & WRAPAROUND)) { 6949 WrapLine(xw); 6950 } 6951 this_col = 1; 6952 } 6953 if (offset + (Cardinal) this_col > len) { 6954 this_col = (int) (len - offset); 6955 } 6956 next_col = screen->cur_col + this_col; 6957 6958 WriteText(xw, offset, (unsigned) this_col); 6959 6960 /* 6961 * The call to WriteText updates screen->cur_col. 6962 * If screen->cur_col is less than next_col, we must have 6963 * hit the right margin - so set the do_wrap flag. 6964 */ 6965 screen->do_wrap = (Boolean) (screen->cur_col < next_col); 6966 } 6967 6968#endif /* OPT_WIDE_CHARS */ 6969} 6970 6971#if OPT_WIDE_CHARS 6972unsigned 6973visual_width(const IChar *str, Cardinal len) 6974{ 6975 /* returns the visual width of a string (doublewide characters count 6976 as 2, normalwide characters count as 1) */ 6977 unsigned my_len = 0; 6978 while (len) { 6979 int ch = (int) *str++; 6980 if (isWide(ch)) 6981 my_len += 2; 6982 else 6983 my_len++; 6984 len--; 6985 } 6986 return my_len; 6987} 6988#endif 6989 6990#if HANDLE_STRUCT_NOTIFY 6991/* Flag icon name with "***" on window output when iconified. 6992 */ 6993static void 6994HandleStructNotify(Widget w GCC_UNUSED, 6995 XtPointer closure GCC_UNUSED, 6996 XEvent *event, 6997 Boolean *cont GCC_UNUSED) 6998{ 6999 XtermWidget xw = term; 7000 TScreen *screen = TScreenOf(xw); 7001 7002 (void) screen; 7003 TRACE_EVENT("HandleStructNotify", event, NULL, NULL); 7004 switch (event->type) { 7005 case MapNotify: 7006 resetZIconBeep(xw); 7007 mapstate = !IsUnmapped; 7008 break; 7009 case UnmapNotify: 7010 mapstate = IsUnmapped; 7011 break; 7012 case MappingNotify: 7013 XRefreshKeyboardMapping(&(event->xmapping)); 7014 VTInitModifiers(xw); 7015 break; 7016 case ConfigureNotify: 7017 if (event->xconfigure.window == XtWindow(toplevel)) { 7018#if !OPT_TOOLBAR 7019 int height = event->xconfigure.height; 7020 int width = event->xconfigure.width; 7021#endif 7022 7023#if USE_DOUBLE_BUFFER 7024 discardRenderDraw(screen); 7025#endif /* USE_DOUBLE_BUFFER */ 7026#if OPT_TOOLBAR 7027 /* 7028 * The notification is for the top-level widget, but we care about 7029 * vt100 (ignore the tek4014 window). 7030 */ 7031 if (screen->Vshow) { 7032 VTwin *Vwin = WhichVWin(screen); 7033 TbInfo *info = &(Vwin->tb_info); 7034 TbInfo save = *info; 7035 7036 if (info->menu_bar) { 7037 XtVaGetValues(info->menu_bar, 7038 XtNheight, &info->menu_height, 7039 XtNborderWidth, &info->menu_border, 7040 (XtPointer) 0); 7041 7042 if (save.menu_height != info->menu_height 7043 || save.menu_border != info->menu_border) { 7044 7045 TRACE(("...menu_height %d\n", info->menu_height)); 7046 TRACE(("...menu_border %d\n", info->menu_border)); 7047 TRACE(("...had height %d, border %d\n", 7048 save.menu_height, 7049 save.menu_border)); 7050 7051 /* 7052 * Window manager still may be using the old values. 7053 * Try to fool it. 7054 */ 7055 REQ_RESIZE((Widget) xw, 7056 screen->fullVwin.fullwidth, 7057 (Dimension) (info->menu_height 7058 - save.menu_height 7059 + screen->fullVwin.fullheight), 7060 NULL, NULL); 7061 repairSizeHints(); 7062 } 7063 } 7064 } 7065#else 7066 if (!xw->work.doing_resize 7067#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 7068 && !(resource.buffered && UsingRenderFont(xw)) /* buggyXft */ 7069#endif 7070 && (height != xw->hints.height 7071 || width != xw->hints.width)) { 7072 /* 7073 * This is a special case: other calls to RequestResize that 7074 * could set the screensize arbitrarily are via escape 7075 * sequences, and we've limited resizing. But a configure 7076 * notify is from the window manager, presumably under control 7077 * of the interactive user (ignoring abuse of wmctrl). Ignore 7078 * the limit for this case. 7079 */ 7080 int saved_limit = xw->misc.limit_resize; 7081 xw->misc.limit_resize = 0; 7082 RequestResize(xw, height, width, False); 7083 xw->misc.limit_resize = saved_limit; 7084 } 7085#endif /* OPT_TOOLBAR */ 7086 } 7087 break; 7088 } 7089} 7090#endif /* HANDLE_STRUCT_NOTIFY */ 7091 7092#if OPT_BLINK_CURS 7093static int 7094DoStartBlinking(TScreen *screen) 7095{ 7096 int actual = ((screen->cursor_blink == cbTrue || 7097 screen->cursor_blink == cbAlways) 7098 ? 1 7099 : 0); 7100 int wanted = screen->cursor_blink_esc ? 1 : 0; 7101 int result; 7102 if (screen->cursor_blink_xor) { 7103 result = actual ^ wanted; 7104 } else { 7105 result = actual | wanted; 7106 } 7107 return result; 7108} 7109 7110static void 7111SetCursorBlink(XtermWidget xw, BlinkOps enable) 7112{ 7113 TScreen *screen = TScreenOf(xw); 7114 7115 if (SettableCursorBlink(screen)) { 7116 screen->cursor_blink = enable; 7117 } 7118 if (DoStartBlinking(screen)) { 7119 StartBlinking(xw); 7120 } else { 7121 /* EMPTY */ 7122#if OPT_BLINK_TEXT 7123 reallyStopBlinking(xw); 7124#else 7125 StopBlinking(xw); 7126#endif 7127 } 7128 update_cursorblink(); 7129} 7130 7131void 7132ToggleCursorBlink(XtermWidget xw) 7133{ 7134 TScreen *screen = TScreenOf(xw); 7135 7136 if (screen->cursor_blink == cbTrue) { 7137 SetCursorBlink(xw, cbFalse); 7138 } else if (screen->cursor_blink == cbFalse) { 7139 SetCursorBlink(xw, cbTrue); 7140 } 7141} 7142#endif 7143 7144/* 7145 * process ANSI modes set, reset 7146 */ 7147static void 7148ansi_modes(XtermWidget xw, BitFunc func) 7149{ 7150 int i; 7151 7152 for (i = 0; i < nparam; ++i) { 7153 switch (GetParam(i)) { 7154 case 2: /* KAM (if set, keyboard locked */ 7155 (*func) (&xw->keyboard.flags, MODE_KAM); 7156 break; 7157 7158 case 4: /* IRM */ 7159 (*func) (&xw->flags, INSERT); 7160 break; 7161 7162 case 12: /* SRM (if set, local echo */ 7163 (*func) (&xw->keyboard.flags, MODE_SRM); 7164 break; 7165 7166 case 20: /* LNM */ 7167 (*func) (&xw->flags, LINEFEED); 7168 update_autolinefeed(); 7169 break; 7170 } 7171 } 7172} 7173 7174#define IsSM() (func == bitset) 7175 7176#define set_bool_mode(flag) \ 7177 flag = (Boolean) IsSM() 7178 7179static void 7180really_set_mousemode(XtermWidget xw, 7181 Bool enabled, 7182 XtermMouseModes mode) 7183{ 7184 TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF; 7185 if (okSendMousePos(xw) != MOUSE_OFF) 7186 xtermShowPointer(xw, True); 7187} 7188 7189#define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode) 7190 7191#if OPT_PASTE64 || OPT_READLINE 7192#define set_mouseflag(f) \ 7193 (IsSM() \ 7194 ? SCREEN_FLAG_set(screen, f) \ 7195 : SCREEN_FLAG_unset(screen, f)) 7196#endif 7197 7198/* 7199 * DEC 070, pp 5-29 to 5-30 (DECLRMM). 7200 * DEC 070, pp 5-71 to 5-72 (DECCOLM). 7201 * 7202 * The descriptions for DECLRMM and DECCOLM agree that setting DECLRMM resets 7203 * double-sized mode to single-size, and that if DECLRMM is being set, then 7204 * double-sized mode is disabled. Resetting DECLRMM has no effect on the 7205 * double-sized mode. The description of DECCOLM has an apparent error in its 7206 * pseudo-code (because it is inconsistent with the description of DECLRMM), 7207 * indicating that left_right_margins_mode is changed to SETABLE no matter 7208 * which way DECCOLM is set. 7209 */ 7210static void 7211set_column_mode(XtermWidget xw) 7212{ 7213 TScreen *screen = TScreenOf(xw); 7214 7215 /* switch 80/132 columns clears the screen and sets to single-width */ 7216 xterm_ResetDouble(xw); 7217 resetMargins(xw); 7218 CursorSet(screen, 0, 0, xw->flags); 7219} 7220 7221/* 7222 * DEC 070, pp 5-29 to 5-30. 7223 */ 7224static void 7225set_left_right_margin_mode(XtermWidget xw) 7226{ 7227 TScreen *screen = TScreenOf(xw); 7228 7229 if (screen->vtXX_level >= 4) { 7230 if (IsLeftRightMode(xw)) { 7231 xterm_ResetDouble(xw); 7232 } else { 7233 reset_lr_margins(screen); 7234 } 7235 } 7236} 7237 7238/* 7239 * process DEC private modes set, reset 7240 */ 7241static void 7242dpmodes(XtermWidget xw, BitFunc func) 7243{ 7244 TScreen *screen = TScreenOf(xw); 7245 int i, j; 7246 unsigned myflags; 7247 7248 TRACE(("changing %d DEC private modes\n", nparam)); 7249 if_STATUS_LINE(screen, { 7250 return; 7251 }); 7252 for (i = 0; i < nparam; ++i) { 7253 int code = GetParam(i); 7254 7255 TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code)); 7256 switch ((DECSET_codes) code) { 7257 case srm_DECCKM: 7258 (*func) (&xw->keyboard.flags, MODE_DECCKM); 7259 update_appcursor(); 7260 break; 7261 case srm_DECANM: /* ANSI/VT52 mode */ 7262#if OPT_STATUS_LINE 7263 if (screen->status_type == 2 && screen->status_active) { 7264 /* DEC 070, section 14.2.3 item 4 */ 7265 /* EMPTY */ ; 7266 } else 7267#endif 7268 if (IsSM()) { /* ANSI (VT100) */ 7269 /* 7270 * Setting DECANM should have no effect, since this function 7271 * cannot be reached from vt52 mode. 7272 */ 7273 /* EMPTY */ ; 7274 } 7275#if OPT_VT52_MODE 7276 else if (screen->terminal_id >= 100) { /* VT52 */ 7277 TRACE(("DECANM terminal_id %d, vtXX_level %d\n", 7278 screen->terminal_id, 7279 screen->vtXX_level)); 7280 /* 7281 * According to DEC STD 070 section A.5.5, the various VT100 7282 * modes have undefined behavior when entering/exiting VT52 7283 * mode. xterm saves/restores/initializes the most commonly 7284 * used settings, but a real VT100 or VT520 may differ. 7285 * 7286 * For instance, DEC's documentation goes on to comment that 7287 * while the VT52 uses hardware tabs (8 columns), the emulation 7288 * (e.g., a VT420) does not alter those tab settings when 7289 * switching modes. 7290 */ 7291 set_vtXX_level(screen, 0); 7292 screen->vt52_save_flags = xw->flags; 7293 xw->flags = 0; 7294 screen->vt52_save_curgl = screen->curgl; 7295 screen->vt52_save_curgr = screen->curgr; 7296 screen->vt52_save_curss = screen->curss; 7297 saveCharsets(screen, screen->vt52_save_gsets); 7298 resetCharsets(screen); 7299 InitParams(); /* ignore the remaining params, if any */ 7300 update_vt52_vt100_settings(); 7301 RequestResize(xw, -1, 80, True); 7302 } 7303#endif 7304 break; 7305 case srm_DECCOLM: 7306 if (screen->c132) { 7307 Boolean willResize = ((j = IsSM() 7308 ? 132 7309 : 80) 7310 != ((xw->flags & IN132COLUMNS) 7311 ? 132 7312 : 80) 7313 || j != MaxCols(screen)); 7314 if (!(xw->flags & NOCLEAR_COLM)) { 7315#if OPT_STATUS_LINE 7316 if (IsStatusShown(screen)) 7317 clear_status_line(xw); 7318#endif 7319 ClearScreen(xw); 7320 } 7321 if (willResize) 7322 RequestResize(xw, -1, j, True); 7323 (*func) (&xw->flags, IN132COLUMNS); 7324 set_column_mode(xw); 7325 } 7326 break; 7327 case srm_DECSCLM: /* (slow scroll) */ 7328 if (IsSM()) { 7329 screen->jumpscroll = 0; 7330 if (screen->scroll_amt) 7331 FlushScroll(xw); 7332 } else 7333 screen->jumpscroll = 1; 7334 (*func) (&xw->flags, SMOOTHSCROLL); 7335 update_jumpscroll(); 7336 break; 7337 case srm_DECSCNM: 7338 myflags = xw->flags; 7339 (*func) (&xw->flags, REVERSE_VIDEO); 7340 if ((xw->flags ^ myflags) & REVERSE_VIDEO) 7341 ReverseVideo(xw); 7342 /* update_reversevideo done in RevVid */ 7343 break; 7344 7345 case srm_DECOM: 7346 (*func) (&xw->flags, ORIGIN); 7347 CursorSet(screen, 0, 0, xw->flags); 7348 break; 7349 7350 case srm_DECAWM: 7351 (*func) (&xw->flags, WRAPAROUND); 7352 update_autowrap(); 7353 break; 7354 case srm_DECARM: 7355 /* ignore autorepeat 7356 * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only 7357 * for the whole display - not limited to a given window. 7358 */ 7359 break; 7360 case srm_X10_MOUSE: /* MIT bogus sequence */ 7361 MotionOff(screen, xw); 7362 set_mousemode(X10_MOUSE); 7363 break; 7364#if OPT_TOOLBAR 7365 case srm_RXVT_TOOLBAR: 7366 ShowToolbar(IsSM()); 7367 break; 7368#else 7369 case srm_DECEDM: /* vt330:edit */ 7370 break; 7371#endif 7372#if OPT_BLINK_CURS 7373 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 7374 if (SettableCursorBlink(screen)) { 7375 set_bool_mode(screen->cursor_blink_esc); 7376 UpdateCursorBlink(xw); 7377 } 7378 break; 7379 case srm_CURSOR_BLINK_OPS: 7380 /* intentionally ignored (this is user-preference) */ 7381 break; 7382 case srm_XOR_CURSOR_BLINKS: 7383 /* intentionally ignored (this is user-preference) */ 7384 break; 7385#else 7386 case srm_DECKANAM: /* vt382:Katakana shift */ 7387 case srm_DECSCFDM: /* vt330:space compression field delimiter */ 7388 case srm_DECTEM: /* vt330:transmission execution */ 7389 break; 7390#endif 7391 case srm_DECPFF: /* print form feed */ 7392 set_bool_mode(PrinterOf(screen).printer_formfeed); 7393 break; 7394 case srm_DECPEX: /* print extent */ 7395 set_bool_mode(PrinterOf(screen).printer_extent); 7396 break; 7397 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 7398 set_bool_mode(screen->cursor_set); 7399 break; 7400 case srm_RXVT_SCROLLBAR: 7401 if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF)) 7402 ToggleScrollBar(xw); 7403 break; 7404#if OPT_SHIFT_FONTS 7405 case srm_RXVT_FONTSIZE: 7406 set_bool_mode(xw->misc.shift_fonts); 7407 break; 7408#endif 7409#if OPT_TEK4014 7410 case srm_DECTEK: 7411 if (IsSM() && !(screen->inhibit & I_TEK)) { 7412 FlushLog(xw); 7413 TEK4014_ACTIVE(xw) = True; 7414 TRACE(("Tek4014 is now active...\n")); 7415 update_vttekmode(); 7416 } 7417 break; 7418#endif 7419 case srm_132COLS: /* 132 column mode */ 7420 set_bool_mode(screen->c132); 7421 update_allow132(); 7422 break; 7423 case srm_CURSES_HACK: 7424 set_bool_mode(screen->curses); 7425 update_cursesemul(); 7426 break; 7427 case srm_DECNRCM: /* national charset (VT220) */ 7428 if (screen->vtXX_level >= 2) { 7429 if ((*func) (&xw->flags, NATIONAL)) { 7430 modified_DECNRCM(xw); 7431 } 7432 } 7433 break; 7434#if OPT_PRINT_GRAPHICS 7435 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 7436 set_bool_mode(screen->graphics_expanded_print_mode); 7437 break; 7438#endif 7439 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 7440 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_mode)) { 7441 set_bool_mode(screen->marginbell); 7442 if (!screen->marginbell) 7443 screen->bellArmed = -1; 7444 update_marginbell(); 7445 } 7446 break; 7447 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 7448 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_syntax)) { 7449 (*func) (&xw->flags, REVERSEWRAP); 7450 update_reversewrap(); 7451 } 7452 break; 7453 case srm_REVERSEWRAP2: /* extended reverse wraparound (xterm) */ 7454 (*func) (&xw->flags, REVERSEWRAP2); 7455 break; 7456#ifdef ALLOWLOGGING 7457 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 7458 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_background_mode)) { 7459#ifdef ALLOWLOGFILEONOFF 7460 /* 7461 * if this feature is enabled, logging may be 7462 * enabled and disabled via escape sequences. 7463 */ 7464 if (IsSM()) 7465 StartLog(xw); 7466 else 7467 CloseLog(xw); 7468#else 7469 Bell(xw, XkbBI_Info, 0); 7470 Bell(xw, XkbBI_Info, 0); 7471#endif /* ALLOWLOGFILEONOFF */ 7472 } 7473 break; 7474#elif OPT_PRINT_GRAPHICS 7475 case srm_DECGPBM: /* Graphics Print Background Mode */ 7476 set_bool_mode(screen->graphics_print_background_mode); 7477 break; 7478#endif /* ALLOWLOGGING */ 7479 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 7480 if (!xw->misc.titeInhibit) { 7481 if (IsSM()) { 7482 CursorSave(xw); 7483 ToAlternate(xw, True); 7484 ClearScreen(xw); 7485 } else { 7486 FromAlternate(xw, False); 7487 CursorRestore(xw); 7488 } 7489 } else if (IsSM()) { 7490 do_ti_xtra_scroll(xw); 7491 } 7492 break; 7493 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 7494 if (!xw->misc.titeInhibit) { 7495 if (IsSM()) { 7496 ToAlternate(xw, False); 7497 } else { 7498 if (screen->whichBuf) 7499 ClearScreen(xw); 7500 FromAlternate(xw, False); 7501 } 7502 } else if (IsSM()) { 7503 do_ti_xtra_scroll(xw); 7504 } 7505 break; 7506 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7507 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_rotated_print_mode)) { 7508 if (!xw->misc.titeInhibit) { 7509 if (IsSM()) { 7510 ToAlternate(xw, False); 7511 } else { 7512 FromAlternate(xw, False); 7513 } 7514 } else if (IsSM()) { 7515 do_ti_xtra_scroll(xw); 7516 } 7517 } 7518 break; 7519 case srm_DECNKM: 7520 (*func) (&xw->keyboard.flags, MODE_DECKPAM); 7521 update_appkeypad(); 7522 break; 7523 case srm_DECBKM: 7524 /* back-arrow mapped to backspace or delete(D) */ 7525 (*func) (&xw->keyboard.flags, MODE_DECBKM); 7526 TRACE(("DECSET DECBKM %s\n", 7527 BtoS(xw->keyboard.flags & MODE_DECBKM))); 7528 update_decbkm(); 7529 break; 7530 case srm_DECLRMM: 7531 if (screen->vtXX_level >= 4) { /* VT420 */ 7532 (*func) (&xw->flags, LEFT_RIGHT); 7533 set_left_right_margin_mode(xw); 7534 } 7535 break; 7536#if OPT_SIXEL_GRAPHICS 7537 case srm_DECSDM: /* sixel display mode (no scrolling) */ 7538 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 7539 (*func) (&xw->keyboard.flags, MODE_DECSDM); 7540 TRACE(("DECSET/DECRST DECSDM %s (resource default is %s)\n", 7541 BtoS(xw->keyboard.flags & MODE_DECSDM), 7542 BtoS(!screen->sixel_scrolling))); 7543 update_decsdm(); 7544 } 7545 break; 7546#endif 7547 case srm_DECNCSM: 7548 if (screen->vtXX_level >= 5) { /* VT510 */ 7549 (*func) (&xw->flags, NOCLEAR_COLM); 7550 } 7551 break; 7552 case srm_VT200_MOUSE: /* xterm bogus sequence */ 7553 MotionOff(screen, xw); 7554 set_mousemode(VT200_MOUSE); 7555 break; 7556 case srm_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */ 7557 MotionOff(screen, xw); 7558 set_mousemode(VT200_HIGHLIGHT_MOUSE); 7559 break; 7560 case srm_BTN_EVENT_MOUSE: 7561 MotionOff(screen, xw); 7562 set_mousemode(BTN_EVENT_MOUSE); 7563 break; 7564 case srm_ANY_EVENT_MOUSE: 7565 set_mousemode(ANY_EVENT_MOUSE); 7566 if (screen->send_mouse_pos == MOUSE_OFF) { 7567 MotionOff(screen, xw); 7568 } else { 7569 MotionOn(screen, xw); 7570 } 7571 break; 7572#if OPT_FOCUS_EVENT 7573 case srm_FOCUS_EVENT_MOUSE: 7574 set_bool_mode(screen->send_focus_pos); 7575 break; 7576#endif 7577 case srm_EXT_MODE_MOUSE: 7578 /* FALLTHRU */ 7579 case srm_SGR_EXT_MODE_MOUSE: 7580 /* FALLTHRU */ 7581 case srm_URXVT_EXT_MODE_MOUSE: 7582 /* FALLTHRU */ 7583 case srm_PIXEL_POSITION_MOUSE: 7584 /* 7585 * Rather than choose an arbitrary precedence among the coordinate 7586 * modes, they are mutually exclusive. For consistency, a reset is 7587 * only effective against the matching mode. 7588 */ 7589 if (IsSM()) { 7590 screen->extend_coords = code; 7591 } else if (screen->extend_coords == code) { 7592 screen->extend_coords = 0; 7593 } 7594 break; 7595 case srm_ALTERNATE_SCROLL: 7596 set_bool_mode(screen->alternateScroll); 7597 break; 7598 case srm_RXVT_SCROLL_TTY_OUTPUT: 7599 set_bool_mode(screen->scrollttyoutput); 7600 update_scrollttyoutput(); 7601 break; 7602 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7603 set_bool_mode(screen->scrollkey); 7604 update_scrollkey(); 7605 break; 7606 case srm_EIGHT_BIT_META: 7607 if (screen->eight_bit_meta != ebNever) { 7608 set_bool_mode(screen->eight_bit_meta); 7609 } 7610 break; 7611#if OPT_NUM_LOCK 7612 case srm_REAL_NUMLOCK: 7613 set_bool_mode(xw->misc.real_NumLock); 7614 update_num_lock(); 7615 break; 7616 case srm_META_SENDS_ESC: 7617 set_bool_mode(screen->meta_sends_esc); 7618 update_meta_esc(); 7619 break; 7620#endif 7621 case srm_DELETE_IS_DEL: 7622 set_bool_mode(screen->delete_is_del); 7623 update_delete_del(); 7624 break; 7625#if OPT_NUM_LOCK 7626 case srm_ALT_SENDS_ESC: 7627 set_bool_mode(screen->alt_sends_esc); 7628 update_alt_esc(); 7629 break; 7630#endif 7631 case srm_KEEP_SELECTION: 7632 set_bool_mode(screen->keepSelection); 7633 update_keepSelection(); 7634 break; 7635 case srm_SELECT_TO_CLIPBOARD: 7636 set_bool_mode(screen->selectToClipboard); 7637 update_selectToClipboard(); 7638 break; 7639 case srm_BELL_IS_URGENT: 7640 set_bool_mode(screen->bellIsUrgent); 7641 update_bellIsUrgent(); 7642 break; 7643 case srm_POP_ON_BELL: 7644 set_bool_mode(screen->poponbell); 7645 update_poponbell(); 7646 break; 7647 case srm_KEEP_CLIPBOARD: 7648 set_bool_mode(screen->keepClipboard); 7649 update_keepClipboard(); 7650 break; 7651 case srm_ALLOW_ALTBUF: 7652 if (IsSM()) { 7653 xw->misc.titeInhibit = False; 7654 } else if (!xw->misc.titeInhibit) { 7655 xw->misc.titeInhibit = True; 7656 FromAlternate(xw, False); 7657 } 7658 update_titeInhibit(); 7659 break; 7660 case srm_SAVE_CURSOR: 7661 if (!xw->misc.titeInhibit) { 7662 if (IsSM()) 7663 CursorSave(xw); 7664 else 7665 CursorRestore(xw); 7666 } 7667 break; 7668 case srm_FAST_SCROLL: 7669 set_bool_mode(screen->fastscroll); 7670 break; 7671#if OPT_TCAP_FKEYS 7672 case srm_TCAP_FKEYS: 7673 set_keyboard_type(xw, keyboardIsTermcap, IsSM()); 7674 break; 7675#endif 7676#if OPT_SUN_FUNC_KEYS 7677 case srm_SUN_FKEYS: 7678 set_keyboard_type(xw, keyboardIsSun, IsSM()); 7679 break; 7680#endif 7681#if OPT_HP_FUNC_KEYS 7682 case srm_HP_FKEYS: 7683 set_keyboard_type(xw, keyboardIsHP, IsSM()); 7684 break; 7685#endif 7686#if OPT_SCO_FUNC_KEYS 7687 case srm_SCO_FKEYS: 7688 set_keyboard_type(xw, keyboardIsSCO, IsSM()); 7689 break; 7690#endif 7691 case srm_LEGACY_FKEYS: 7692 set_keyboard_type(xw, keyboardIsLegacy, IsSM()); 7693 break; 7694#if OPT_SUNPC_KBD 7695 case srm_VT220_FKEYS: 7696 set_keyboard_type(xw, keyboardIsVT220, IsSM()); 7697 break; 7698#endif 7699#if OPT_PASTE64 || OPT_READLINE 7700 case srm_PASTE_IN_BRACKET: 7701 set_mouseflag(paste_brackets); 7702 break; 7703#endif 7704#if OPT_READLINE 7705 case srm_BUTTON1_MOVE_POINT: 7706 set_mouseflag(click1_moves); 7707 break; 7708 case srm_BUTTON2_MOVE_POINT: 7709 set_mouseflag(paste_moves); 7710 break; 7711 case srm_DBUTTON3_DELETE: 7712 set_mouseflag(dclick3_deletes); 7713 break; 7714 case srm_PASTE_QUOTE: 7715 set_mouseflag(paste_quotes); 7716 break; 7717 case srm_PASTE_LITERAL_NL: 7718 set_mouseflag(paste_literal_nl); 7719 break; 7720#endif /* OPT_READLINE */ 7721#if OPT_GRAPHICS 7722 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 7723 TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n", 7724 BtoS(screen->privatecolorregisters), 7725 BtoS(screen->privatecolorregisters0))); 7726 set_bool_mode(screen->privatecolorregisters); 7727 update_privatecolorregisters(); 7728 break; 7729#endif 7730#if OPT_SIXEL_GRAPHICS 7731 case srm_SIXEL_SCROLLS_RIGHT: /* sixel scrolling moves cursor to right */ 7732 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 7733 set_bool_mode(screen->sixel_scrolls_right); 7734 TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n", 7735 BtoS(screen->sixel_scrolls_right), 7736 BtoS(TScreenOf(xw)->sixel_scrolls_right))); 7737 } 7738 break; 7739#endif 7740 case srm_DEC131TM: /* ignore */ 7741 case srm_DECAAM: /* ignore */ 7742 case srm_DECARSM: /* ignore */ 7743 case srm_DECATCBM: /* ignore */ 7744 case srm_DECATCUM: /* ignore */ 7745 case srm_DECBBSM: /* ignore */ 7746 case srm_DECCANSM: /* ignore */ 7747 case srm_DECCAPSLK: /* ignore */ 7748 case srm_DECCRTSM: /* ignore */ 7749 case srm_DECECM: /* ignore */ 7750 case srm_DECEKEM: /* ignore */ 7751 case srm_DECESKM: /* ignore */ 7752 case srm_DECFWM: /* ignore */ 7753 case srm_DECHCCM: /* ignore */ 7754 case srm_DECHDPXM: /* ignore */ 7755 case srm_DECHEM: /* ignore */ 7756 case srm_DECHWUM: /* ignore */ 7757 case srm_DECIPEM: /* ignore */ 7758 case srm_DECKBUM: /* ignore */ 7759 case srm_DECKLHIM: /* ignore */ 7760 case srm_DECKKDM: /* ignore */ 7761 case srm_DECKPM: /* ignore */ 7762 case srm_DECLTM: /* ignore */ 7763 case srm_DECMCM: /* ignore */ 7764 case srm_DECNAKB: /* ignore */ 7765 case srm_DECNULM: /* ignore */ 7766 case srm_DECNUMLK: /* ignore */ 7767 case srm_DECOSCNM: /* ignore */ 7768 case srm_DECPCCM: /* ignore */ 7769 case srm_DECRLCM: /* ignore */ 7770 case srm_DECRLM: /* ignore */ 7771 case srm_DECRPL: /* ignore */ 7772 case srm_DECVCCM: /* ignore */ 7773 case srm_DECXRLM: /* ignore */ 7774 default: 7775 TRACE(("DATA_ERROR: unknown private code %d\n", code)); 7776 break; 7777 } 7778 } 7779} 7780 7781/* 7782 * process xterm private modes save 7783 */ 7784static void 7785savemodes(XtermWidget xw) 7786{ 7787 TScreen *screen = TScreenOf(xw); 7788 int i; 7789 7790 if_STATUS_LINE(screen, { 7791 return; 7792 }); 7793 for (i = 0; i < nparam; i++) { 7794 int code = GetParam(i); 7795 7796 TRACE(("savemodes %d\n", code)); 7797 switch ((DECSET_codes) code) { 7798 case srm_DECCKM: 7799 DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM); 7800 break; 7801 case srm_DECANM: /* ANSI/VT52 mode */ 7802 /* no effect */ 7803 break; 7804 case srm_DECCOLM: 7805 if (screen->c132) 7806 DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS); 7807 break; 7808 case srm_DECSCLM: /* (slow scroll) */ 7809 DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL); 7810 break; 7811 case srm_DECSCNM: 7812 DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO); 7813 break; 7814 case srm_DECOM: 7815 DoSM(DP_DECOM, xw->flags & ORIGIN); 7816 break; 7817 case srm_DECAWM: 7818 DoSM(DP_DECAWM, xw->flags & WRAPAROUND); 7819 break; 7820 case srm_DECARM: 7821 /* ignore autorepeat */ 7822 break; 7823 case srm_X10_MOUSE: /* mouse bogus sequence */ 7824 DoSM(DP_X_X10MSE, screen->send_mouse_pos); 7825 break; 7826#if OPT_TOOLBAR 7827 case srm_RXVT_TOOLBAR: 7828 DoSM(DP_TOOLBAR, resource.toolBar); 7829 break; 7830#else 7831 case srm_DECEDM: /* vt330:edit */ 7832 break; 7833#endif 7834#if OPT_BLINK_CURS 7835 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 7836 if (SettableCursorBlink(screen)) { 7837 DoSM(DP_CRS_BLINK, screen->cursor_blink_esc); 7838 } 7839 break; 7840 case srm_CURSOR_BLINK_OPS: 7841 /* intentionally ignored (this is user-preference) */ 7842 break; 7843 case srm_XOR_CURSOR_BLINKS: 7844 /* intentionally ignored (this is user-preference) */ 7845 break; 7846#else 7847 case srm_DECKANAM: /* vt382:Katakana shift */ 7848 case srm_DECSCFDM: /* vt330:space compression field delimiter */ 7849 case srm_DECTEM: /* vt330:transmission execution */ 7850 break; 7851#endif 7852 case srm_DECPFF: /* print form feed */ 7853 DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 7854 break; 7855 case srm_DECPEX: /* print extent */ 7856 DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 7857 break; 7858 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 7859 DoSM(DP_CRS_VISIBLE, screen->cursor_set); 7860 break; 7861 case srm_RXVT_SCROLLBAR: 7862 DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0)); 7863 break; 7864#if OPT_SHIFT_FONTS 7865 case srm_RXVT_FONTSIZE: 7866 DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 7867 break; 7868#endif 7869#if OPT_TEK4014 7870 case srm_DECTEK: 7871 DoSM(DP_DECTEK, TEK4014_ACTIVE(xw)); 7872 break; 7873#endif 7874 case srm_132COLS: /* 132 column mode */ 7875 DoSM(DP_X_DECCOLM, screen->c132); 7876 break; 7877 case srm_CURSES_HACK: /* curses hack */ 7878 DoSM(DP_X_MORE, screen->curses); 7879 break; 7880 case srm_DECNRCM: /* national charset (VT220) */ 7881 if (screen->vtXX_level >= 2) { 7882 DoSM(DP_DECNRCM, xw->flags & NATIONAL); 7883 } 7884 break; 7885#if OPT_PRINT_GRAPHICS 7886 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 7887 DoSM(DP_DECGEPM, screen->graphics_expanded_print_mode); 7888 break; 7889#endif 7890 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 7891 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCM, screen->graphics_print_color_mode)) { 7892 DoSM(DP_X_MARGIN, screen->marginbell); 7893 } 7894 break; 7895 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 7896 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 7897 DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP); 7898 } 7899 break; 7900 case srm_REVERSEWRAP2: /* extended reverse wraparound (xterm) */ 7901 DoSM(DP_X_REVWRAP2, xw->flags & REVERSEWRAP2); 7902 break; 7903#ifdef ALLOWLOGGING 7904 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 7905 if_PRINT_GRAPHICS2(DoSM(DP_DECGPBM, screen->graphics_print_background_mode)) { 7906#ifdef ALLOWLOGFILEONOFF 7907 DoSM(DP_X_LOGGING, screen->logging); 7908#endif /* ALLOWLOGFILEONOFF */ 7909 } 7910 break; 7911#elif OPT_PRINT_GRAPHICS 7912 case srm_DECGPBM: /* Graphics Print Background Mode */ 7913 DoSM(DP_DECGPBM, screen->graphics_print_background_mode); 7914 break; 7915#endif /* ALLOWLOGGING */ 7916 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 7917 /* FALLTHRU */ 7918 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 7919 DoSM(DP_X_ALTBUF, screen->whichBuf); 7920 break; 7921 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7922 if_PRINT_GRAPHICS2(DoSM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 7923 DoSM(DP_X_ALTBUF, screen->whichBuf); 7924 } 7925 break; 7926 case srm_DECNKM: 7927 DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM); 7928 break; 7929 case srm_DECBKM: /* backarrow mapping */ 7930 DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM); 7931 break; 7932 case srm_DECLRMM: /* left-right */ 7933 DoSM(DP_X_LRMM, LEFT_RIGHT); 7934 break; 7935#if OPT_SIXEL_GRAPHICS 7936 case srm_DECSDM: /* sixel display mode (no scroll) */ 7937 DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM); 7938 update_decsdm(); 7939 break; 7940#endif 7941 case srm_DECNCSM: /* noclear */ 7942 DoSM(DP_X_NCSM, NOCLEAR_COLM); 7943 break; 7944 case srm_VT200_MOUSE: /* mouse bogus sequence */ 7945 /* FALLTHRU */ 7946 case srm_VT200_HIGHLIGHT_MOUSE: 7947 /* FALLTHRU */ 7948 case srm_BTN_EVENT_MOUSE: 7949 /* FALLTHRU */ 7950 case srm_ANY_EVENT_MOUSE: 7951 DoSM(DP_X_MOUSE, screen->send_mouse_pos); 7952 break; 7953#if OPT_FOCUS_EVENT 7954 case srm_FOCUS_EVENT_MOUSE: 7955 DoSM(DP_X_FOCUS, screen->send_focus_pos); 7956 break; 7957#endif 7958 case srm_EXT_MODE_MOUSE: 7959 /* FALLTHRU */ 7960 case srm_SGR_EXT_MODE_MOUSE: 7961 /* FALLTHRU */ 7962 case srm_URXVT_EXT_MODE_MOUSE: 7963 /* FALLTHRU */ 7964 case srm_PIXEL_POSITION_MOUSE: 7965 DoSM(DP_X_EXT_MOUSE, screen->extend_coords); 7966 break; 7967 case srm_ALTERNATE_SCROLL: 7968 DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 7969 break; 7970 case srm_RXVT_SCROLL_TTY_OUTPUT: 7971 DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 7972 break; 7973 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7974 DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 7975 break; 7976 case srm_EIGHT_BIT_META: 7977 DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 7978 break; 7979#if OPT_NUM_LOCK 7980 case srm_REAL_NUMLOCK: 7981 DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 7982 break; 7983 case srm_META_SENDS_ESC: 7984 DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc); 7985 break; 7986#endif 7987 case srm_DELETE_IS_DEL: 7988 DoSM(DP_DELETE_IS_DEL, screen->delete_is_del); 7989 break; 7990#if OPT_NUM_LOCK 7991 case srm_ALT_SENDS_ESC: 7992 DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 7993 break; 7994#endif 7995 case srm_KEEP_SELECTION: 7996 DoSM(DP_KEEP_SELECTION, screen->keepSelection); 7997 break; 7998 case srm_SELECT_TO_CLIPBOARD: 7999 DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 8000 break; 8001 case srm_BELL_IS_URGENT: 8002 DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 8003 break; 8004 case srm_POP_ON_BELL: 8005 DoSM(DP_POP_ON_BELL, screen->poponbell); 8006 break; 8007 case srm_KEEP_CLIPBOARD: 8008 DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 8009 break; 8010#if OPT_TCAP_FKEYS 8011 case srm_TCAP_FKEYS: 8012 /* FALLTHRU */ 8013#endif 8014#if OPT_SUN_FUNC_KEYS 8015 case srm_SUN_FKEYS: 8016 /* FALLTHRU */ 8017#endif 8018#if OPT_HP_FUNC_KEYS 8019 case srm_HP_FKEYS: 8020 /* FALLTHRU */ 8021#endif 8022#if OPT_SCO_FUNC_KEYS 8023 case srm_SCO_FKEYS: 8024 /* FALLTHRU */ 8025#endif 8026#if OPT_SUNPC_KBD 8027 case srm_VT220_FKEYS: 8028 /* FALLTHRU */ 8029#endif 8030 case srm_LEGACY_FKEYS: 8031 DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type); 8032 break; 8033 case srm_ALLOW_ALTBUF: 8034 DoSM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 8035 break; 8036 case srm_SAVE_CURSOR: 8037 if (!xw->misc.titeInhibit) { 8038 CursorSave(xw); 8039 } 8040 break; 8041 case srm_FAST_SCROLL: 8042 DoSM(DP_FAST_SCROLL, screen->fastscroll); 8043 break; 8044#if OPT_PASTE64 || OPT_READLINE 8045 case srm_PASTE_IN_BRACKET: 8046 SCREEN_FLAG_save(screen, paste_brackets); 8047 break; 8048#endif 8049#if OPT_READLINE 8050 case srm_BUTTON1_MOVE_POINT: 8051 SCREEN_FLAG_save(screen, click1_moves); 8052 break; 8053 case srm_BUTTON2_MOVE_POINT: 8054 SCREEN_FLAG_save(screen, paste_moves); 8055 break; 8056 case srm_DBUTTON3_DELETE: 8057 SCREEN_FLAG_save(screen, dclick3_deletes); 8058 break; 8059 case srm_PASTE_QUOTE: 8060 SCREEN_FLAG_save(screen, paste_quotes); 8061 break; 8062 case srm_PASTE_LITERAL_NL: 8063 SCREEN_FLAG_save(screen, paste_literal_nl); 8064 break; 8065#endif /* OPT_READLINE */ 8066#if OPT_GRAPHICS 8067 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 8068 TRACE(("save PRIVATE_COLOR_REGISTERS %s\n", 8069 BtoS(screen->privatecolorregisters))); 8070 DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 8071 update_privatecolorregisters(); 8072 break; 8073#endif 8074#if OPT_SIXEL_GRAPHICS 8075 case srm_SIXEL_SCROLLS_RIGHT: 8076 TRACE(("save SIXEL_SCROLLS_RIGHT %s\n", 8077 BtoS(screen->sixel_scrolls_right))); 8078 DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 8079 break; 8080#endif 8081 case srm_DEC131TM: /* ignore */ 8082 case srm_DECAAM: /* ignore */ 8083 case srm_DECARSM: /* ignore */ 8084 case srm_DECATCBM: /* ignore */ 8085 case srm_DECATCUM: /* ignore */ 8086 case srm_DECBBSM: /* ignore */ 8087 case srm_DECCANSM: /* ignore */ 8088 case srm_DECCAPSLK: /* ignore */ 8089 case srm_DECCRTSM: /* ignore */ 8090 case srm_DECECM: /* ignore */ 8091 case srm_DECEKEM: /* ignore */ 8092 case srm_DECESKM: /* ignore */ 8093 case srm_DECFWM: /* ignore */ 8094 case srm_DECHCCM: /* ignore */ 8095 case srm_DECHDPXM: /* ignore */ 8096 case srm_DECHEM: /* ignore */ 8097 case srm_DECHWUM: /* ignore */ 8098 case srm_DECIPEM: /* ignore */ 8099 case srm_DECKBUM: /* ignore */ 8100 case srm_DECKKDM: /* ignore */ 8101 case srm_DECKLHIM: /* ignore */ 8102 case srm_DECKPM: /* ignore */ 8103 case srm_DECLTM: /* ignore */ 8104 case srm_DECMCM: /* ignore */ 8105 case srm_DECNAKB: /* ignore */ 8106 case srm_DECNULM: /* ignore */ 8107 case srm_DECNUMLK: /* ignore */ 8108 case srm_DECOSCNM: /* ignore */ 8109 case srm_DECPCCM: /* ignore */ 8110 case srm_DECRLCM: /* ignore */ 8111 case srm_DECRLM: /* ignore */ 8112 case srm_DECRPL: /* ignore */ 8113 case srm_DECVCCM: /* ignore */ 8114 case srm_DECXRLM: /* ignore */ 8115 default: 8116 break; 8117 } 8118 } 8119} 8120 8121/* 8122 * process xterm private modes restore 8123 */ 8124static void 8125restoremodes(XtermWidget xw) 8126{ 8127 TScreen *screen = TScreenOf(xw); 8128 int i, j; 8129 8130 if_STATUS_LINE(screen, { 8131 return; 8132 }); 8133 for (i = 0; i < nparam; i++) { 8134 int code = GetParam(i); 8135 8136 TRACE(("restoremodes %d\n", code)); 8137 switch ((DECSET_codes) code) { 8138 case srm_DECCKM: 8139 bitcpy(&xw->keyboard.flags, 8140 screen->save_modes[DP_DECCKM], MODE_DECCKM); 8141 update_appcursor(); 8142 break; 8143 case srm_DECANM: /* ANSI/VT52 mode */ 8144 /* no effect */ 8145 break; 8146 case srm_DECCOLM: 8147 if (screen->c132) { 8148 if (!(xw->flags & NOCLEAR_COLM)) 8149 ClearScreen(xw); 8150 CursorSet(screen, 0, 0, xw->flags); 8151 if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS) 8152 ? 132 : 80) != ((xw->flags & IN132COLUMNS) 8153 ? 132 : 80) || j != MaxCols(screen)) 8154 RequestResize(xw, -1, j, True); 8155 bitcpy(&xw->flags, 8156 screen->save_modes[DP_DECCOLM], 8157 IN132COLUMNS); 8158 } 8159 break; 8160 case srm_DECSCLM: /* (slow scroll) */ 8161 if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) { 8162 screen->jumpscroll = 0; 8163 if (screen->scroll_amt) 8164 FlushScroll(xw); 8165 } else 8166 screen->jumpscroll = 1; 8167 bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL); 8168 update_jumpscroll(); 8169 break; 8170 case srm_DECSCNM: 8171 if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) { 8172 bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO); 8173 ReverseVideo(xw); 8174 /* update_reversevideo done in RevVid */ 8175 } 8176 break; 8177 case srm_DECOM: 8178 bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN); 8179 CursorSet(screen, 0, 0, xw->flags); 8180 break; 8181 8182 case srm_DECAWM: 8183 bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND); 8184 update_autowrap(); 8185 break; 8186 case srm_DECARM: 8187 /* ignore autorepeat */ 8188 break; 8189 case srm_X10_MOUSE: /* MIT bogus sequence */ 8190 DoRM0(DP_X_X10MSE, screen->send_mouse_pos); 8191 really_set_mousemode(xw, 8192 screen->send_mouse_pos != MOUSE_OFF, 8193 (XtermMouseModes) screen->send_mouse_pos); 8194 break; 8195#if OPT_TOOLBAR 8196 case srm_RXVT_TOOLBAR: 8197 DoRM(DP_TOOLBAR, resource.toolBar); 8198 ShowToolbar(resource.toolBar); 8199 break; 8200#else 8201 case srm_DECEDM: /* vt330:edit */ 8202 break; 8203#endif 8204#if OPT_BLINK_CURS 8205 case srm_ATT610_BLINK: /* Start/stop blinking cursor */ 8206 if (SettableCursorBlink(screen)) { 8207 DoRM(DP_CRS_BLINK, screen->cursor_blink_esc); 8208 UpdateCursorBlink(xw); 8209 } 8210 break; 8211 case srm_CURSOR_BLINK_OPS: 8212 /* intentionally ignored (this is user-preference) */ 8213 break; 8214 case srm_XOR_CURSOR_BLINKS: 8215 /* intentionally ignored (this is user-preference) */ 8216 break; 8217#else 8218 case srm_DECKANAM: /* vt382:Katakana shift */ 8219 case srm_DECSCFDM: /* vt330:space compression field delimiter */ 8220 case srm_DECTEM: /* vt330:transmission execution */ 8221 break; 8222#endif 8223 case srm_DECPFF: /* print form feed */ 8224 DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 8225 break; 8226 case srm_DECPEX: /* print extent */ 8227 DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 8228 break; 8229 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 8230 DoRM(DP_CRS_VISIBLE, screen->cursor_set); 8231 updateCursor(xw); 8232 break; 8233 case srm_RXVT_SCROLLBAR: 8234 if ((screen->fullVwin.sb_info.width != 0) != 8235 screen->save_modes[DP_RXVT_SCROLLBAR]) { 8236 ToggleScrollBar(xw); 8237 } 8238 break; 8239#if OPT_SHIFT_FONTS 8240 case srm_RXVT_FONTSIZE: 8241 DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 8242 break; 8243#endif 8244#if OPT_TEK4014 8245 case srm_DECTEK: 8246 if (!(screen->inhibit & I_TEK) && 8247 (TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) { 8248 FlushLog(xw); 8249 TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK]; 8250 update_vttekmode(); 8251 } 8252 break; 8253#endif 8254 case srm_132COLS: /* 132 column mode */ 8255 DoRM(DP_X_DECCOLM, screen->c132); 8256 update_allow132(); 8257 break; 8258 case srm_CURSES_HACK: /* curses hack */ 8259 DoRM(DP_X_MORE, screen->curses); 8260 update_cursesemul(); 8261 break; 8262 case srm_DECNRCM: /* national charset (VT220) */ 8263 if (screen->vtXX_level >= 2) { 8264 if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL)) 8265 modified_DECNRCM(xw); 8266 } 8267 break; 8268#if OPT_PRINT_GRAPHICS 8269 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 8270 DoRM(DP_DECGEPM, screen->graphics_expanded_print_mode); 8271 break; 8272#endif 8273 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 8274 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCM, screen->graphics_print_color_mode)) { 8275 if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0) 8276 screen->bellArmed = -1; 8277 update_marginbell(); 8278 } 8279 break; 8280 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 8281 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 8282 bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP); 8283 update_reversewrap(); 8284 } 8285 break; 8286 case srm_REVERSEWRAP2: /* extended reverse wraparound (xterm) */ 8287 bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP2], REVERSEWRAP2); 8288 break; 8289#ifdef ALLOWLOGGING 8290 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 8291 if_PRINT_GRAPHICS2(DoRM(DP_DECGPBM, screen->graphics_print_background_mode)) { 8292#ifdef ALLOWLOGFILEONOFF 8293 if (screen->save_modes[DP_X_LOGGING]) 8294 StartLog(xw); 8295 else 8296 CloseLog(xw); 8297#endif /* ALLOWLOGFILEONOFF */ 8298 /* update_logging done by StartLog and CloseLog */ 8299 } 8300 break; 8301#elif OPT_PRINT_GRAPHICS 8302 case srm_DECGPBM: /* Graphics Print Background Mode */ 8303 DoRM(DP_DECGPBM, screen->graphics_print_background_mode); 8304 break; 8305#endif /* ALLOWLOGGING */ 8306 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 8307 /* FALLTHRU */ 8308 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 8309 if (!xw->misc.titeInhibit) { 8310 if (screen->save_modes[DP_X_ALTBUF]) 8311 ToAlternate(xw, False); 8312 else 8313 FromAlternate(xw, False); 8314 /* update_altscreen done by ToAlt and FromAlt */ 8315 } else if (screen->save_modes[DP_X_ALTBUF]) { 8316 do_ti_xtra_scroll(xw); 8317 } 8318 break; 8319 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 8320 if_PRINT_GRAPHICS2(DoRM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 8321 if (!xw->misc.titeInhibit) { 8322 if (screen->save_modes[DP_X_ALTBUF]) 8323 ToAlternate(xw, False); 8324 else 8325 FromAlternate(xw, False); 8326 /* update_altscreen done by ToAlt and FromAlt */ 8327 } else if (screen->save_modes[DP_X_ALTBUF]) { 8328 do_ti_xtra_scroll(xw); 8329 } 8330 } 8331 break; 8332 case srm_DECNKM: 8333 bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM); 8334 update_appkeypad(); 8335 break; 8336 case srm_DECBKM: /* backarrow mapping */ 8337 bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM); 8338 update_decbkm(); 8339 break; 8340 case srm_DECLRMM: /* left-right */ 8341 bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT); 8342 if (IsLeftRightMode(xw)) { 8343 xterm_ResetDouble(xw); 8344 } else { 8345 reset_lr_margins(screen); 8346 } 8347 break; 8348#if OPT_SIXEL_GRAPHICS 8349 case srm_DECSDM: /* sixel display mode (no scroll) */ 8350 bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM); 8351 update_decsdm(); 8352 break; 8353#endif 8354 case srm_DECNCSM: /* noclear */ 8355 bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM); 8356 break; 8357 case srm_VT200_MOUSE: /* mouse bogus sequence */ 8358 /* FALLTHRU */ 8359 case srm_VT200_HIGHLIGHT_MOUSE: 8360 /* FALLTHRU */ 8361 case srm_BTN_EVENT_MOUSE: 8362 /* FALLTHRU */ 8363 case srm_ANY_EVENT_MOUSE: 8364 DoRM0(DP_X_MOUSE, screen->send_mouse_pos); 8365 really_set_mousemode(xw, 8366 screen->send_mouse_pos != MOUSE_OFF, 8367 (XtermMouseModes) screen->send_mouse_pos); 8368 break; 8369#if OPT_FOCUS_EVENT 8370 case srm_FOCUS_EVENT_MOUSE: 8371 DoRM(DP_X_FOCUS, screen->send_focus_pos); 8372 break; 8373#endif 8374 case srm_EXT_MODE_MOUSE: 8375 /* FALLTHRU */ 8376 case srm_SGR_EXT_MODE_MOUSE: 8377 /* FALLTHRU */ 8378 case srm_URXVT_EXT_MODE_MOUSE: 8379 /* FALLTHRU */ 8380 case srm_PIXEL_POSITION_MOUSE: 8381 DoRM(DP_X_EXT_MOUSE, screen->extend_coords); 8382 break; 8383 case srm_ALLOW_ALTBUF: 8384 DoRM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 8385 if (xw->misc.titeInhibit) 8386 FromAlternate(xw, False); 8387 update_titeInhibit(); 8388 break; 8389 case srm_SAVE_CURSOR: 8390 if (!xw->misc.titeInhibit) { 8391 CursorRestore(xw); 8392 } 8393 break; 8394 case srm_FAST_SCROLL: 8395 DoRM(DP_FAST_SCROLL, screen->fastscroll); 8396 break; 8397 case srm_ALTERNATE_SCROLL: 8398 DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 8399 break; 8400 case srm_RXVT_SCROLL_TTY_OUTPUT: 8401 DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 8402 update_scrollttyoutput(); 8403 break; 8404 case srm_RXVT_SCROLL_TTY_KEYPRESS: 8405 DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 8406 update_scrollkey(); 8407 break; 8408 case srm_EIGHT_BIT_META: 8409 DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 8410 break; 8411#if OPT_NUM_LOCK 8412 case srm_REAL_NUMLOCK: 8413 DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 8414 update_num_lock(); 8415 break; 8416 case srm_META_SENDS_ESC: 8417 DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc); 8418 update_meta_esc(); 8419 break; 8420#endif 8421 case srm_DELETE_IS_DEL: 8422 DoRM(DP_DELETE_IS_DEL, screen->delete_is_del); 8423 update_delete_del(); 8424 break; 8425#if OPT_NUM_LOCK 8426 case srm_ALT_SENDS_ESC: 8427 DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 8428 update_alt_esc(); 8429 break; 8430#endif 8431 case srm_KEEP_SELECTION: 8432 DoRM(DP_KEEP_SELECTION, screen->keepSelection); 8433 update_keepSelection(); 8434 break; 8435 case srm_SELECT_TO_CLIPBOARD: 8436 DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 8437 update_selectToClipboard(); 8438 break; 8439 case srm_BELL_IS_URGENT: 8440 DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 8441 update_bellIsUrgent(); 8442 break; 8443 case srm_POP_ON_BELL: 8444 DoRM(DP_POP_ON_BELL, screen->poponbell); 8445 update_poponbell(); 8446 break; 8447 case srm_KEEP_CLIPBOARD: 8448 DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 8449 update_keepClipboard(); 8450 break; 8451#if OPT_TCAP_FKEYS 8452 case srm_TCAP_FKEYS: 8453 /* FALLTHRU */ 8454#endif 8455#if OPT_SUN_FUNC_KEYS 8456 case srm_SUN_FKEYS: 8457 /* FALLTHRU */ 8458#endif 8459#if OPT_HP_FUNC_KEYS 8460 case srm_HP_FKEYS: 8461 /* FALLTHRU */ 8462#endif 8463#if OPT_SCO_FUNC_KEYS 8464 case srm_SCO_FKEYS: 8465 /* FALLTHRU */ 8466#endif 8467#if OPT_SUNPC_KBD 8468 case srm_VT220_FKEYS: 8469 /* FALLTHRU */ 8470#endif 8471 case srm_LEGACY_FKEYS: 8472 xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE]; 8473 break; 8474#if OPT_PASTE64 || OPT_READLINE 8475 case srm_PASTE_IN_BRACKET: 8476 SCREEN_FLAG_restore(screen, paste_brackets); 8477 break; 8478#endif 8479#if OPT_READLINE 8480 case srm_BUTTON1_MOVE_POINT: 8481 SCREEN_FLAG_restore(screen, click1_moves); 8482 break; 8483 case srm_BUTTON2_MOVE_POINT: 8484 SCREEN_FLAG_restore(screen, paste_moves); 8485 break; 8486 case srm_DBUTTON3_DELETE: 8487 SCREEN_FLAG_restore(screen, dclick3_deletes); 8488 break; 8489 case srm_PASTE_QUOTE: 8490 SCREEN_FLAG_restore(screen, paste_quotes); 8491 break; 8492 case srm_PASTE_LITERAL_NL: 8493 SCREEN_FLAG_restore(screen, paste_literal_nl); 8494 break; 8495#endif /* OPT_READLINE */ 8496#if OPT_GRAPHICS 8497 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 8498 TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n", 8499 BtoS(screen->privatecolorregisters))); 8500 DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 8501 TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n", 8502 BtoS(screen->privatecolorregisters))); 8503 update_privatecolorregisters(); 8504 break; 8505#endif 8506#if OPT_SIXEL_GRAPHICS 8507 case srm_SIXEL_SCROLLS_RIGHT: 8508 TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n", 8509 BtoS(screen->sixel_scrolls_right))); 8510 DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 8511 TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n", 8512 BtoS(screen->sixel_scrolls_right))); 8513 break; 8514#endif 8515 case srm_DEC131TM: /* ignore */ 8516 case srm_DECAAM: /* ignore */ 8517 case srm_DECARSM: /* ignore */ 8518 case srm_DECATCBM: /* ignore */ 8519 case srm_DECATCUM: /* ignore */ 8520 case srm_DECBBSM: /* ignore */ 8521 case srm_DECCANSM: /* ignore */ 8522 case srm_DECCAPSLK: /* ignore */ 8523 case srm_DECCRTSM: /* ignore */ 8524 case srm_DECECM: /* ignore */ 8525 case srm_DECEKEM: /* ignore */ 8526 case srm_DECESKM: /* ignore */ 8527 case srm_DECFWM: /* ignore */ 8528 case srm_DECHCCM: /* ignore */ 8529 case srm_DECHDPXM: /* ignore */ 8530 case srm_DECHEM: /* ignore */ 8531 case srm_DECHWUM: /* ignore */ 8532 case srm_DECIPEM: /* ignore */ 8533 case srm_DECKBUM: /* ignore */ 8534 case srm_DECKKDM: /* ignore */ 8535 case srm_DECKLHIM: /* ignore */ 8536 case srm_DECKPM: /* ignore */ 8537 case srm_DECLTM: /* ignore */ 8538 case srm_DECMCM: /* ignore */ 8539 case srm_DECNAKB: /* ignore */ 8540 case srm_DECNULM: /* ignore */ 8541 case srm_DECNUMLK: /* ignore */ 8542 case srm_DECOSCNM: /* ignore */ 8543 case srm_DECPCCM: /* ignore */ 8544 case srm_DECRLCM: /* ignore */ 8545 case srm_DECRLM: /* ignore */ 8546 case srm_DECRPL: /* ignore */ 8547 case srm_DECVCCM: /* ignore */ 8548 case srm_DECXRLM: /* ignore */ 8549 default: 8550 break; 8551 } 8552 } 8553} 8554 8555/* 8556 * Convert an XTextProperty to a string. 8557 * 8558 * This frees the data owned by the XTextProperty, and returns in its place the 8559 * string, which must be freed by the caller. 8560 */ 8561static char * 8562property_to_string(XtermWidget xw, XTextProperty * text) 8563{ 8564 TScreen *screen = TScreenOf(xw); 8565 Display *dpy = screen->display; 8566 char *result = NULL; 8567 char **list = NULL; 8568 int length = 0; 8569 int rc; 8570 8571 TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n", 8572 text->value, 8573 TraceAtomName(dpy, text->encoding), 8574 text->format, 8575 text->nitems)); 8576 8577#if OPT_WIDE_CHARS 8578 /* 8579 * We will use the XmbTextPropertyToTextList call to extract UTF-8 data. 8580 * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to 8581 * ISO-8859-1. 8582 */ 8583 rc = -1; 8584 if ((text->format != 8) 8585 || IsTitleMode(xw, tmGetUtf8) 8586 || (text->encoding == XA_UTF8_STRING(dpy) && 8587 !(screen->wide_chars || screen->c1_printable) && 8588 (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0) 8589 || (rc < 0)) 8590#endif 8591 if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0) 8592 rc = XTextPropertyToStringList(text, &list, &length); 8593 8594 if (rc >= 0) { 8595 int n, c, pass; 8596 size_t need; 8597 8598 for (pass = 0; pass < 2; ++pass) { 8599 for (n = 0, need = 0; n < length; n++) { 8600 char *s = list[n]; 8601 while ((c = *s++) != '\0') { 8602 if (pass) 8603 result[need] = (char) c; 8604 ++need; 8605 } 8606 } 8607 if (pass) 8608 result[need] = '\0'; 8609 else 8610 result = malloc(need + 1); 8611 if (result == NULL) 8612 break; 8613 } 8614 XFreeStringList(list); 8615 } 8616 if (text->value != NULL) 8617 XFree(text->value); 8618 8619 return result; 8620} 8621 8622static char * 8623get_icon_label(XtermWidget xw) 8624{ 8625 XTextProperty text; 8626 char *result = NULL; 8627 8628 if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 8629 result = property_to_string(xw, &text); 8630 } 8631 return result; 8632} 8633 8634static char * 8635get_window_label(XtermWidget xw) 8636{ 8637 XTextProperty text; 8638 char *result = NULL; 8639 8640 if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 8641 result = property_to_string(xw, &text); 8642 } 8643 return result; 8644} 8645 8646/* 8647 * Report window label (icon or title) in dtterm protocol 8648 * ESC ] code label ESC backslash 8649 */ 8650static void 8651report_win_label(XtermWidget xw, 8652 int code, 8653 char *text) 8654{ 8655 unparseputc(xw, ANSI_ESC); 8656 unparseputc(xw, ']'); 8657 unparseputc(xw, code); 8658 8659 if (text != NULL) { 8660 int copy = IsTitleMode(xw, tmGetBase16); 8661 if (copy) { 8662 TRACE(("Encoding hex:%s\n", text)); 8663 text = x_encode_hex(text); 8664 } 8665 unparseputs(xw, text); 8666 if (copy) 8667 free(text); 8668 } 8669 8670 unparseputc(xw, ANSI_ESC); 8671 unparseputc(xw, '\\'); /* should be ST */ 8672 unparse_end(xw); 8673} 8674 8675/* 8676 * Window operations (from CDE dtterm description, as well as extensions). 8677 * See also "allowWindowOps" resource. 8678 */ 8679static void 8680window_ops(XtermWidget xw) 8681{ 8682 TScreen *screen = TScreenOf(xw); 8683 XWindowChanges values; 8684 XWindowAttributes win_attrs; 8685#if OPT_MAXIMIZE 8686 unsigned root_width; 8687 unsigned root_height; 8688#endif 8689 int code = zero_if_default(0); 8690 char *label; 8691 8692 TRACE(("window_ops %d\n", code)); 8693 switch (code) { 8694 case ewRestoreWin: /* Restore (de-iconify) window */ 8695 if (AllowWindowOps(xw, ewRestoreWin)) { 8696 xtermDeiconify(xw); 8697 } 8698 break; 8699 8700 case ewMinimizeWin: /* Minimize (iconify) window */ 8701 if (AllowWindowOps(xw, ewMinimizeWin)) { 8702 xtermIconify(xw); 8703 } 8704 break; 8705 8706 case ewSetWinPosition: /* Move the window to the given position */ 8707 if (AllowWindowOps(xw, ewSetWinPosition)) { 8708 unsigned value_mask; 8709 8710 values.x = (Position) zero_if_default(1); 8711 values.y = (Position) zero_if_default(2); 8712 TRACE(("...move window to %d,%d\n", values.x, values.y)); 8713 value_mask = (CWX | CWY); 8714 XReconfigureWMWindow(screen->display, 8715 VShellWindow(xw), 8716 DefaultScreen(screen->display), 8717 value_mask, 8718 &values); 8719 } 8720 break; 8721 8722 case ewSetWinSizePixels: /* Resize the window to given size in pixels */ 8723 if (AllowWindowOps(xw, ewSetWinSizePixels)) { 8724 RequestResize(xw, optional_param(1), optional_param(2), False); 8725 } 8726 break; 8727 8728 case ewRaiseWin: /* Raise the window to the front of the stack */ 8729 if (AllowWindowOps(xw, ewRaiseWin)) { 8730 TRACE(("...raise window\n")); 8731 XRaiseWindow(screen->display, VShellWindow(xw)); 8732 } 8733 break; 8734 8735 case ewLowerWin: /* Lower the window to the bottom of the stack */ 8736 if (AllowWindowOps(xw, ewLowerWin)) { 8737 TRACE(("...lower window\n")); 8738 XLowerWindow(screen->display, VShellWindow(xw)); 8739 } 8740 break; 8741 8742 case ewRefreshWin: /* Refresh the window */ 8743 if (AllowWindowOps(xw, ewRefreshWin)) { 8744 TRACE(("...redraw window\n")); 8745 Redraw(); 8746 } 8747 break; 8748 8749 case ewSetWinSizeChars: /* Resize the text-area, in characters */ 8750 if (AllowWindowOps(xw, ewSetWinSizeChars)) { 8751 RequestResize(xw, optional_param(1), optional_param(2), True); 8752 } 8753 break; 8754 8755#if OPT_MAXIMIZE 8756 case ewMaximizeWin: /* Maximize or restore */ 8757 if (AllowWindowOps(xw, ewMaximizeWin)) { 8758 RequestMaximize(xw, zero_if_default(1)); 8759 } 8760 break; 8761 case ewFullscreenWin: /* Fullscreen or restore */ 8762 if (AllowWindowOps(xw, ewFullscreenWin)) { 8763 switch (zero_if_default(1)) { 8764 default: 8765 RequestMaximize(xw, 0); 8766 break; 8767 case 1: 8768 RequestMaximize(xw, 1); 8769 break; 8770 case 2: 8771 RequestMaximize(xw, !(screen->restore_data)); 8772 break; 8773 } 8774 } 8775 break; 8776#endif 8777 8778 case ewGetWinState: /* Report the window's state */ 8779 if (AllowWindowOps(xw, ewGetWinState)) { 8780 TRACE(("...get window attributes\n")); 8781 init_reply(ANSI_CSI); 8782 reply.a_nparam = 1; 8783 reply.a_param[0] = (ParmType) (xtermIsIconified(xw) ? 2 : 1); 8784 reply.a_final = 't'; 8785 unparseseq(xw, &reply); 8786 } 8787 break; 8788 8789 case ewGetWinPosition: /* Report the window's position */ 8790 if (AllowWindowOps(xw, ewGetWinPosition)) { 8791 Window win; 8792 Window result_win; 8793 int result_y, result_x; 8794 8795 TRACE(("...get window position\n")); 8796 init_reply(ANSI_CSI); 8797 reply.a_nparam = 3; 8798 reply.a_param[0] = 3; 8799 switch (zero_if_default(1)) { 8800 case 2: /* report the text-window's position */ 8801 result_y = 0; 8802 result_x = 0; 8803 { 8804 Widget mw; 8805 for (mw = (Widget) xw; mw != NULL; mw = XtParent(mw)) { 8806 result_x += mw->core.x; 8807 result_y += mw->core.y; 8808 if (mw == SHELL_OF(xw)) 8809 break; 8810 } 8811 } 8812 result_x += OriginX(screen); 8813 result_y += OriginY(screen); 8814 break; 8815 default: 8816 win = WMFrameWindow(xw); 8817 xtermGetWinAttrs(screen->display, 8818 win, 8819 &win_attrs); 8820 XTranslateCoordinates(screen->display, 8821 VShellWindow(xw), 8822 win_attrs.root, 8823 -win_attrs.border_width, 8824 -win_attrs.border_width, 8825 &result_x, &result_y, &result_win); 8826 TRACE(("translated position %d,%d vs %d,%d\n", 8827 result_y, result_x, 8828 win_attrs.y, win_attrs.x)); 8829 if (!discount_frame_extents(xw, &result_y, &result_x)) { 8830 TRACE(("...cancelled translation\n")); 8831 result_y = win_attrs.y; 8832 result_x = win_attrs.x; 8833 } 8834 break; 8835 } 8836 reply.a_param[1] = (ParmType) result_x; 8837 reply.a_param[2] = (ParmType) result_y; 8838 reply.a_final = 't'; 8839 unparseseq(xw, &reply); 8840 } 8841 break; 8842 8843 case ewGetWinSizePixels: /* Report the window's size in pixels */ 8844 if (AllowWindowOps(xw, ewGetWinSizePixels)) { 8845 ParmType high = (ParmType) Height(screen); 8846 ParmType wide = (ParmType) Width(screen); 8847 8848 TRACE(("...get window size in pixels\n")); 8849 init_reply(ANSI_CSI); 8850 reply.a_nparam = 3; 8851 reply.a_param[0] = 4; 8852 switch (zero_if_default(1)) { 8853 case 2: /* report the shell-window's size */ 8854 xtermGetWinAttrs(screen->display, 8855 WMFrameWindow(xw), 8856 &win_attrs); 8857 high = (ParmType) win_attrs.height; 8858 wide = (ParmType) win_attrs.width; 8859 /* FALLTHRU */ 8860 default: 8861 reply.a_param[1] = high; 8862 reply.a_param[2] = wide; 8863 break; 8864 } 8865 reply.a_final = 't'; 8866 unparseseq(xw, &reply); 8867 } 8868 break; 8869 8870#if OPT_MAXIMIZE 8871 case ewGetScreenSizePixels: /* Report the screen's size, in Pixels */ 8872 if (AllowWindowOps(xw, ewGetScreenSizePixels)) { 8873 TRACE(("...get screen size in pixels\n")); 8874 (void) QueryMaximize(xw, &root_width, &root_height); 8875 init_reply(ANSI_CSI); 8876 reply.a_nparam = 3; 8877 reply.a_param[0] = 5; 8878 reply.a_param[1] = (ParmType) root_height; 8879 reply.a_param[2] = (ParmType) root_width; 8880 reply.a_final = 't'; 8881 unparseseq(xw, &reply); 8882 } 8883 break; 8884 case ewGetCharSizePixels: /* Report the font's size, in pixel */ 8885 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 8886 TRACE(("...get font size in pixels\n")); 8887 TRACE(("...using font size %dx%d\n", 8888 FontHeight(screen), 8889 FontWidth(screen))); 8890 init_reply(ANSI_CSI); 8891 reply.a_nparam = 3; 8892 reply.a_param[0] = 6; 8893 reply.a_param[1] = (ParmType) FontHeight(screen); 8894 reply.a_param[2] = (ParmType) FontWidth(screen); 8895 reply.a_final = 't'; 8896 unparseseq(xw, &reply); 8897 } 8898 break; 8899#endif 8900 8901 case ewGetWinSizeChars: /* Report the text's size in characters */ 8902 if (AllowWindowOps(xw, ewGetWinSizeChars)) { 8903 TRACE(("...get window size in characters\n")); 8904 init_reply(ANSI_CSI); 8905 reply.a_nparam = 3; 8906 reply.a_param[0] = 8; 8907 reply.a_param[1] = (ParmType) MaxRows(screen); 8908 reply.a_param[2] = (ParmType) MaxCols(screen); 8909 reply.a_final = 't'; 8910 unparseseq(xw, &reply); 8911 } 8912 break; 8913 8914#if OPT_MAXIMIZE 8915 case ewGetScreenSizeChars: /* Report the screen's size, in characters */ 8916 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 8917 TRACE(("...get screen size in characters\n")); 8918 TRACE(("...using font size %dx%d\n", 8919 FontHeight(screen), 8920 FontWidth(screen))); 8921 (void) QueryMaximize(xw, &root_width, &root_height); 8922 init_reply(ANSI_CSI); 8923 reply.a_nparam = 3; 8924 reply.a_param[0] = 9; 8925 reply.a_param[1] = (ParmType) (root_height 8926 / (unsigned) FontHeight(screen)); 8927 reply.a_param[2] = (ParmType) (root_width 8928 / (unsigned) FontWidth(screen)); 8929 reply.a_final = 't'; 8930 unparseseq(xw, &reply); 8931 } 8932 break; 8933#endif 8934 8935 case ewGetIconTitle: /* Report the icon's label */ 8936 if (AllowWindowOps(xw, ewGetIconTitle)) { 8937 TRACE(("...get icon's label\n")); 8938 report_win_label(xw, 'L', label = get_icon_label(xw)); 8939 free(label); 8940 } 8941 break; 8942 8943 case ewGetWinTitle: /* Report the window's title */ 8944 if (AllowWindowOps(xw, ewGetWinTitle)) { 8945 TRACE(("...get window's label\n")); 8946 report_win_label(xw, 'l', label = get_window_label(xw)); 8947 free(label); 8948 } 8949 break; 8950 8951#define WhichTitle(n) \ 8952 ((n) == 0 \ 8953 ? "window/icon titles" \ 8954 : ((n) == 1 \ 8955 ? "icon title" \ 8956 : ((n) == 2 \ 8957 ? "window title" \ 8958 : "no titles"))) 8959 8960 case ewPushTitle: /* save the window's title(s) on stack */ 8961 if (AllowWindowOps(xw, ewPushTitle)) { 8962 SaveTitle item; 8963 8964 TRACE(("...push %s onto stack\n", WhichTitle(zero_if_default(1)))); 8965 memset(&item, 0, sizeof(item)); 8966 switch (zero_if_default(1)) { 8967 case 0: 8968 item.iconName = get_icon_label(xw); 8969 item.windowName = get_window_label(xw); 8970 break; 8971 case 1: 8972 item.iconName = get_icon_label(xw); 8973 break; 8974 case 2: 8975 item.windowName = get_window_label(xw); 8976 break; 8977 } 8978 xtermPushTitle(screen, zero_if_default(2), &item); 8979 } 8980 break; 8981 8982 case ewPopTitle: /* restore the window's title(s) from stack */ 8983 if (AllowWindowOps(xw, ewPopTitle)) { 8984 SaveTitle item; 8985 8986 TRACE(("...%s %s off stack\n", 8987 (zero_if_default(2) 8988 ? "get" 8989 : "pop"), 8990 WhichTitle(zero_if_default(1)))); 8991 8992 if (xtermPopTitle(screen, zero_if_default(2), &item)) { 8993 switch (zero_if_default(1)) { 8994 case 0: 8995 ChangeIconName(xw, item.iconName); 8996 ChangeTitle(xw, item.windowName); 8997 break; 8998 case 1: 8999 ChangeIconName(xw, item.iconName); 9000 break; 9001 case 2: 9002 ChangeTitle(xw, item.windowName); 9003 break; 9004 } 9005 if (!zero_if_default(2)) 9006 xtermFreeTitle(&item); 9007 } 9008 } 9009 break; 9010 9011 default: /* DECSLPP (24, 25, 36, 48, 72, 144) */ 9012 if (AllowWindowOps(xw, ewSetWinLines)) { 9013 if (code >= 24) 9014 RequestResize(xw, code, -1, True); 9015 } 9016 break; 9017 } 9018} 9019 9020/* 9021 * set a bit in a word given a pointer to the word and a mask. 9022 */ 9023static int 9024bitset(unsigned *p, unsigned mask) 9025{ 9026 unsigned before = *p; 9027 *p |= mask; 9028 return (before != *p); 9029} 9030 9031/* 9032 * clear a bit in a word given a pointer to the word and a mask. 9033 */ 9034static int 9035bitclr(unsigned *p, unsigned mask) 9036{ 9037 unsigned before = *p; 9038 *p &= ~mask; 9039 return (before != *p); 9040} 9041 9042/* 9043 * Copy bits from one word to another, given a mask 9044 */ 9045static int 9046bitcpy(unsigned *p, unsigned q, unsigned mask) 9047{ 9048 unsigned before = *p; 9049 bitclr(p, mask); 9050 bitset(p, q & mask); 9051 return (before != *p); 9052} 9053 9054void 9055unparseputc1(XtermWidget xw, int c) 9056{ 9057 if (c >= 0x80 && c <= 0x9F) { 9058 if (!TScreenOf(xw)->control_eight_bits) { 9059 unparseputc(xw, ANSI_ESC); 9060 c = c - 0x40; 9061 } 9062 } 9063 unparseputc(xw, c); 9064} 9065 9066void 9067unparseseq(XtermWidget xw, ANSI *ap) 9068{ 9069 int c; 9070 9071 assert(ap->a_nparam < NPARAM); 9072 unparseputc1(xw, c = ap->a_type); 9073 if (c == ANSI_ESC 9074 || c == ANSI_DCS 9075 || c == ANSI_CSI 9076 || c == ANSI_OSC 9077 || c == ANSI_PM 9078 || c == ANSI_APC 9079 || c == ANSI_SS3) { 9080 int i; 9081 int inters; 9082 char temp[8]; 9083 9084 if (ap->a_pintro != 0) 9085 unparseputc(xw, ap->a_pintro); 9086 for (i = 0; i < ap->a_nparam; ++i) { 9087 if (i != 0) { 9088 if (ap->a_radix[i] == 1 || ap->a_radix[i - 1] == 1) { 9089 ; 9090 } else if (ap->a_delim) { 9091 unparseputs(xw, ap->a_delim); 9092 } else { 9093 unparseputc(xw, ';'); 9094 } 9095 } 9096 switch (ap->a_radix[i]) { 9097 case 16: 9098 sprintf(temp, "%04X", UParmOf(ap->a_param[i])); 9099 unparseputs(xw, temp); 9100 break; 9101 case 1: 9102 unparseputc(xw, ap->a_param[i]); 9103 break; 9104 default: 9105 unparseputn(xw, UParmOf(ap->a_param[i])); 9106 break; 9107 } 9108 } 9109 if ((inters = ap->a_inters) != 0) { 9110 for (i = 3; i >= 0; --i) { 9111 c = CharOf(inters >> (8 * i)); 9112 if (c != 0) 9113 unparseputc(xw, c); 9114 } 9115 } 9116 switch (ap->a_type) { 9117 case ANSI_DCS: 9118 /* FALLTHRU */ 9119 case ANSI_OSC: 9120 /* FALLTHRU */ 9121 case ANSI_PM: 9122 /* FALLTHRU */ 9123 case ANSI_APC: 9124 unparseputc1(xw, ANSI_ST); 9125 break; 9126 default: 9127 unparseputc(xw, (char) ap->a_final); 9128 break; 9129 } 9130 } 9131 unparse_end(xw); 9132} 9133 9134void 9135unparseputn(XtermWidget xw, unsigned n) 9136{ 9137 unsigned q; 9138 9139 q = n / 10; 9140 if (q != 0) 9141 unparseputn(xw, q); 9142 unparseputc(xw, (char) ('0' + (n % 10))); 9143} 9144 9145void 9146unparseputs(XtermWidget xw, const char *s) 9147{ 9148 if (s != NULL) { 9149 while (*s) 9150 unparseputc(xw, *s++); 9151 } 9152} 9153 9154void 9155unparseputc(XtermWidget xw, int c) 9156{ 9157 TScreen *screen = TScreenOf(xw); 9158 IChar *buf = screen->unparse_bfr; 9159 unsigned len; 9160 9161 if ((screen->unparse_len + 2) >= screen->unparse_max) 9162 unparse_end(xw); 9163 9164 len = screen->unparse_len; 9165 9166#if OPT_TCAP_QUERY 9167 /* 9168 * If we're returning a termcap string, it has to be translated since 9169 * a DCS must not contain any characters except for the normal 7-bit 9170 * printable ASCII (counting tab, carriage return, etc). For now, 9171 * just use hexadecimal for the whole thing. 9172 */ 9173 if (screen->tc_query_code >= 0) { 9174 char tmp[3]; 9175 sprintf(tmp, "%02X", (unsigned) (c & 0xFF)); 9176 buf[len++] = CharOf(tmp[0]); 9177 buf[len++] = CharOf(tmp[1]); 9178 } else 9179#endif 9180 if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) { 9181 buf[len++] = '\n'; 9182 } 9183 9184 screen->unparse_len = len; 9185 9186 /* If send/receive mode is reset, we echo characters locally */ 9187 if ((xw->keyboard.flags & MODE_SRM) == 0) { 9188 doparsing(xw, (unsigned) c, &myState); 9189 } 9190} 9191 9192void 9193unparse_end(XtermWidget xw) 9194{ 9195 TScreen *screen = TScreenOf(xw); 9196 9197#if OPT_TCAP_QUERY 9198 /* 9199 * tcap-query works by simulating key-presses, which ordinarily would be 9200 * flushed out at the end of each key. For better efficiency, do not do 9201 * the flush unless we are about to fill the buffer used to capture the 9202 * response. 9203 */ 9204 if ((screen->tc_query_code >= 0) 9205 && (screen->unparse_len + 2 < screen->unparse_max)) { 9206 return; 9207 } 9208#endif 9209 if (screen->unparse_len) { 9210 TRACE(("unparse_end %u:%s\n", 9211 screen->unparse_len, 9212 visibleIChars(screen->unparse_bfr, (size_t) screen->unparse_len))); 9213 writePtyData(screen->respond, screen->unparse_bfr, (size_t) screen->unparse_len); 9214 screen->unparse_len = 0; 9215 } 9216} 9217 9218void 9219ToggleAlternate(XtermWidget xw) 9220{ 9221 if (TScreenOf(xw)->whichBuf) 9222 FromAlternate(xw, False); 9223 else 9224 ToAlternate(xw, False); 9225} 9226 9227static void 9228ToAlternate(XtermWidget xw, Bool clearFirst) 9229{ 9230 TScreen *screen = TScreenOf(xw); 9231 9232 if (screen->whichBuf == 0) { 9233 TRACE(("ToAlternate\n")); 9234 if (!screen->editBuf_index[1]) { 9235 screen->editBuf_index[1] = allocScrnBuf(xw, 9236 (unsigned) MaxRows(screen), 9237 (unsigned) MaxCols(screen), 9238 &screen->editBuf_data[1]); 9239 } 9240 SwitchBufs(xw, 1, clearFirst); 9241 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 9242 update_altscreen(); 9243 } 9244} 9245 9246static void 9247FromAlternate(XtermWidget xw, Bool clearFirst) 9248{ 9249 TScreen *screen = TScreenOf(xw); 9250 9251 if (screen->whichBuf != 0) { 9252 TRACE(("FromAlternate\n")); 9253 if (screen->scroll_amt) { 9254 FlushScroll(xw); 9255 } 9256 if (clearFirst) 9257 ClearScreen(xw); 9258 SwitchBufs(xw, 0, False); 9259 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 9260 update_altscreen(); 9261 } 9262} 9263 9264static void 9265SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst) 9266{ 9267 TScreen *screen = TScreenOf(xw); 9268 int rows, top; 9269 9270 screen->whichBuf = toBuf; 9271 if (screen->cursor_state) 9272 HideCursor(xw); 9273 9274 rows = MaxRows(screen); 9275#if OPT_STATUS_LINE 9276 if (IsStatusShown(screen) && (rows > 0)) { 9277 /* avoid clearing the status-line in this function */ 9278 --rows; 9279 } 9280#endif 9281 SwitchBufPtrs(xw, toBuf); 9282 9283 if ((top = INX2ROW(screen, 0)) < rows) { 9284 if (screen->scroll_amt) { 9285 FlushScroll(xw); 9286 } 9287 xtermClear2(xw, 9288 (int) OriginX(screen), 9289 (int) top * FontHeight(screen) + screen->border, 9290 (unsigned) Width(screen), 9291 (unsigned) ((rows - top) * FontHeight(screen))); 9292 if (clearFirst) { 9293 ClearBufRows(xw, top, rows); 9294 } 9295 } 9296 ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False); 9297} 9298 9299Bool 9300CheckBufPtrs(TScreen *screen) 9301{ 9302 return (screen->visbuf != NULL 9303 && screen->editBuf_index[0] != NULL 9304 && screen->editBuf_index[1] != NULL); 9305} 9306 9307/* 9308 * Swap buffer line pointers between alternate and regular screens. 9309 */ 9310void 9311SwitchBufPtrs(XtermWidget xw, int toBuf) 9312{ 9313 TScreen *screen = TScreenOf(xw); 9314 9315 if (CheckBufPtrs(screen)) { 9316#if OPT_STATUS_LINE 9317 if (IsStatusShown(screen) 9318 && (screen->visbuf != screen->editBuf_index[toBuf])) { 9319 LineData *oldLD; 9320 LineData *newLD; 9321 int row = MaxRows(screen); 9322 9323 oldLD = getLineData(screen, row); 9324 screen->visbuf = screen->editBuf_index[toBuf]; 9325 newLD = getLineData(screen, row); 9326 9327 copyLineData(newLD, oldLD); 9328 } else 9329#endif 9330 screen->visbuf = screen->editBuf_index[toBuf]; 9331 } 9332} 9333 9334void 9335VTRun(XtermWidget xw) 9336{ 9337 TScreen *screen = TScreenOf(xw); 9338 9339 TRACE(("VTRun ...\n")); 9340 9341 if (!screen->Vshow && !resource.notMapped) { 9342 set_vt_visibility(True); 9343 } 9344 update_vttekmode(); 9345 update_vtshow(); 9346 update_tekshow(); 9347 set_vthide_sensitivity(); 9348 9349 ScrnAllocBuf(xw); 9350 9351 screen->cursor_state = OFF; 9352 screen->cursor_set = ON; 9353#if OPT_BLINK_CURS 9354 if (DoStartBlinking(screen)) 9355 StartBlinking(xw); 9356#endif 9357 9358#if OPT_TEK4014 9359 if (Tpushb > Tpushback) { 9360 fillPtyData(xw, VTbuffer, (char *) Tpushback, (size_t) (Tpushb - Tpushback)); 9361 Tpushb = Tpushback; 9362 } 9363#endif 9364 screen->is_running = True; 9365 if (screen->embed_high && screen->embed_wide) { 9366 ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags)); 9367 } 9368#if OPT_MAXIMIZE 9369 else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways) 9370 FullScreen(xw, True); 9371#endif 9372 if (!setjmp(VTend)) 9373 VTparse(xw); 9374 StopBlinking(xw); 9375 HideCursor(xw); 9376 screen->cursor_set = OFF; 9377 TRACE(("... VTRun\n")); 9378} 9379 9380/*ARGSUSED*/ 9381static void 9382VTExpose(Widget w GCC_UNUSED, 9383 XEvent *event, 9384 Region region GCC_UNUSED) 9385{ 9386 DEBUG_MSG("Expose\n"); 9387 if (event->type == Expose) 9388 HandleExposure(term, event); 9389} 9390 9391static void 9392VTGraphicsOrNoExpose(XEvent *event) 9393{ 9394 XtermWidget xw = term; 9395 TScreen *screen = TScreenOf(xw); 9396 if (screen->incopy <= 0) { 9397 screen->incopy = 1; 9398 if (screen->scrolls > 0) 9399 screen->scrolls--; 9400 } 9401 if (event->type == GraphicsExpose) 9402 if (HandleExposure(xw, event)) 9403 screen->cursor_state = OFF; 9404 if ((event->type == NoExpose) 9405 || ((XGraphicsExposeEvent *) event)->count == 0) { 9406 if (screen->incopy <= 0 && screen->scrolls > 0) 9407 screen->scrolls--; 9408 if (screen->scrolls) 9409 screen->incopy = -1; 9410 else 9411 screen->incopy = 0; 9412 } 9413} 9414 9415/*ARGSUSED*/ 9416static void 9417VTNonMaskableEvent(Widget w GCC_UNUSED, 9418 XtPointer closure GCC_UNUSED, 9419 XEvent *event, 9420 Boolean *cont GCC_UNUSED) 9421{ 9422 switch (event->type) { 9423 case GraphicsExpose: 9424 /* FALLTHRU */ 9425 case NoExpose: 9426 VTGraphicsOrNoExpose(event); 9427 break; 9428 } 9429} 9430 9431static void 9432VTResize(Widget w) 9433{ 9434 if (XtIsRealized(w)) { 9435 XtermWidget xw = (XtermWidget) w; 9436 ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags); 9437 } 9438} 9439 9440#define okDimension(src,dst) ((src <= MAX_U_COORD) \ 9441 && ((dst = (Dimension) src) == src)) 9442 9443static void 9444RequestResize(XtermWidget xw, int rows, int cols, Bool text) 9445{ 9446 TScreen *screen = TScreenOf(xw); 9447 Dimension replyWidth, replyHeight; 9448 Dimension askedWidth, askedHeight; 9449 XtGeometryResult status; 9450 XWindowAttributes attrs; 9451#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 9452 Boolean buggyXft = False; 9453 Cardinal ignore = 0; 9454#endif 9455 9456 TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text)); 9457#if OPT_STATUS_LINE 9458 if (IsStatusShown(screen)) { 9459 if (rows == -1) { 9460 /* prevent shrinking on DECCOLM, XTRESTORE, DECSCPP, DECANM */ 9461 rows = MaxRows(screen); 9462 } 9463 if (rows > 0) { 9464 TRACE(("...reserve a row for status-line\n")); 9465 ++rows; 9466 } 9467 } 9468#endif 9469 9470 /* check first if the row/column values fit into a Dimension */ 9471 if (cols > 0) { 9472 if ((int) (askedWidth = (Dimension) cols) < cols) { 9473 TRACE(("... cols too large for Dimension\n")); 9474 return; 9475 } 9476 } else { 9477 askedWidth = 0; 9478 } 9479 if (rows > 0) { 9480 if ((int) (askedHeight = (Dimension) rows) < rows) { 9481 TRACE(("... rows too large for Dimension\n")); 9482 return; 9483 } 9484 } else { 9485 askedHeight = 0; 9486 } 9487 9488 xw->work.doing_resize = True; 9489 9490#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 9491 /* 9492 * Work around a bug seen when vttest switches from 132 columns back to 80 9493 * columns, while double-buffering is active. If Xft is active during the 9494 * resize, the screen will be blank thereafter. This workaround causes 9495 * some extra flickering, but that is preferable to a blank screen. 9496 * 9497 * Since the bitmap- and TrueType-fonts do not always have identical sizes, 9498 * do this switching early, to use the updated font-sizes in the request 9499 * for resizing the window. 9500 */ 9501#define ToggleXft() HandleRenderFont((Widget)xw, (XEvent *)0, (String *)0, &ignore) 9502 if (resource.buffered 9503 && UsingRenderFont(xw)) { 9504 ToggleXft(); 9505 buggyXft = True; 9506 } 9507#endif 9508 9509 /* 9510 * If the requested values will fit into a Dimension, and one or both are 9511 * zero, get the current corresponding screen dimension to use as a limit. 9512 */ 9513 if (askedHeight == 0 9514 || askedWidth == 0 9515 || xw->misc.limit_resize > 0) { 9516 xtermGetWinAttrs(XtDisplay(xw), 9517 RootWindowOfScreen(XtScreen(xw)), &attrs); 9518 } 9519 9520 /* 9521 * Using the current font metrics, translate the requested character 9522 * rows/columns into pixels. 9523 */ 9524 if (text) { 9525 unsigned long value; 9526 9527 if ((value = (unsigned long) rows) != 0) { 9528 if (rows < 0) 9529 value = (unsigned long) MaxRows(screen); 9530 value *= (unsigned long) FontHeight(screen); 9531 value += (unsigned long) (2 * screen->border); 9532 if (!okDimension(value, askedHeight)) 9533 goto give_up; 9534 } 9535 9536 if ((value = (unsigned long) cols) != 0) { 9537 if (cols < 0) 9538 value = (unsigned long) MaxCols(screen); 9539 value *= (unsigned long) FontWidth(screen); 9540 value += (unsigned long) ((2 * screen->border) 9541 + ScrollbarWidth(screen)); 9542 if (!okDimension(value, askedWidth)) 9543 goto give_up; 9544 } 9545 9546 } else { 9547 if (rows < 0) 9548 askedHeight = FullHeight(screen); 9549 if (cols < 0) 9550 askedWidth = FullWidth(screen); 9551 } 9552 9553 if (rows == 0) { 9554 askedHeight = (Dimension) attrs.height; 9555 } 9556 if (cols == 0) { 9557 askedWidth = (Dimension) attrs.width; 9558 } 9559 9560 if (xw->misc.limit_resize > 0) { 9561 Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height); 9562 Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width); 9563 if ((int) high < attrs.height) 9564 high = (Dimension) attrs.height; 9565 if (askedHeight > high) 9566 askedHeight = high; 9567 if ((int) wide < attrs.width) 9568 wide = (Dimension) attrs.width; 9569 if (askedWidth > wide) 9570 askedWidth = wide; 9571 } 9572#ifndef nothack 9573 getXtermSizeHints(xw); 9574#endif 9575 9576 TRACE(("...requesting resize %dx%d (%dx%d)\n", 9577 askedHeight, askedWidth, 9578 askedHeight / FontHeight(screen), 9579 askedWidth / FontWidth(screen))); 9580 status = REQ_RESIZE((Widget) xw, 9581 askedWidth, askedHeight, 9582 &replyWidth, &replyHeight); 9583 9584 if (status == XtGeometryYes || 9585 status == XtGeometryDone) { 9586 ScreenResize(xw, replyWidth, replyHeight, &xw->flags); 9587 } 9588#ifndef nothack 9589 /* 9590 * XtMakeResizeRequest() has the undesirable side-effect of clearing 9591 * the window manager's hints, even on a failed request. This would 9592 * presumably be fixed if the shell did its own work. 9593 */ 9594 if (xw->hints.flags 9595 && replyHeight 9596 && replyWidth) { 9597 xw->hints.height = replyHeight; 9598 xw->hints.width = replyWidth; 9599 9600 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 9601 TRACE_HINTS(&xw->hints); 9602 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints); 9603 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 9604 TRACE_WM_HINTS(xw); 9605 } 9606#endif 9607 9608 XSync(screen->display, False); /* synchronize */ 9609 if (xtermAppPending()) { 9610 xevents(xw); 9611 } 9612 9613 give_up: 9614#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 9615 if (buggyXft) { 9616 ToggleXft(); 9617 if (xtermAppPending()) { 9618 xevents(xw); 9619 } 9620 } 9621#endif 9622 9623 xw->work.doing_resize = False; 9624 9625 TRACE(("...RequestResize done\n")); 9626 return; 9627} 9628 9629static String xterm_trans = 9630"<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\ 9631 <MappingNotify>: KeyboardMapping()\n"; 9632 9633int 9634VTInit(XtermWidget xw) 9635{ 9636 Widget vtparent = SHELL_OF(xw); 9637 9638 TRACE(("VTInit " TRACE_L "\n")); 9639 9640 XtRealizeWidget(vtparent); 9641 XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans)); 9642 (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent), 9643 &wm_delete_window, 1); 9644 9645 if (IsEmpty(xw->keyboard.print_translations)) { 9646 TRACE_TRANS("shell", vtparent); 9647 TRACE_TRANS("vt100", (Widget) (xw)); 9648 xtermButtonInit(xw); 9649 } 9650 9651 ScrnAllocBuf(xw); 9652 9653 TRACE(("..." TRACE_R " VTInit\n")); 9654 return (1); 9655} 9656 9657static void 9658VTClassInit(void) 9659{ 9660 XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, 9661 (XtConvertArgList) NULL, (Cardinal) 0); 9662} 9663 9664/* 9665 * Override the use of XtDefaultForeground/XtDefaultBackground to make some 9666 * colors, such as cursor color, use the actual foreground/background value 9667 * if there is no explicit resource value used. 9668 */ 9669static Pixel 9670fill_Tres(XtermWidget target, XtermWidget source, int offset) 9671{ 9672 char *name; 9673 ScrnColors temp; 9674 TScreen *src = TScreenOf(source); 9675 TScreen *dst = TScreenOf(target); 9676 9677 dst->Tcolors[offset] = src->Tcolors[offset]; 9678 dst->Tcolors[offset].mode = False; 9679 9680 if ((name = x_strtrim(dst->Tcolors[offset].resource)) != NULL) 9681 dst->Tcolors[offset].resource = name; 9682 9683 if (name == NULL) { 9684 dst->Tcolors[offset].value = target->dft_foreground; 9685 } else if (isDefaultForeground(name)) { 9686 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 9687 ? target->dft_foreground 9688 : dst->Tcolors[TEXT_FG].value); 9689 } else if (isDefaultBackground(name)) { 9690 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 9691 ? target->dft_background 9692 : dst->Tcolors[TEXT_BG].value); 9693 } else { 9694 memset(&temp, 0, sizeof(temp)); 9695 if (AllocateTermColor(target, &temp, offset, name, True)) { 9696 if (COLOR_DEFINED(&(temp), offset)) 9697 free(temp.names[offset]); 9698 dst->Tcolors[offset].value = temp.colors[offset]; 9699 } else if (offset == TEXT_FG || offset == TEXT_BG) { 9700 free(name); 9701 dst->Tcolors[offset].resource = NULL; 9702 } 9703 } 9704 return dst->Tcolors[offset].value; 9705} 9706 9707/* 9708 * If one or both of the foreground/background colors cannot be allocated, 9709 * e.g., due to gross misconfiguration, recover by setting both to the 9710 * display's default values. 9711 */ 9712static void 9713repairColors(XtermWidget target) 9714{ 9715 TScreen *screen = TScreenOf(target); 9716 9717 if (screen->Tcolors[TEXT_FG].resource == NULL || 9718 screen->Tcolors[TEXT_BG].resource == NULL) { 9719 xtermWarning("unable to allocate fg/bg colors\n"); 9720 screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground); 9721 screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground); 9722 if (screen->Tcolors[TEXT_FG].resource == NULL || 9723 screen->Tcolors[TEXT_BG].resource == NULL) { 9724 Exit(ERROR_MISC); 9725 } 9726 screen->Tcolors[TEXT_FG].value = target->dft_foreground; 9727 screen->Tcolors[TEXT_BG].value = target->dft_background; 9728 } 9729} 9730 9731#if OPT_WIDE_CHARS 9732static void 9733set_utf8_feature(TScreen *screen, int *feature) 9734{ 9735 if (*feature == uDefault) { 9736 switch (screen->utf8_mode) { 9737 case uFalse: 9738 /* FALLTHRU */ 9739 case uTrue: 9740 *feature = screen->utf8_mode; 9741 break; 9742 case uDefault: 9743 /* should not happen */ 9744 *feature = uTrue; 9745 break; 9746 case uAlways: 9747 /* use this to disable menu entry */ 9748 break; 9749 } 9750 } 9751} 9752 9753static void 9754VTInitialize_locale(XtermWidget xw) 9755{ 9756 TScreen *screen = TScreenOf(xw); 9757 Bool is_utf8 = xtermEnvUTF8(); 9758 9759 TRACE(("VTInitialize_locale\n")); 9760 TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode)); 9761 TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts)); 9762 TRACE(("... request screen.utf8_title = %d\n", screen->utf8_title)); 9763 9764 screen->utf8_always = (screen->utf8_mode == uAlways); 9765 if (screen->utf8_mode < 0) 9766 screen->utf8_mode = uFalse; 9767 9768 if (screen->utf8_mode > 3) 9769 screen->utf8_mode = uDefault; 9770 9771 screen->latin9_mode = 0; 9772 screen->unicode_font = 0; 9773#if OPT_LUIT_PROG 9774 xw->misc.callfilter = 0; 9775 xw->misc.use_encoding = 0; 9776 9777 TRACE(("... setup for luit:\n")); 9778 TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str)); 9779 9780 if (screen->utf8_mode == uFalse) { 9781 TRACE(("... command-line +u8 overrides\n")); 9782 } else 9783#if OPT_MINI_LUIT 9784 if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) { 9785 int fl = (int) strlen(DefaultFontN(xw)); 9786 if (fl > 11 9787 && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) { 9788 screen->unicode_font = 1; 9789 /* unicode font, use True */ 9790#ifdef HAVE_LANGINFO_CODESET 9791 if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968") 9792 || !strcmp(xtermEnvEncoding(), "ISO-8859-1")) { 9793 if (screen->utf8_mode == uDefault) 9794 screen->utf8_mode = uFalse; 9795 } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) { 9796 if (screen->utf8_mode == uDefault) 9797 screen->utf8_mode = uFalse; 9798 screen->latin9_mode = 1; 9799 } else { 9800 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 9801 screen->utf8_mode = uAlways; 9802 } 9803#else 9804 xw->misc.callfilter = is_utf8 ? 0 : 1; 9805 screen->utf8_mode = uAlways; 9806#endif 9807 } else { 9808 /* other encoding, use False */ 9809 if (screen->utf8_mode == uDefault) { 9810 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9811 } 9812 } 9813 } else 9814#endif /* OPT_MINI_LUIT */ 9815 if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 || 9816 x_strcasecmp(xw->misc.locale_str, "ON") == 0 || 9817 x_strcasecmp(xw->misc.locale_str, "YES") == 0 || 9818 x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 || 9819 strcmp(xw->misc.locale_str, "1") == 0) { 9820 /* when true ... fully obeying LC_CTYPE locale */ 9821 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 9822 screen->utf8_mode = uAlways; 9823 } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 || 9824 x_strcasecmp(xw->misc.locale_str, "OFF") == 0 || 9825 x_strcasecmp(xw->misc.locale_str, "NO") == 0 || 9826 strcmp(xw->misc.locale_str, "0") == 0) { 9827 /* when false ... original value of utf8_mode is effective */ 9828 if (screen->utf8_mode == uDefault) { 9829 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9830 } 9831 } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 || 9832 x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) { 9833 /* when medium ... obeying locale only for UTF-8 and Asian */ 9834 if (is_utf8) { 9835 screen->utf8_mode = uAlways; 9836 } else if ( 9837#ifdef MB_CUR_MAX 9838 MB_CUR_MAX > 1 || 9839#else 9840 !strncmp(xtermEnvLocale(), "ja", (size_t) 2) || 9841 !strncmp(xtermEnvLocale(), "ko", (size_t) 2) || 9842 !strncmp(xtermEnvLocale(), "zh", (size_t) 2) || 9843#endif 9844 !strncmp(xtermEnvLocale(), "th", (size_t) 2) || 9845 !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) { 9846 xw->misc.callfilter = 1; 9847 screen->utf8_mode = uAlways; 9848 } else { 9849 screen->utf8_mode = uFalse; 9850 } 9851 } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 || 9852 x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) { 9853 /* when UTF-8 ... UTF-8 mode */ 9854 screen->utf8_mode = uAlways; 9855 } else { 9856 /* other words are regarded as encoding name passed to luit */ 9857 xw->misc.callfilter = 1; 9858 screen->utf8_mode = uAlways; 9859 xw->misc.use_encoding = 1; 9860 } 9861 TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter))); 9862 TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding))); 9863#else 9864 if (screen->utf8_mode == uDefault) { 9865 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9866 } 9867#endif /* OPT_LUIT_PROG */ 9868 9869 set_utf8_feature(screen, &screen->utf8_fonts); 9870 set_utf8_feature(screen, &screen->utf8_title); 9871 9872 screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse); 9873 9874 TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode)); 9875 TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts)); 9876 TRACE(("... updated screen.utf8_title = %d\n", screen->utf8_title)); 9877 TRACE(("...VTInitialize_locale done\n")); 9878} 9879#endif 9880 9881void 9882lookupSelectUnit(XtermWidget xw, Cardinal item, String value) 9883{ 9884 /* *INDENT-OFF* */ 9885 static const struct { 9886 const char * name; 9887 SelectUnit code; 9888 } table[] = { 9889 { "char", Select_CHAR }, 9890 { "word", Select_WORD }, 9891 { "line", Select_LINE }, 9892 { "group", Select_GROUP }, 9893 { "page", Select_PAGE }, 9894 { "all", Select_ALL }, 9895#if OPT_SELECT_REGEX 9896 { "regex", Select_REGEX }, 9897#endif 9898 }; 9899 /* *INDENT-ON* */ 9900 9901 TScreen *screen = TScreenOf(xw); 9902 String next = x_skip_nonblanks(value); 9903 Cardinal n; 9904 9905 screen->selectMap[item] = NSELECTUNITS; 9906 for (n = 0; n < XtNumber(table); ++n) { 9907 if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) { 9908 screen->selectMap[item] = table[n].code; 9909#if OPT_SELECT_REGEX 9910 if (table[n].code == Select_REGEX) { 9911 screen->selectExpr[item] = x_strtrim(next); 9912 TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item])); 9913 } 9914#endif 9915 break; 9916 } 9917 } 9918} 9919 9920static void 9921ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item) 9922{ 9923 lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]); 9924} 9925 9926/* 9927 * Parse a comma-separated list, returning a string which the caller must 9928 * free, and updating the source pointer. 9929 */ 9930static char * 9931ParseList(const char **source) 9932{ 9933 const char *base = *source; 9934 const char *next; 9935 char *value = NULL; 9936 char *result; 9937 9938 /* ignore empty values */ 9939 while (*base == ',') 9940 ++base; 9941 9942 if (*base != '\0') { 9943 size_t size; 9944 9945 next = base; 9946 while (*next != '\0' && *next != ',') 9947 ++next; 9948 size = (size_t) (1 + next - base); 9949 value = malloc(size); 9950 if (value != NULL) { 9951 memcpy(value, base, size); 9952 value[size - 1] = '\0'; 9953 } 9954 *source = next; 9955 } else { 9956 *source = base; 9957 } 9958 result = x_strtrim(value); 9959 free(value); 9960 return result; 9961} 9962 9963static void 9964set_flags_from_list(char *target, 9965 const char *source, 9966 const FlagList * list) 9967{ 9968 Cardinal n; 9969 9970 while (!IsEmpty(source)) { 9971 char *next = ParseList(&source); 9972 Boolean found = False; 9973 char flag = 1; 9974 9975 if (next == NULL) 9976 break; 9977 if (*next == '~') { 9978 flag = 0; 9979 next++; 9980 } 9981 if (isdigit(CharOf(*next))) { 9982 char *temp; 9983 int value = (int) strtol(next, &temp, 0); 9984 if (!FullS2L(next, temp)) { 9985 xtermWarning("Expected a number: %s\n", next); 9986 } else { 9987 for (n = 0; list[n].name != NULL; ++n) { 9988 if (list[n].code == value) { 9989 target[value] = flag; 9990 found = True; 9991 TRACE(("...found %s (%d)\n", list[n].name, value)); 9992 break; 9993 } 9994 } 9995 } 9996 } else { 9997 for (n = 0; list[n].name != NULL; ++n) { 9998 if (!x_wildstrcmp(next, list[n].name)) { 9999 int value = list[n].code; 10000 target[value] = flag; 10001 found = True; 10002 TRACE(("...found %s (%d)\n", list[n].name, value)); 10003 } 10004 } 10005 } 10006 if (!found) { 10007 xtermWarning("Unrecognized keyword: %s\n", next); 10008 } 10009 free(next); 10010 } 10011} 10012 10013#define InitCursorShape(target, source) \ 10014 target->cursor_shape = source->cursor_underline ? CURSOR_UNDERLINE : \ 10015 source->cursor_bar ? CURSOR_BAR : CURSOR_BLOCK 10016 10017#if OPT_XRES_QUERY 10018static XtResource * 10019findVT100Resource(const char *name) 10020{ 10021 Cardinal n; 10022 XtResource *result = NULL; 10023 10024 if (!IsEmpty(name)) { 10025 XrmQuark quarkName = XrmPermStringToQuark(name); 10026 for (n = 0; n < XtNumber(xterm_resources); ++n) { 10027 if ((int) xterm_resources[n].resource_offset >= 0 10028 && !strcmp(xterm_resources[n].resource_name, name)) { 10029 result = &xterm_resources[n]; 10030 break; 10031 } else if (xterm_resources[n].resource_name 10032 == (String) (intptr_t) quarkName) { 10033 result = &xterm_resources[n]; 10034 break; 10035 } 10036 } 10037 } 10038 return result; 10039} 10040 10041static int 10042cmp_resources(const void *a, const void *b) 10043{ 10044 return strcmp((*(const String *) a), 10045 (*(const String *) b)); 10046} 10047 10048static void 10049reportResources(XtermWidget xw) 10050{ 10051 String *list = TypeMallocN(String, XtNumber(xterm_resources)); 10052 Cardinal n; 10053 int widest = 0; 10054 10055 if (list == NULL) 10056 return; 10057 10058 for (n = 0; n < XtNumber(xterm_resources); ++n) { 10059 int width; 10060 list[n] = (((int) xterm_resources[n].resource_offset < 0) 10061 ? XrmQuarkToString((XrmQuark) (intptr_t) 10062 xterm_resources[n].resource_name) 10063 : xterm_resources[n].resource_name); 10064 width = (int) strlen(list[n]); 10065 if (widest < width) 10066 widest = width; 10067 } 10068 qsort(list, (size_t) XtNumber(xterm_resources), sizeof(String), cmp_resources); 10069 for (n = 0; n < XtNumber(xterm_resources); ++n) { 10070 char *value = vt100ResourceToString(xw, list[n]); 10071 printf("%-*s : %s\n", widest, list[n], value ? value : "(skip)"); 10072 free(value); 10073 } 10074 free(list); 10075} 10076 10077char * 10078vt100ResourceToString(XtermWidget xw, const char *name) 10079{ 10080 XtResource *data; 10081 char *result = NULL; 10082 10083 if ((data = findVT100Resource(name)) != NULL) { 10084 int fake_offset = (int) data->resource_offset; 10085 void *res_addr; 10086 int real_offset; 10087 String res_type; 10088 10089 /* 10090 * X Toolkit "compiles" the resource-list into quarks and changes the 10091 * resource-offset at the same time to a negative value. 10092 */ 10093 if (fake_offset < 0) { 10094 real_offset = -(fake_offset + 1); 10095 res_type = XrmQuarkToString((XrmQuark) (intptr_t) data->resource_type); 10096 } else { 10097 real_offset = fake_offset; 10098 res_type = data->resource_type; 10099 } 10100 res_addr = (void *) ((char *) xw + real_offset); 10101 10102 if (!strcmp(res_type, XtRString)) { 10103 char *value = *(char **) res_addr; 10104 if (value != NULL) { 10105 size_t need = strlen(value); 10106 if ((result = malloc(1 + need)) != NULL) 10107 strcpy(result, value); 10108 } 10109 } else if (!strcmp(res_type, XtRInt)) { 10110 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != NULL) 10111 sprintf(result, "%d", *(int *) res_addr); 10112 } else if (!strcmp(res_type, XtRFloat)) { 10113 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != NULL) 10114 sprintf(result, "%f", (double) (*(float *) res_addr)); 10115 } else if (!strcmp(res_type, XtRBoolean)) { 10116 if ((result = malloc((size_t) 6)) != NULL) 10117 strcpy(result, *(Boolean *) res_addr ? "true" : "false"); 10118 } 10119 } 10120 TRACE(("vt100ResourceToString(%s) %s\n", name, NonNull(result))); 10121 return result; 10122} 10123#endif /* OPT_XRES_QUERY */ 10124 10125/* 10126 * Decode a terminal-ID or graphics-terminal-ID, using the default terminal-ID 10127 * if the value is outside a (looser) range than limitedTerminalID. This uses 10128 * a wider range, to avoid being a nuisance when using X resources with 10129 * different configurations of xterm. 10130 */ 10131static int 10132decodeTerminalID(const char *value) 10133{ 10134 const char *s; 10135 char *t; 10136 long result; 10137 10138 for (s = value; *s; s++) { 10139 if (!isalpha(CharOf(*s))) 10140 break; 10141 } 10142 result = strtol(s, &t, 10); 10143 if (t == s || *t != '\0' || result <= 0L || result > 1000L) { 10144 xtermWarning("unexpected value for terminalID: \"%s\"\n", value); 10145 result = atoi(DFT_DECID); 10146 } 10147 TRACE(("decodeTerminalID \"%s\" ->%d\n", value, (int) result)); 10148 return (int) result; 10149} 10150 10151/* 10152 * Ensures that the value returned by decodeTerminalID is either in the range 10153 * of IDs matching a known terminal, or (failing that), set to the built-in 10154 * default. The DA response relies on having the ID being set to a known 10155 * value. 10156 */ 10157static int 10158limitedTerminalID(int terminal_id) 10159{ 10160 if (terminal_id < MIN_DECID) 10161 terminal_id = MIN_DECID; 10162 else if (terminal_id > MAX_DECID) 10163 terminal_id = MAX_DECID; 10164 else 10165 terminal_id = atoi(DFT_DECID); 10166 return terminal_id; 10167} 10168 10169#define DATA_END { NULL, -1 } 10170 10171#define DATA(name) { #name, ec##name } 10172static const FlagList tblColorOps[] = 10173{ 10174 DATA(SetColor) 10175 ,DATA(GetColor) 10176 ,DATA(GetAnsiColor) 10177 ,DATA_END 10178}; 10179#undef DATA 10180 10181#define DATA(name) { #name, ef##name } 10182static const FlagList tblFontOps[] = 10183{ 10184 DATA(SetFont) 10185 ,DATA(GetFont) 10186 ,DATA_END 10187}; 10188#undef DATA 10189 10190#define DATA(name) { #name, em##name } 10191static const FlagList tblMouseOps[] = 10192{ 10193 DATA(X10) 10194 ,DATA(Locator) 10195 ,DATA(VT200Click) 10196 ,DATA(VT200Hilite) 10197 ,DATA(AnyButton) 10198 ,DATA(AnyEvent) 10199 ,DATA(FocusEvent) 10200 ,DATA(Extended) 10201 ,DATA(SGR) 10202 ,DATA(URXVT) 10203 ,DATA(AlternateScroll) 10204 ,DATA_END 10205}; 10206#undef DATA 10207 10208#define DATA(name) { #name, ep##name } 10209#define DATA2(alias,name) { #alias, ep##name } 10210static const FlagList tblPasteOps[] = 10211{ 10212 DATA(NUL) 10213 ,DATA(SOH) 10214 ,DATA(STX) 10215 ,DATA(ETX) 10216 ,DATA(EOT) 10217 ,DATA(ENQ) 10218 ,DATA(ACK) 10219 ,DATA(BEL) 10220 ,DATA(BS) 10221 ,DATA(HT) 10222 ,DATA(LF) 10223 ,DATA(VT) 10224 ,DATA(FF) 10225 ,DATA(CR) 10226 ,DATA(SO) 10227 ,DATA(SI) 10228 ,DATA(DLE) 10229 ,DATA(DC1) 10230 ,DATA(DC2) 10231 ,DATA(DC3) 10232 ,DATA(DC4) 10233 ,DATA(NAK) 10234 ,DATA(SYN) 10235 ,DATA(ETB) 10236 ,DATA(CAN) 10237 ,DATA(EM) 10238 ,DATA(SUB) 10239 ,DATA(ESC) 10240 ,DATA(FS) 10241 ,DATA(GS) 10242 ,DATA(RS) 10243 ,DATA(US) 10244/* aliases */ 10245 ,DATA2(NL, LF) 10246 ,DATA(C0) 10247 ,DATA(DEL) 10248 ,DATA(STTY) 10249 ,DATA_END 10250}; 10251#undef DATA 10252#undef DATA2 10253 10254#define DATA(name) { #name, et##name } 10255static const FlagList tblTcapOps[] = 10256{ 10257 DATA(SetTcap) 10258 ,DATA(GetTcap) 10259 ,DATA_END 10260}; 10261#undef DATA 10262 10263#define DATA(name) { #name, ew##name } 10264static const FlagList tblWindowOps[] = 10265{ 10266 DATA(RestoreWin) 10267 ,DATA(MinimizeWin) 10268 ,DATA(SetWinPosition) 10269 ,DATA(SetWinSizePixels) 10270 ,DATA(RaiseWin) 10271 ,DATA(LowerWin) 10272 ,DATA(RefreshWin) 10273 ,DATA(SetWinSizeChars) 10274#if OPT_MAXIMIZE 10275 ,DATA(MaximizeWin) 10276 ,DATA(FullscreenWin) 10277#endif 10278 ,DATA(GetWinState) 10279 ,DATA(GetWinPosition) 10280 ,DATA(GetWinSizePixels) 10281 ,DATA(GetWinSizeChars) 10282#if OPT_MAXIMIZE 10283 ,DATA(GetScreenSizeChars) 10284#endif 10285 ,DATA(GetIconTitle) 10286 ,DATA(GetWinTitle) 10287 ,DATA(PushTitle) 10288 ,DATA(PopTitle) 10289/* this item uses all remaining numbers in the sequence */ 10290 ,DATA(SetWinLines) 10291/* starting at this point, numbers do not apply */ 10292 ,DATA(SetXprop) 10293 ,DATA(GetSelection) 10294 ,DATA(SetSelection) 10295 ,DATA(GetChecksum) 10296 ,DATA(SetChecksum) 10297 ,DATA_END 10298}; 10299#undef DATA 10300 10301void 10302unparse_disallowed_ops(XtermWidget xw, char *value) 10303{ 10304 TScreen *screen = TScreenOf(xw); 10305#define DATA(mixed, plain, flags) { #mixed, offsetof(TScreen, plain), sizeof(screen->plain), flags } 10306 /* *INDENT-OFF* */ 10307 static const struct { 10308 const char * name; 10309 size_t offset; 10310 size_t length; 10311 const FlagList *codes; 10312 } table[] = { 10313 DATA(allowColorOps, disallow_color_ops, tblColorOps), 10314 DATA(allowFontOps, disallow_font_ops, tblFontOps), 10315 DATA(allowMouseOps, disallow_mouse_ops, tblMouseOps), 10316 DATA(allowPasteControls, disallow_paste_ops, tblPasteOps), 10317 DATA(allowTcapOps, disallow_tcap_ops, tblTcapOps), 10318 DATA(allowWinOps, disallow_win_ops, tblWindowOps), 10319 }; 10320 /* *INDENT-ON* */ 10321#undef DATA 10322 Cardinal j, k, jk; 10323 char delim = ';'; 10324 10325 for (j = 0; j < XtNumber(table); ++j) { 10326 if (!x_strcasecmp(value, table[j].name)) { 10327 const char *flags = (char *) screen + table[j].offset; 10328 10329 for (k = 0; k < table[j].length; ++k) { 10330 if (flags[k]) { 10331 const FlagList *codes = table[j].codes; 10332 Boolean found = False; 10333 10334 unparseputc(xw, delim); 10335 for (jk = 0; codes[jk].name; ++jk) { 10336 if (codes[jk].code == (int) k) { 10337 unparseputs(xw, codes[jk].name); 10338 found = True; 10339 break; 10340 } 10341 } 10342 if (!found) 10343 unparseputn(xw, k); 10344 delim = ','; 10345 } 10346 } 10347 break; 10348 } 10349 } 10350} 10351 10352/* ARGSUSED */ 10353static void 10354VTInitialize(Widget wrequest, 10355 Widget new_arg, 10356 ArgList args GCC_UNUSED, 10357 Cardinal *num_args GCC_UNUSED) 10358{ 10359#define Kolor(name) TScreenOf(wnew)->name.resource 10360#define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name)) 10361#define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name)) 10362#define DftFg(name) isDefaultForeground(Kolor(name)) 10363#define DftBg(name) isDefaultBackground(Kolor(name)) 10364 10365#if OPT_BLINK_CURS 10366#define DATA(name) { #name, cb##name } 10367 static const FlagList tblBlinkOps[] = 10368 { 10369 DATA(Always) 10370 ,DATA(Never) 10371 ,DATA_END 10372 }; 10373#undef DATA 10374#endif 10375 10376#if OPT_RENDERFONT 10377#define DATA(name) { #name, er##name } 10378 static const FlagList tblRenderFont[] = 10379 { 10380 DATA(Default) 10381 ,DATA(DefaultOff) 10382 ,DATA_END 10383 }; 10384#undef DATA 10385#endif 10386 10387#define DATA(name) { #name, ss##name } 10388 static const FlagList tblShift2S[] = 10389 { 10390 DATA(Always) 10391 ,DATA(Never) 10392 ,DATA_END 10393 }; 10394#undef DATA 10395 10396#if OPT_WIDE_CHARS 10397#define DATA(name) { #name, u##name } 10398 static const FlagList tblUtf8Mode[] = 10399 { 10400 DATA(Always) 10401 ,DATA(Default) 10402 ,DATA_END 10403 }; 10404#undef DATA 10405#endif 10406 10407#ifndef NO_ACTIVE_ICON 10408#define DATA(name) { #name, ei##name } 10409 static const FlagList tblAIconOps[] = 10410 { 10411 DATA(Default) 10412 ,DATA_END 10413 }; 10414#undef DATA 10415#endif 10416 10417#define DATA(name) { #name, eb##name } 10418 static const FlagList tbl8BitMeta[] = 10419 { 10420 DATA(Never) 10421 ,DATA(Locale) 10422 ,DATA_END 10423 }; 10424#undef DATA 10425 10426#define DATA(name) { #name, ed##name } 10427 static const FlagList tblCdXtraScroll[] = 10428 { 10429 DATA(Trim) 10430 ,DATA_END 10431 }; 10432#undef DATA 10433 10434 XtermWidget request = (XtermWidget) wrequest; 10435 XtermWidget wnew = (XtermWidget) new_arg; 10436 Widget my_parent = SHELL_OF(wnew); 10437 int i; 10438 10439#if OPT_ISO_COLORS 10440 Bool color_ok; 10441#endif 10442 10443#if OPT_ISO_COLORS 10444 static XtResource fake_resources[] = 10445 { 10446#if OPT_256_COLORS 10447# include <256colres.h> 10448#elif OPT_88_COLORS 10449# include <88colres.h> 10450#endif 10451 }; 10452#endif 10453 10454 TScreen *screen = TScreenOf(wnew); 10455 char *saveLocale = xtermSetLocale(LC_NUMERIC, "C"); 10456#if OPT_BLINK_CURS 10457 int ebValue; 10458#endif 10459 10460#if OPT_TRACE 10461 check_bitmasks(); 10462 check_tables(); 10463#endif 10464 10465 TRACE(("VTInitialize wnew %p, %d / %d resources " TRACE_L "\n", 10466 (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES)); 10467 assert(XtNumber(xterm_resources) < MAXRESOURCES); 10468 10469 /* Zero out the entire "screen" component of "wnew" widget, then do 10470 * field-by-field assignment of "screen" fields that are named in the 10471 * resource list. 10472 */ 10473 memset(screen, 0, sizeof(wnew->screen)); 10474 10475 /* DESCO Sys#67660 10476 * Zero out the entire "keyboard" component of "wnew" widget. 10477 */ 10478 memset(&wnew->keyboard, 0, sizeof(wnew->keyboard)); 10479 10480 /* 10481 * The workspace has no resources - clear it. 10482 */ 10483 memset(&wnew->work, 0, sizeof(wnew->work)); 10484 10485 /* dummy values so that we don't try to Realize the parent shell with height 10486 * or width of 0, which is illegal in X. The real size is computed in the 10487 * xtermWidget's Realize proc, but the shell's Realize proc is called first, 10488 * and must see a valid size. 10489 */ 10490 wnew->core.height = wnew->core.width = 1; 10491 10492 /* 10493 * The definition of -rv now is that it changes the definition of 10494 * XtDefaultForeground and XtDefaultBackground. So, we no longer 10495 * need to do anything special. 10496 */ 10497 screen->display = wnew->core.screen->display; 10498 10499 /* prep getVisualInfo() */ 10500 wnew->visInfo = NULL; 10501 wnew->numVisuals = 0; 10502 (void) getVisualInfo(wnew); 10503 10504#if OPT_STATUS_LINE 10505 StatusInit(&screen->status_data[0]); 10506 StatusInit(&screen->status_data[1]); 10507#endif 10508 10509 /* 10510 * We use the default foreground/background colors to compare/check if a 10511 * color-resource has been set. 10512 */ 10513#define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy)) 10514#define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy)) 10515 10516 if (request->misc.re_verse) { 10517 wnew->dft_foreground = MyWhitePixel(screen->display); 10518 wnew->dft_background = MyBlackPixel(screen->display); 10519 } else { 10520 wnew->dft_foreground = MyBlackPixel(screen->display); 10521 wnew->dft_background = MyWhitePixel(screen->display); 10522 } 10523 10524 init_Tres(TEXT_FG); 10525 init_Tres(TEXT_BG); 10526 repairColors(wnew); 10527 10528 wnew->old_foreground = T_COLOR(screen, TEXT_FG); 10529 wnew->old_background = T_COLOR(screen, TEXT_BG); 10530 10531 TRACE(("Color resource initialization:\n")); 10532 TRACE((" Default foreground 0x%06lx\n", wnew->dft_foreground)); 10533 TRACE((" Default background 0x%06lx\n", wnew->dft_background)); 10534 TRACE((" Screen foreground 0x%06lx\n", T_COLOR(screen, TEXT_FG))); 10535 TRACE((" Screen background 0x%06lx\n", T_COLOR(screen, TEXT_BG))); 10536 TRACE((" Actual foreground 0x%06lx\n", wnew->old_foreground)); 10537 TRACE((" Actual background 0x%06lx\n", wnew->old_background)); 10538 10539 screen->mouse_button = 0; 10540 screen->mouse_row = -1; 10541 screen->mouse_col = -1; 10542 10543#if OPT_BOX_CHARS 10544 init_Bres(screen.force_box_chars); 10545 init_Bres(screen.force_packed); 10546 init_Bres(screen.assume_all_chars); 10547#endif 10548#if OPT_BOX_CHARS || OPT_WIDE_CHARS 10549 init_Bres(screen.force_all_chars); 10550#endif 10551 init_Bres(screen.free_bold_box); 10552 init_Bres(screen.allowBoldFonts); 10553 10554 init_Bres(screen.c132); 10555 init_Bres(screen.curses); 10556 init_Bres(screen.hp_ll_bc); 10557#if OPT_XMC_GLITCH 10558 init_Ires(screen.xmc_glitch); 10559 init_Ires(screen.xmc_attributes); 10560 init_Bres(screen.xmc_inline); 10561 init_Bres(screen.move_sgr_ok); 10562#endif 10563#if OPT_BLINK_CURS 10564 init_Sres(screen.cursor_blink_s); 10565 ebValue = extendedBoolean(wnew->screen.cursor_blink_s, tblBlinkOps, cbLAST); 10566 wnew->screen.cursor_blink = (BlinkOps) ebValue; 10567 init_Bres(screen.cursor_blink_xor); 10568 init_Ires(screen.blink_on); 10569 init_Ires(screen.blink_off); 10570 screen->cursor_blink_i = screen->cursor_blink; 10571#endif 10572 init_Bres(screen.cursor_underline); 10573 init_Bres(screen.cursor_bar); 10574 /* resources allow for underline or block, not (yet) bar */ 10575 InitCursorShape(screen, TScreenOf(request)); 10576#if OPT_BLINK_CURS 10577 TRACE(("cursor_shape:%d blinks:%d\n", 10578 screen->cursor_shape, 10579 screen->cursor_blink)); 10580#endif 10581#if OPT_BLINK_TEXT 10582 init_Ires(screen.blink_as_bold); 10583#endif 10584 init_Ires(screen.border); 10585 init_Bres(screen.jumpscroll); 10586 init_Bres(screen.fastscroll); 10587 10588 init_Bres(screen.old_fkeys); 10589 wnew->screen.old_fkeys0 = wnew->screen.old_fkeys; 10590 wnew->keyboard.type = screen->old_fkeys 10591 ? keyboardIsLegacy 10592 : keyboardIsDefault; 10593 10594 init_Mres(screen.delete_is_del); 10595#ifdef ALLOWLOGGING 10596 init_Bres(misc.logInhibit); 10597 init_Bres(misc.log_on); 10598 init_Sres(screen.logfile); 10599#endif 10600 init_Bres(screen.bellIsUrgent); 10601 init_Bres(screen.bellOnReset); 10602 init_Bres(screen.marginbell); 10603 init_Bres(screen.multiscroll); 10604 init_Ires(screen.nmarginbell); 10605 init_Ires(screen.savelines); 10606 init_Ires(screen.scrollBarBorder); 10607 init_Ires(screen.scrolllines); 10608 init_Bres(screen.alternateScroll); 10609 init_Bres(screen.scrollttyoutput); 10610 init_Bres(screen.scrollkey); 10611 10612 init_Dres(screen.scale_height); 10613 if (screen->scale_height < MIN_SCALE_HEIGHT) 10614 screen->scale_height = MIN_SCALE_HEIGHT; 10615 if (screen->scale_height > MAX_SCALE_HEIGHT) 10616 screen->scale_height = MAX_SCALE_HEIGHT; 10617 10618 init_Bres(misc.autoWrap); 10619 init_Bres(misc.login_shell); 10620 init_Bres(misc.reverseWrap); 10621 init_Bres(misc.scrollbar); 10622 init_Sres(misc.geo_metry); 10623 init_Sres(misc.T_geometry); 10624 10625 init_Sres(screen.term_id); 10626 screen->terminal_id = decodeTerminalID(TScreenOf(request)->term_id); 10627 screen->display_da1 = screen->terminal_id; 10628 /* 10629 * (1) If a known terminal model, and not a graphical terminal, preserve 10630 * the terminal id. 10631 * (2) Otherwise, if ReGIS or sixel graphics are enabled, preserve the ID, 10632 * even if it is not a known terminal. 10633 * (3) Otherwise force the terminal ID to the min, max, or VT420 depending 10634 * on the input. 10635 */ 10636 switch (screen->terminal_id) { 10637 case 52: /* MIN_DECID */ 10638 case 100: 10639 case 101: 10640 case 102: 10641 case 131: 10642 case 132: 10643 case 220: 10644 case 320: 10645 case 420: /* DFT_DECID, unless overridden in configure */ 10646 case 510: 10647 case 520: 10648 case 525: /* MAX_DECID */ 10649 break; 10650 default: 10651#if OPT_REGIS_GRAPHICS 10652 if (optRegisGraphics(screen)) 10653 break; 10654#endif 10655#if OPT_SIXEL_GRAPHICS 10656 if (optSixelGraphics(screen)) 10657 break; 10658#endif 10659 screen->terminal_id = limitedTerminalID(screen->terminal_id); 10660 screen->display_da1 = screen->terminal_id; 10661 break; 10662 } 10663 TRACE(("term_id '%s' -> terminal_id %d\n", 10664 screen->term_id, 10665 screen->terminal_id)); 10666 10667 set_vtXX_level(screen, (screen->terminal_id / 100)); 10668 10669 init_Ires(screen.title_modes); 10670 screen->title_modes0 = screen->title_modes; 10671 10672 init_Ires(screen.nextEventDelay); 10673 if (screen->nextEventDelay <= 0) 10674 screen->nextEventDelay = 1; 10675 10676 init_Bres(screen.visualbell); 10677 init_Bres(screen.flash_line); 10678 init_Ires(screen.visualBellDelay); 10679 init_Bres(screen.poponbell); 10680 10681 init_Bres(screen.eraseSavedLines0); 10682 screen->eraseSavedLines = screen->eraseSavedLines0; 10683 10684 init_Ires(misc.limit_resize); 10685 10686#if OPT_NUM_LOCK 10687 init_Bres(misc.real_NumLock); 10688 init_Bres(misc.alwaysUseMods); 10689#endif 10690 10691#if OPT_INPUT_METHOD 10692 init_Bres(misc.open_im); 10693 init_Ires(misc.retry_im); 10694 init_Sres(misc.f_x); 10695 init_Sres(misc.input_method); 10696 init_Sres(misc.preedit_type); 10697#endif 10698 10699#if OPT_SHIFT_FONTS 10700 init_Bres(misc.shift_fonts); 10701#endif 10702#if OPT_SUNPC_KBD 10703 init_Ires(misc.ctrl_fkeys); 10704#endif 10705#if OPT_TEK4014 10706 TEK4014_SHOWN(wnew) = False; /* not a resource... */ 10707 init_Bres(misc.tekInhibit); 10708 init_Bres(misc.tekSmall); 10709 init_Bres(misc.TekEmu); 10710#endif 10711#if OPT_TCAP_QUERY 10712 screen->tc_query_code = -1; 10713#endif 10714 wnew->misc.re_verse0 = request->misc.re_verse; 10715 init_Bres(misc.re_verse); 10716 init_Ires(screen.multiClickTime); 10717 init_Ires(screen.bellSuppressTime); 10718 init_Sres(screen.charClass); 10719 10720 init_Bres(screen.always_highlight); 10721 init_Bres(screen.brokenSelections); 10722 init_Bres(screen.cutNewline); 10723 init_Bres(screen.cutToBeginningOfLine); 10724 init_Bres(screen.highlight_selection); 10725 init_Bres(screen.show_wrap_marks); 10726 init_Bres(screen.i18nSelections); 10727 init_Bres(screen.keepClipboard); 10728 init_Bres(screen.keepSelection); 10729 init_Bres(screen.selectToClipboard); 10730 init_Bres(screen.trim_selection); 10731 10732 screen->pointer_cursor = TScreenOf(request)->pointer_cursor; 10733 init_Ires(screen.pointer_mode); 10734 wnew->screen.pointer_mode0 = wnew->screen.pointer_mode; 10735 10736 init_Sres(screen.answer_back); 10737 init_Bres(screen.prefer_latin1); 10738 10739 wnew->SPS.printer_checked = False; 10740 init_Sres(SPS.printer_command); 10741 init_Bres(SPS.printer_autoclose); 10742 init_Bres(SPS.printer_extent); 10743 init_Bres(SPS.printer_formfeed); 10744 init_Bres(SPS.printer_newline); 10745 init_Ires(SPS.printer_controlmode); 10746#if OPT_PRINT_COLORS 10747 init_Ires(SPS.print_attributes); 10748#endif 10749 init_Bres(screen.print_rawchars); 10750 10751 init_Sres(screen.keyboard_dialect); 10752 10753 init_Sres(screen.cursor_font_name); 10754 init_Sres(screen.pointer_shape); 10755 10756 init_Bres(screen.input_eight_bits); 10757 init_Bres(screen.output_eight_bits); 10758 init_Bres(screen.control_eight_bits); 10759 init_Bres(screen.backarrow_key); 10760 init_Bres(screen.alt_is_not_meta); 10761 init_Bres(screen.alt_sends_esc); 10762 init_Bres(screen.meta_sends_esc); 10763 10764 init_Bres(screen.allowPasteControl0); 10765 init_Bres(screen.allowSendEvent0); 10766 init_Bres(screen.allowColorOp0); 10767 init_Bres(screen.allowFontOp0); 10768 init_Bres(screen.allowMouseOp0); 10769 init_Bres(screen.allowTcapOp0); 10770 init_Bres(screen.allowTitleOp0); 10771 init_Bres(screen.allowWindowOp0); 10772 10773#if OPT_SCROLL_LOCK 10774 init_Bres(screen.allowScrollLock0); 10775 init_Bres(screen.autoScrollLock); 10776#endif 10777 10778 init_Sres(screen.disallowedColorOps); 10779 10780 set_flags_from_list(screen->disallow_color_ops, 10781 screen->disallowedColorOps, 10782 tblColorOps); 10783 10784 init_Sres(screen.disallowedFontOps); 10785 10786 set_flags_from_list(screen->disallow_font_ops, 10787 screen->disallowedFontOps, 10788 tblFontOps); 10789 10790 init_Sres(screen.disallowedMouseOps); 10791 10792 set_flags_from_list(screen->disallow_mouse_ops, 10793 screen->disallowedMouseOps, 10794 tblMouseOps); 10795 10796 init_Sres(screen.disallowedPasteOps); 10797 10798 set_flags_from_list(screen->disallow_paste_ops, 10799 screen->disallowedPasteOps, 10800 tblPasteOps); 10801 10802 init_Sres(screen.disallowedTcapOps); 10803 10804 set_flags_from_list(screen->disallow_tcap_ops, 10805 screen->disallowedTcapOps, 10806 tblTcapOps); 10807 10808 init_Sres(screen.disallowedWinOps); 10809 10810 set_flags_from_list(screen->disallow_win_ops, 10811 screen->disallowedWinOps, 10812 tblWindowOps); 10813 10814 init_Sres(screen.default_string); 10815 init_Sres(screen.eightbit_select_types); 10816#if OPT_WIDE_CHARS 10817 init_Sres(screen.utf8_select_types); 10818#endif 10819 10820 /* make a copy so that editres cannot change the resource after startup */ 10821 screen->allowPasteControls = screen->allowPasteControl0; 10822 screen->allowSendEvents = screen->allowSendEvent0; 10823 screen->allowColorOps = screen->allowColorOp0; 10824 screen->allowFontOps = screen->allowFontOp0; 10825 screen->allowMouseOps = screen->allowMouseOp0; 10826 screen->allowTcapOps = screen->allowTcapOp0; 10827 screen->allowTitleOps = screen->allowTitleOp0; 10828 screen->allowWindowOps = screen->allowWindowOp0; 10829 10830#if OPT_SCROLL_LOCK 10831 screen->allowScrollLock = screen->allowScrollLock0; 10832#endif 10833 10834 init_Bres(screen.quiet_grab); 10835 10836#ifndef NO_ACTIVE_ICON 10837 init_Sres(screen.icon_fontname); 10838 getIconicFont(screen)->fs = xtermLoadQueryFont(wnew, 10839 screen->icon_fontname); 10840 TRACE(("iconFont '%s' %sloaded successfully\n", 10841 screen->icon_fontname, 10842 getIconicFont(screen)->fs ? "" : "NOT ")); 10843 init_Sres(misc.active_icon_s); 10844 wnew->work.active_icon = 10845 (Boolean) extendedBoolean(wnew->misc.active_icon_s, 10846 tblAIconOps, eiLAST); 10847 init_Ires(misc.icon_border_width); 10848 wnew->misc.icon_border_pixel = request->misc.icon_border_pixel; 10849#endif /* NO_ACTIVE_ICON */ 10850 10851 init_Bres(misc.signalInhibit); 10852 init_Bres(misc.titeInhibit); 10853 init_Bres(misc.color_inner_border); 10854 init_Bres(misc.dynamicColors); 10855 init_Bres(misc.resizeByPixel); 10856 10857 init_Sres(misc.cdXtraScroll_s); 10858 wnew->misc.cdXtraScroll = 10859 extendedBoolean(request->misc.cdXtraScroll_s, tblCdXtraScroll, edLast); 10860 10861 init_Sres(misc.tiXtraScroll_s); 10862 wnew->misc.tiXtraScroll = 10863 extendedBoolean(request->misc.tiXtraScroll_s, tblCdXtraScroll, edLast); 10864 10865#if OPT_DEC_CHRSET 10866 for (i = 0; i < NUM_CHRSET; i++) { 10867 screen->double_fonts[i].warn = fwResource; 10868 } 10869#endif 10870 for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) { 10871 init_Sres2(screen.MenuFontName, i); 10872 } 10873 for (i = 0; i < fMAX; i++) { 10874 screen->fnts[i].warn = fwResource; 10875#if OPT_WIDE_ATTRS 10876 screen->ifnts[i].warn = fwResource; 10877#endif 10878 } 10879#ifndef NO_ACTIVE_ICON 10880 screen->fnt_icon.warn = fwResource; 10881#endif 10882 10883 init_Ires(misc.fontWarnings); 10884 10885 initFontLists(wnew); 10886 10887#define DefaultFontNames screen->menu_font_names[fontMenu_default] 10888 10889 /* 10890 * Process Xft font resources first, since faceName may contain X11 fonts 10891 * that should override the "font" resource. 10892 */ 10893#if OPT_RENDERFONT 10894 init_Bres(screen.force_xft_height); 10895 for (i = 0; i <= fontMenu_lastBuiltin; ++i) { 10896 init_Dres2(misc.face_size, i); 10897 } 10898 init_Ires(screen.xft_max_glyph_memory); 10899 init_Ires(screen.xft_max_unref_fonts); 10900 init_Bres(screen.xft_track_mem_usage); 10901 10902#define ALLOC_FONTLIST(name,which,field) \ 10903 init_Sres(misc.default_xft.field);\ 10904 allocFontList(wnew,\ 10905 name,\ 10906 &(wnew->work.fonts),\ 10907 which,\ 10908 wnew->misc.default_xft.field,\ 10909 True) 10910 10911 ALLOC_FONTLIST(XtNfaceName, fNorm, f_n); 10912 10913#if OPT_WIDE_CHARS 10914 ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w); 10915#endif 10916 10917#undef ALLOC_FONTLIST 10918 10919#endif 10920 10921 /* 10922 * Process X11 (XLFD) font specifications. 10923 */ 10924#define ALLOC_FONTLIST(name,which,field) \ 10925 init_Sres(misc.default_font.field);\ 10926 allocFontList(wnew,\ 10927 name,\ 10928 &(wnew->work.fonts),\ 10929 which,\ 10930 wnew->misc.default_font.field,\ 10931 False) 10932 10933 ALLOC_FONTLIST(XtNfont, fNorm, f_n); 10934 ALLOC_FONTLIST(XtNboldFont, fBold, f_b); 10935 10936 DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew)); 10937 DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew)); 10938 10939#if OPT_WIDE_CHARS 10940 ALLOC_FONTLIST(XtNwideFont, fWide, f_w); 10941 ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb); 10942 10943 DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew)); 10944 DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew)); 10945#endif 10946 10947#undef ALLOC_FONTLIST 10948 10949 screen->EscapeFontName() = NULL; 10950 screen->SelectFontName() = NULL; 10951 10952 screen->menu_font_number = fontMenu_default; 10953 init_Sres(screen.initial_font); 10954 if (screen->initial_font != NULL) { 10955 int result = xtermGetFont(screen->initial_font); 10956 if (result >= 0) 10957 screen->menu_font_number = result; 10958 } 10959#if OPT_BROKEN_OSC 10960 init_Bres(screen.brokenLinuxOSC); 10961#endif 10962 10963#if OPT_BROKEN_ST 10964 init_Bres(screen.brokenStringTerm); 10965#endif 10966 10967#if OPT_C1_PRINT 10968 init_Bres(screen.c1_printable); 10969#endif 10970 10971#if OPT_CLIP_BOLD 10972 init_Bres(screen.use_border_clipping); 10973 init_Bres(screen.use_clipping); 10974#endif 10975 10976#if OPT_DEC_CHRSET 10977 init_Bres(screen.font_doublesize); 10978 init_Ires(screen.cache_doublesize); 10979 if (screen->cache_doublesize > NUM_CHRSET) 10980 screen->cache_doublesize = NUM_CHRSET; 10981 if (screen->cache_doublesize == 0) 10982 screen->font_doublesize = False; 10983 TRACE(("Doublesize%s enabled, up to %d fonts\n", 10984 screen->font_doublesize ? "" : " not", 10985 screen->cache_doublesize)); 10986#endif 10987#if OPT_DEC_RECTOPS 10988 init_Ires(screen.checksum_ext0); 10989 screen->checksum_ext = screen->checksum_ext0; 10990#endif 10991 10992#if OPT_ISO_COLORS 10993 init_Ires(screen.veryBoldColors); 10994 init_Bres(screen.boldColors); 10995 init_Bres(screen.colorAttrMode); 10996 init_Bres(screen.colorBDMode); 10997 init_Bres(screen.colorBLMode); 10998 init_Bres(screen.colorMode); 10999 init_Bres(screen.colorULMode); 11000 init_Bres(screen.italicULMode); 11001 init_Bres(screen.colorRVMode); 11002 11003#if OPT_WIDE_ATTRS 11004 init_Bres(screen.colorITMode); 11005#endif 11006#if OPT_DIRECT_COLOR 11007 init_Bres(screen.direct_color); 11008#endif 11009#if OPT_WIDE_ATTRS && OPT_SGR2_HASH 11010 init_Bres(screen.faint_relative); 11011#endif 11012 11013#if OPT_VT525_COLORS 11014 screen->assigned_fg = 7; 11015 screen->assigned_bg = 0; 11016#if MIN_ANSI_COLORS >= 16 11017 /* 11018 * VT520-RM does not define the initial palette, but this is preferable 11019 * to black-on-black. 11020 */ 11021 for (i = 0; i < 16; i++) { 11022 screen->alt_colors[i].fg = screen->assigned_fg; 11023 screen->alt_colors[i].bg = screen->assigned_bg; 11024 } 11025#endif 11026#endif 11027 11028 TRACE(("...will fake resources for color%d to color%d\n", 11029 MIN_ANSI_COLORS, 11030 NUM_ANSI_COLORS - 1)); 11031 11032 for (i = 0, color_ok = False; i < MAXCOLORS; i++) { 11033 /* 11034 * Xt has a hardcoded limit on the maximum number of resources that can 11035 * be used in a widget. If we configured both luit (which implies 11036 * wide-characters) and 256-colors, it goes over that limit. Most 11037 * people would not need a resource-file with 256-colors; the default 11038 * values in our table are sufficient. Fake the resource setting by 11039 * copying the default value from the table. The #define's can be 11040 * overridden to make these true resources. 11041 */ 11042 if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) { 11043 screen->Acolors[i].resource = 11044 x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr); 11045 if (screen->Acolors[i].resource == NULL) 11046 screen->Acolors[i].resource = XtDefaultForeground; 11047 } else { 11048 screen->Acolors[i] = TScreenOf(request)->Acolors[i]; 11049 screen->Acolors[i].resource = 11050 x_strtrim(screen->Acolors[i].resource); 11051 } 11052 11053 TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource)); 11054 screen->Acolors[i].mode = False; 11055 if (DftFg(Acolors[i])) { 11056 screen->Acolors[i].value = T_COLOR(screen, TEXT_FG); 11057 screen->Acolors[i].mode = True; 11058 } else if (DftBg(Acolors[i])) { 11059 screen->Acolors[i].value = T_COLOR(screen, TEXT_BG); 11060 screen->Acolors[i].mode = True; 11061 } else { 11062 color_ok = True; 11063 } 11064 } 11065 11066 /* 11067 * Check if we're trying to use color in a monochrome screen. Disable 11068 * color in that case, since that would make ANSI colors unusable. A 4-bit 11069 * or 8-bit display is usable, so we do not have to check for anything more 11070 * specific. 11071 */ 11072 if (color_ok) { 11073 if (getVisualDepth(wnew) <= 1) { 11074 TRACE(("disabling color since screen is monochrome\n")); 11075 color_ok = False; 11076 } 11077 } 11078 11079 /* If none of the colors are anything other than the foreground or 11080 * background, we'll assume this isn't color, no matter what the colorMode 11081 * resource says. (There doesn't seem to be any good way to determine if 11082 * the resource lookup failed versus the user having misconfigured this). 11083 */ 11084 if (!color_ok) { 11085 screen->colorMode = False; 11086 TRACE(("All colors are foreground or background: disable colorMode\n")); 11087 } 11088 wnew->sgr_foreground = -1; 11089 wnew->sgr_background = -1; 11090 wnew->sgr_38_xcolors = False; 11091 clrDirectFG(wnew->flags); 11092 clrDirectFG(wnew->flags); 11093#endif /* OPT_ISO_COLORS */ 11094 11095 /* 11096 * Decode the resources that control the behavior on multiple mouse clicks. 11097 * A single click is always bound to normal character selection, but the 11098 * other flavors can be changed. 11099 */ 11100 for (i = 0; i < NSELECTUNITS; ++i) { 11101 int ck = (i + 1); 11102 screen->maxClicks = ck; 11103 if (i == Select_CHAR) 11104 screen->selectMap[i] = Select_CHAR; 11105 else if (TScreenOf(request)->onClick[i] != NULL) 11106 ParseOnClicks(wnew, request, (unsigned) i); 11107 else if (i <= Select_LINE) 11108 screen->selectMap[i] = (SelectUnit) i; 11109 else 11110 break; 11111#if OPT_XRES_QUERY 11112 init_Sres(screen.onClick[i]); 11113#endif 11114 TRACE(("on%dClicks %s=%d\n", ck, 11115 NonNull(TScreenOf(request)->onClick[i]), 11116 screen->selectMap[i])); 11117 if (screen->selectMap[i] == NSELECTUNITS) 11118 break; 11119 } 11120 TRACE(("maxClicks %d\n", screen->maxClicks)); 11121 11122 init_Tres(MOUSE_FG); 11123 init_Tres(MOUSE_BG); 11124 init_Tres(TEXT_CURSOR); 11125#if OPT_HIGHLIGHT_COLOR 11126 init_Tres(HIGHLIGHT_BG); 11127 init_Tres(HIGHLIGHT_FG); 11128 init_Bres(screen.hilite_reverse); 11129 init_Mres(screen.hilite_color); 11130 if (screen->hilite_color == Maybe) { 11131 screen->hilite_color = False; 11132 /* 11133 * If the highlight text/background are both set, and if they are 11134 * not equal to either the text/background or background/text, then 11135 * set the highlightColorMode automatically. 11136 */ 11137 if (!DftFg(Tcolors[HIGHLIGHT_BG]) 11138 && !DftBg(Tcolors[HIGHLIGHT_FG]) 11139 && !TxtFg(Tcolors[HIGHLIGHT_BG]) 11140 && !TxtBg(Tcolors[HIGHLIGHT_FG]) 11141 && !TxtBg(Tcolors[HIGHLIGHT_BG]) 11142 && !TxtFg(Tcolors[HIGHLIGHT_FG])) { 11143 TRACE(("...setting hilite_color automatically\n")); 11144 screen->hilite_color = True; 11145 } 11146 } 11147#endif 11148 11149#if OPT_TEK4014 11150 /* 11151 * The Tek4014 window has no separate resources for foreground, background 11152 * and cursor color. Since xterm always creates the vt100 widget first, we 11153 * can set the Tektronix colors here. That lets us use escape sequences to 11154 * set its dynamic colors and get consistent behavior whether or not the 11155 * window is displayed. 11156 */ 11157 screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG]; 11158 screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG]; 11159 screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR]; 11160#endif 11161 11162#ifdef SCROLLBAR_RIGHT 11163 init_Bres(misc.useRight); 11164#endif 11165 11166#if OPT_RENDERFONT 11167 init_Ires(misc.limit_fontsets); 11168 init_Ires(misc.limit_fontheight); 11169 if (wnew->misc.limit_fontheight > 50) { 11170 xtermWarning("limiting extra fontheight percent to 50 (was %d)\n", 11171 wnew->misc.limit_fontheight); 11172 wnew->misc.limit_fontheight = 50; 11173 } 11174 init_Ires(misc.limit_fontwidth); 11175 if (wnew->misc.limit_fontwidth > 50) { 11176 xtermWarning("limiting extra fontwidth percent to 50 (was %d)\n", 11177 wnew->misc.limit_fontwidth); 11178 wnew->misc.limit_fontwidth = 50; 11179 } 11180 wnew->work.max_fontsets = (unsigned) wnew->misc.limit_fontsets; 11181 if (wnew->work.max_fontsets > 255) { 11182 xtermWarning("limiting number of fontsets to 255 (was %u)\n", 11183 wnew->work.max_fontsets); 11184 wnew->work.max_fontsets = 255; 11185 } 11186 11187 init_Sres(misc.render_font_s); 11188 wnew->work.render_font = 11189 (Boolean) extendedBoolean(wnew->misc.render_font_s, 11190 tblRenderFont, erLast); 11191 if (wnew->work.render_font == erDefault) { 11192 if (IsEmpty(CurrentXftFont(wnew))) { 11193 free((void *) CurrentXftFont(wnew)); 11194 CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO); 11195 TRACE(("will allow runtime switch to render_font using \"%s\"\n", 11196 CurrentXftFont(wnew))); 11197 } else { 11198 wnew->work.render_font = erTrue; 11199 TRACE(("initially using TrueType font\n")); 11200 } 11201 } else if (wnew->work.render_font == erDefaultOff) { 11202 wnew->work.render_font = erFalse; 11203 } 11204 /* minor tweak to make debug traces consistent: */ 11205 if (wnew->work.render_font) { 11206 if (IsEmpty(CurrentXftFont(wnew))) { 11207 wnew->work.render_font = False; 11208 TRACE(("reset render_font since there is no face_name\n")); 11209 } 11210 } 11211#endif 11212 11213#if OPT_WIDE_CHARS 11214 /* setup data for next call */ 11215 init_Sres(screen.utf8_mode_s); 11216 request->screen.utf8_mode = 11217 extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast); 11218 11219 init_Sres(screen.utf8_fonts_s); 11220 request->screen.utf8_fonts = 11221 extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast); 11222 11223 init_Sres(screen.utf8_title_s); 11224 request->screen.utf8_title = 11225 extendedBoolean(request->screen.utf8_title_s, tblUtf8Mode, uLast); 11226 11227 /* 11228 * Make a copy in the input/request so that DefaultFontN() works for 11229 * the "CHECKFONT" option. 11230 */ 11231 copyFontList(&(request->work.fonts.x11.list_n), 11232 wnew->work.fonts.x11.list_n); 11233 11234 VTInitialize_locale(request); 11235 init_Bres(screen.normalized_c); 11236 init_Bres(screen.utf8_latin1); 11237 init_Bres(screen.utf8_weblike); 11238 11239#if OPT_LUIT_PROG 11240 init_Bres(misc.callfilter); 11241 init_Bres(misc.use_encoding); 11242 init_Sres(misc.locale_str); 11243 init_Sres(misc.localefilter); 11244#endif 11245 11246 init_Ires(screen.utf8_inparse); 11247 init_Ires(screen.utf8_mode); 11248 init_Ires(screen.utf8_fonts); 11249 init_Ires(screen.utf8_title); 11250 init_Ires(screen.max_combining); 11251 11252 init_Ires(screen.utf8_always); /* from utf8_mode, used in doparse */ 11253 11254 if (screen->max_combining < 0) { 11255 screen->max_combining = 0; 11256 } 11257 if (screen->max_combining > 5) { 11258 screen->max_combining = 5; 11259 } 11260 11261 init_Bres(screen.vt100_graphics); 11262 init_Bres(screen.wide_chars); 11263 init_Bres(misc.mk_width); 11264 init_Bres(misc.cjk_width); 11265 11266 init_Ires(misc.mk_samplesize); 11267 init_Ires(misc.mk_samplepass); 11268 11269 if (wnew->misc.mk_samplesize > 0xffff) 11270 wnew->misc.mk_samplesize = 0xffff; 11271 if (wnew->misc.mk_samplesize < 0) 11272 wnew->misc.mk_samplesize = 0; 11273 11274 if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize) 11275 wnew->misc.mk_samplepass = wnew->misc.mk_samplesize; 11276 if (wnew->misc.mk_samplepass < 0) 11277 wnew->misc.mk_samplepass = 0; 11278 11279 if (TScreenOf(request)->utf8_mode) { 11280 TRACE(("setting wide_chars on\n")); 11281 screen->wide_chars = True; 11282 } else { 11283 TRACE(("setting utf8_mode to 0\n")); 11284 screen->utf8_mode = uFalse; 11285 } 11286 mk_wcwidth_init(screen->utf8_mode); 11287 TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode)); 11288 11289#if OPT_MINI_LUIT 11290 if (TScreenOf(request)->latin9_mode) { 11291 screen->latin9_mode = True; 11292 } 11293 if (TScreenOf(request)->unicode_font) { 11294 screen->unicode_font = True; 11295 } 11296 TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode)); 11297 TRACE(("initialized unicode_font to %d\n", screen->unicode_font)); 11298#endif 11299 11300 decode_wcwidth(wnew); 11301 xtermSaveVTFonts(wnew); 11302#endif /* OPT_WIDE_CHARS */ 11303 11304 init_Sres(screen.eight_bit_meta_s); 11305 wnew->screen.eight_bit_meta = 11306 extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, ebLast); 11307 if (wnew->screen.eight_bit_meta == ebLocale) { 11308#if OPT_WIDE_CHARS 11309 if (xtermEnvUTF8()) { 11310 wnew->screen.eight_bit_meta = ebFalse; 11311 TRACE(("...eightBitMeta is false due to locale\n")); 11312 } else 11313#endif /* OPT_WIDE_CHARS */ 11314 { 11315 wnew->screen.eight_bit_meta = ebTrue; 11316 TRACE(("...eightBitMeta is true due to locale\n")); 11317 } 11318 } 11319 11320 init_Bres(screen.always_bold_mode); 11321 init_Bres(screen.bold_mode); 11322 init_Bres(screen.underline); 11323 11324 wnew->cur_foreground = 0; 11325 wnew->cur_background = 0; 11326 11327 wnew->keyboard.flags = MODE_SRM; 11328 11329 if (screen->backarrow_key) 11330 wnew->keyboard.flags |= MODE_DECBKM; 11331 TRACE(("initialized DECBKM %s\n", 11332 BtoS(wnew->keyboard.flags & MODE_DECBKM))); 11333 11334#if OPT_SIXEL_GRAPHICS 11335 /* Sixel scrolling is opposite of Sixel Display Mode */ 11336 init_Bres(screen.sixel_scrolling); 11337 if (screen->sixel_scrolling) 11338 UIntClr(wnew->keyboard.flags, MODE_DECSDM); 11339 else 11340 UIntSet(wnew->keyboard.flags, MODE_DECSDM); 11341 TRACE(("initialized DECSDM %s\n", 11342 BtoS(wnew->keyboard.flags & MODE_DECSDM))); 11343#endif 11344 11345#if OPT_GRAPHICS 11346 init_Sres(screen.graph_termid); 11347 screen->graphics_termid = decodeTerminalID(TScreenOf(request)->graph_termid); 11348 switch (screen->graphics_termid) { 11349 case 125: 11350 case 240: 11351 case 241: 11352 case 330: 11353 case 340: 11354 case 382: 11355 break; 11356 default: 11357 screen->graphics_termid = 0; 11358 break; 11359 } 11360 TRACE(("graph_termid '%s' -> graphics_termid %d\n", 11361 screen->graph_termid, 11362 screen->graphics_termid)); 11363 11364 init_Ires(screen.numcolorregisters); 11365 TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n", 11366 screen->numcolorregisters)); 11367 11368 init_Bres(screen.privatecolorregisters); /* FIXME: should this be off unconditionally here? */ 11369 TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n", 11370 BtoS(screen->privatecolorregisters))); 11371 screen->privatecolorregisters0 = screen->privatecolorregisters; 11372 11373 init_Bres(screen.incremental_graphics); 11374 TRACE(("initialized INCREMENTAL_GRAPHICS to resource default: %s\n", 11375 BtoS(screen->incremental_graphics))); 11376#endif 11377 11378#if OPT_GRAPHICS 11379 { 11380 int native_w, native_h; 11381 11382 switch (GraphicsTermId(screen)) { 11383 case 125: 11384 native_w = 768; 11385 native_h = 460; 11386 break; 11387 case 240: 11388 /* FALLTHRU */ 11389 case 241: 11390 native_w = 800; 11391 native_h = 460; 11392 break; 11393 case 330: 11394 /* FALLTHRU */ 11395 case 340: 11396 native_w = 800; 11397 native_h = 480; 11398 break; 11399 default: 11400 native_w = 800; 11401 native_h = 480; 11402 break; 11403 case 382: 11404 native_w = 960; 11405 native_h = 720; 11406 break; 11407 } 11408 11409# if OPT_REGIS_GRAPHICS 11410 init_Sres(screen.graphics_regis_default_font); 11411 TRACE(("default ReGIS font: %s\n", 11412 screen->graphics_regis_default_font)); 11413 11414 init_Sres(screen.graphics_regis_screensize); 11415 screen->graphics_regis_def_high = 1000; 11416 screen->graphics_regis_def_wide = 1000; 11417 if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) { 11418 TRACE(("setting default ReGIS screensize based on graphics_id %d\n", 11419 GraphicsTermId(screen))); 11420 screen->graphics_regis_def_high = (Dimension) native_h; 11421 screen->graphics_regis_def_wide = (Dimension) native_w; 11422 } else { 11423 int conf_high; 11424 int conf_wide; 11425 char ignore; 11426 11427 if (sscanf(screen->graphics_regis_screensize, 11428 "%dx%d%c", 11429 &conf_wide, 11430 &conf_high, 11431 &ignore) == 2) { 11432 if (conf_high > 0 && conf_wide > 0) { 11433 screen->graphics_regis_def_high = 11434 (Dimension) conf_high; 11435 screen->graphics_regis_def_wide = 11436 (Dimension) conf_wide; 11437 } else { 11438 TRACE(("ignoring invalid regisScreenSize %s\n", 11439 screen->graphics_regis_screensize)); 11440 } 11441 } else { 11442 TRACE(("ignoring invalid regisScreenSize %s\n", 11443 screen->graphics_regis_screensize)); 11444 } 11445 } 11446 TRACE(("default ReGIS graphics screensize %dx%d\n", 11447 (int) screen->graphics_regis_def_wide, 11448 (int) screen->graphics_regis_def_high)); 11449# endif 11450 11451 init_Sres(screen.graphics_max_size); 11452 screen->graphics_max_high = 1000; 11453 screen->graphics_max_wide = 1000; 11454 if (!x_strcasecmp(screen->graphics_max_size, "auto")) { 11455 TRACE(("setting max graphics screensize based on graphics_id %d\n", 11456 GraphicsTermId(screen))); 11457 screen->graphics_max_high = (Dimension) native_h; 11458 screen->graphics_max_wide = (Dimension) native_w; 11459 } else { 11460 int conf_high; 11461 int conf_wide; 11462 char ignore; 11463 11464 if (sscanf(screen->graphics_max_size, 11465 "%dx%d%c", 11466 &conf_wide, 11467 &conf_high, 11468 &ignore) == 2) { 11469 if (conf_high > 0 && conf_wide > 0) { 11470 screen->graphics_max_high = (Dimension) conf_high; 11471 screen->graphics_max_wide = (Dimension) conf_wide; 11472 } else { 11473 TRACE(("ignoring invalid maxGraphicSize %s\n", 11474 screen->graphics_max_size)); 11475 } 11476 } else { 11477 TRACE(("ignoring invalid maxGraphicSize %s\n", 11478 screen->graphics_max_size)); 11479 } 11480 } 11481# if OPT_REGIS_GRAPHICS 11482 /* Make sure the max is large enough for the default ReGIS size. */ 11483 if (screen->graphics_regis_def_high > 11484 screen->graphics_max_high) { 11485 screen->graphics_max_high = 11486 screen->graphics_regis_def_high; 11487 } 11488 if (screen->graphics_regis_def_wide > 11489 screen->graphics_max_wide) { 11490 screen->graphics_max_wide = 11491 screen->graphics_regis_def_wide; 11492 } 11493# endif 11494 TRACE(("max graphics screensize %dx%d\n", 11495 (int) screen->graphics_max_wide, 11496 (int) screen->graphics_max_high)); 11497 } 11498#endif 11499 11500#if OPT_SIXEL_GRAPHICS 11501 init_Bres(screen.sixel_scrolls_right); 11502 screen->sixel_scrolls_right0 = screen->sixel_scrolls_right; 11503#endif 11504#if OPT_PRINT_GRAPHICS 11505 init_Bres(screen.graphics_print_to_host); 11506 init_Bres(screen.graphics_expanded_print_mode); 11507 init_Bres(screen.graphics_print_color_mode); 11508 init_Bres(screen.graphics_print_color_syntax); 11509 init_Bres(screen.graphics_print_background_mode); 11510 init_Bres(screen.graphics_rotated_print_mode); 11511#endif 11512 11513#if OPT_STATUS_LINE 11514 init_Sres(screen.status_fmt); 11515#endif 11516 11517 /* look for focus related events on the shell, because we need 11518 * to care about the shell's border being part of our focus. 11519 */ 11520 TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent)); 11521 XtAddEventHandler(my_parent, EnterWindowMask, False, 11522 HandleEnterWindow, (Opaque) NULL); 11523 XtAddEventHandler(my_parent, LeaveWindowMask, False, 11524 HandleLeaveWindow, (Opaque) NULL); 11525 XtAddEventHandler(my_parent, FocusChangeMask, False, 11526 HandleFocusChange, (Opaque) NULL); 11527 XtAddEventHandler((Widget) wnew, 0L, True, 11528 VTNonMaskableEvent, (Opaque) NULL); 11529 XtAddEventHandler((Widget) wnew, PropertyChangeMask, False, 11530 HandleBellPropertyChange, (Opaque) NULL); 11531 11532#if HANDLE_STRUCT_NOTIFY 11533#if OPT_TOOLBAR 11534 wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar); 11535 init_Ires(VT100_TB_INFO(menu_height)); 11536#endif 11537 XtAddEventHandler(my_parent, MappingNotify | StructureNotifyMask, False, 11538 HandleStructNotify, (Opaque) 0); 11539#endif /* HANDLE_STRUCT_NOTIFY */ 11540 11541 screen->bellInProgress = False; 11542 11543 set_character_class(screen->charClass); 11544#if OPT_REPORT_CCLASS 11545 if (resource.reportCClass) 11546 report_char_class(wnew); 11547#endif 11548 11549 /* create it, but don't realize it */ 11550 ScrollBarOn(wnew, True); 11551 11552 /* make sure that the resize gravity acceptable */ 11553 if (!GravityIsNorthWest(wnew) && 11554 !GravityIsSouthWest(wnew)) { 11555 char value[80]; 11556 String temp[2]; 11557 Cardinal nparams = 1; 11558 11559 sprintf(value, "%d", wnew->misc.resizeGravity); 11560 temp[0] = value; 11561 temp[1] = NULL; 11562 XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError", 11563 "unsupported resizeGravity resource value (%s)", 11564 temp, &nparams); 11565 wnew->misc.resizeGravity = SouthWestGravity; 11566 } 11567#ifndef NO_ACTIVE_ICON 11568 screen->whichVwin = &screen->fullVwin; 11569#endif /* NO_ACTIVE_ICON */ 11570 11571 init_Ires(screen.unparse_max); 11572 if ((int) screen->unparse_max < 256) 11573 screen->unparse_max = 256; 11574 screen->unparse_bfr = (IChar *) (void *) XtCalloc(screen->unparse_max, 11575 (Cardinal) sizeof(IChar)); 11576 11577 init_Ires(screen.strings_max); 11578 11579 if (screen->savelines < 0) 11580 screen->savelines = 0; 11581 11582 init_Bres(screen.awaitInput); 11583 11584 wnew->flags = 0; 11585 if (!screen->jumpscroll) 11586 wnew->flags |= SMOOTHSCROLL; 11587 if (wnew->misc.reverseWrap) 11588 wnew->flags |= REVERSEWRAP; 11589 if (wnew->misc.autoWrap) 11590 wnew->flags |= WRAPAROUND; 11591 if (wnew->misc.re_verse != wnew->misc.re_verse0) 11592 wnew->flags |= REVERSE_VIDEO; 11593 if (screen->c132) 11594 wnew->flags |= IN132COLUMNS; 11595 11596 wnew->initflags = wnew->flags; 11597 11598 init_Sres(keyboard.shift_escape_s); 11599 wnew->keyboard.shift_escape = 11600 extendedBoolean(wnew->keyboard.shift_escape_s, tblShift2S, ssLAST); 11601 11602#if OPT_MOD_FKEYS 11603 init_Ires(keyboard.modify_1st.allow_keys); 11604 init_Ires(keyboard.modify_1st.cursor_keys); 11605 init_Ires(keyboard.modify_1st.function_keys); 11606 init_Ires(keyboard.modify_1st.keypad_keys); 11607 init_Ires(keyboard.modify_1st.other_keys); 11608 init_Ires(keyboard.modify_1st.string_keys); 11609 init_Ires(keyboard.format_keys); 11610 wnew->keyboard.modify_now = wnew->keyboard.modify_1st; 11611#endif 11612 11613 init_Ires(misc.appcursorDefault); 11614 if (wnew->misc.appcursorDefault) 11615 wnew->keyboard.flags |= MODE_DECCKM; 11616 11617 init_Ires(misc.appkeypadDefault); 11618 if (wnew->misc.appkeypadDefault) 11619 wnew->keyboard.flags |= MODE_DECKPAM; 11620 11621 initLineData(wnew); 11622#if OPT_WIDE_CHARS 11623 freeFontList(&(request->work.fonts.x11.list_n)); 11624#endif 11625#if OPT_XRES_QUERY 11626 if (resource.reportXRes) 11627 reportResources(wnew); 11628#endif 11629 xtermResetLocale(LC_NUMERIC, saveLocale); 11630 TRACE(("" TRACE_R " VTInitialize\n")); 11631 return; 11632} 11633 11634void 11635releaseCursorGCs(XtermWidget xw) 11636{ 11637 TScreen *screen = TScreenOf(xw); 11638 VTwin *win = WhichVWin(screen); 11639 int n; 11640 11641 for_each_curs_gc(n) { 11642 freeCgs(xw, win, (CgsEnum) n); 11643 } 11644} 11645 11646void 11647releaseWindowGCs(XtermWidget xw, VTwin *win) 11648{ 11649 int n; 11650 11651 for_each_text_gc(n) { 11652 switch (n) { 11653 case gcBorder: 11654 case gcFiller: 11655 break; 11656 default: 11657 freeCgs(xw, win, (CgsEnum) n); 11658 break; 11659 } 11660 } 11661} 11662 11663#define TRACE_FREE_LEAK(name) \ 11664 if (name) { \ 11665 TRACE(("freed " #name ": %p\n", (const void *) name)); \ 11666 FreeAndNull(name); \ 11667 } 11668 11669#define TRACE_FREE_GC(name,part) \ 11670 if (part) { \ 11671 TRACE(("freed %s " #part ": %p\n", name, (const void *) part)); \ 11672 XFreeGC(dpy, part); \ 11673 part = NULL; \ 11674 } 11675 11676#if OPT_INPUT_METHOD 11677static void 11678cleanupInputMethod(XtermWidget xw) 11679{ 11680 TInput *input = lookupTInput(xw, (Widget) xw); 11681 11682 if (input && input->xim) { 11683 XCloseIM(input->xim); 11684 input->xim = NULL; 11685 TRACE(("freed screen->xim\n")); 11686 } 11687} 11688#else 11689#define cleanupInputMethod(xw) /* nothing */ 11690#endif 11691 11692#ifdef NO_LEAKS 11693#define FREE_VT_WIN(name) freeVTwin(dpy, #name, &(screen->name)) 11694static void 11695freeVTwin(Display *dpy, const char *whichWin, VTwin *win) 11696{ 11697 (void) whichWin; 11698 TRACE_FREE_GC(whichWin, win->filler_gc); 11699 TRACE_FREE_GC(whichWin, win->border_gc); 11700 TRACE_FREE_GC(whichWin, win->marker_gc[0]); 11701 TRACE_FREE_GC(whichWin, win->marker_gc[1]); 11702} 11703#endif 11704 11705static void 11706VTDestroy(Widget w GCC_UNUSED) 11707{ 11708#ifdef NO_LEAKS 11709 XtermWidget xw = (XtermWidget) w; 11710 TScreen *screen = TScreenOf(xw); 11711 Display *dpy = screen->display; 11712 Cardinal n, k; 11713 11714 StopBlinking(xw); 11715 11716 if (screen->scrollWidget) { 11717 XtUninstallTranslations(screen->scrollWidget); 11718 XtDestroyWidget(screen->scrollWidget); 11719 } 11720 11721 while (screen->saved_fifo > 0) { 11722 deleteScrollback(screen); 11723 } 11724 11725 for (n = 0; n < MAX_SAVED_TITLES; ++n) 11726 xtermFreeTitle(&screen->saved_titles.data[n]); 11727 11728#if OPT_STATUS_LINE 11729 free(screen->status_fmt); 11730#endif 11731#ifndef NO_ACTIVE_ICON 11732 TRACE_FREE_LEAK(xw->misc.active_icon_s); 11733#endif 11734#if OPT_ISO_COLORS 11735 TRACE_FREE_LEAK(screen->cmap_data); 11736 for (n = 0; n < MAXCOLORS; n++) { 11737 TRACE_FREE_LEAK(screen->Acolors[n].resource); 11738 } 11739 for (n = 0; n < MAX_SAVED_SGR; n++) { 11740 TRACE_FREE_LEAK(xw->saved_colors.palettes[n]); 11741 } 11742#endif 11743 for (n = 0; n < NCOLORS; n++) { 11744 switch (n) { 11745#if OPT_TEK4014 11746 case TEK_BG: 11747 /* FALLTHRU */ 11748 case TEK_FG: 11749 /* FALLTHRU */ 11750 case TEK_CURSOR: 11751 break; 11752#endif 11753 default: 11754 TRACE_FREE_LEAK(screen->Tcolors[n].resource); 11755 break; 11756 } 11757 } 11758 FreeMarkGCs(xw); 11759 TRACE_FREE_LEAK(screen->unparse_bfr); 11760 TRACE_FREE_LEAK(screen->save_ptr); 11761 TRACE_FREE_LEAK(screen->saveBuf_data); 11762 TRACE_FREE_LEAK(screen->saveBuf_index); 11763 for (n = 0; n < 2; ++n) { 11764 TRACE_FREE_LEAK(screen->editBuf_data[n]); 11765 TRACE_FREE_LEAK(screen->editBuf_index[n]); 11766 } 11767 TRACE_FREE_LEAK(screen->keyboard_dialect); 11768 TRACE_FREE_LEAK(screen->cursor_font_name); 11769 TRACE_FREE_LEAK(screen->pointer_shape); 11770 TRACE_FREE_LEAK(screen->term_id); 11771#if OPT_WIDE_CHARS 11772 TRACE_FREE_LEAK(screen->utf8_mode_s); 11773 TRACE_FREE_LEAK(screen->utf8_fonts_s); 11774 TRACE_FREE_LEAK(screen->utf8_title_s); 11775#if OPT_LUIT_PROG 11776 TRACE_FREE_LEAK(xw->misc.locale_str); 11777 TRACE_FREE_LEAK(xw->misc.localefilter); 11778#endif 11779#endif 11780 TRACE_FREE_LEAK(xw->misc.T_geometry); 11781 TRACE_FREE_LEAK(xw->misc.geo_metry); 11782#if OPT_INPUT_METHOD 11783 cleanupInputMethod(xw); 11784 TRACE_FREE_LEAK(xw->misc.f_x); 11785 TRACE_FREE_LEAK(xw->misc.input_method); 11786 TRACE_FREE_LEAK(xw->misc.preedit_type); 11787#endif 11788 releaseCursorGCs(xw); 11789 releaseWindowGCs(xw, &(screen->fullVwin)); 11790#ifndef NO_ACTIVE_ICON 11791 XFreeFont(screen->display, getIconicFont(screen)->fs); 11792 releaseWindowGCs(xw, &(screen->iconVwin)); 11793#endif 11794 XtUninstallTranslations((Widget) xw); 11795#if OPT_TOOLBAR 11796 XtUninstallTranslations((Widget) XtParent(xw)); 11797#endif 11798 XtUninstallTranslations((Widget) SHELL_OF(xw)); 11799 11800 if (screen->hidden_cursor) 11801 XFreeCursor(screen->display, screen->hidden_cursor); 11802 11803 xtermCloseFonts(xw, screen->fnts); 11804#if OPT_WIDE_ATTRS 11805 xtermCloseFonts(xw, screen->ifnts); 11806#endif 11807 noleaks_cachedCgs(xw); 11808 free_termcap(xw); 11809 11810 FREE_VT_WIN(fullVwin); 11811#ifndef NO_ACTIVE_ICON 11812 FREE_VT_WIN(iconVwin); 11813#endif /* NO_ACTIVE_ICON */ 11814 11815 TRACE_FREE_LEAK(screen->selection_targets_8bit); 11816#if OPT_SELECT_REGEX 11817 for (n = 0; n < NSELECTUNITS; ++n) { 11818 if (screen->selectMap[n] == Select_REGEX) { 11819 TRACE_FREE_LEAK(screen->selectExpr[n]); 11820 } 11821 } 11822#endif 11823 11824#if OPT_RENDERFONT 11825 for (n = 0; n < NMENUFONTS; ++n) { 11826 int e; 11827 for (e = 0; e < fMAX; ++e) { 11828 xtermCloseXft(screen, getMyXftFont(xw, e, (int) n)); 11829 } 11830 } 11831 discardRenderDraw(screen); 11832 { 11833 ListXftFonts *p; 11834 while ((p = screen->list_xft_fonts) != NULL) { 11835 screen->list_xft_fonts = p->next; 11836 free(p); 11837 } 11838 } 11839#endif 11840 11841 /* free things allocated via init_Sres or Init_Sres2 */ 11842#ifndef NO_ACTIVE_ICON 11843 TRACE_FREE_LEAK(screen->icon_fontname); 11844#endif 11845#ifdef ALLOWLOGGING 11846 TRACE_FREE_LEAK(screen->logfile); 11847#endif 11848 TRACE_FREE_LEAK(screen->eight_bit_meta_s); 11849 TRACE_FREE_LEAK(screen->charClass); 11850 TRACE_FREE_LEAK(screen->answer_back); 11851 TRACE_FREE_LEAK(screen->printer_state.printer_command); 11852 TRACE_FREE_LEAK(screen->disallowedColorOps); 11853 TRACE_FREE_LEAK(screen->disallowedFontOps); 11854 TRACE_FREE_LEAK(screen->disallowedMouseOps); 11855 TRACE_FREE_LEAK(screen->disallowedPasteOps); 11856 TRACE_FREE_LEAK(screen->disallowedTcapOps); 11857 TRACE_FREE_LEAK(screen->disallowedWinOps); 11858 TRACE_FREE_LEAK(screen->default_string); 11859 TRACE_FREE_LEAK(screen->eightbit_select_types); 11860 11861#if OPT_WIDE_CHARS 11862 TRACE_FREE_LEAK(screen->utf8_select_types); 11863#endif 11864 11865#if 0 11866 for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) { 11867 TRACE_FREE_LEAK(screen->MenuFontName(n)); 11868 } 11869#endif 11870 11871 TRACE_FREE_LEAK(screen->initial_font); 11872 11873#if OPT_LUIT_PROG 11874 TRACE_FREE_LEAK(xw->misc.locale_str); 11875 TRACE_FREE_LEAK(xw->misc.localefilter); 11876#endif 11877 11878 TRACE_FREE_LEAK(xw->misc.cdXtraScroll_s); 11879 TRACE_FREE_LEAK(xw->misc.tiXtraScroll_s); 11880 11881#if OPT_RENDERFONT 11882 TRACE_FREE_LEAK(xw->misc.default_xft.f_n); 11883#if OPT_WIDE_CHARS 11884 TRACE_FREE_LEAK(xw->misc.default_xft.f_w); 11885#endif 11886 TRACE_FREE_LEAK(xw->misc.render_font_s); 11887#endif 11888 11889 TRACE_FREE_LEAK(xw->misc.default_font.f_n); 11890 TRACE_FREE_LEAK(xw->misc.default_font.f_b); 11891 11892#if OPT_WIDE_CHARS 11893 TRACE_FREE_LEAK(xw->misc.default_font.f_w); 11894 TRACE_FREE_LEAK(xw->misc.default_font.f_wb); 11895#endif 11896 11897 TRACE_FREE_LEAK(xw->work.wm_name); 11898 freeFontLists(&(xw->work.fonts.x11)); 11899#if OPT_RENDERFONT 11900 freeFontLists(&(xw->work.fonts.xft)); 11901#endif 11902 11903 xtermFontName(NULL); 11904#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 11905 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n); 11906 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b); 11907#if OPT_WIDE_CHARS 11908 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w); 11909 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb); 11910#endif 11911 freeFontLists(&(screen->cacheVTFonts.fonts.x11)); 11912 for (n = 0; n < NMENUFONTS; ++n) { 11913 for (k = 0; k < fMAX; ++k) { 11914 if (screen->menu_font_names[n][k] != 11915 screen->cacheVTFonts.menu_font_names[n][k]) { 11916 if (screen->menu_font_names[n][k] != _Font_Selected_) { 11917 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 11918 } 11919 TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]); 11920 } else { 11921 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 11922 } 11923 } 11924 } 11925#endif 11926 11927#if OPT_BLINK_CURS 11928 TRACE_FREE_LEAK(screen->cursor_blink_s); 11929#endif 11930 11931#if OPT_REGIS_GRAPHICS 11932 TRACE_FREE_LEAK(screen->graphics_regis_default_font); 11933 TRACE_FREE_LEAK(screen->graphics_regis_screensize); 11934#endif 11935#if OPT_GRAPHICS 11936 TRACE_FREE_LEAK(screen->graph_termid); 11937 TRACE_FREE_LEAK(screen->graphics_max_size); 11938#endif 11939 11940 for (n = 0; n < NSELECTUNITS; ++n) { 11941#if OPT_SELECT_REGEX 11942 TRACE_FREE_LEAK(screen->selectExpr[n]); 11943#endif 11944#if OPT_XRES_QUERY 11945 TRACE_FREE_LEAK(screen->onClick[n]); 11946#endif 11947 } 11948 11949 XtFree((void *) (screen->selection_atoms)); 11950 11951 for (n = 0; n < MAX_SELECTIONS; ++n) { 11952 free(screen->selected_cells[n].data_buffer); 11953 } 11954 11955 if (defaultTranslations != xtermClassRec.core_class.tm_table) { 11956 TRACE_FREE_LEAK(defaultTranslations); 11957 } 11958 TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table); 11959 TRACE_FREE_LEAK(xw->keyboard.shift_escape_s); 11960 TRACE_FREE_LEAK(xw->keyboard.extra_translations); 11961 TRACE_FREE_LEAK(xw->keyboard.shell_translations); 11962 TRACE_FREE_LEAK(xw->keyboard.xterm_translations); 11963 TRACE_FREE_LEAK(xw->keyboard.print_translations); 11964 UnmapSelections(xw); 11965 11966 XtFree((void *) (xw->visInfo)); 11967 11968#if OPT_WIDE_CHARS 11969 FreeTypedBuffer(IChar); 11970 FreeTypedBuffer(XChar2b); 11971 FreeTypedBuffer(Char); 11972#endif 11973#if OPT_RENDERFONT 11974#if OPT_RENDERWIDE 11975 FreeTypedBuffer(XftCharSpec); 11976#else 11977 FreeTypedBuffer(XftChar8); 11978#endif 11979#endif 11980 11981 TRACE_FREE_LEAK(myState.print_area); 11982 TRACE_FREE_LEAK(myState.string_area); 11983 memset(&myState, 0, sizeof(myState)); 11984 11985#endif /* defined(NO_LEAKS) */ 11986} 11987 11988#ifndef NO_ACTIVE_ICON 11989static void * 11990getProperty(Display *dpy, 11991 Window w, 11992 Atom req_type, 11993 const char *prop_name) 11994{ 11995 Atom property; 11996 Atom actual_return_type; 11997 int actual_format_return = 0; 11998 unsigned long nitems_return = 0; 11999 unsigned long bytes_after_return = 0; 12000 unsigned char *prop_return = NULL; 12001 long long_length = 1024; 12002 size_t limit; 12003 char *result = NULL; 12004 12005 TRACE(("getProperty %s(%s)\n", prop_name, 12006 req_type ? TraceAtomName(dpy, req_type) : "?")); 12007 property = CachedInternAtom(dpy, prop_name); 12008 12009 if (!xtermGetWinProp(dpy, 12010 w, 12011 property, 12012 0L, 12013 long_length, 12014 req_type, 12015 &actual_return_type, 12016 &actual_format_return, 12017 &nitems_return, 12018 &bytes_after_return, 12019 &prop_return)) { 12020 TRACE((".. Cannot get %s property.\n", prop_name)); 12021 } else if (prop_return != NULL) { 12022 12023 if (nitems_return != 0 && 12024 actual_format_return != 0 && 12025 actual_return_type == req_type) { 12026 /* 12027 * Null-terminate the result to make string handling easier. 12028 * The format==8 corresponds to strings, and the number of items 12029 * is the number of characters. 12030 */ 12031 if (actual_format_return == 8) { 12032 limit = nitems_return; 12033 } else { 12034 /* manpage is misleading - X really uses 'long', not 32-bits */ 12035 limit = sizeof(long) * nitems_return; 12036 } 12037 if ((result = malloc(limit + 1)) != NULL) { 12038 memcpy(result, prop_return, limit); 12039 result[limit] = '\0'; 12040 } 12041 TRACE(("... result %s\n", result ? ("ok") : "null")); 12042 } 12043 XFree(prop_return); 12044 } else { 12045 TRACE((".. no property returned\n")); 12046 } 12047 return (void *) result; 12048} 12049 12050/* 12051 * Active icons are supported by fvwm. This feature is not supported by 12052 * metacity (gnome) or kwin (kde). Both metacity and kwin support (in 12053 * incompatible ways, e.g., one uses the icon theme as a fallback for window 12054 * decorations but the other does not, etc, ...) an icon as part of the window 12055 * decoration (usually on the upper-left of the window). 12056 * 12057 * In either case, xterm's icon will only be shown in the window decorations if 12058 * xterm does not use the active icon feature. 12059 * 12060 * This function (tries to) determine the window manager's name, so that we can 12061 * provide a useful automatic default for active icons. It is based on reading 12062 * wmctrl, which covers most of EWMH and ICCM. 12063 */ 12064static char * 12065getWindowManagerName(XtermWidget xw) 12066{ 12067 TScreen *screen = TScreenOf(xw); 12068 Display *dpy = screen->display; 12069 Window *sup_window = NULL; 12070 char *result = NULL; 12071 12072 TRACE(("getWindowManagerName\n")); 12073#define getWinProp(type, name) \ 12074 (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name) 12075 if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == NULL) { 12076 sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK"); 12077 } 12078 12079 /* 12080 * If we found the supporting window, get the property containing the 12081 * window manager's name. EWMH defines _NET_WM_NAME, while ICCM defines 12082 * WM_CLASS. There is no standard for the names stored there; 12083 * conventionally it is mixed case. In practice, the former is more often 12084 * set; the latter is not given (or is a lowercased version of the former). 12085 */ 12086 if (sup_window != NULL) { 12087#define getStringProp(type,name) \ 12088 (char *)getProperty(dpy, *sup_window, type, name) 12089 if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == NULL 12090 && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == NULL 12091 && (result = getStringProp(XA_STRING, "WM_CLASS")) == NULL) { 12092 TRACE(("... window manager does not tell its name\n")); 12093 } 12094 free(sup_window); 12095 } else { 12096 TRACE(("... Cannot get window manager info properties\n")); 12097 } 12098 if (result == NULL) 12099 result = x_strdup("unknown"); 12100 TRACE(("... window manager name is %s\n", result)); 12101 return result; 12102} 12103 12104static Boolean 12105discount_frame_extents(XtermWidget xw, int *high, int *wide) 12106{ 12107 TScreen *screen = TScreenOf(xw); 12108 Display *dpy = screen->display; 12109 12110 Atom atom_supported = CachedInternAtom(dpy, "_NET_FRAME_EXTENTS"); 12111 Atom actual_type; 12112 int actual_format; 12113 long long_offset = 0; 12114 long long_length = 128; /* number of items to ask for at a time */ 12115 unsigned long nitems; 12116 unsigned long bytes_after; 12117 unsigned char *args; 12118 Boolean rc; 12119 12120 rc = xtermGetWinProp(dpy, 12121 VShellWindow(xw), 12122 atom_supported, 12123 long_offset, 12124 long_length, 12125 XA_CARDINAL, /* req_type */ 12126 &actual_type, /* actual_type_return */ 12127 &actual_format, /* actual_format_return */ 12128 &nitems, /* nitems_return */ 12129 &bytes_after, /* bytes_after_return */ 12130 &args /* prop_return */ 12131 ); 12132 12133 if (rc && args && (nitems == 4) && (actual_format == 32)) { 12134 long *extents = (long *) (void *) args; 12135 12136 TRACE(("_NET_FRAME_EXTENTS:\n")); 12137 TRACE((" left: %ld\n", extents[0])); 12138 TRACE((" right: %ld\n", extents[1])); 12139 TRACE((" top: %ld\n", extents[2])); 12140 TRACE((" bottom: %ld\n", extents[3])); 12141 12142 if (!x_strncasecmp(xw->work.wm_name, "gnome shell", 11)) { 12143 *wide -= (int) (extents[0] + extents[1]); /* -= (left+right) */ 12144 *high -= (int) (extents[2] + extents[3]); /* -= (top+bottom) */ 12145 TRACE(("...applied extents %d,%d\n", *high, *wide)); 12146 } else if (!x_strncasecmp(xw->work.wm_name, "compiz", 6)) { 12147 /* Ubuntu 16.04 is really off-by-one */ 12148 *wide -= (int) (extents[0] + extents[1] - 1); 12149 *high -= (int) (extents[2] + extents[3] - 1); 12150 TRACE(("...applied extents %d,%d\n", *high, *wide)); 12151 } else if (!x_strncasecmp(xw->work.wm_name, "fvwm", 4)) { 12152 TRACE(("...skipping extents\n")); 12153 } else { 12154 TRACE(("...ignoring extents\n")); 12155 rc = False; 12156 } 12157 XFree(args); 12158 } else { 12159 rc = False; 12160 } 12161 return rc; 12162} 12163#endif /* !NO_ACTIVE_ICON */ 12164 12165void 12166initBorderGC(XtermWidget xw, VTwin *win) 12167{ 12168 TScreen *screen = TScreenOf(xw); 12169 Pixel filler; 12170 12171 TRACE(("initBorderGC(%s) core bg %#lx, bd %#lx text fg %#lx, bg %#lx %s\n", 12172 (win == &(screen->fullVwin)) ? "full" : "icon", 12173 xw->core.background_pixel, 12174 xw->core.border_pixel, 12175 T_COLOR(screen, TEXT_FG), 12176 T_COLOR(screen, TEXT_BG), 12177 xw->misc.re_verse ? "reverse" : "normal")); 12178 if (xw->misc.color_inner_border 12179 && (xw->core.background_pixel != xw->core.border_pixel)) { 12180 /* 12181 * By default, try to match the inner window's background. 12182 */ 12183 if ((xw->core.background_pixel == T_COLOR(screen, TEXT_BG)) && 12184 (xw->core.border_pixel == T_COLOR(screen, TEXT_FG))) { 12185 filler = T_COLOR(screen, TEXT_BG); 12186 } else { 12187 filler = xw->core.border_pixel; 12188 } 12189 TRACE((" border %#lx\n", filler)); 12190 setCgsFore(xw, win, gcBorder, filler); 12191 setCgsBack(xw, win, gcBorder, filler); 12192 win->border_gc = getCgsGC(xw, win, gcBorder); 12193 } 12194#if USE_DOUBLE_BUFFER 12195 else if (resource.buffered) { 12196 filler = T_COLOR(screen, TEXT_BG); 12197 TRACE((" border %#lx (buffered)\n", filler)); 12198 setCgsFore(xw, win, gcBorder, filler); 12199 setCgsBack(xw, win, gcBorder, filler); 12200 win->border_gc = getCgsGC(xw, win, gcBorder); 12201 } 12202#endif 12203 else { 12204 TRACE((" border unused\n")); 12205 win->border_gc = NULL; 12206 } 12207 12208 /* 12209 * Initialize a GC for double-buffering, needed for XFillRectangle call 12210 * in xtermClear2(). When not double-buffering, the XClearArea call works, 12211 * without requiring a separate GC. 12212 */ 12213#if USE_DOUBLE_BUFFER 12214 if (resource.buffered) { 12215 filler = (((xw->flags & BG_COLOR) && (xw->cur_background >= 0)) 12216 ? getXtermBG(xw, xw->flags, xw->cur_background) 12217 : T_COLOR(screen, TEXT_BG)); 12218 12219 TRACE((" filler %#lx %s\n", 12220 filler, 12221 xw->misc.re_verse ? "reverse" : "normal")); 12222 12223 setCgsFore(xw, win, gcFiller, filler); 12224 setCgsBack(xw, win, gcFiller, filler); 12225 12226 win->filler_gc = getCgsGC(xw, win, gcFiller); 12227 } 12228#endif 12229} 12230#if USE_DOUBLE_BUFFER 12231static Boolean 12232allocateDbe(XtermWidget xw, VTwin *target) 12233{ 12234 TScreen *screen = TScreenOf(xw); 12235 Boolean result = False; 12236 12237 target->drawable = target->window; 12238 12239 if (resource.buffered) { 12240 Window win = target->window; 12241 Drawable d; 12242 int major, minor; 12243 if (XdbeQueryExtension(XtDisplay(xw), &major, &minor)) { 12244 d = XdbeAllocateBackBufferName(XtDisplay(xw), win, 12245 (XdbeSwapAction) XdbeCopied); 12246 if (d == None) { 12247 fprintf(stderr, "Couldn't allocate a back buffer!\n"); 12248 exit(3); 12249 } 12250 target->drawable = d; 12251 screen->needSwap = 1; 12252 TRACE(("initialized double-buffering\n")); 12253 result = True; 12254 } else { 12255 resource.buffered = False; 12256 } 12257 } 12258 return result; 12259} 12260#endif /* USE_DOUBLE_BUFFER */ 12261 12262/*ARGSUSED*/ 12263static void 12264VTRealize(Widget w, 12265 XtValueMask * valuemask, 12266 XSetWindowAttributes * values) 12267{ 12268 XtermWidget xw = (XtermWidget) w; 12269 TScreen *screen = TScreenOf(xw); 12270 12271 const VTFontNames *myfont; 12272 struct Xinerama_geometry pos; 12273 int pr; 12274 Atom pid_atom; 12275 int i; 12276 12277 TRACE(("VTRealize " TRACE_L "\n")); 12278 12279 TabReset(xw->tabs); 12280 12281 if (screen->menu_font_number == fontMenu_default) { 12282 myfont = defaultVTFontNames(xw); 12283 } else { 12284 myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number)); 12285 } 12286 memset(screen->fnts, 0, sizeof(screen->fnts)); 12287 12288 if (!xtermLoadFont(xw, 12289 myfont, 12290 False, 12291 screen->menu_font_number)) { 12292 if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) { 12293 char *use_font = x_strdup(DEFFONT); 12294 xtermWarning("unable to open font \"%s\", trying \"%s\"....\n", 12295 myfont->f_n, use_font); 12296 (void) xtermLoadFont(xw, 12297 xtermFontName(use_font), 12298 False, 12299 screen->menu_font_number); 12300 screen->MenuFontName(screen->menu_font_number) = use_font; 12301 } 12302 } 12303 12304 /* really screwed if we couldn't open default font */ 12305 if (!GetNormalFont(screen, fNorm)->fs) { 12306 xtermWarning("unable to locate a suitable font\n"); 12307 Exit(ERROR_MISC); 12308 } 12309#if OPT_WIDE_CHARS 12310 if (screen->utf8_mode) { 12311 TRACE(("check if this is a wide font, if not try again\n")); 12312 if (xtermLoadWideFonts(xw, False)) { 12313 SetVTFont(xw, screen->menu_font_number, True, NULL); 12314 /* we will not be able to switch to ISO-8859-1 */ 12315 if (!screen->mergedVTFonts) { 12316 screen->utf8_fonts = uAlways; 12317 update_font_utf8_fonts(); 12318 } 12319 } 12320 } 12321#endif 12322 12323 xtermSetupPointer(xw, screen->pointer_shape); 12324 12325 /* set defaults */ 12326 pos.x = 1; 12327 pos.y = 1; 12328 pos.w = 80; 12329 pos.h = 24; 12330 12331 TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry))); 12332 pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos); 12333 TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w)); 12334 12335 set_max_col(screen, (int) (pos.w - 1)); /* units in character cells */ 12336 set_max_row(screen, (int) (pos.h - 1)); /* units in character cells */ 12337 xtermUpdateFontInfo(xw, False); 12338 12339 pos.w = screen->fullVwin.fullwidth; 12340 pos.h = screen->fullVwin.fullheight; 12341 12342 TRACE(("... BorderWidth: widget %d parent %d shell %d\n", 12343 BorderWidth(xw), 12344 BorderWidth(XtParent(xw)), 12345 BorderWidth(SHELL_OF(xw)))); 12346 12347 if ((pr & XValue) && (XNegative & pr)) { 12348 pos.x = (Position) (pos.x + (pos.scr_w 12349 - (int) pos.w 12350 - (BorderWidth(XtParent(xw)) * 2))); 12351 } 12352 if ((pr & YValue) && (YNegative & pr)) { 12353 pos.y = (Position) (pos.y + (pos.scr_h 12354 - (int) pos.h 12355 - (BorderWidth(XtParent(xw)) * 2))); 12356 } 12357 pos.x = (Position) (pos.x + pos.scr_x); 12358 pos.y = (Position) (pos.y + pos.scr_y); 12359 12360 /* set up size hints for window manager; min 1 char by 1 char */ 12361 getXtermSizeHints(xw); 12362 xtermSizeHints(xw, (xw->misc.scrollbar 12363 ? (screen->scrollWidget->core.width 12364 + BorderWidth(screen->scrollWidget)) 12365 : 0)); 12366 12367 xw->hints.x = pos.x; 12368 xw->hints.y = pos.y; 12369#if OPT_MAXIMIZE 12370 /* assure single-increment resize for fullscreen */ 12371 if (xw->work.ewmh[0].mode) { 12372 xw->hints.width_inc = 1; 12373 xw->hints.height_inc = 1; 12374 } 12375#endif 12376 if ((XValue & pr) || (YValue & pr)) { 12377 xw->hints.flags |= USSize | USPosition; 12378 xw->hints.flags |= PWinGravity; 12379 switch (pr & (XNegative | YNegative)) { 12380 case 0: 12381 xw->hints.win_gravity = NorthWestGravity; 12382 break; 12383 case XNegative: 12384 xw->hints.win_gravity = NorthEastGravity; 12385 break; 12386 case YNegative: 12387 xw->hints.win_gravity = SouthWestGravity; 12388 break; 12389 default: 12390 xw->hints.win_gravity = SouthEastGravity; 12391 break; 12392 } 12393 } else { 12394 /* set a default size, but do *not* set position */ 12395 xw->hints.flags |= PSize; 12396 } 12397 xw->hints.height = xw->hints.base_height 12398 + xw->hints.height_inc * MaxRows(screen); 12399 xw->hints.width = xw->hints.base_width 12400 + xw->hints.width_inc * MaxCols(screen); 12401 12402 if ((WidthValue & pr) || (HeightValue & pr)) 12403 xw->hints.flags |= USSize; 12404 else 12405 xw->hints.flags |= PSize; 12406 12407 /* 12408 * Note that the size-hints are for the shell, while the resize-request 12409 * is for the vt100 widget. They are not the same size. 12410 */ 12411 (void) REQ_RESIZE((Widget) xw, 12412 (Dimension) pos.w, (Dimension) pos.h, 12413 &xw->core.width, &xw->core.height); 12414 12415 /* XXX This is bogus. We are parsing geometries too late. This 12416 * is information that the shell widget ought to have before we get 12417 * realized, so that it can do the right thing. 12418 */ 12419 if (xw->hints.flags & USPosition) 12420 XMoveWindow(XtDisplay(xw), VShellWindow(xw), 12421 xw->hints.x, xw->hints.y); 12422 12423 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 12424 TRACE_HINTS(&xw->hints); 12425 XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints); 12426 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 12427 TRACE_WM_HINTS(xw); 12428 12429 if ((pid_atom = CachedInternAtom(XtDisplay(xw), "_NET_WM_PID")) != None) { 12430 /* XChangeProperty format 32 really is "long" */ 12431 unsigned long pid_l = (unsigned long) getpid(); 12432 TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l)); 12433 XChangeProperty(XtDisplay(xw), VShellWindow(xw), 12434 pid_atom, XA_CARDINAL, 32, PropModeReplace, 12435 (unsigned char *) &pid_l, 1); 12436 } 12437 12438 XFlush(XtDisplay(xw)); /* get it out to window manager */ 12439 12440 /* use ForgetGravity instead of SouthWestGravity because translating 12441 the Expose events for ConfigureNotifys is too hard */ 12442 values->bit_gravity = (GravityIsNorthWest(xw) 12443 ? NorthWestGravity 12444 : ForgetGravity); 12445 screen->fullVwin.window = XtWindow(xw) = 12446 XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)), 12447 xw->core.x, xw->core.y, 12448 xw->core.width, xw->core.height, BorderWidth(xw), 12449 (int) xw->core.depth, 12450 InputOutput, CopyFromParent, 12451 *valuemask | CWBitGravity, values); 12452#if USE_DOUBLE_BUFFER 12453 if (allocateDbe(xw, &(screen->fullVwin))) { 12454 screen->needSwap = 1; 12455 TRACE(("initialized full double-buffering\n")); 12456 } else { 12457 resource.buffered = False; 12458 screen->fullVwin.drawable = screen->fullVwin.window; 12459 } 12460#endif /* USE_DOUBLE_BUFFER */ 12461 screen->event_mask = values->event_mask; 12462 12463#ifndef NO_ACTIVE_ICON 12464 /* 12465 * Normally, the font-number for icon fonts does not correspond with any of 12466 * the menu-selectable fonts. If we cannot load the font given for the 12467 * iconFont resource, try with font1 aka "Unreadable". 12468 */ 12469 screen->icon_fontnum = -1; 12470 if (getIconicFont(screen)->fs == NULL) { 12471 getIconicFont(screen)->fs = 12472 xtermLoadQueryFont(xw, screen->MenuFontName(fontMenu_font1)); 12473 ReportIcons(("%susing font1 '%s' as iconFont\n", 12474 (getIconicFont(screen)->fs 12475 ? "" 12476 : "NOT "), 12477 screen->MenuFontName(fontMenu_font1))); 12478 } 12479#if OPT_RENDERFONT 12480 /* 12481 * If we still have no result from iconFont resource (perhaps because fonts 12482 * are missing) but are using Xft, try to use that instead. We prefer 12483 * bitmap fonts in any case, since scaled fonts are usually less readable, 12484 * particularly at small sizes. 12485 */ 12486 if (UsingRenderFont(xw) 12487 && getIconicFont(screen)->fs == NULL) { 12488 screen->icon_fontnum = fontMenu_default; 12489 getIconicFont(screen)->fs = GetNormalFont(screen, fNorm)->fs; /* need for next-if */ 12490 ReportIcons(("using TrueType font as iconFont\n")); 12491 } 12492#endif 12493 xw->work.wm_name = getWindowManagerName(xw); 12494 if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) { 12495 ReportIcons(("window manager name is %s\n", xw->work.wm_name)); 12496 if (x_strncasecmp(xw->work.wm_name, "fvwm", 4) && 12497 x_strncasecmp(xw->work.wm_name, "window maker", 12)) { 12498 xw->work.active_icon = eiFalse; 12499 TRACE(("... disable active_icon\n")); 12500 } 12501 } 12502 TRACE((".. if active_icon (%d), get its font\n", xw->work.active_icon)); 12503 if (xw->work.active_icon && getIconicFont(screen)->fs) { 12504 int iconX = 0, iconY = 0; 12505 Widget shell = SHELL_OF(xw); 12506 VTwin *win = &(screen->iconVwin); 12507 int save_fontnum = screen->menu_font_number; 12508 12509 ReportIcons(("initializing active-icon %d\n", screen->icon_fontnum)); 12510 screen->menu_font_number = screen->icon_fontnum; 12511 XtVaGetValues(shell, 12512 XtNiconX, &iconX, 12513 XtNiconY, &iconY, 12514 (XtPointer) 0); 12515 xtermComputeFontInfo(xw, &(screen->iconVwin), 12516 getIconicFont(screen)->fs, 0); 12517 screen->menu_font_number = save_fontnum; 12518 12519 /* since only one client is permitted to select for Button 12520 * events, we have to let the window manager get 'em... 12521 */ 12522 values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask); 12523 values->border_pixel = xw->misc.icon_border_pixel; 12524 12525 screen->iconVwin.window = 12526 XCreateWindow(XtDisplay(xw), 12527 RootWindowOfScreen(XtScreen(shell)), 12528 iconX, iconY, 12529 screen->iconVwin.fullwidth, 12530 screen->iconVwin.fullheight, 12531 xw->misc.icon_border_width, 12532 (int) xw->core.depth, 12533 InputOutput, CopyFromParent, 12534 *valuemask | CWBitGravity | CWBorderPixel, 12535 values); 12536#if USE_DOUBLE_BUFFER 12537 if (allocateDbe(xw, &(screen->iconVwin))) { 12538 TRACE(("initialized icon double-buffering\n")); 12539 } else { 12540 resource.buffered = False; 12541 screen->iconVwin.drawable = screen->iconVwin.window; 12542 screen->fullVwin.drawable = screen->fullVwin.window; 12543 } 12544#endif /* USE_DOUBLE_BUFFER */ 12545 XtVaSetValues(shell, 12546 XtNiconWindow, screen->iconVwin.window, 12547 (XtPointer) 0); 12548 XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w); 12549 12550 setCgsFont(xw, win, gcNorm, getIconicFont(screen)); 12551 setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG)); 12552 setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG)); 12553 12554 copyCgs(xw, win, gcBold, gcNorm); 12555 12556 setCgsFont(xw, win, gcNormReverse, getIconicFont(screen)); 12557 setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG)); 12558 setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG)); 12559 12560 copyCgs(xw, win, gcBoldReverse, gcNormReverse); 12561 12562 initBorderGC(xw, win); 12563 } else { 12564 ReportIcons(("disabled active-icon\n")); 12565 xw->work.active_icon = eiFalse; 12566 } 12567#if OPT_TOOLBAR 12568 update_activeicon(); 12569#endif 12570#endif /* NO_ACTIVE_ICON */ 12571 12572#if OPT_INPUT_METHOD 12573 VTInitI18N(xw); 12574#endif 12575#if OPT_NUM_LOCK 12576 VTInitModifiers(xw); 12577#if OPT_EXTRA_PASTE 12578 if (xw->keyboard.extra_translations) { 12579 XtOverrideTranslations((Widget) xw, 12580 XtParseTranslationTable(xw->keyboard.extra_translations)); 12581 } 12582#endif 12583#endif 12584 12585 set_cursor_gcs(xw); 12586 initBorderGC(xw, &(screen->fullVwin)); 12587 12588 /* Reset variables used by ANSI emulation. */ 12589 12590 resetCharsets(screen); 12591 12592 XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor); 12593 12594 set_cur_col(screen, 0); 12595 set_cur_row(screen, 0); 12596 set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1); 12597 set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1); 12598 resetMarginMode(xw); 12599 12600 memset(screen->sc, 0, sizeof(screen->sc)); 12601 12602 /* Mark screen buffer as unallocated. We wait until the run loop so 12603 that the child process does not fork and exec with all the dynamic 12604 memory it will never use. If we were to do it here, the 12605 swap space for new process would be huge for huge savelines. */ 12606#if OPT_TEK4014 12607 if (!tekWidget) /* if not called after fork */ 12608#endif 12609 { 12610 screen->visbuf = NULL; 12611 screen->saveBuf_index = NULL; 12612 } 12613 12614 ResetWrap(screen); 12615 screen->scrolls = screen->incopy = 0; 12616 xtermSetCursorBox(screen); 12617 12618 screen->savedlines = 0; 12619 12620 for (i = 0; i < 2; ++i) { 12621 screen->whichBuf = !screen->whichBuf; 12622 CursorSave(xw); 12623 } 12624 12625#ifndef NO_ACTIVE_ICON 12626 if (!xw->work.active_icon) 12627#endif 12628 xtermLoadIcon(xw, resource.icon_hint); 12629 12630 /* 12631 * Do this last, since it may change the layout via a resize. 12632 */ 12633 if (xw->misc.scrollbar) { 12634 screen->fullVwin.sb_info.width = 0; 12635 ScrollBarOn(xw, False); 12636 } 12637 12638 xtermSetWinSize(xw); 12639 TRACE(("" TRACE_R " VTRealize\n")); 12640} 12641 12642#if OPT_INPUT_METHOD 12643 12644/* limit this feature to recent XFree86 since X11R6.x core dumps */ 12645#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING) 12646#define USE_XIM_INSTANTIATE_CB 12647 12648static void 12649xim_instantiate_cb(Display *display, 12650 XPointer client_data GCC_UNUSED, 12651 XPointer call_data GCC_UNUSED) 12652{ 12653 XtermWidget xw = term; 12654 12655 TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data)); 12656 12657 if (display == XtDisplay(xw)) { 12658 VTInitI18N(xw); 12659 } 12660} 12661 12662static void 12663xim_destroy_cb(XIM im GCC_UNUSED, 12664 XPointer client_data GCC_UNUSED, 12665 XPointer call_data GCC_UNUSED) 12666{ 12667 XtermWidget xw = term; 12668 TInput *input = lookupTInput(xw, (Widget) xw); 12669 12670 TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n", 12671 (long) im, client_data, call_data)); 12672 if (input) 12673 input->xic = NULL; 12674 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 12675 xim_instantiate_cb, NULL); 12676} 12677#endif /* X11R6+ */ 12678 12679static Boolean 12680xim_create_fs(XtermWidget xw) 12681{ 12682 XFontStruct **fonts; 12683 char **font_name_list; 12684 char **missing_charset_list; 12685 char *def_string; 12686 int missing_charset_count; 12687 unsigned i, j; 12688 12689 if (xw->work.xim_fs == NULL) { 12690 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 12691 xw->misc.f_x, 12692 &missing_charset_list, 12693 &missing_charset_count, 12694 &def_string); 12695 if (xw->work.xim_fs == NULL) { 12696 xtermWarning("Preparation of font set " 12697 "\"%s\" for XIM failed.\n", xw->misc.f_x); 12698 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 12699 DEFXIMFONT, 12700 &missing_charset_list, 12701 &missing_charset_count, 12702 &def_string); 12703 } 12704 } 12705 if (xw->work.xim_fs == NULL) { 12706 xtermWarning("Preparation of default font set " 12707 "\"%s\" for XIM failed.\n", DEFXIMFONT); 12708 cleanupInputMethod(xw); 12709 xw->work.cannot_im = True; 12710 } else { 12711 (void) XExtentsOfFontSet(xw->work.xim_fs); 12712 j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list); 12713 for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) { 12714 if (xw->work.xim_fs_ascent < (*fonts)->ascent) 12715 xw->work.xim_fs_ascent = (*fonts)->ascent; 12716 } 12717 } 12718 return (Boolean) !(xw->work.cannot_im); 12719} 12720 12721static void 12722xim_create_xic(XtermWidget xw, Widget theInput) 12723{ 12724 Display *myDisplay = XtDisplay(theInput); 12725 Window myWindow = XtWindow(theInput); 12726 unsigned i, j; 12727 char *p = NULL, *s, *t, *ns, *end, buf[32]; 12728 XIMStyles *xim_styles; 12729 XIMStyle input_style = 0; 12730 Bool found; 12731 static struct { 12732 const char *name; 12733 unsigned long code; 12734 } known_style[] = { 12735 { 12736 "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing) 12737 }, 12738 { 12739 "OffTheSpot", (XIMPreeditArea | XIMStatusArea) 12740 }, 12741 { 12742 "Root", (XIMPreeditNothing | XIMStatusNothing) 12743 }, 12744 }; 12745 TInput *input = lookupTInput(xw, theInput); 12746 12747 if (xw->work.cannot_im) { 12748 return; 12749 } 12750 12751 if (input == NULL) { 12752 for (i = 0; i < NINPUTWIDGETS; ++i) { 12753 if (xw->work.inputs[i].w == NULL) { 12754 input = xw->work.inputs + i; 12755 input->w = theInput; 12756 break; 12757 } 12758 } 12759 } 12760 12761 if (input == NULL) { 12762 xtermWarning("attempted to add too many input widgets\n"); 12763 return; 12764 } 12765 12766 TRACE(("xim_real_init\n")); 12767 12768 if (IsEmpty(xw->misc.input_method)) { 12769 if ((p = XSetLocaleModifiers("")) != NULL && *p) { 12770 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 12771 } 12772 } else { 12773 s = xw->misc.input_method; 12774 i = 5 + (unsigned) strlen(s); 12775 12776 t = (char *) MyStackAlloc(i, buf); 12777 if (t == NULL) { 12778 SysError(ERROR_VINIT); 12779 } else { 12780 12781 for (ns = s; ns && *s;) { 12782 while (*s && isspace(CharOf(*s))) 12783 s++; 12784 if (!*s) 12785 break; 12786 if ((ns = end = strchr(s, ',')) == NULL) 12787 end = s + strlen(s); 12788 while ((end != s) && isspace(CharOf(end[-1]))) 12789 end--; 12790 12791 if (end != s) { 12792 strcpy(t, "@im="); 12793 strncat(t, s, (size_t) (end - s)); 12794 12795 if ((p = XSetLocaleModifiers(t)) != NULL && *p 12796 && (input->xim = XOpenIM(myDisplay, 12797 NULL, 12798 NULL, 12799 NULL)) != NULL) { 12800 break; 12801 } 12802 12803 } 12804 s = ns + 1; 12805 } 12806 MyStackFree(t, buf); 12807 } 12808 } 12809 12810 if (input->xim == NULL 12811 && (p = XSetLocaleModifiers("@im=none")) != NULL 12812 && *p) { 12813 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 12814 } 12815 12816 if (!input->xim) { 12817 xtermWarning("Failed to open input method\n"); 12818 return; 12819 } 12820 TRACE(("VTInitI18N opened input method:%s\n", NonNull(p))); 12821 12822 if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0) 12823 || !xim_styles 12824 || !xim_styles->count_styles) { 12825 xtermWarning("input method doesn't support any style\n"); 12826 cleanupInputMethod(xw); 12827 xw->work.cannot_im = True; 12828 return; 12829 } 12830 12831 found = False; 12832 for (s = xw->misc.preedit_type; s && !found;) { 12833 while (*s && isspace(CharOf(*s))) 12834 s++; 12835 if (!*s) 12836 break; 12837 if ((ns = end = strchr(s, ',')) != NULL) 12838 ns++; 12839 else 12840 end = s + strlen(s); 12841 while ((end != s) && isspace(CharOf(end[-1]))) 12842 end--; 12843 12844 if (end != s) { /* just in case we have a spurious comma */ 12845 TRACE(("looking for style '%.*s'\n", (int) (end - s), s)); 12846 for (i = 0; i < XtNumber(known_style); i++) { 12847 if ((int) strlen(known_style[i].name) == (end - s) 12848 && !strncmp(s, known_style[i].name, (size_t) (end - s))) { 12849 input_style = known_style[i].code; 12850 for (j = 0; j < xim_styles->count_styles; j++) { 12851 if (input_style == xim_styles->supported_styles[j]) { 12852 found = True; 12853 break; 12854 } 12855 } 12856 if (found) 12857 break; 12858 } 12859 } 12860 } 12861 12862 s = ns; 12863 } 12864 XFree(xim_styles); 12865 12866 if (!found) { 12867 xtermWarning("input method doesn't support my preedit type (%s)\n", 12868 xw->misc.preedit_type); 12869 cleanupInputMethod(xw); 12870 xw->work.cannot_im = True; 12871 return; 12872 } 12873 12874 /* 12875 * Check for styles we do not yet support. 12876 */ 12877 TRACE(("input_style %#lx\n", input_style)); 12878 if (input_style == (XIMPreeditArea | XIMStatusArea)) { 12879 xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n"); 12880 cleanupInputMethod(xw); 12881 xw->work.cannot_im = True; 12882 return; 12883 } 12884 12885 /* 12886 * For XIMPreeditPosition (or OverTheSpot), XIM client has to 12887 * prepare a font. 12888 * The font has to be locale-dependent XFontSet, whereas 12889 * XTerm use Unicode font. This leads a problem that the 12890 * same font cannot be used for XIM preedit. 12891 */ 12892 if (input_style != (XIMPreeditNothing | XIMStatusNothing)) { 12893 XVaNestedList p_list; 12894 XPoint spot = 12895 {0, 0}; 12896 12897 if (xim_create_fs(xw)) { 12898 p_list = XVaCreateNestedList(0, 12899 XNSpotLocation, &spot, 12900 XNFontSet, xw->work.xim_fs, 12901 (void *) 0); 12902 input->xic = XCreateIC(input->xim, 12903 XNInputStyle, input_style, 12904 XNClientWindow, myWindow, 12905 XNFocusWindow, myWindow, 12906 XNPreeditAttributes, p_list, 12907 (void *) 0); 12908 } 12909 } else { 12910 input->xic = XCreateIC(input->xim, XNInputStyle, input_style, 12911 XNClientWindow, myWindow, 12912 XNFocusWindow, myWindow, 12913 (void *) 0); 12914 } 12915 12916 if (!input->xic) { 12917 xtermWarning("Failed to create input context\n"); 12918 cleanupInputMethod(xw); 12919 } 12920#if defined(USE_XIM_INSTANTIATE_CB) 12921 else { 12922 XIMCallback destroy_cb; 12923 12924 destroy_cb.callback = xim_destroy_cb; 12925 destroy_cb.client_data = NULL; 12926 if (XSetIMValues(input->xim, 12927 XNDestroyCallback, 12928 &destroy_cb, 12929 (void *) 0)) { 12930 xtermWarning("Could not set destroy callback to IM\n"); 12931 } 12932 } 12933#endif 12934 12935 return; 12936} 12937 12938static void 12939xim_real_init(XtermWidget xw) 12940{ 12941 xim_create_xic(xw, (Widget) xw); 12942} 12943 12944static void 12945VTInitI18N(XtermWidget xw) 12946{ 12947 if (xw->misc.open_im) { 12948 xim_real_init(xw); 12949 12950#if defined(USE_XIM_INSTANTIATE_CB) 12951 if (lookupTInput(xw, (Widget) xw) == NULL 12952 && !xw->work.cannot_im 12953 && xw->misc.retry_im-- > 0) { 12954 sleep(3); 12955 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 12956 xim_instantiate_cb, NULL); 12957 } 12958#endif 12959 } 12960} 12961 12962TInput * 12963lookupTInput(XtermWidget xw, Widget w) 12964{ 12965 TInput *result = NULL; 12966 unsigned n; 12967 12968 for (n = 0; n < NINPUTWIDGETS; ++n) { 12969 if (xw->work.inputs[n].w == w) { 12970 result = xw->work.inputs + n; 12971 break; 12972 } 12973 } 12974 12975 return result; 12976} 12977#endif /* OPT_INPUT_METHOD */ 12978 12979static void 12980set_cursor_outline_gc(XtermWidget xw, 12981 Bool filled, 12982 Pixel fg, 12983 Pixel bg, 12984 Pixel cc) 12985{ 12986 TScreen *screen = TScreenOf(xw); 12987 VTwin *win = WhichVWin(screen); 12988 CgsEnum cgsId = gcVTcursOutline; 12989 12990 if (cc == bg) 12991 cc = fg; 12992 12993 if (filled) { 12994 setCgsFore(xw, win, cgsId, bg); 12995 setCgsBack(xw, win, cgsId, cc); 12996 } else { 12997 setCgsFore(xw, win, cgsId, cc); 12998 setCgsBack(xw, win, cgsId, bg); 12999 } 13000} 13001 13002static Boolean 13003VTSetValues(Widget cur, 13004 Widget request GCC_UNUSED, 13005 Widget wnew, 13006 ArgList args GCC_UNUSED, 13007 Cardinal *num_args GCC_UNUSED) 13008{ 13009 XtermWidget curvt = (XtermWidget) cur; 13010 XtermWidget newvt = (XtermWidget) wnew; 13011 Boolean refresh_needed = False; 13012 Boolean fonts_redone = False; 13013 13014 if ((T_COLOR(TScreenOf(curvt), TEXT_BG) != 13015 T_COLOR(TScreenOf(newvt), TEXT_BG)) || 13016 (T_COLOR(TScreenOf(curvt), TEXT_FG) != 13017 T_COLOR(TScreenOf(newvt), TEXT_FG)) || 13018 (TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) != 13019 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) || 13020 strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) { 13021 if (strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) { 13022 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt); 13023 } 13024 if (xtermLoadFont(newvt, 13025 xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)), 13026 True, TScreenOf(newvt)->menu_font_number)) { 13027 /* resizing does the redisplay, so don't ask for it here */ 13028 refresh_needed = True; 13029 fonts_redone = True; 13030 } else if (strcmp(NonNull(DefaultFontN(curvt)), NonNull(DefaultFontN(newvt)))) { 13031 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt); 13032 } 13033 } 13034 if (!fonts_redone 13035 && (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) != 13036 T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) { 13037 if (set_cursor_gcs(newvt)) 13038 refresh_needed = True; 13039 } 13040 if (curvt->misc.re_verse != newvt->misc.re_verse) { 13041 newvt->flags ^= REVERSE_VIDEO; 13042 ReverseVideo(newvt); 13043 /* ReverseVideo toggles */ 13044 newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse); 13045 refresh_needed = True; 13046 } 13047 if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) != 13048 T_COLOR(TScreenOf(newvt), MOUSE_FG)) || 13049 (T_COLOR(TScreenOf(curvt), MOUSE_BG) != 13050 T_COLOR(TScreenOf(newvt), MOUSE_BG))) { 13051 recolor_cursor(TScreenOf(newvt), 13052 TScreenOf(newvt)->pointer_cursor, 13053 T_COLOR(TScreenOf(newvt), MOUSE_FG), 13054 T_COLOR(TScreenOf(newvt), MOUSE_BG)); 13055 refresh_needed = True; 13056 } 13057 if (curvt->misc.scrollbar != newvt->misc.scrollbar) { 13058 ToggleScrollBar(newvt); 13059 } 13060 13061 return refresh_needed; 13062} 13063 13064/* 13065 * Given a font-slot and information about selection/reverse, find the 13066 * corresponding cached-GC slot. 13067 */ 13068#if OPT_WIDE_ATTRS 13069static int 13070reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font) 13071{ 13072 TScreen *screen = TScreenOf(xw); 13073 CgsEnum result = gcMAX; 13074 13075 (void) screen; 13076 if (ReverseOrHilite(screen, attr_flags, hilite)) { 13077 switch (font) { 13078 case fNorm: 13079 result = gcNormReverse; 13080 break; 13081 case fBold: 13082 result = gcBoldReverse; 13083 break; 13084#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 13085 case fItal: 13086 result = gcNormReverse; /* FIXME */ 13087 break; 13088#endif 13089#if OPT_WIDE_CHARS 13090 case fWide: 13091 result = gcWideReverse; 13092 break; 13093 case fWBold: 13094 result = gcWBoldReverse; 13095 break; 13096 case fWItal: 13097 result = gcWideReverse; /* FIXME */ 13098 break; 13099#endif 13100 } 13101 } else { 13102 switch (font) { 13103 case fNorm: 13104 result = gcNorm; 13105 break; 13106 case fBold: 13107 result = gcBold; 13108 break; 13109#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 13110 case fItal: 13111 result = gcNorm; /* FIXME */ 13112 break; 13113#endif 13114#if OPT_WIDE_CHARS 13115 case fWide: 13116 result = gcWide; 13117 break; 13118 case fWBold: 13119 result = gcWBold; 13120 break; 13121 case fWItal: 13122 result = gcWide; /* FIXME */ 13123 break; 13124#endif 13125 } 13126 } 13127 return (int) result; 13128} 13129#endif 13130 13131#define setGC(code) set_at = __LINE__, currentCgs = code 13132 13133#define OutsideSelection(screen,srow,scol) \ 13134 ((srow) > (screen)->endH.row || \ 13135 ((srow) == (screen)->endH.row && \ 13136 (scol) >= (screen)->endH.col) || \ 13137 (srow) < (screen)->startH.row || \ 13138 ((srow) == (screen)->startH.row && \ 13139 (scol) < (screen)->startH.col)) 13140 13141/* 13142 * Shows cursor at new cursor position in screen. 13143 */ 13144void 13145ShowCursor(XtermWidget xw) 13146{ 13147 TScreen *screen = TScreenOf(xw); 13148 XTermDraw params; 13149 IChar base; 13150 unsigned flags; 13151 CellColor fg_bg = initCColor; 13152 GC currentGC; 13153 GC outlineGC; 13154 CgsEnum currentCgs = gcMAX; 13155 VTwin *currentWin = WhichVWin(screen); 13156 int set_at; 13157 Bool in_selection; 13158 Bool reversed; 13159 Bool filled; 13160 Pixel fg_pix; 13161 Pixel bg_pix; 13162 Pixel tmp; 13163#if OPT_HIGHLIGHT_COLOR 13164 Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG); 13165 Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG); 13166 Boolean use_selbg; 13167 Boolean use_selfg; 13168#endif 13169#if OPT_WIDE_CHARS 13170 int my_col = 0; 13171#endif 13172 int cursor_col; 13173 CLineData *ld = NULL; 13174 13175 if (screen->cursor_state == BLINKED_OFF) 13176 return; 13177 13178 if (screen->eventMode != NORMAL) 13179 return; 13180 13181 if (INX2ROW(screen, screen->cur_row) > screen->max_row) 13182 return; 13183 13184 screen->cursorp.row = screen->cur_row; 13185 cursor_col = screen->cursorp.col = screen->cur_col; 13186 screen->cursor_moved = False; 13187 13188#ifndef NO_ACTIVE_ICON 13189 if (IsIcon(screen)) { 13190 screen->cursor_state = ON; 13191 return; 13192 } 13193#endif /* NO_ACTIVE_ICON */ 13194 13195 ld = getLineData(screen, screen->cur_row); 13196 13197 base = ld->charData[cursor_col]; 13198 flags = ld->attribs[cursor_col]; 13199 13200 if_OPT_WIDE_CHARS(screen, { 13201 if (base == HIDDEN_CHAR && cursor_col > 0) { 13202 /* if cursor points to non-initial part of wide character, 13203 * back it up 13204 */ 13205 --cursor_col; 13206 base = ld->charData[cursor_col]; 13207 } 13208 my_col = cursor_col; 13209 if (base == 0) 13210 base = ' '; 13211 if (isWide((int) base)) 13212 my_col += 1; 13213 }); 13214 13215 if (base == 0) { 13216 base = ' '; 13217 } 13218#if OPT_ISO_COLORS 13219#ifdef EXP_BOGUS_FG 13220 /* 13221 * If the cursor happens to be on blanks, and we have not set both 13222 * foreground and background color, do not treat it as a colored cell. 13223 */ 13224 if (base == ' ') { 13225 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 13226 TRACE(("ShowCursor - do not treat as a colored cell\n")); 13227 flags &= ~(FG_COLOR | BG_COLOR); 13228 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 13229 TRACE(("ShowCursor - should we treat as a colored cell?\n")); 13230 if (!(xw->flags & FG_COLOR)) { 13231 if (CheckBogusForeground(screen, "ShowCursor")) { 13232 flags &= ~(FG_COLOR | BG_COLOR); 13233 } 13234 } 13235 } 13236 } 13237#else /* !EXP_BOGUS_FG */ 13238 /* 13239 * If the cursor happens to be on blanks, and the foreground color is set 13240 * but not the background, do not treat it as a colored cell. 13241 */ 13242 if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR 13243 && base == ' ') { 13244 flags &= ~TERM_COLOR_FLAGS(xw); 13245 } 13246#endif 13247#endif 13248 13249 /* 13250 * Compare the current cell to the last set of colors used for the 13251 * cursor and update the GC's if needed. 13252 */ 13253 (void) fg_bg; 13254 if_OPT_ISO_COLORS(screen, { 13255 fg_bg = ld->color[cursor_col]; 13256 }); 13257 13258 fg_pix = getXtermFG(xw, flags, (int) extract_fg(xw, fg_bg, flags)); 13259 bg_pix = getXtermBG(xw, flags, (int) extract_bg(xw, fg_bg, flags)); 13260 13261 /* 13262 * If we happen to have the same foreground/background colors, choose 13263 * a workable foreground color from which we can obtain a visible cursor. 13264 */ 13265 if (fg_pix == bg_pix) { 13266 long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG)); 13267 long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG)); 13268 if (bg_diff < 0) 13269 bg_diff = -bg_diff; 13270 if (fg_diff < 0) 13271 fg_diff = -fg_diff; 13272 if (bg_diff < fg_diff) { 13273 fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG); 13274 } else { 13275 fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG); 13276 } 13277 } 13278 13279 if (OutsideSelection(screen, screen->cur_row, screen->cur_col)) 13280 in_selection = False; 13281 else 13282 in_selection = True; 13283 13284 reversed = ReverseOrHilite(screen, flags, in_selection); 13285 13286 /* This is like updatedXtermGC(), except that we have to worry about 13287 * whether the window has focus, since in that case we want just an 13288 * outline for the cursor. 13289 */ 13290 filled = (screen->select || screen->always_highlight) && isCursorBlock(screen); 13291#if OPT_HIGHLIGHT_COLOR 13292 use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix); 13293 use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix); 13294#endif 13295 if (filled) { 13296 if (reversed) { /* text is reverse video */ 13297 if (getCgsGC(xw, currentWin, gcVTcursNormal)) { 13298 setGC(gcVTcursNormal); 13299 } else { 13300 if (flags & BOLDATTR(screen)) { 13301 setGC(gcBold); 13302 } else { 13303 setGC(gcNorm); 13304 } 13305 } 13306 EXCHANGE(fg_pix, bg_pix, tmp); 13307#if OPT_HIGHLIGHT_COLOR 13308 if (screen->hilite_reverse) { 13309 if (use_selbg && !use_selfg) 13310 fg_pix = bg_pix; 13311 if (use_selfg && !use_selbg) 13312 bg_pix = fg_pix; 13313 if (use_selbg) 13314 bg_pix = selbg_pix; 13315 if (use_selfg) 13316 fg_pix = selfg_pix; 13317 } 13318#endif 13319 } else { /* normal video */ 13320 if (getCgsGC(xw, currentWin, gcVTcursReverse)) { 13321 setGC(gcVTcursReverse); 13322 } else { 13323 if (flags & BOLDATTR(screen)) { 13324 setGC(gcBoldReverse); 13325 } else { 13326 setGC(gcNormReverse); 13327 } 13328 } 13329 } 13330 13331#define CUR_XX T_COLOR(screen, TEXT_CURSOR) 13332#define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 13333#define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 13334 13335#define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground)) 13336#define FIX_328 (CUR_XX == bg_pix) 13337#define FIX_330 (FIX_328 && reversed && in_selection) 13338 13339 if (FIX_330 || FIX_311) { 13340 setCgsBack(xw, currentWin, currentCgs, fg_pix); 13341 } 13342 setCgsFore(xw, currentWin, currentCgs, bg_pix); 13343 } else { /* not selected */ 13344 if (reversed) { /* text is reverse video */ 13345 EXCHANGE(fg_pix, bg_pix, tmp); 13346 setGC(gcNormReverse); 13347 } else { /* normal video */ 13348 setGC(gcNorm); 13349 } 13350#if OPT_HIGHLIGHT_COLOR 13351 if (screen->hilite_reverse) { 13352 if (in_selection && !reversed) { 13353 /* EMPTY */ 13354 /* really INVERSE ... */ 13355 ; 13356 } else if (in_selection || reversed) { 13357 if (use_selbg) { 13358 if (use_selfg) { 13359 bg_pix = fg_pix; 13360 } else { 13361 fg_pix = bg_pix; 13362 bg_pix = selbg_pix; 13363 } 13364 } 13365 if (use_selfg) { 13366 fg_pix = selfg_pix; 13367 } 13368 } 13369 } else { 13370 if (in_selection) { 13371 if (use_selbg) { 13372 bg_pix = selbg_pix; 13373 } 13374 if (use_selfg) { 13375 fg_pix = selfg_pix; 13376 } 13377 } 13378 } 13379#endif 13380 setCgsFore(xw, currentWin, currentCgs, fg_pix); 13381 setCgsBack(xw, currentWin, currentCgs, bg_pix); 13382 } 13383 13384 if (screen->cursor_busy == 0 13385 && (screen->cursor_state != ON || screen->cursor_GC != set_at)) { 13386 int x, y; 13387 13388 screen->cursor_GC = set_at; 13389 TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n", 13390 screen->cur_row, screen->cur_col, 13391 (filled ? "filled" : "outline"), 13392 (isCursorBlock(screen) ? "box" : 13393 isCursorUnderline(screen) ? "underline" : "bar"), 13394 set_at)); 13395 13396 currentGC = getCgsGC(xw, currentWin, currentCgs); 13397 x = LineCursorX(screen, ld, cursor_col); 13398 y = CursorY(screen, screen->cur_row); 13399 13400 if (!isCursorBlock(screen)) { 13401 /* 13402 * Overriding the combination of filled, reversed, in_selection is 13403 * too complicated since the underline or bar and the text-cell use 13404 * different rules. Just redraw the text-cell, and draw the 13405 * underline or bar on top of it. 13406 */ 13407 HideCursor(xw); 13408 13409 /* 13410 * Our current-GC is likely to have been modified in HideCursor(). 13411 * Set up a new request. 13412 */ 13413 if (filled) { 13414 if (FIX_330 || FIX_311) { 13415 setCgsBack(xw, currentWin, currentCgs, fg_pix); 13416 } 13417 setCgsFore(xw, currentWin, currentCgs, bg_pix); 13418 } else { 13419 setCgsFore(xw, currentWin, currentCgs, fg_pix); 13420 setCgsBack(xw, currentWin, currentCgs, bg_pix); 13421 } 13422 } 13423 13424 /* 13425 * Update the outline-gc, to keep the cursor color distinct from the 13426 * background color. 13427 */ 13428 set_cursor_outline_gc(xw, 13429 filled, 13430 fg_pix, 13431 bg_pix, 13432 T_COLOR(screen, TEXT_CURSOR)); 13433 13434 outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline); 13435 if (outlineGC == NULL) 13436 outlineGC = currentGC; 13437 13438 if (isCursorUnderline(screen)) { 13439 13440 /* 13441 * Finally, draw the underline. 13442 */ 13443 screen->box->x = (short) x; 13444 screen->box->y = (short) (y 13445 + FontHeight(screen) 13446 - screen->box[2].y); 13447 XFillRectangle(screen->display, VDrawable(screen), outlineGC, 13448 screen->box->x, 13449 screen->box->y, 13450 (unsigned) screen->box[1].x, 13451 (unsigned) screen->box[2].y); 13452 } else if (isCursorBar(screen)) { 13453 13454 /* 13455 * Or draw the bar. 13456 */ 13457 screen->box->x = (short) x; 13458 screen->box->y = (short) y; 13459 XFillRectangle(screen->display, VDrawable(screen), outlineGC, 13460 screen->box->x, 13461 screen->box->y, 13462 (unsigned) screen->box[1].x, 13463 (unsigned) screen->box[2].y); 13464 } else { 13465#if OPT_WIDE_ATTRS 13466 int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0); 13467 int italics_off = ((xw->flags & ATR_ITALIC) != 0); 13468 int fix_italics = (italics_on != italics_off); 13469 int which_font = ((xw->flags & BOLD) ? fBold : fNorm); 13470 MyGetFont getter = italics_on ? getItalicFont : getNormalFont; 13471 13472 if_OPT_WIDE_CHARS(screen, { 13473 if (isWide((int) base)) { 13474 which_font = ((xw->flags & BOLD) ? fWBold : fWide); 13475 } 13476 }); 13477 13478 if (fix_italics && UseItalicFont(screen)) { 13479 xtermLoadItalics(xw); 13480 setCgsFont(xw, currentWin, currentCgs, 13481 getter(screen, which_font)); 13482 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 13483 ? getItalicFont 13484 : getNormalFont); 13485 } 13486 currentGC = getCgsGC(xw, currentWin, currentCgs); 13487#endif /* OPT_WIDE_ATTRS */ 13488 13489 /* *INDENT-EQLS* */ 13490 params.xw = xw; 13491 params.attr_flags = (flags & DRAWX_MASK); 13492 params.draw_flags = 0; 13493 params.this_chrset = LineCharSet(screen, ld); 13494 params.real_chrset = CSET_SWL; 13495 params.on_wide = 0; 13496 13497 drawXtermText(¶ms, 13498 currentGC, x, y, 13499 &base, 1); 13500 13501#if OPT_WIDE_CHARS 13502 if_OPT_WIDE_CHARS(screen, { 13503 size_t off; 13504 13505 /* *INDENT-EQLS* */ 13506 params.draw_flags = NOBACKGROUND; 13507 params.on_wide = isWide((int) base); 13508 13509 for_each_combData(off, ld) { 13510 if (!(ld->combData[off][my_col])) 13511 break; 13512 drawXtermText(¶ms, 13513 currentGC, x, y, 13514 ld->combData[off] + my_col, 1); 13515 } 13516 }); 13517#endif 13518 13519 if (!filled) { 13520 screen->box->x = (short) x; 13521 screen->box->y = (short) y; 13522 XDrawLines(screen->display, VDrawable(screen), outlineGC, 13523 screen->box, NBOX, CoordModePrevious); 13524 } 13525#if OPT_WIDE_ATTRS 13526 if (fix_italics && UseItalicFont(screen)) { 13527 setCgsFont(xw, currentWin, currentCgs, 13528 getter(screen, which_font)); 13529 } 13530#endif 13531 } 13532 } 13533 screen->cursor_state = ON; 13534 13535 return; 13536} 13537 13538/* 13539 * hide cursor at previous cursor position in screen. 13540 */ 13541void 13542HideCursor(XtermWidget xw) 13543{ 13544 TScreen *screen = TScreenOf(xw); 13545 XTermDraw params; 13546 GC currentGC; 13547 int x, y; 13548 IChar base; 13549 unsigned flags; 13550 CellColor fg_bg = initCColor; 13551 Bool in_selection; 13552#if OPT_WIDE_CHARS 13553 int my_col = 0; 13554#endif 13555 int cursor_col; 13556 CLineData *ld = NULL; 13557#if OPT_WIDE_ATTRS 13558 int which_Cgs = gcMAX; 13559 unsigned attr_flags; 13560 int which_font = fNorm; 13561 MyGetFont getter = getNormalFont; 13562#endif 13563 13564 if (screen->cursor_state == OFF) 13565 return; 13566 if (INX2ROW(screen, screen->cursorp.row) > screen->max_row) 13567 return; 13568 13569 cursor_col = screen->cursorp.col; 13570 13571#ifndef NO_ACTIVE_ICON 13572 if (IsIcon(screen)) { 13573 screen->cursor_state = OFF; 13574 return; 13575 } 13576#endif /* NO_ACTIVE_ICON */ 13577 13578 ld = getLineData(screen, screen->cursorp.row); 13579 13580 base = ld->charData[cursor_col]; 13581 flags = ld->attribs[cursor_col]; 13582 13583 if_OPT_WIDE_CHARS(screen, { 13584 if (base == HIDDEN_CHAR && cursor_col > 0) { 13585 /* if cursor points to non-initial part of wide character, 13586 * back it up 13587 */ 13588 --cursor_col; 13589 base = ld->charData[cursor_col]; 13590 } 13591 my_col = cursor_col; 13592 if (base == 0) 13593 base = ' '; 13594 if (isWide((int) base)) 13595 my_col += 1; 13596 }); 13597 13598 if (base == 0) { 13599 base = ' '; 13600 } 13601#ifdef EXP_BOGUS_FG 13602 /* 13603 * If the cursor happens to be on blanks, and we have not set both 13604 * foreground and background color, do not treat it as a colored cell. 13605 */ 13606#if OPT_ISO_COLORS 13607 if (base == ' ') { 13608 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 13609 TRACE(("HideCursor - do not treat as a colored cell\n")); 13610 flags &= ~(FG_COLOR | BG_COLOR); 13611 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 13612 TRACE(("HideCursor - should we treat as a colored cell?\n")); 13613 if (!(xw->flags & FG_COLOR)) 13614 if (CheckBogusForeground(screen, "HideCursor")) 13615 flags &= ~(FG_COLOR | BG_COLOR); 13616 } 13617 } 13618#endif 13619#endif 13620 13621 /* 13622 * Compare the current cell to the last set of colors used for the 13623 * cursor and update the GC's if needed. 13624 */ 13625 if_OPT_ISO_COLORS(screen, { 13626 fg_bg = ld->color[cursor_col]; 13627 }); 13628 13629 if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col)) 13630 in_selection = False; 13631 else 13632 in_selection = True; 13633 13634#if OPT_WIDE_ATTRS 13635 attr_flags = ld->attribs[cursor_col]; 13636 if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) { 13637 which_font = ((attr_flags & BOLD) ? fBold : fNorm); 13638 if ((attr_flags & ATR_ITALIC) && UseItalicFont(screen)) 13639 getter = getItalicFont; 13640 13641 if_OPT_WIDE_CHARS(screen, { 13642 if (isWide((int) base)) { 13643 which_font = ((attr_flags & BOLD) ? fWBold : fWide); 13644 } 13645 }); 13646 13647 which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font); 13648 if (which_Cgs != gcMAX) { 13649 setCgsFont(xw, WhichVWin(screen), 13650 (CgsEnum) which_Cgs, 13651 getter(screen, which_font)); 13652 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 13653 ? getItalicFont 13654 : getNormalFont); 13655 } 13656 } 13657#endif 13658 13659 currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection); 13660 13661 TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n", 13662 screen->cursorp.row, screen->cursorp.col)); 13663 13664 x = LineCursorX(screen, ld, cursor_col); 13665 y = CursorY(screen, screen->cursorp.row); 13666 13667 /* *INDENT-EQLS* */ 13668 params.xw = xw; 13669 params.attr_flags = (flags & DRAWX_MASK); 13670 params.draw_flags = 0; 13671 params.this_chrset = LineCharSet(screen, ld); 13672 params.real_chrset = CSET_SWL; 13673 params.on_wide = 0; 13674 13675 drawXtermText(¶ms, 13676 currentGC, x, y, 13677 &base, 1); 13678 13679#if OPT_WIDE_CHARS 13680 if_OPT_WIDE_CHARS(screen, { 13681 size_t off; 13682 13683 /* *INDENT-EQLS* */ 13684 params.draw_flags = NOBACKGROUND; 13685 params.on_wide = isWide((int) base); 13686 13687 for_each_combData(off, ld) { 13688 if (!(ld->combData[off][my_col])) 13689 break; 13690 drawXtermText(¶ms, 13691 currentGC, x, y, 13692 ld->combData[off] + my_col, 1); 13693 } 13694 }); 13695#endif 13696 screen->cursor_state = OFF; 13697 13698#if OPT_WIDE_ATTRS 13699 if (which_Cgs != gcMAX) { 13700 setCgsFont(xw, WhichVWin(screen), 13701 (CgsEnum) which_Cgs, 13702 getter(screen, which_font)); 13703 } 13704#endif 13705 resetXtermGC(xw, flags, in_selection); 13706 13707 refresh_displayed_graphics(xw, 13708 screen->cursorp.col, 13709 screen->cursorp.row, 13710 1, 1); 13711 13712 return; 13713} 13714 13715#if OPT_BLINK_CURS || OPT_BLINK_TEXT 13716static void 13717StartBlinking(XtermWidget xw) 13718{ 13719 TScreen *screen = TScreenOf(xw); 13720 13721 if (screen->blink_timer == 0) { 13722 unsigned long interval = (unsigned long) ((screen->cursor_state == ON) 13723 ? screen->blink_on 13724 : screen->blink_off); 13725 if (interval == 0) /* wow! */ 13726 interval = 1; /* let's humor him anyway */ 13727 screen->blink_timer = XtAppAddTimeOut(app_con, 13728 interval, 13729 HandleBlinking, 13730 xw); 13731 } 13732} 13733 13734static void 13735StopBlinking(XtermWidget xw) 13736{ 13737 TScreen *screen = TScreenOf(xw); 13738 13739 if (screen->blink_timer) { 13740 XtRemoveTimeOut(screen->blink_timer); 13741 screen->blink_timer = 0; 13742 reallyStopBlinking(xw); 13743 } else { 13744 screen->blink_timer = 0; 13745 } 13746} 13747 13748#if OPT_BLINK_TEXT 13749Bool 13750LineHasBlinking(TScreen *screen, CLineData *ld) 13751{ 13752 Bool result = False; 13753 if (ld != NULL) { 13754 int col; 13755 13756 for (col = 0; col < MaxCols(screen); ++col) { 13757 if (ld->attribs[col] & BLINK) { 13758 result = True; 13759 break; 13760 } 13761 } 13762 } 13763 return result; 13764} 13765#endif 13766 13767/* 13768 * Blink the cursor by alternately showing/hiding cursor. We leave the timer 13769 * running all the time (even though that's a little inefficient) to make the 13770 * logic simple. 13771 */ 13772static void 13773HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED) 13774{ 13775 XtermWidget xw = (XtermWidget) closure; 13776 TScreen *screen = TScreenOf(xw); 13777 Bool resume = False; 13778 13779 screen->blink_timer = 0; 13780 screen->blink_state = !screen->blink_state; 13781 13782#if OPT_BLINK_CURS 13783 if (DoStartBlinking(screen)) { 13784 if (screen->cursor_state == ON) { 13785 if (screen->select || screen->always_highlight) { 13786 HideCursor(xw); 13787 if (screen->cursor_state == OFF) 13788 screen->cursor_state = BLINKED_OFF; 13789 } 13790 } else if (screen->cursor_state == BLINKED_OFF) { 13791 screen->cursor_state = OFF; 13792 ShowCursor(xw); 13793 if (screen->cursor_state == OFF) 13794 screen->cursor_state = BLINKED_OFF; 13795 } 13796 resume = True; 13797 } 13798#endif 13799 13800#if OPT_BLINK_TEXT 13801 /* 13802 * Inspect the lines on the current screen to see if any have the BLINK flag 13803 * associated with them. Prune off any that have had the corresponding 13804 * cells reset. If any are left, repaint those lines with ScrnRefresh(). 13805 */ 13806 if (!(screen->blink_as_bold)) { 13807 int row; 13808 int start_row = LastRowNumber(screen); 13809 int first_row = start_row; 13810 int last_row = -1; 13811 13812 for (row = start_row; row >= 0; row--) { 13813 LineData *ld = getLineData(screen, ROW2INX(screen, row)); 13814 13815 if (ld != NULL && LineTstBlinked(ld)) { 13816 if (LineHasBlinking(screen, ld)) { 13817 resume = True; 13818 if (row > last_row) 13819 last_row = row; 13820 if (row < first_row) 13821 first_row = row; 13822 } else { 13823 LineClrBlinked(ld); 13824 } 13825 } 13826 } 13827 /* 13828 * FIXME: this could be a little more efficient, e.g,. by limiting the 13829 * columns which are updated. 13830 */ 13831 if (first_row <= last_row) { 13832 ScrnRefresh(xw, 13833 first_row, 13834 0, 13835 last_row + 1 - first_row, 13836 MaxCols(screen), 13837 True); 13838 } 13839 } 13840#endif 13841 13842 /* 13843 * If either the cursor or text is blinking, restart the timer. 13844 */ 13845 if (resume) 13846 StartBlinking(xw); 13847} 13848#endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */ 13849 13850void 13851RestartBlinking(XtermWidget xw) 13852{ 13853#if OPT_BLINK_CURS || OPT_BLINK_TEXT 13854 TScreen *screen = TScreenOf(xw); 13855 13856 if (screen->blink_timer == 0) { 13857 Bool resume = False; 13858 13859#if OPT_BLINK_CURS 13860 if (DoStartBlinking(screen)) { 13861 resume = True; 13862 } 13863#endif 13864#if OPT_BLINK_TEXT 13865 if (!resume) { 13866 int row; 13867 13868 for (row = screen->max_row; row >= 0; row--) { 13869 CLineData *ld = getLineData(screen, ROW2INX(screen, row)); 13870 13871 if (ld != NULL && LineTstBlinked(ld)) { 13872 if (LineHasBlinking(screen, ld)) { 13873 resume = True; 13874 break; 13875 } 13876 } 13877 } 13878 } 13879#endif 13880 if (resume) 13881 StartBlinking(xw); 13882 } 13883#else 13884 (void) xw; 13885#endif 13886} 13887 13888/* 13889 * Implement soft or hard (full) reset of the VTxxx emulation. There are a 13890 * couple of differences from real DEC VTxxx terminals (to avoid breaking 13891 * applications which have come to rely on xterm doing this): 13892 * 13893 * + autowrap mode should be reset (instead it's reset to the resource 13894 * default). 13895 * + the popup menu offers a choice of resetting the savedLines, or not. 13896 * (but the control sequence does this anyway). 13897 */ 13898static void 13899ReallyReset(XtermWidget xw, Bool full, Bool saved) 13900{ 13901 TScreen *screen = TScreenOf(xw); 13902 IFlags saveflags = xw->flags; 13903 13904 TRACE(("ReallyReset %s, %s\n", 13905 full ? "hard" : "soft", 13906 saved ? "clear savedLines" : "keep savedLines")); 13907 13908 if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) { 13909 Bell(xw, XkbBI_MinorError, 0); 13910 return; 13911 } 13912 13913 if (saved) { 13914 screen->savedlines = 0; 13915 ScrollBarDrawThumb(xw, 0); 13916 } 13917 13918 /* make cursor visible */ 13919 screen->cursor_set = ON; 13920 InitCursorShape(screen, screen); 13921 xtermSetCursorBox(screen); 13922#if OPT_BLINK_CURS 13923 screen->cursor_blink_esc = 0; 13924 SetCursorBlink(xw, screen->cursor_blink_i); 13925 TRACE(("cursor_shape:%d blinks:%d\n", 13926 screen->cursor_shape, 13927 screen->cursor_blink)); 13928#endif 13929#if OPT_STATUS_LINE 13930 if (screen->vtXX_level >= 2) { 13931 if (full) 13932 handle_DECSSDT(xw, 0); /* DEC STD 070, page 14-10, RIS */ 13933 else 13934 handle_DECSASD(xw, 0); /* DEC STD 070, page 14-9, DECSTR */ 13935 } 13936#endif 13937 13938 /* reset scrolling region */ 13939 resetMarginMode(xw); 13940 13941 bitclr(&xw->flags, ORIGIN); 13942 13943 if_OPT_ISO_COLORS(screen, { 13944 static char empty[1]; 13945 reset_SGR_Colors(xw); 13946 if (ResetAnsiColorRequest(xw, empty, 0)) 13947 xtermRepaint(xw); 13948 }); 13949 13950 /* Reset character-sets to initial state */ 13951 resetCharsets(screen); 13952 13953 UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM)); 13954 if (xw->misc.appcursorDefault) 13955 xw->keyboard.flags |= MODE_DECCKM; 13956 if (xw->misc.appkeypadDefault) 13957 xw->keyboard.flags |= MODE_DECKPAM; 13958 13959#if OPT_MOD_FKEYS 13960 /* Reset modifier-resources to initial state */ 13961 xw->keyboard.modify_now = xw->keyboard.modify_1st; 13962#endif 13963#if OPT_DEC_RECTOPS 13964 screen->checksum_ext = screen->checksum_ext0; 13965#endif 13966 13967 /* Reset DECSCA */ 13968 bitclr(&xw->flags, PROTECTED); 13969 screen->protected_mode = OFF_PROTECT; 13970 13971 if (full) { /* RIS */ 13972 if (screen->bellOnReset) 13973 Bell(xw, XkbBI_TerminalBell, 0); 13974 13975 reset_displayed_graphics(screen); 13976 13977 /* reset the mouse mode */ 13978 screen->send_mouse_pos = MOUSE_OFF; 13979 screen->send_focus_pos = OFF; 13980 screen->extend_coords = 0; 13981 screen->waitingForTrackInfo = False; 13982 screen->eventMode = NORMAL; 13983 13984 xtermShowPointer(xw, True); 13985 13986 TabReset(xw->tabs); 13987 xw->keyboard.flags |= MODE_SRM; 13988 13989 guard_keyboard_type = False; 13990 screen->old_fkeys = screen->old_fkeys0; 13991 decode_keyboard_type(xw, &resource); 13992 update_keyboard_type(); 13993 13994 UIntClr(xw->keyboard.flags, MODE_DECBKM); 13995#if OPT_INITIAL_ERASE 13996 if (xw->keyboard.reset_DECBKM == 1) 13997 xw->keyboard.flags |= MODE_DECBKM; 13998 else if (xw->keyboard.reset_DECBKM == 2) 13999#endif 14000 if (screen->backarrow_key) 14001 xw->keyboard.flags |= MODE_DECBKM; 14002 TRACE(("full reset DECBKM %s\n", 14003 BtoS(xw->keyboard.flags & MODE_DECBKM))); 14004 14005#if OPT_SCROLL_LOCK 14006 xtermClearLEDs(screen); 14007#endif 14008 screen->title_modes = screen->title_modes0; 14009 screen->pointer_mode = screen->pointer_mode0; 14010#if OPT_SIXEL_GRAPHICS 14011 if (screen->sixel_scrolling) 14012 UIntClr(xw->keyboard.flags, MODE_DECSDM); 14013 else 14014 UIntSet(xw->keyboard.flags, MODE_DECSDM); 14015 TRACE(("full reset DECSDM to %s (resource default is %s)\n", 14016 BtoS(xw->keyboard.flags & MODE_DECSDM), 14017 BtoS(!screen->sixel_scrolling))); 14018#endif 14019 14020#if OPT_GRAPHICS 14021 screen->privatecolorregisters = screen->privatecolorregisters0; 14022 TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s\n", 14023 BtoS(screen->privatecolorregisters))); 14024 update_privatecolorregisters(); 14025#endif 14026 14027#if OPT_SIXEL_GRAPHICS 14028 screen->sixel_scrolls_right = screen->sixel_scrolls_right0; 14029 TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s\n", 14030 BtoS(screen->sixel_scrolls_right))); 14031#endif 14032 14033 update_appcursor(); 14034 update_appkeypad(); 14035 update_decbkm(); 14036 update_decsdm(); 14037 show_8bit_control(False); 14038 reset_decudk(xw); 14039 14040 FromAlternate(xw, True); 14041 ClearScreen(xw); 14042 screen->cursor_state = OFF; 14043 14044 if (xw->flags & REVERSE_VIDEO) 14045 ReverseVideo(xw); 14046 ResetItalics(xw); 14047 xw->flags = xw->initflags; 14048 14049 update_reversevideo(); 14050 update_autowrap(); 14051 update_reversewrap(); 14052 update_autolinefeed(); 14053 14054 screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL)); 14055 update_jumpscroll(); 14056 14057#if OPT_DEC_RECTOPS 14058 screen->cur_decsace = 0; 14059#endif 14060#if OPT_PASTE64 || OPT_READLINE 14061 screen->paste_brackets = OFF; 14062#endif 14063#if OPT_READLINE 14064 screen->click1_moves = OFF; 14065 screen->paste_moves = OFF; 14066 screen->dclick3_deletes = OFF; 14067 screen->paste_quotes = OFF; 14068 screen->paste_literal_nl = OFF; 14069#endif /* OPT_READLINE */ 14070 14071 if (screen->c132 && (saveflags & IN132COLUMNS)) { 14072 TRACE(("Making resize-request to restore 80-columns %dx%d\n", 14073 MaxRows(screen), MaxCols(screen))); 14074 RequestResize(xw, MaxRows(screen), 80, True); 14075 repairSizeHints(); 14076 XSync(screen->display, False); /* synchronize */ 14077 if (xtermAppPending()) 14078 xevents(xw); 14079 } 14080 14081 CursorSet(screen, 0, 0, xw->flags); 14082 CursorSave(xw); 14083 } else { /* DECSTR */ 14084 bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP | REVERSEWRAP2); 14085 bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE); 14086 ResetItalics(xw); 14087 if_OPT_ISO_COLORS(screen, { 14088 reset_SGR_Colors(xw); 14089 }); 14090 update_appcursor(); 14091 update_autowrap(); 14092 update_reversewrap(); 14093 14094 CursorSave(xw); 14095 screen->sc[screen->whichBuf].row = 14096 screen->sc[screen->whichBuf].col = 0; 14097 } 14098} 14099 14100void 14101VTReset(XtermWidget xw, Bool full, Bool saved) 14102{ 14103 ReallyReset(xw, full, saved); 14104 14105 FreeAndNull(myState.string_area); 14106 FreeAndNull(myState.print_area); 14107 14108 longjmp(vtjmpbuf, 1); /* force ground state in parser */ 14109} 14110 14111typedef enum { 14112 ccLO, 14113 ccDASH, 14114 ccHI, 14115 ccCOLON, 14116 ccID, 14117 ccCOMMA 14118} CCLASS; 14119 14120/* 14121 * set_character_class - takes a string of the form 14122 * 14123 * low[-high][:id][,low[-high][:id][...]] 14124 * 14125 * and sets the indicated ranges to the indicated values. 14126 */ 14127static int 14128set_character_class(char *s) 14129{ 14130#define FMT "%s in range string \"%s\" (position %d)\n" 14131 14132 TRACE(("set_character_class(%s) " TRACE_L "\n", NonNull(s))); 14133 if (IsEmpty(s)) { 14134 TRACE((TRACE_R " ERR set_character_class\n")); 14135 return -1; 14136 } else { 14137 CCLASS state = ccLO; 14138 int arg[3]; 14139 int i; 14140 int len = (int) strlen(s); 14141 14142 arg[0] = 14143 arg[1] = 14144 arg[2] = -1; 14145 14146 for (i = 0; i < len; ++i) { 14147 int ch = CharOf(s[i]); 14148 char *t = NULL; 14149 long value = 0; 14150 14151 if (isspace(ch)) 14152 continue; 14153 14154 switch (state) { 14155 case ccLO: 14156 case ccHI: 14157 case ccID: 14158 if (!isdigit(ch)) { 14159 xtermWarning(FMT, "missing number", s, i); 14160 TRACE((TRACE_R " ERR set_character_class\n")); 14161 return (-1); 14162 } 14163 value = strtol(s + i, &t, 0); 14164 i = (int) (t - s - 1); 14165 break; 14166 case ccDASH: 14167 case ccCOLON: 14168 case ccCOMMA: 14169 break; 14170 } 14171 14172 switch (state) { 14173 case ccLO: 14174 arg[0] = 14175 arg[1] = (int) value; 14176 arg[2] = -1; 14177 state = ccDASH; 14178 break; 14179 14180 case ccDASH: 14181 if (ch == '-') { 14182 state = ccHI; 14183 } else { 14184 goto parse_class; 14185 } 14186 break; 14187 14188 case ccHI: 14189 arg[1] = (int) value; 14190 state = ccCOLON; 14191 break; 14192 14193 parse_class: 14194 /* FALLTHRU */ 14195 case ccCOLON: 14196 if (ch == ':') { 14197 state = ccID; 14198 } else if (ch == ',') { 14199 goto apply_class; 14200 } else { 14201 xtermWarning(FMT, "unexpected character", s, i); 14202 TRACE((TRACE_R " ERR set_character_class\n")); 14203 return (-1); 14204 } 14205 break; 14206 14207 case ccID: 14208 arg[2] = (int) value; 14209 state = ccCOMMA; 14210 break; 14211 14212 apply_class: 14213 /* FALLTHRU */ 14214 case ccCOMMA: 14215 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 14216 xtermWarning(FMT, "bad range", s, i); 14217 TRACE((TRACE_R " ERR set_character_class\n")); 14218 return -1; 14219 } 14220 state = ccLO; 14221 break; 14222 } 14223 } 14224 if (state >= ccDASH) { 14225 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 14226 xtermWarning(FMT, "bad range", s, i); 14227 TRACE((TRACE_R " ERR set_character_class\n")); 14228 return -1; 14229 } 14230 } 14231 } 14232 14233 TRACE((TRACE_R " OK set_character_class\n")); 14234 return (0); 14235#undef FMT 14236} 14237 14238void 14239getKeymapResources(Widget w, 14240 const char *mapName, 14241 const char *mapClass, 14242 const char *type, 14243 void *result, 14244 size_t size) 14245{ 14246 XtResource key_resources[1]; 14247 key_resources[0].resource_name = XtNtranslations; 14248 key_resources[0].resource_class = XtCTranslations; 14249 key_resources[0].resource_type = (char *) type; 14250 key_resources[0].resource_size = (Cardinal) size; 14251 key_resources[0].resource_offset = 0; 14252 key_resources[0].default_type = key_resources[0].resource_type; 14253 key_resources[0].default_addr = NULL; 14254 XtGetSubresources(w, (XtPointer) result, mapName, mapClass, 14255 key_resources, (Cardinal) 1, NULL, (Cardinal) 0); 14256} 14257 14258/* ARGSUSED */ 14259static void 14260HandleKeymapChange(Widget w, 14261 XEvent *event GCC_UNUSED, 14262 String *params, 14263 Cardinal *param_count) 14264{ 14265 static XtTranslations keymap, original; 14266 14267 TRACE(("HandleKeymapChange(%#lx, %s)\n", 14268 (unsigned long) w, 14269 (*param_count 14270 ? params[0] 14271 : "missing"))); 14272 14273 if (*param_count != 1) 14274 return; 14275 14276 if (original == NULL) { 14277 TRACE(("...saving original keymap-translations\n")); 14278 original = w->core.tm.translations; 14279 } 14280 14281 if (strcmp(params[0], "None") == 0) { 14282 TRACE(("...restoring original keymap-translations\n")); 14283 XtOverrideTranslations(w, original); 14284 } else { 14285 char mapName[1000]; 14286 char mapClass[1000]; 14287 char *pmapName; 14288 char *pmapClass; 14289 size_t len; 14290 14291 len = strlen(params[0]) + 7; 14292 14293 pmapName = (char *) MyStackAlloc(len, mapName); 14294 pmapClass = (char *) MyStackAlloc(len, mapClass); 14295 if (pmapName == NULL 14296 || pmapClass == NULL) { 14297 SysError(ERROR_KMMALLOC1); 14298 } else { 14299 14300 (void) sprintf(pmapName, "%sKeymap", params[0]); 14301 (void) strcpy(pmapClass, pmapName); 14302 if (islower(CharOf(pmapClass[0]))) 14303 pmapClass[0] = x_toupper(pmapClass[0]); 14304 getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable, 14305 &keymap, sizeof(keymap)); 14306 if (keymap != NULL) { 14307 TRACE(("...applying keymap \"%s\"\n", pmapName)); 14308 XtOverrideTranslations(w, keymap); 14309 } else { 14310 TRACE(("...found no match for keymap \"%s\"\n", pmapName)); 14311 } 14312 14313 MyStackFree(pmapName, mapName); 14314 MyStackFree(pmapClass, mapClass); 14315 } 14316 } 14317} 14318 14319/* ARGSUSED */ 14320static void 14321HandleBell(Widget w GCC_UNUSED, 14322 XEvent *event GCC_UNUSED, 14323 String *params, /* [0] = volume */ 14324 Cardinal *param_count) /* 0 or 1 */ 14325{ 14326 int percent = (*param_count) ? atoi(params[0]) : 0; 14327 14328 Bell(term, XkbBI_TerminalBell, percent); 14329} 14330 14331/* ARGSUSED */ 14332static void 14333HandleVisualBell(Widget w GCC_UNUSED, 14334 XEvent *event GCC_UNUSED, 14335 String *params GCC_UNUSED, 14336 Cardinal *param_count GCC_UNUSED) 14337{ 14338 VisualBell(); 14339} 14340 14341/* ARGSUSED */ 14342static void 14343HandleIgnore(Widget w, 14344 XEvent *event, 14345 String *params GCC_UNUSED, 14346 Cardinal *param_count GCC_UNUSED) 14347{ 14348 XtermWidget xw; 14349 14350 TRACE(("Handle ignore for %p %s\n", 14351 (void *) w, visibleEventType(event->type))); 14352 if ((xw = getXtermWidget(w)) != NULL) { 14353 /* do nothing, but check for funny escape sequences */ 14354 switch (event->type) { 14355 case ButtonPress: 14356 case ButtonRelease: 14357 case MotionNotify: 14358 (void) SendMousePosition(xw, event); 14359 break; 14360 } 14361 } 14362} 14363 14364/* ARGSUSED */ 14365static void 14366DoSetSelectedFont(Widget w, 14367 XtPointer client_data GCC_UNUSED, 14368 Atom *selection GCC_UNUSED, 14369 Atom *type, 14370 XtPointer value, 14371 unsigned long *length, 14372 int *format) 14373{ 14374 XtermWidget xw = getXtermWidget(w); 14375 14376 if (xw == NULL) { 14377 xtermWarning("unexpected widget in DoSetSelectedFont\n"); 14378 } else if (*type != XA_STRING || *format != 8) { 14379 Bell(xw, XkbBI_MinorError, 0); 14380 } else { 14381 Boolean failed = False; 14382 char *save = TScreenOf(xw)->SelectFontName(); 14383 char *val; 14384 char *test; 14385 unsigned len = (unsigned) *length; 14386 unsigned tst; 14387 14388 /* 14389 * Some versions of X deliver null-terminated selections, some do not. 14390 */ 14391 for (tst = 0; tst < len; ++tst) { 14392 if (((char *) value)[tst] == '\0') { 14393 len = tst; 14394 break; 14395 } 14396 } 14397 14398 if (len > 0 && (val = TypeMallocN(char, len + 1)) != NULL) { 14399 char *used; 14400 14401 memcpy(val, value, (size_t) len); 14402 val[len] = '\0'; 14403 used = x_strtrim(val); 14404 TRACE(("DoSetSelectedFont(%s)\n", used)); 14405 /* Do some sanity checking to avoid sending a long selection 14406 back to the server in an OpenFont that is unlikely to succeed. 14407 XLFD allows up to 255 characters and no control characters; 14408 we are a little more liberal here. */ 14409 if (len < 1000 14410 && used != NULL 14411 && !strchr(used, '\n') 14412 && (test = x_strdup(used)) != NULL) { 14413 TScreenOf(xw)->SelectFontName() = test; 14414 if (!xtermLoadFont(xw, 14415 xtermFontName(used), 14416 True, 14417 fontMenu_fontsel)) { 14418 failed = True; 14419 free(test); 14420 TScreenOf(xw)->SelectFontName() = save; 14421 } 14422 } else { 14423 failed = True; 14424 } 14425 if (failed) { 14426 Bell(xw, XkbBI_MinorError, 0); 14427 } 14428 free(used); 14429 free(val); 14430 } 14431 } 14432} 14433 14434Bool 14435FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe) 14436{ 14437 TScreen *screen = TScreenOf(xw); 14438 static AtomPtr *atoms; 14439 static unsigned int atomCount = 0; 14440 AtomPtr *pAtom; 14441 unsigned a; 14442 Atom target; 14443 14444 if (!atom_name) 14445 atom_name = ((screen->mappedSelect && atomCount) 14446 ? screen->mappedSelect[0] 14447 : "PRIMARY"); 14448 TRACE(("FindFontSelection(%s)\n", atom_name)); 14449 14450 for (pAtom = atoms, a = atomCount; a; a--, pAtom++) { 14451 if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) { 14452 TRACE(("...found atom %d:%s\n", a + 1, atom_name)); 14453 break; 14454 } 14455 } 14456 if (!a) { 14457 atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1); 14458 *(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name); 14459 ++atomCount; 14460 TRACE(("...added atom %d:%s\n", atomCount, atom_name)); 14461 } 14462 14463 target = XmuInternAtom(XtDisplay(xw), *pAtom); 14464 if (justprobe) { 14465 screen->SelectFontName() = 14466 XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : NULL; 14467 TRACE(("...selected fontname '%s'\n", 14468 NonNull(screen->SelectFontName()))); 14469 } else { 14470 XtGetSelectionValue((Widget) xw, target, XA_STRING, 14471 DoSetSelectedFont, NULL, 14472 XtLastTimestampProcessed(XtDisplay(xw))); 14473 } 14474 return (screen->SelectFontName() != NULL) ? True : False; 14475} 14476 14477Bool 14478set_cursor_gcs(XtermWidget xw) 14479{ 14480 TScreen *screen = TScreenOf(xw); 14481 VTwin *win = WhichVWin(screen); 14482 14483 Pixel cc = T_COLOR(screen, TEXT_CURSOR); 14484 Pixel fg = T_COLOR(screen, TEXT_FG); 14485 Pixel bg = T_COLOR(screen, TEXT_BG); 14486 Bool changed = False; 14487 14488 /* 14489 * Let's see, there are three things that have "color": 14490 * 14491 * background 14492 * text 14493 * cursorblock 14494 * 14495 * And, there are four situations when drawing a cursor, if we decide 14496 * that we like have a solid block of cursor color with the letter 14497 * that it is highlighting shown in the background color to make it 14498 * stand out: 14499 * 14500 * selected window, normal video - background on cursor 14501 * selected window, reverse video - foreground on cursor 14502 * unselected window, normal video - foreground on background 14503 * unselected window, reverse video - background on foreground 14504 * 14505 * Since the last two are really just normalGC and reverseGC, we only 14506 * need two new GC's. Under monochrome, we get the same effect as 14507 * above by setting cursor color to foreground. 14508 */ 14509 14510 TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg)); 14511 if (win != NULL && (cc != bg)) { 14512 Pixel xx = ((fg == cc) ? bg : cc); 14513 14514 /* set the fonts to the current one */ 14515 setCgsFont(xw, win, gcVTcursNormal, NULL); 14516 setCgsFont(xw, win, gcVTcursFilled, NULL); 14517 setCgsFont(xw, win, gcVTcursReverse, NULL); 14518 setCgsFont(xw, win, gcVTcursOutline, NULL); 14519 14520 /* we have a colored cursor */ 14521 setCgsFore(xw, win, gcVTcursNormal, fg); 14522 setCgsBack(xw, win, gcVTcursNormal, xx); 14523 14524 setCgsFore(xw, win, gcVTcursFilled, xx); 14525 setCgsBack(xw, win, gcVTcursFilled, fg); 14526 14527 if (screen->always_highlight) { 14528 /* both GC's use the same color */ 14529 setCgsFore(xw, win, gcVTcursReverse, bg); 14530 setCgsBack(xw, win, gcVTcursReverse, cc); 14531 } else { 14532 setCgsFore(xw, win, gcVTcursReverse, bg); 14533 setCgsBack(xw, win, gcVTcursReverse, cc); 14534 } 14535 set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc); 14536 changed = True; 14537 FreeMarkGCs(xw); 14538 } 14539 14540 if (changed) { 14541 TRACE(("...set_cursor_gcs - done\n")); 14542 } 14543 return changed; 14544} 14545 14546/* 14547 * Build up the default translations string, allowing the user to suppress 14548 * some of the features. 14549 */ 14550void 14551VTInitTranslations(void) 14552{ 14553 /* *INDENT-OFF* */ 14554 static struct { 14555 Boolean wanted; 14556 const char *name; 14557 const char *value; 14558 } table[] = { 14559#define DATA(name,value) { False, name, value } 14560 DATA("select", 14561"\ 14562 Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\ 14563 Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\ 14564" 14565 ), 14566#if OPT_MAXIMIZE 14567 DATA("fullscreen", 14568"\ 14569 Alt <Key>Return:fullscreen() \n\ 14570" 14571 ), 14572#endif 14573#if OPT_SCROLL_LOCK 14574 DATA("scroll-lock", 14575"\ 14576 <KeyRelease> Scroll_Lock:scroll-lock() \n\ 14577" 14578 ), 14579#endif 14580#if OPT_SHIFT_FONTS 14581 DATA("shift-fonts", 14582"\ 14583 Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\ 14584 Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\ 14585 Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\ 14586" 14587 ), 14588#endif 14589 DATA("paging", 14590"\ 14591 Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\ 14592 Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\ 14593" 14594 ), 14595 /* This must be the last set mentioning "KeyPress" */ 14596 DATA("keypress", 14597"\ 14598 ~Meta <KeyPress>:insert-seven-bit() \n\ 14599 Meta <KeyPress>:insert-eight-bit() \n\ 14600" 14601 ), 14602 DATA("popup-menu", 14603"\ 14604 !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 14605 !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 14606 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\ 14607 ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 14608 !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 14609 !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 14610 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\ 14611 ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 14612 !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 14613 !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 14614 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\ 14615 ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 14616" 14617 ), 14618 /* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */ 14619 DATA("reset", 14620"\ 14621 Meta <Btn2Down>:clear-saved-lines() \n\ 14622" 14623 ), 14624 DATA("select", 14625"\ 14626 ~Meta <Btn1Down>:select-start() \n\ 14627 ~Meta <Btn1Motion>:select-extend() \n\ 14628 ~Ctrl ~Meta <Btn2Down>:ignore() \n\ 14629 ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\ 14630 ~Ctrl ~Meta <Btn3Down>:start-extend() \n\ 14631 ~Meta <Btn3Motion>:select-extend() \n\ 14632 <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\ 14633" 14634 ), 14635#if OPT_BLOCK_SELECT 14636 DATA("block-select", 14637"\ 14638 Meta <Btn1Down>:select-start(block) \n\ 14639" 14640 ), 14641#endif 14642 DATA("wheel-mouse", 14643"\ 14644 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 14645 Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 14646 Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 14647 @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 14648 <Btn4Down>:scroll-back(5,line,m) \n\ 14649 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 14650 Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 14651 Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 14652 @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 14653 <Btn5Down>:scroll-forw(5,line,m) \n\ 14654" 14655 ), 14656 DATA("pointer", 14657"\ 14658 <BtnMotion>:pointer-motion() \n\ 14659 <BtnDown>:pointer-button() \n\ 14660 <BtnUp>:pointer-button() \n\ 14661" 14662 ), 14663 DATA("default", 14664"\ 14665 <BtnUp>:ignore() \n\ 14666" 14667 ) 14668 }; 14669#undef DATA 14670 /* *INDENT-ON* */ 14671 14672 char *result = NULL; 14673 14674 int pass; 14675 Cardinal item; 14676 14677 TRACE(("VTInitTranslations\n")); 14678 for (item = 0; item < XtNumber(table); ++item) { 14679 table[item].wanted = True; 14680 } 14681#if OPT_MAXIMIZE 14682 /* 14683 * As a special case, allow for disabling the alt-enter translation if 14684 * the resource settings prevent fullscreen from being used. We would 14685 * do the same for scroll-lock and shift-fonts if they were application 14686 * resources too, rather than in the widget. 14687 */ 14688 if (resource.fullscreen == esNever) { 14689 for (item = 0; item < XtNumber(table); ++item) { 14690 if (!strcmp(table[item].name, "fullscreen")) { 14691 table[item].wanted = False; 14692 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 14693 } 14694 } 14695 } 14696#endif 14697 if (!IsEmpty(resource.omitTranslation)) { 14698 char *value; 14699 const char *source = resource.omitTranslation; 14700 14701 while (*source != '\0' && (value = ParseList(&source)) != NULL) { 14702 size_t len = strlen(value); 14703 14704 TRACE(("parsed:%s\n", value)); 14705 for (item = 0; item < XtNumber(table); ++item) { 14706 if (strlen(table[item].name) >= len 14707 && x_strncasecmp(table[item].name, 14708 value, 14709 (unsigned) len) == 0) { 14710 table[item].wanted = False; 14711 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 14712 /* continue: "select", for instance is two chunks */ 14713 } 14714 } 14715 free(value); 14716 } 14717 } 14718 14719 for (pass = 0; pass < 2; ++pass) { 14720 size_t needed = 0; 14721 for (item = 0; item < XtNumber(table); ++item) { 14722 if (table[item].wanted) { 14723 if (pass) { 14724 strcat(result, table[item].value); 14725 } else { 14726 needed += strlen(table[item].value) + 1; 14727 } 14728 } 14729 } 14730 if (!pass) { 14731 result = XtMalloc((Cardinal) needed); 14732 *result = '\0'; 14733 } 14734 } 14735 14736 TRACE(("result:\n%s\n", result)); 14737 14738 defaultTranslations = result; 14739 free((void *) xtermClassRec.core_class.tm_table); 14740 xtermClassRec.core_class.tm_table = result; 14741} 14742 14743#ifdef NO_LEAKS 14744void 14745noleaks_charproc(void) 14746{ 14747 free(v_buffer); 14748} 14749#endif 14750