charproc.c revision ae137402
1/* $XTermId: charproc.c,v 1.1832 2021/06/07 19:51:06 tom Exp $ */ 2 3/* 4 * Copyright 1999-2020,2021 by Thomas E. Dickey 5 * 6 * All Rights Reserved 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the 29 * sale, use or other dealings in this Software without prior written 30 * authorization. 31 * 32 * 33 * Copyright 1988 X Consortium 34 * 35 * Permission to use, copy, modify, distribute, and sell this software and its 36 * documentation for any purpose is hereby granted without fee, provided that 37 * the above copyright notice appear in all copies and that both that 38 * copyright notice and this permission notice appear in supporting 39 * documentation. 40 * 41 * The above copyright notice and this permission notice shall be included in 42 * all copies or substantial portions of the Software. 43 * 44 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 48 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 49 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 50 * 51 * Except as contained in this notice, the name of the X Consortium shall not be 52 * used in advertising or otherwise to promote the sale, use or other dealings 53 * in this Software without prior written authorization from the X Consortium. 54 * 55 */ 56/* 57 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 58 * 59 * All Rights Reserved 60 * 61 * Permission to use, copy, modify, and distribute this software and its 62 * documentation for any purpose and without fee is hereby granted, 63 * provided that the above copyright notice appear in all copies and that 64 * both that copyright notice and this permission notice appear in 65 * supporting documentation, and that the name of Digital Equipment 66 * Corporation not be used in advertising or publicity pertaining to 67 * distribution of the software without specific, written prior permission. 68 * 69 * 70 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 71 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 72 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 73 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 74 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 75 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 76 * SOFTWARE. 77 */ 78 79/* charproc.c */ 80 81#include <version.h> 82#include <xterm.h> 83 84#include <X11/Xatom.h> 85#include <X11/Xutil.h> 86#include <X11/Xmu/Atoms.h> 87#include <X11/Xmu/CharSet.h> 88#include <X11/Xmu/Converters.h> 89 90#if OPT_INPUT_METHOD 91 92#if defined(HAVE_LIB_XAW) 93#include <X11/Xaw/XawImP.h> 94#elif defined(HAVE_LIB_XAW3D) 95#include <X11/Xaw3d/XawImP.h> 96#elif defined(HAVE_LIB_XAW3DXFT) 97#include <X11/Xaw3dxft/XawImP.h> 98#elif defined(HAVE_LIB_NEXTAW) 99#include <X11/neXtaw/XawImP.h> 100#elif defined(HAVE_LIB_XAWPLUS) 101#include <X11/XawPlus/XawImP.h> 102#endif 103 104#endif 105 106#if OPT_WIDE_CHARS 107#include <xutf8.h> 108#include <wcwidth.h> 109#include <precompose.h> 110#ifdef HAVE_LANGINFO_CODESET 111#include <langinfo.h> 112#endif 113#endif 114 115#if USE_DOUBLE_BUFFER 116#include <X11/extensions/Xdbe.h> 117#endif 118 119#include <stdio.h> 120#include <ctype.h> 121#include <assert.h> 122 123#if defined(HAVE_SCHED_YIELD) 124#include <sched.h> 125#endif 126 127#include <VTparse.h> 128#include <data.h> 129#include <error.h> 130#include <menu.h> 131#include <main.h> 132#include <fontutils.h> 133#include <charclass.h> 134#include <xstrings.h> 135#include <graphics.h> 136 137#ifdef NO_LEAKS 138#include <xtermcap.h> 139#endif 140 141typedef int (*BitFunc) (unsigned * /* p */ , 142 unsigned /* mask */ ); 143 144static IChar doinput(XtermWidget /* xw */ ); 145static int set_character_class(char * /*s */ ); 146static void FromAlternate(XtermWidget /* xw */ ); 147static void ReallyReset(XtermWidget /* xw */ , 148 Bool /* full */ , 149 Bool /* saved */ ); 150static void RequestResize(XtermWidget /* xw */ , 151 int /* rows */ , 152 int /* cols */ , 153 Bool /* text */ ); 154static void SwitchBufs(XtermWidget /* xw */ , 155 int /* toBuf */ , 156 Bool /* clearFirst */ ); 157static void ToAlternate(XtermWidget /* xw */ , 158 Bool /* clearFirst */ ); 159static void ansi_modes(XtermWidget /* xw */ , 160 BitFunc /* func */ ); 161static int bitclr(unsigned *p, unsigned mask); 162static int bitcpy(unsigned *p, unsigned q, unsigned mask); 163static int bitset(unsigned *p, unsigned mask); 164static void dpmodes(XtermWidget /* xw */ , 165 BitFunc /* func */ ); 166static void restoremodes(XtermWidget /* xw */ ); 167static void savemodes(XtermWidget /* xw */ ); 168static void window_ops(XtermWidget /* xw */ ); 169 170#if OPT_BLINK_CURS || OPT_BLINK_TEXT 171#define SettableCursorBlink(screen) \ 172 (((screen)->cursor_blink != cbAlways) && \ 173 ((screen)->cursor_blink != cbNever)) 174#define UpdateCursorBlink(xw) \ 175 SetCursorBlink(xw, TScreenOf(xw)->cursor_blink) 176static void SetCursorBlink(XtermWidget /* xw */ , 177 BlinkOps /* enable */ ); 178static void HandleBlinking(XtPointer /* closure */ , 179 XtIntervalId * /* id */ ); 180static void StartBlinking(XtermWidget /* xw */ ); 181static void StopBlinking(XtermWidget /* xw */ ); 182#else 183#define StartBlinking(xw) /* nothing */ 184#define StopBlinking(xw) /* nothing */ 185#endif 186 187#ifndef NO_ACTIVE_ICON 188static Boolean discount_frame_extents(XtermWidget /* xw */ , 189 int * /* height */ , 190 int * /* width */ ); 191#else 192#define discount_frame_extents(xw, height, width) False 193#endif 194 195#if OPT_INPUT_METHOD 196static void PreeditPosition(XtermWidget /* xw */ ); 197#endif 198 199#define DEFAULT -1 200#define BELLSUPPRESSMSEC 200 201 202static ANSI reply; 203static PARAMS parms; 204 205#define nparam parms.count 206 207#define InitParams() init_params() 208#define GetParam(n) parms.params[(n)] 209#define SetParam(n,v) parms.params[(n)] = v 210#define ParamPair(n) nparam - (n), parms.params + (n) 211 212static jmp_buf vtjmpbuf; 213 214/* event handlers */ 215static void HandleBell PROTO_XT_ACTIONS_ARGS; 216static void HandleIgnore PROTO_XT_ACTIONS_ARGS; 217static void HandleKeymapChange PROTO_XT_ACTIONS_ARGS; 218static void HandleVisualBell PROTO_XT_ACTIONS_ARGS; 219#if HANDLE_STRUCT_NOTIFY 220static void HandleStructNotify PROTO_XT_EV_HANDLER_ARGS; 221#endif 222 223/* 224 * NOTE: VTInitialize zeros out the entire ".screen" component of the 225 * XtermWidget, so make sure to add an assignment statement in VTInitialize() 226 * for each new ".screen" field added to this resource list. 227 */ 228 229/* Defaults */ 230#if OPT_ISO_COLORS 231 232/* 233 * If we default to colorMode enabled, compile-in defaults for the ANSI colors. 234 */ 235#if DFT_COLORMODE 236#define DFT_COLOR(name) name 237#else 238#define DFT_COLOR(name) XtDefaultForeground 239#endif 240#endif 241 242static char _Font_Selected_[] = "yes"; /* string is arbitrary */ 243 244static const char *defaultTranslations; 245/* *INDENT-OFF* */ 246static XtActionsRec actionsList[] = { 247 { "allow-bold-fonts", HandleAllowBoldFonts }, 248 { "allow-send-events", HandleAllowSends }, 249 { "bell", HandleBell }, 250 { "clear-saved-lines", HandleClearSavedLines }, 251 { "copy-selection", HandleCopySelection }, 252 { "create-menu", HandleCreateMenu }, 253 { "delete-is-del", HandleDeleteIsDEL }, 254 { "dired-button", DiredButton }, 255 { "hard-reset", HandleHardReset }, 256 { "ignore", HandleIgnore }, 257 { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */ 258 { "insert-eight-bit", HandleEightBitKeyPressed }, 259 { "insert-selection", HandleInsertSelection }, 260 { "insert-seven-bit", HandleKeyPressed }, 261 { "interpret", HandleInterpret }, 262 { "keymap", HandleKeymapChange }, 263 { "pointer-motion", HandlePointerMotion }, 264 { "pointer-button", HandlePointerButton }, 265 { "popup-menu", HandlePopupMenu }, 266 { "print", HandlePrintScreen }, 267 { "print-everything", HandlePrintEverything }, 268 { "print-redir", HandlePrintControlMode }, 269 { "quit", HandleQuit }, 270 { "redraw", HandleRedraw }, 271 { "scroll-back", HandleScrollBack }, 272 { "scroll-forw", HandleScrollForward }, 273 { "scroll-to", HandleScrollTo }, 274 { "secure", HandleSecure }, 275 { "select-cursor-end", HandleKeyboardSelectEnd }, 276 { "select-cursor-extend", HandleKeyboardSelectExtend }, 277 { "select-cursor-start", HandleKeyboardSelectStart }, 278 { "select-end", HandleSelectEnd }, 279 { "select-extend", HandleSelectExtend }, 280 { "select-set", HandleSelectSet }, 281 { "select-start", HandleSelectStart }, 282 { "send-signal", HandleSendSignal }, 283 { "set-8-bit-control", Handle8BitControl }, 284 { "set-allow132", HandleAllow132 }, 285 { "set-altscreen", HandleAltScreen }, 286 { "set-appcursor", HandleAppCursor }, 287 { "set-appkeypad", HandleAppKeypad }, 288 { "set-autolinefeed", HandleAutoLineFeed }, 289 { "set-autowrap", HandleAutoWrap }, 290 { "set-backarrow", HandleBackarrow }, 291 { "set-bellIsUrgent", HandleBellIsUrgent }, 292 { "set-cursesemul", HandleCursesEmul }, 293 { "set-jumpscroll", HandleJumpscroll }, 294 { "set-keep-clipboard", HandleKeepClipboard }, 295 { "set-keep-selection", HandleKeepSelection }, 296 { "set-marginbell", HandleMarginBell }, 297 { "set-old-function-keys", HandleOldFunctionKeys }, 298 { "set-pop-on-bell", HandleSetPopOnBell }, 299 { "set-reverse-video", HandleReverseVideo }, 300 { "set-reversewrap", HandleReverseWrap }, 301 { "set-scroll-on-key", HandleScrollKey }, 302 { "set-scroll-on-tty-output", HandleScrollTtyOutput }, 303 { "set-scrollbar", HandleScrollbar }, 304 { "set-select", HandleSetSelect }, 305 { "set-sun-keyboard", HandleSunKeyboard }, 306 { "set-titeInhibit", HandleTiteInhibit }, 307 { "set-visual-bell", HandleSetVisualBell }, 308 { "set-vt-font", HandleSetFont }, 309 { "soft-reset", HandleSoftReset }, 310 { "start-cursor-extend", HandleKeyboardStartExtend }, 311 { "start-extend", HandleStartExtend }, 312 { "string", HandleStringEvent }, 313 { "vi-button", ViButton }, 314 { "visual-bell", HandleVisualBell }, 315#ifdef ALLOWLOGGING 316 { "set-logging", HandleLogging }, 317#endif 318#if OPT_ALLOW_XXX_OPS 319 { "allow-color-ops", HandleAllowColorOps }, 320 { "allow-font-ops", HandleAllowFontOps }, 321 { "allow-mouse-ops", HandleAllowMouseOps }, 322 { "allow-tcap-ops", HandleAllowTcapOps }, 323 { "allow-title-ops", HandleAllowTitleOps }, 324 { "allow-window-ops", HandleAllowWindowOps }, 325#endif 326#if OPT_BLINK_CURS 327 { "set-cursorblink", HandleCursorBlink }, 328#endif 329#if OPT_BOX_CHARS 330 { "set-font-linedrawing", HandleFontBoxChars }, 331 { "set-font-packed", HandleFontPacked }, 332#endif 333#if OPT_DABBREV 334 { "dabbrev-expand", HandleDabbrevExpand }, 335#endif 336#if OPT_DEC_CHRSET 337 { "set-font-doublesize", HandleFontDoublesize }, 338#endif 339#if OPT_DEC_SOFTFONT 340 { "set-font-loading", HandleFontLoading }, 341#endif 342#if OPT_SCREEN_DUMPS 343 { "dump-html", HandleDumpHtml }, 344 { "dump-svg", HandleDumpSvg }, 345#endif 346#if OPT_EXEC_XTERM 347 { "spawn-new-terminal", HandleSpawnTerminal }, 348#endif 349#if OPT_HP_FUNC_KEYS 350 { "set-hp-function-keys", HandleHpFunctionKeys }, 351#endif 352#if OPT_LOAD_VTFONTS 353 { "load-vt-fonts", HandleLoadVTFonts }, 354#endif 355#if OPT_MAXIMIZE 356 { "deiconify", HandleDeIconify }, 357 { "fullscreen", HandleFullscreen }, 358 { "iconify", HandleIconify }, 359 { "maximize", HandleMaximize }, 360 { "restore", HandleRestoreSize }, 361#endif 362#if OPT_NUM_LOCK 363 { "alt-sends-escape", HandleAltEsc }, 364 { "meta-sends-escape", HandleMetaEsc }, 365 { "set-num-lock", HandleNumLock }, 366#endif 367#ifdef OPT_PRINT_ON_EXIT 368 { "print-immediate", HandlePrintImmediate }, 369 { "print-on-error", HandlePrintOnError }, 370#endif 371#if OPT_READLINE 372 { "readline-button", ReadLineButton }, 373#endif 374#if OPT_RENDERFONT 375 { "set-render-font", HandleRenderFont }, 376#endif 377#if OPT_SCO_FUNC_KEYS 378 { "set-sco-function-keys", HandleScoFunctionKeys }, 379#endif 380#if OPT_SCROLL_LOCK 381 { "scroll-lock", HandleScrollLock }, 382#endif 383#if OPT_SELECTION_OPS 384 { "exec-formatted", HandleExecFormatted }, 385 { "exec-selectable", HandleExecSelectable }, 386 { "insert-formatted", HandleInsertFormatted }, 387 { "insert-selectable", HandleInsertSelectable }, 388#endif 389#if OPT_SHIFT_FONTS 390 { "larger-vt-font", HandleLargerFont }, 391 { "smaller-vt-font", HandleSmallerFont }, 392#endif 393#if OPT_SIXEL_GRAPHICS 394 { "set-sixel-scrolling", HandleSixelScrolling }, 395#endif 396#if OPT_GRAPHICS 397 { "set-private-colors", HandleSetPrivateColorRegisters }, 398#endif 399#if OPT_SUN_FUNC_KEYS 400 { "set-sun-function-keys", HandleSunFunctionKeys }, 401#endif 402#if OPT_TEK4014 403 { "set-terminal-type", HandleSetTerminalType }, 404 { "set-visibility", HandleVisibility }, 405 { "set-tek-text", HandleSetTekText }, 406 { "tek-page", HandleTekPage }, 407 { "tek-reset", HandleTekReset }, 408 { "tek-copy", HandleTekCopy }, 409#endif 410#if OPT_TOOLBAR 411 { "set-toolbar", HandleToolbar }, 412#endif 413#if OPT_WIDE_CHARS 414 { "set-utf8-mode", HandleUTF8Mode }, 415 { "set-utf8-fonts", HandleUTF8Fonts }, 416 { "set-utf8-title", HandleUTF8Title }, 417#endif 418}; 419/* *INDENT-ON* */ 420 421#define SPS screen.printer_state 422 423static XtResource xterm_resources[] = 424{ 425 Bres(XtNallowPasteControls, XtCAllowPasteControls, 426 screen.allowPasteControl0, False), 427 Bres(XtNallowSendEvents, XtCAllowSendEvents, screen.allowSendEvent0, False), 428 Bres(XtNallowColorOps, XtCAllowColorOps, screen.allowColorOp0, DEF_ALLOW_COLOR), 429 Bres(XtNallowFontOps, XtCAllowFontOps, screen.allowFontOp0, DEF_ALLOW_FONT), 430 Bres(XtNallowMouseOps, XtCAllowMouseOps, screen.allowMouseOp0, DEF_ALLOW_MOUSE), 431 Bres(XtNallowTcapOps, XtCAllowTcapOps, screen.allowTcapOp0, DEF_ALLOW_TCAP), 432 Bres(XtNallowTitleOps, XtCAllowTitleOps, screen.allowTitleOp0, DEF_ALLOW_TITLE), 433 Bres(XtNallowWindowOps, XtCAllowWindowOps, screen.allowWindowOp0, DEF_ALLOW_WINDOW), 434 Bres(XtNaltIsNotMeta, XtCAltIsNotMeta, screen.alt_is_not_meta, False), 435 Bres(XtNaltSendsEscape, XtCAltSendsEscape, screen.alt_sends_esc, DEF_ALT_SENDS_ESC), 436 Bres(XtNallowBoldFonts, XtCAllowBoldFonts, screen.allowBoldFonts, True), 437 Bres(XtNalwaysBoldMode, XtCAlwaysBoldMode, screen.always_bold_mode, False), 438 Bres(XtNalwaysHighlight, XtCAlwaysHighlight, screen.always_highlight, False), 439 Bres(XtNappcursorDefault, XtCAppcursorDefault, misc.appcursorDefault, False), 440 Bres(XtNappkeypadDefault, XtCAppkeypadDefault, misc.appkeypadDefault, False), 441 Bres(XtNalternateScroll, XtCScrollCond, screen.alternateScroll, False), 442 Bres(XtNautoWrap, XtCAutoWrap, misc.autoWrap, True), 443 Bres(XtNawaitInput, XtCAwaitInput, screen.awaitInput, False), 444 Bres(XtNfreeBoldBox, XtCFreeBoldBox, screen.free_bold_box, False), 445 Bres(XtNbackarrowKey, XtCBackarrowKey, screen.backarrow_key, DEF_BACKARO_BS), 446 Bres(XtNbellIsUrgent, XtCBellIsUrgent, screen.bellIsUrgent, False), 447 Bres(XtNbellOnReset, XtCBellOnReset, screen.bellOnReset, True), 448 Bres(XtNboldMode, XtCBoldMode, screen.bold_mode, True), 449 Bres(XtNbrokenSelections, XtCBrokenSelections, screen.brokenSelections, False), 450 Bres(XtNc132, XtCC132, screen.c132, False), 451 Bres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll, False), 452 Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False), 453 Bres(XtNcurses, XtCCurses, screen.curses, False), 454 Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True), 455 Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, 456 screen.cutToBeginningOfLine, True), 457 Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL), 458 Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True), 459 Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False), 460 Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True), 461 Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True), 462 Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True), 463 Bres(XtNhighlightSelection, XtCHighlightSelection, 464 screen.highlight_selection, False), 465 Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False), 466 Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False), 467 Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True), 468 Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False), 469 Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True), 470 Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False), 471 Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True), 472 Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False), 473 Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False), 474 Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC), 475 Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False), 476 Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False), 477 Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False), 478 Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False), 479 Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False), 480 Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False), 481 Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True), 482 Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False), 483 Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False), 484 Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False), 485 Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False), 486 Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False), 487 Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False), 488 Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True), 489 Bres(XtNselectToClipboard, XtCSelectToClipboard, 490 screen.selectToClipboard, False), 491 Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False), 492 Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False), 493 Bres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll, False), 494 Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False), 495 Bres(XtNunderLine, XtCUnderLine, screen.underline, True), 496 Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False), 497 Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False), 498 499 Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"), 500 501 Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC), 502 Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource), 503 Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER), 504 Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1), 505 Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE), 506 Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME), 507 Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL), 508 Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE), 509 Ires(XtNprinterControlMode, XtCPrinterControlMode, 510 SPS.printer_controlmode, 0), 511 Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES), 512 Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1), 513 Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100), 514 Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES), 515 Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1), 516 Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES), 517 518 Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL), 519 Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL), 520 Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL), 521 Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL), 522 Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL), 523 Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL), 524 Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL), 525 Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL), 526 527 Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""), 528 Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT), 529 Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL), 530 Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID), 531 Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"), 532 Sres(XtNdisallowedColorOps, XtCDisallowedColorOps, 533 screen.disallowedColorOps, DEF_DISALLOWED_COLOR), 534 Sres(XtNdisallowedFontOps, XtCDisallowedFontOps, 535 screen.disallowedFontOps, DEF_DISALLOWED_FONT), 536 Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps, 537 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE), 538 Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls, 539 screen.disallowedPasteControls, DEF_DISALLOWED_PASTE_CONTROLS), 540 Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps, 541 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP), 542 Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps, 543 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW), 544 Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META), 545 Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes, 546 screen.eightbit_select_types, NULL), 547 Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT), 548 Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL), 549 Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT), 550 Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""), 551 Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL), 552 Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL), 553 554 Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground), 555 Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground), 556 Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground), 557 Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground), 558 Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground), 559 560 {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity), 561 XtOffsetOf(XtermWidgetRec, misc.resizeGravity), 562 XtRImmediate, (XtPointer) SouthWestGravity}, 563 564 Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"), 565 566#ifdef ALLOWLOGGING 567 Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False), 568 Bres(XtNlogging, XtCLogging, misc.log_on, False), 569 Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL), 570#endif 571 572#ifndef NO_ACTIVE_ICON 573 Sres("activeIcon", "ActiveIcon", misc.active_icon_s, "default"), 574 Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2), 575 Sres("iconFont", "IconFont", screen.icon_fontname, "nil2"), 576 Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground), 577#endif /* NO_ACTIVE_ICON */ 578 579#if OPT_BLINK_CURS 580 Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True), 581 Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"), 582#endif 583 Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False), 584 585#if OPT_BLINK_TEXT 586 Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD), 587#endif 588 589#if OPT_BLINK_CURS || OPT_BLINK_TEXT 590 Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600), 591 Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300), 592#endif 593 594#if OPT_BOX_CHARS 595 Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False), 596 Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True), 597 Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False), 598 Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True), 599#endif 600 601#if OPT_BROKEN_OSC 602 Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True), 603#endif 604 605#if OPT_BROKEN_ST 606 Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False), 607#endif 608 609#if OPT_C1_PRINT 610 Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False), 611#endif 612 613#if OPT_CLIP_BOLD 614 Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True), 615 Bres(XtNuseBorderClipping, XtCUseBorderClipping, 616 screen.use_border_clipping, False), 617#endif 618 619#if OPT_DEC_CHRSET 620 Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True), 621 Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET), 622#endif 623 624#if OPT_DEC_RECTOPS 625 Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC), 626#endif 627 628#if OPT_HIGHLIGHT_COLOR 629 Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground), 630 Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground), 631 Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True), 632 Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe), 633#endif /* OPT_HIGHLIGHT_COLOR */ 634 635#if OPT_INPUT_METHOD 636 Bres(XtNopenIm, XtCOpenIm, misc.open_im, True), 637 Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL), 638 Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type, 639 "OverTheSpot,Root"), 640 Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3), 641#endif 642 643#if OPT_ISO_COLORS 644 Bres(XtNboldColors, XtCColorMode, screen.boldColors, True), 645 Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0), 646 Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE), 647 648 Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False), 649 Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False), 650 Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False), 651 Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False), 652 Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False), 653 Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False), 654#if OPT_WIDE_ATTRS 655 Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False), 656#endif 657#if OPT_DIRECT_COLOR 658 Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True), 659#endif 660 661 COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")), 662 COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")), 663 COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")), 664 COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")), 665 COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)), 666 COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")), 667 COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")), 668 COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")), 669 COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")), 670 COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")), 671 COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")), 672 COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")), 673 COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)), 674 COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")), 675 COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")), 676 COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")), 677 COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)), 678 COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)), 679 COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)), 680 COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)), 681 682#if OPT_WIDE_ATTRS 683 COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)), 684#endif 685 686#if !OPT_COLOR_RES2 687#if OPT_256_COLORS 688# include <256colres.h> 689#elif OPT_88_COLORS 690# include <88colres.h> 691#endif 692#endif /* !OPT_COLOR_RES2 */ 693 694#endif /* OPT_ISO_COLORS */ 695 696 CLICK_RES("2", screen.onClick[1], "word"), 697 CLICK_RES("3", screen.onClick[2], "line"), 698 CLICK_RES("4", screen.onClick[3], 0), 699 CLICK_RES("5", screen.onClick[4], 0), 700 701 Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"), 702 703#if OPT_MOD_FKEYS 704 Ires(XtNmodifyKeyboard, XtCModifyKeyboard, 705 keyboard.modify_1st.allow_keys, 0), 706 Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys, 707 keyboard.modify_1st.cursor_keys, 2), 708 Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys, 709 keyboard.modify_1st.function_keys, 2), 710 Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys, 711 keyboard.modify_1st.keypad_keys, 0), 712 Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys, 713 keyboard.modify_1st.other_keys, 0), 714 Ires(XtNmodifyStringKeys, XtCModifyStringKeys, 715 keyboard.modify_1st.string_keys, 0), 716 Ires(XtNformatOtherKeys, XtCFormatOtherKeys, 717 keyboard.format_keys, 0), 718#endif 719 720#if OPT_NUM_LOCK 721 Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False), 722 Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True), 723#endif 724 725#if OPT_PRINT_COLORS 726 Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1), 727#endif 728 729#if OPT_REGIS_GRAPHICS 730 Sres(XtNregisDefaultFont, XtCRegisDefaultFont, 731 screen.graphics_regis_default_font, ""), 732 Sres(XtNregisScreenSize, XtCRegisScreenSize, 733 screen.graphics_regis_screensize, "auto"), 734#endif 735 736#if OPT_GRAPHICS 737 Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID), 738 Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size, 739 "1000x1000"), 740#endif 741 742#if OPT_SHIFT_FONTS 743 Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True), 744#endif 745 746#if OPT_SIXEL_GRAPHICS 747 Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, True), 748 Bres(XtNsixelScrollsRight, XtCSixelScrollsRight, 749 screen.sixel_scrolls_right, False), 750#endif 751 752#if OPT_GRAPHICS 753 Ires(XtNnumColorRegisters, XtCNumColorRegisters, 754 screen.numcolorregisters, 0), 755 Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters, 756 screen.privatecolorregisters, True), 757#endif 758 759#if OPT_SUNPC_KBD 760 Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10), 761#endif 762 763#if OPT_TEK4014 764 Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False), 765 Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False), 766 Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False), 767#endif 768 769#if OPT_TOOLBAR 770 Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0), 771 Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25), 772#endif 773 774#if OPT_WIDE_CHARS 775 Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False), 776 Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False), 777 Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True), 778 Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False), 779 Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False), 780 Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True), 781 Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False), 782 Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2), 783 Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655), 784 Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536), 785 Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"), 786 Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"), 787 Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"), 788 Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT), 789 Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT), 790 Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL), 791#endif 792 793#if OPT_LUIT_PROG 794 Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"), 795 Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER), 796#endif 797 798#if OPT_INPUT_METHOD 799 Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT), 800#endif 801 802#if OPT_SCROLL_LOCK 803 Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False), 804 Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False), 805#endif 806 807 /* these are used only for testing ncurses, not in the manual page */ 808#if OPT_XMC_GLITCH 809 Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False), 810 Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True), 811 Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1), 812 Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0), 813#endif 814 815#ifdef SCROLLBAR_RIGHT 816 Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False), 817#endif 818 819#if OPT_RENDERFONT 820 Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False), 821#define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0") 822 RES_FACESIZE(1), 823 RES_FACESIZE(2), 824 RES_FACESIZE(3), 825 RES_FACESIZE(4), 826 RES_FACESIZE(5), 827 RES_FACESIZE(6), 828 Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE), 829 Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME), 830 Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"), 831 Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE), 832#if OPT_RENDERWIDE 833 Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME), 834#endif 835#endif 836}; 837 838static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg, 839 ArgList args, Cardinal *num_args); 840static void VTClassInit(void); 841static void VTDestroy(Widget w); 842static void VTExpose(Widget w, XEvent *event, Region region); 843static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args, 844 Cardinal *num_args); 845static void VTRealize(Widget w, XtValueMask * valuemask, 846 XSetWindowAttributes * values); 847static void VTResize(Widget w); 848 849#if OPT_INPUT_METHOD 850static void VTInitI18N(XtermWidget); 851#endif 852 853#ifdef VMS 854globaldef { 855 "xtermclassrec" 856} noshare 857 858#else 859static 860#endif /* VMS */ 861WidgetClassRec xtermClassRec = 862{ 863 { 864 /* core_class fields */ 865 (WidgetClass) & widgetClassRec, /* superclass */ 866 "VT100", /* class_name */ 867 sizeof(XtermWidgetRec), /* widget_size */ 868 VTClassInit, /* class_initialize */ 869 NULL, /* class_part_initialize */ 870 False, /* class_inited */ 871 VTInitialize, /* initialize */ 872 NULL, /* initialize_hook */ 873 VTRealize, /* realize */ 874 actionsList, /* actions */ 875 XtNumber(actionsList), /* num_actions */ 876 xterm_resources, /* resources */ 877 XtNumber(xterm_resources), /* num_resources */ 878 NULLQUARK, /* xrm_class */ 879 True, /* compress_motion */ 880 False, /* compress_exposure */ 881 True, /* compress_enterleave */ 882 False, /* visible_interest */ 883 VTDestroy, /* destroy */ 884 VTResize, /* resize */ 885 VTExpose, /* expose */ 886 VTSetValues, /* set_values */ 887 NULL, /* set_values_hook */ 888 XtInheritSetValuesAlmost, /* set_values_almost */ 889 NULL, /* get_values_hook */ 890 NULL, /* accept_focus */ 891 XtVersion, /* version */ 892 NULL, /* callback_offsets */ 893 0, /* tm_table */ 894 XtInheritQueryGeometry, /* query_geometry */ 895 XtInheritDisplayAccelerator, /* display_accelerator */ 896 NULL /* extension */ 897 } 898}; 899 900#ifdef VMS 901globaldef { 902 "xtermwidgetclass" 903} 904noshare 905#endif /* VMS */ 906WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec; 907 908/* 909 * Add input-actions for widgets that are overlooked (scrollbar and toolbar): 910 * 911 * a) Sometimes the scrollbar passes through translations, sometimes it 912 * doesn't. We add the KeyPress translations here, just to be sure. 913 * b) In the normal (non-toolbar) configuration, the xterm widget covers 914 * almost all of the window. With a toolbar, there's a relatively 915 * large area that the user would expect to enter keystrokes since the 916 * program can get the focus. 917 */ 918void 919xtermAddInput(Widget w) 920{ 921 /* *INDENT-OFF* */ 922 XtActionsRec input_actions[] = { 923 { "insert", HandleKeyPressed }, /* alias */ 924 { "insert-eight-bit", HandleEightBitKeyPressed }, 925 { "insert-seven-bit", HandleKeyPressed }, 926 { "pointer-motion", HandlePointerMotion }, 927 { "pointer-button", HandlePointerButton }, 928 { "secure", HandleSecure }, 929 { "string", HandleStringEvent }, 930 { "scroll-back", HandleScrollBack }, 931 { "scroll-forw", HandleScrollForward }, 932 { "scroll-to", HandleScrollTo }, 933 { "select-cursor-end", HandleKeyboardSelectEnd }, 934 { "select-cursor-extend", HandleKeyboardSelectExtend }, 935 { "select-cursor-start", HandleKeyboardSelectStart }, 936 { "insert-selection", HandleInsertSelection }, 937 { "select-start", HandleSelectStart }, 938 { "select-extend", HandleSelectExtend }, 939 { "start-extend", HandleStartExtend }, 940 { "select-end", HandleSelectEnd }, 941 { "clear-saved-lines", HandleClearSavedLines }, 942 { "popup-menu", HandlePopupMenu }, 943 { "bell", HandleBell }, 944 { "ignore", HandleIgnore }, 945#if OPT_DABBREV 946 { "dabbrev-expand", HandleDabbrevExpand }, 947#endif 948#if OPT_MAXIMIZE 949 { "fullscreen", HandleFullscreen }, 950#endif 951#if OPT_SCROLL_LOCK 952 { "scroll-lock", HandleScrollLock }, 953#endif 954#if OPT_SHIFT_FONTS 955 { "larger-vt-font", HandleLargerFont }, 956 { "smaller-vt-font", HandleSmallerFont }, 957#endif 958 }; 959 /* *INDENT-ON* */ 960 961 TRACE_TRANS("BEFORE", w); 962 XtAppAddActions(app_con, input_actions, XtNumber(input_actions)); 963 XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations)); 964 TRACE_TRANS("AFTER:", w); 965 966#if OPT_EXTRA_PASTE 967 if (term && term->keyboard.extra_translations) 968 XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations)); 969#endif 970} 971 972#if OPT_ISO_COLORS 973#ifdef EXP_BOGUS_FG 974static Bool 975CheckBogusForeground(TScreen *screen, const char *tag) 976{ 977 int row = -1, col = -1, pass; 978 Bool isClear = True; 979 980 (void) tag; 981 for (pass = 0; pass < 2; ++pass) { 982 row = screen->cur_row; 983 for (; isClear && (row <= screen->max_row); ++row) { 984 CLineData *ld = getLineData(screen, row); 985 986 if (ld != 0) { 987 IAttr *attribs = ld->attribs; 988 989 col = (row == screen->cur_row) ? screen->cur_col : 0; 990 for (; isClear && (col <= screen->max_col); ++col) { 991 unsigned flags = attribs[col]; 992 if (pass) { 993 flags &= ~FG_COLOR; 994 attribs[col] = (IAttr) flags; 995 } else if ((flags & BG_COLOR)) { 996 isClear = False; 997 } else if ((flags & FG_COLOR)) { 998 unsigned ch = ld->charData[col]; 999 isClear = ((ch == ' ') || (ch == 0)); 1000 } else { 1001 isClear = False; 1002 } 1003 } 1004 } 1005 } 1006 } 1007 TRACE(("%s checked %d,%d to %d,%d %s pass %d\n", 1008 tag, screen->cur_row, screen->cur_col, 1009 row, col, 1010 isClear && pass ? "cleared" : "unchanged", 1011 pass)); 1012 1013 return isClear; 1014} 1015#endif 1016 1017/* 1018 * The terminal's foreground and background colors are set via two mechanisms: 1019 * text (cur_foreground, cur_background values that are passed down to 1020 * XDrawImageString and XDrawString) 1021 * area (X11 graphics context used in XClearArea and XFillRectangle) 1022 */ 1023void 1024SGR_Foreground(XtermWidget xw, int color) 1025{ 1026 TScreen *screen = TScreenOf(xw); 1027 Pixel fg; 1028 1029 if (color >= 0) { 1030 UIntSet(xw->flags, FG_COLOR); 1031 } else { 1032 UIntClr(xw->flags, FG_COLOR); 1033 } 1034 fg = getXtermFG(xw, xw->flags, color); 1035 xw->cur_foreground = color; 1036 1037 setCgsFore(xw, WhichVWin(screen), gcNorm, fg); 1038 setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg); 1039 1040 setCgsFore(xw, WhichVWin(screen), gcBold, fg); 1041 setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg); 1042 1043#ifdef EXP_BOGUS_FG 1044 /* 1045 * If we've just turned off the foreground color, check for blank cells 1046 * which have no background color, but do have foreground color. This 1047 * could happen due to setting the foreground color just before scrolling. 1048 * 1049 * Those cells look uncolored, but will confuse ShowCursor(), which looks 1050 * for the colors in the current cell, and will see the foreground color. 1051 * In that case, remove the foreground color from the blank cells. 1052 */ 1053 if (color < 0) { 1054 CheckBogusForeground(screen, "SGR_Foreground"); 1055 } 1056#endif 1057} 1058 1059void 1060SGR_Background(XtermWidget xw, int color) 1061{ 1062 TScreen *screen = TScreenOf(xw); 1063 Pixel bg; 1064 1065 /* 1066 * An indexing operation may have set screen->scroll_amt, which would 1067 * normally result in calling FlushScroll() in WriteText(). However, 1068 * if we're changing the background color now, then the new value 1069 * should not apply to the pending blank lines. 1070 */ 1071 if (screen->scroll_amt && (color != xw->cur_background)) 1072 FlushScroll(xw); 1073 1074 if (color >= 0) { 1075 UIntSet(xw->flags, BG_COLOR); 1076 } else { 1077 UIntClr(xw->flags, BG_COLOR); 1078 } 1079 bg = getXtermBG(xw, xw->flags, color); 1080 xw->cur_background = color; 1081 1082 setCgsBack(xw, WhichVWin(screen), gcNorm, bg); 1083 setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg); 1084 1085 setCgsBack(xw, WhichVWin(screen), gcBold, bg); 1086 setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg); 1087} 1088 1089/* Invoked after updating bold/underline flags, computes the extended color 1090 * index to use for foreground. (See also 'extract_fg()'). 1091 */ 1092static void 1093setExtendedFG(XtermWidget xw) 1094{ 1095 int fg = xw->sgr_foreground; 1096 1097 if (TScreenOf(xw)->colorAttrMode 1098 || (fg < 0)) { 1099 fg = MapToColorMode(fg, TScreenOf(xw), xw->flags); 1100 } 1101 1102 /* This implements the IBM PC-style convention of 8-colors, with one 1103 * bit for bold, thus mapping the 0-7 codes to 8-15. It won't make 1104 * much sense for 16-color applications, but we keep it to retain 1105 * compatibility with ANSI-color applications. 1106 */ 1107#if OPT_PC_COLORS /* XXXJTL should be settable at runtime (resource or OSC?) */ 1108 if (TScreenOf(xw)->boldColors 1109 && (!xw->sgr_38_xcolors) 1110 && (fg >= 0) 1111 && (fg < 8) 1112 && (xw->flags & BOLD)) 1113 fg |= 8; 1114#endif 1115 1116 SGR_Foreground(xw, fg); 1117} 1118 1119/* Invoked after updating inverse flag, computes the extended color 1120 * index to use for background. (See also 'extract_bg()'). 1121 */ 1122static void 1123setExtendedBG(XtermWidget xw) 1124{ 1125 int bg = xw->sgr_background; 1126 1127 if (TScreenOf(xw)->colorAttrMode 1128 || (bg < 0)) { 1129 if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE)) 1130 bg = COLOR_RV; 1131 } 1132 1133 SGR_Background(xw, bg); 1134} 1135 1136void 1137setExtendedColors(XtermWidget xw) 1138{ 1139 setExtendedFG(xw); 1140 setExtendedBG(xw); 1141} 1142 1143static void 1144reset_SGR_Foreground(XtermWidget xw) 1145{ 1146 xw->sgr_foreground = -1; 1147 xw->sgr_38_xcolors = False; 1148 clrDirectFG(xw->flags); 1149 setExtendedFG(xw); 1150} 1151 1152static void 1153reset_SGR_Background(XtermWidget xw) 1154{ 1155 xw->sgr_background = -1; 1156 clrDirectBG(xw->flags); 1157 setExtendedBG(xw); 1158} 1159 1160static void 1161reset_SGR_Colors(XtermWidget xw) 1162{ 1163 reset_SGR_Foreground(xw); 1164 reset_SGR_Background(xw); 1165} 1166#endif /* OPT_ISO_COLORS */ 1167 1168#if OPT_WIDE_ATTRS 1169/* 1170 * Call this before changing the state of ATR_ITALIC, to update the GC fonts. 1171 */ 1172static void 1173setItalicFont(XtermWidget xw, Bool enable) 1174{ 1175 if (enable) { 1176 if ((xw->flags & ATR_ITALIC) == 0) { 1177 xtermLoadItalics(xw); 1178 TRACE(("setItalicFont: enabling Italics\n")); 1179 xtermUpdateFontGCs(xw, getItalicFont); 1180 } 1181 } else if ((xw->flags & ATR_ITALIC) != 0) { 1182 TRACE(("setItalicFont: disabling Italics\n")); 1183 xtermUpdateFontGCs(xw, getNormalFont); 1184 } 1185} 1186 1187static void 1188ResetItalics(XtermWidget xw) 1189{ 1190 setItalicFont(xw, False); 1191 UIntClr(xw->flags, ATR_ITALIC); 1192} 1193 1194#else 1195#define ResetItalics(xw) /* nothing */ 1196#endif 1197 1198static void 1199initCharset(TScreen *screen, int which, DECNRCM_codes code) 1200{ 1201 screen->gsets[which] = code; 1202} 1203 1204void 1205saveCharsets(TScreen *screen, DECNRCM_codes * target) 1206{ 1207 int g; 1208 for (g = 0; g < NUM_GSETS; ++g) { 1209 target[g] = screen->gsets[g]; 1210 } 1211} 1212 1213void 1214restoreCharsets(TScreen *screen, DECNRCM_codes * source) 1215{ 1216 int g; 1217 for (g = 0; g < NUM_GSETS; ++g) { 1218 screen->gsets[g] = source[g]; 1219 } 1220} 1221 1222void 1223resetCharsets(TScreen *screen) 1224{ 1225 TRACE(("resetCharsets\n")); 1226 1227 initCharset(screen, 0, nrc_ASCII); 1228 initCharset(screen, 1, nrc_ASCII); 1229 initCharset(screen, 2, nrc_ASCII); 1230 initCharset(screen, 3, nrc_ASCII); 1231 1232 screen->curgl = 0; /* G0 => GL. */ 1233 screen->curgr = 2; /* G2 => GR. */ 1234 screen->curss = 0; /* No single shift. */ 1235 1236#if OPT_VT52_MODE 1237 if (screen->vtXX_level == 0) 1238 initCharset(screen, 1, nrc_DEC_Spec_Graphic); /* Graphics */ 1239#endif 1240} 1241 1242static void 1243modified_DECNRCM(XtermWidget xw) 1244{ 1245#if OPT_WIDE_CHARS 1246 TScreen *screen = TScreenOf(xw); 1247 if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) { 1248 int enabled = ((xw->flags & NATIONAL) != 0); 1249 int modefix; 1250 EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix); 1251 switchPtyData(screen, !enabled); 1252 TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF")); 1253 } 1254#else 1255 (void) xw; 1256#endif 1257} 1258 1259/* 1260 * VT300 and up support three ANSI conformance levels, defined according to 1261 * the dpANSI X3.134.1 standard. DEC's manuals equate levels 1 and 2, and 1262 * are unclear. This code is written based on the manuals. 1263 */ 1264static void 1265set_ansi_conformance(TScreen *screen, int level) 1266{ 1267 TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n", 1268 level, 1269 screen->vtXX_level * 100, 1270 screen->terminal_id, 1271 screen->ansi_level)); 1272 if (screen->vtXX_level >= 3) { 1273 switch (screen->ansi_level = level) { 1274 case 1: 1275 /* FALLTHRU */ 1276 case 2: 1277 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */ 1278 initCharset(screen, 1, nrc_ASCII); /* G1 is ISO Latin-1 */ 1279 screen->curgl = 0; 1280 screen->curgr = 1; 1281 break; 1282 case 3: 1283 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */ 1284 screen->curgl = 0; 1285 break; 1286 } 1287 } 1288} 1289 1290/* 1291 * Set scrolling margins. VTxxx terminals require that the top/bottom are 1292 * different, so we have at least two lines in the scrolling region. 1293 */ 1294static void 1295set_tb_margins(TScreen *screen, int top, int bottom) 1296{ 1297 TRACE(("set_tb_margins %d..%d, prior %d..%d\n", 1298 top, bottom, 1299 screen->top_marg, 1300 screen->bot_marg)); 1301 if (bottom > top) { 1302 screen->top_marg = top; 1303 screen->bot_marg = bottom; 1304 } 1305 if (screen->top_marg > screen->max_row) 1306 screen->top_marg = screen->max_row; 1307 if (screen->bot_marg > screen->max_row) 1308 screen->bot_marg = screen->max_row; 1309} 1310 1311static void 1312set_lr_margins(TScreen *screen, int left, int right) 1313{ 1314 TRACE(("set_lr_margins %d..%d, prior %d..%d\n", 1315 left, right, 1316 screen->lft_marg, 1317 screen->rgt_marg)); 1318 if (right > left) { 1319 screen->lft_marg = left; 1320 screen->rgt_marg = right; 1321 } 1322 if (screen->lft_marg > screen->max_col) 1323 screen->lft_marg = screen->max_col; 1324 if (screen->rgt_marg > screen->max_col) 1325 screen->rgt_marg = screen->max_col; 1326} 1327 1328#define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row) 1329#define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col) 1330 1331void 1332resetMargins(XtermWidget xw) 1333{ 1334 TScreen *screen = TScreenOf(xw); 1335 1336 UIntClr(xw->flags, LEFT_RIGHT); 1337 reset_tb_margins(screen); 1338 reset_lr_margins(screen); 1339} 1340 1341static void 1342resetRendition(XtermWidget xw) 1343{ 1344 TScreen *screen = TScreenOf(xw); 1345 (void) screen; 1346 ResetItalics(xw); 1347 UIntClr(xw->flags, 1348 (SGR_MASK | SGR_MASK2 | INVISIBLE)); 1349} 1350 1351void 1352set_max_col(TScreen *screen, int cols) 1353{ 1354 TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col)); 1355 if (cols < 0) 1356 cols = 0; 1357 screen->max_col = cols; 1358} 1359 1360void 1361set_max_row(TScreen *screen, int rows) 1362{ 1363 TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row)); 1364 if (rows < 0) 1365 rows = 0; 1366 screen->max_row = rows; 1367} 1368 1369#if OPT_MOD_FKEYS 1370static void 1371set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled) 1372{ 1373#define SET_MOD_FKEYS(field) \ 1374 xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \ 1375 ? xw->keyboard.modify_1st.field \ 1376 : what; \ 1377 TRACE(("set modify_now.%s to %d\n", #field, \ 1378 xw->keyboard.modify_now.field)); 1379 1380 switch (which) { 1381 case 0: 1382 SET_MOD_FKEYS(allow_keys); 1383 break; 1384 case 1: 1385 SET_MOD_FKEYS(cursor_keys); 1386 break; 1387 case 2: 1388 SET_MOD_FKEYS(function_keys); 1389 break; 1390 case 3: 1391 SET_MOD_FKEYS(keypad_keys); 1392 break; 1393 case 4: 1394 SET_MOD_FKEYS(other_keys); 1395 break; 1396 case 5: 1397 SET_MOD_FKEYS(string_keys); 1398 break; 1399 } 1400} 1401#endif /* OPT_MOD_FKEYS */ 1402 1403#if OPT_TRACE 1404#define DATA(name) { name, #name } 1405static const struct { 1406 Const PARSE_T *table; 1407 const char *name; 1408} all_tables[] = { 1409 1410 DATA(ansi_table) 1411 ,DATA(cigtable) 1412 ,DATA(csi2_table) 1413 ,DATA(csi_ex_table) 1414 ,DATA(csi_quo_table) 1415 ,DATA(csi_table) 1416 ,DATA(dec2_table) 1417 ,DATA(dec3_table) 1418 ,DATA(dec_table) 1419 ,DATA(eigtable) 1420 ,DATA(esc_sp_table) 1421 ,DATA(esc_table) 1422 ,DATA(scrtable) 1423 ,DATA(scs96table) 1424 ,DATA(scstable) 1425 ,DATA(sos_table) 1426#if OPT_BLINK_CURS 1427 ,DATA(csi_sp_table) 1428#endif 1429#if OPT_DEC_LOCATOR 1430 ,DATA(csi_tick_table) 1431#endif 1432#if OPT_DEC_RECTOPS 1433 ,DATA(csi_dollar_table) 1434 ,DATA(csi_star_table) 1435 ,DATA(csi_dec_dollar_table) 1436#endif 1437#if OPT_WIDE_CHARS 1438 ,DATA(esc_pct_table) 1439 ,DATA(scs_amp_table) 1440 ,DATA(scs_pct_table) 1441 ,DATA(scs_2qt_table) 1442#endif 1443#if OPT_VT52_MODE 1444 ,DATA(vt52_table) 1445 ,DATA(vt52_esc_table) 1446 ,DATA(vt52_ignore_table) 1447#endif 1448#if OPT_XTERM_SGR 1449 ,DATA(csi_hash_table) 1450#endif 1451#undef DATA 1452}; 1453 1454#define WHICH_TABLE(name) if (table == name) result = #name 1455static const char * 1456which_table(Const PARSE_T * table) 1457{ 1458 const char *result = "?"; 1459 Cardinal n; 1460 for (n = 0; n < XtNumber(all_tables); ++n) { 1461 if (table == all_tables[n].table) { 1462 result = all_tables[n].name; 1463 break; 1464 } 1465 } 1466 1467 return result; 1468} 1469 1470static void 1471check_tables(void) 1472{ 1473 Cardinal n; 1474 int ch; 1475 int total_codes = 0; 1476 int total_ground = 0; 1477 int total_ignored = 0; 1478 1479 TRACE(("** check_tables\n")); 1480 for (n = 0; n < XtNumber(all_tables); ++n) { 1481 Const PARSE_T *table = all_tables[n].table; 1482 TRACE(("*** %s\n", all_tables[n].name)); 1483 /* 1484 * Most of the tables should use the same codes in 0..31, 128..159 1485 * as the "ansi" table. 1486 */ 1487 if (strncmp(all_tables[n].name, "ansi", 4) && 1488 strncmp(all_tables[n].name, "sos_", 4) && 1489 strncmp(all_tables[n].name, "vt52", 4)) { 1490 for (ch = 0; ch < 32; ++ch) { 1491 int c1 = ch + 128; 1492 PARSE_T st_l = table[ch]; 1493 PARSE_T st_r = table[c1]; 1494 if (st_l != ansi_table[ch]) { 1495 TRACE((" %3d: %d vs %d\n", ch, st_l, ansi_table[ch])); 1496 } 1497 if (st_r != ansi_table[c1]) { 1498 TRACE((" %3d: %d vs %d\n", c1, st_r, ansi_table[c1])); 1499 } 1500 } 1501 } 1502 /* 1503 * All of the tables should have their GL/GR parts encoded the same. 1504 */ 1505 for (ch = 32; ch < 127; ++ch) { 1506 PARSE_T st_l = table[ch]; 1507 PARSE_T st_r = table[ch + 128]; 1508 if (st_l != st_r) { 1509 if (st_r == CASE_IGNORE && 1510 !strncmp(all_tables[n].name, "vt52", 4)) { 1511 ; 1512 } else { 1513 TRACE((" %3d: %d vs %d\n", ch, st_l, st_r)); 1514 } 1515 } 1516 } 1517 /* 1518 * Just for amusement, show how sparse the encoding tables are. 1519 */ 1520 for (ch = 0; ch < 256; ++ch) { 1521 ++total_codes; 1522 switch (table[ch]) { 1523 case CASE_GROUND_STATE: 1524 total_ground++; 1525 break; 1526 case CASE_ESC_IGNORE: 1527 /* FALLTHRU */ 1528 case CASE_IGNORE: 1529 /* FALLTHRU */ 1530 case CASE_VT52_IGNORE: 1531 total_ignored++; 1532 break; 1533 } 1534 } 1535 } 1536 TRACE(("VTPrsTbl:\n")); 1537 TRACE(("%d total codes\n", total_codes)); 1538 TRACE(("%d total ignored\n", total_ignored)); 1539 TRACE(("%d total reset/ground\n", total_ground)); 1540} 1541 1542static void 1543check_bitmasks(void) 1544{ 1545#define dMSK 0x100 1546#define DATA(mode,name) { mode, name, #name } 1547#define DMSK(what) (dMSK | (what)) 1548#define DGRP(offs) (1 << ((offs) - 1)) 1549 static struct { 1550 int mode; 1551 int code; 1552 Const char *name; 1553 } table[] = { 1554 DATA(DGRP(1), INVERSE), 1555 DATA(DGRP(1), UNDERLINE), 1556 DATA(DGRP(1), BOLD), 1557 DATA(DGRP(1), BLINK), 1558 DATA(DMSK(DGRP(1)), SGR_MASK), 1559 DATA(DGRP(2), BG_COLOR), 1560 DATA(DGRP(2), FG_COLOR), 1561 DATA(DGRP(2), PROTECTED), 1562 DATA(DGRP(4), CHARDRAWN), 1563#if OPT_WIDE_ATTRS 1564 DATA(DGRP(2), ATR_FAINT), 1565 DATA(DGRP(2), ATR_ITALIC), 1566 DATA(DGRP(2), ATR_STRIKEOUT), 1567 DATA(DGRP(2), ATR_DBL_UNDER), 1568 DATA(DGRP(2), ATR_DIRECT_FG), 1569 DATA(DGRP(2), ATR_DIRECT_BG), 1570#endif 1571 DATA(DMSK(DGRP(2)), SGR_MASK2), 1572 DATA(DGRP(3), WRAPAROUND), 1573 DATA(DGRP(3), REVERSEWRAP), 1574 DATA(DGRP(3), REVERSE_VIDEO), 1575 DATA(DGRP(3), LINEFEED), 1576 DATA(DGRP(3), ORIGIN), 1577 DATA(DGRP(3), INSERT), 1578 DATA(DGRP(3), SMOOTHSCROLL), 1579 DATA(DGRP(3), IN132COLUMNS), 1580 DATA(DGRP(3), INVISIBLE), 1581 DATA(DMSK(DGRP(3)), ATTRIBUTES), 1582 DATA(DGRP(5), NATIONAL), 1583 DATA(DGRP(5), LEFT_RIGHT), 1584 DATA(DGRP(5), NOCLEAR_COLM), 1585 DATA(DGRP(4), NOBACKGROUND), 1586 DATA(DGRP(4), NOTRANSLATION), 1587 DATA(DGRP(4), DOUBLEWFONT), 1588 DATA(DGRP(4), DOUBLEHFONT), 1589 DATA(DGRP(4), CHARBYCHAR), 1590 DATA(DGRP(4), NORESOLUTION), 1591 DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK), 1592 DATA(-1, EOF) 1593 }; 1594#undef DATA 1595 int j, k; 1596 TRACE(("** check_bitmasks:\n")); 1597 for (j = 0; table[j].mode >= 0; ++j) { 1598 TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name)); 1599 if (table[j].mode & dMSK) { 1600 int mask = dMSK; 1601 for (k = 0; table[k].mode >= 0; ++k) { 1602 if (j == k) 1603 continue; 1604 if (table[k].mode & dMSK) 1605 continue; 1606 if ((table[j].mode & table[k].mode) != 0) 1607 mask |= table[k].mode; 1608 } 1609 if (mask != table[j].mode) { 1610 TRACE(("...expected %08X\n", mask)); 1611 } 1612 } else { 1613 for (k = 0; table[k].mode >= 0; ++k) { 1614 if (j == k) 1615 continue; 1616 if (table[k].mode & dMSK) 1617 continue; 1618 if ((table[j].code & table[k].code) != 0) { 1619 TRACE(("...same bits %s\n", table[k].name)); 1620 } 1621 } 1622 } 1623 } 1624} 1625#endif 1626 1627static int 1628init_params(void) 1629{ 1630 while (parms.count-- > 0) { 1631 parms.is_sub[parms.count] = 0; 1632 parms.params[parms.count] = 0; 1633 } 1634 parms.count = 0; 1635 parms.has_subparams = 0; 1636 return 0; 1637} 1638 1639#if OPT_TRACE > 0 1640static void 1641dump_params(void) 1642{ 1643 int n; 1644 int arg; 1645 TRACE(("params %d (%d)\n", nparam, parms.has_subparams)); 1646 for (arg = 1, n = 0; n < nparam; ++n) { 1647 TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n])); 1648 if (!parms.is_sub[n]) 1649 ++arg; 1650 } 1651} 1652#define DumpParams() dump_params() 1653#else 1654#define DumpParams() /* nothing */ 1655#endif 1656 1657 /* allocate larger buffer if needed/possible */ 1658#define SafeAlloc(type, area, used, size) \ 1659 type *new_string = area; \ 1660 size_t new_length = size; \ 1661 if (new_length == 0) { \ 1662 new_length = 1024; \ 1663 new_string = TypeMallocN(type, new_length); \ 1664 } else if (used+1 >= new_length) { \ 1665 new_length = size * 2; \ 1666 new_string = TypeMallocN(type, new_length); \ 1667 if (new_string != 0 \ 1668 && area != 0 \ 1669 && used != 0) { \ 1670 memcpy(new_string, area, used * sizeof(type)); \ 1671 } \ 1672 } 1673#define SafeFree(area, size) \ 1674 if (area != new_string) { \ 1675 free(area); \ 1676 area = new_string; \ 1677 } \ 1678 size = new_length 1679 1680#define WriteNow() { \ 1681 unsigned single = 0; \ 1682 \ 1683 if (screen->curss) { \ 1684 dotext(xw, \ 1685 screen->gsets[(int) (screen->curss)], \ 1686 sp->print_area, \ 1687 (Cardinal) 1); \ 1688 screen->curss = 0; \ 1689 single++; \ 1690 } \ 1691 if (sp->print_used > single) { \ 1692 dotext(xw, \ 1693 screen->gsets[(int) (screen->curgl)], \ 1694 sp->print_area + single, \ 1695 (Cardinal) (sp->print_used - single)); \ 1696 } \ 1697 sp->print_used = 0; \ 1698 } \ 1699 1700#define PARSE_SRM 1 1701 1702struct ParseState { 1703 unsigned check_recur; 1704#if OPT_VT52_MODE 1705 Bool vt52_cup; 1706#endif 1707 Const PARSE_T *groundtable; 1708 Const PARSE_T *parsestate; 1709 int scstype; 1710 int scssize; 1711 Bool private_function; /* distinguish private-mode from standard */ 1712 int string_mode; /* nonzero iff we're processing a string */ 1713 int lastchar; /* positive iff we had a graphic character */ 1714 int nextstate; 1715#if OPT_WIDE_CHARS 1716 int last_was_wide; 1717#endif 1718 /* Buffer for processing printable text */ 1719 IChar *print_area; 1720 size_t print_size; 1721 size_t print_used; 1722 /* Buffer for processing strings (e.g., OSC ... ST) */ 1723 Char *string_area; 1724 size_t string_size; 1725 size_t string_used; 1726 /* Buffer for deferring input */ 1727 Char *defer_area; 1728 size_t defer_size; 1729 size_t defer_used; 1730}; 1731 1732static struct ParseState myState; 1733 1734static void 1735init_groundtable(TScreen *screen, struct ParseState *sp) 1736{ 1737 (void) screen; 1738 1739#if OPT_VT52_MODE 1740 if (!(screen->vtXX_level)) { 1741 sp->groundtable = vt52_table; 1742 } else if (screen->terminal_id >= 100) 1743#endif 1744 { 1745 sp->groundtable = ansi_table; 1746 } 1747} 1748 1749static void 1750select_charset(struct ParseState *sp, int type, int size) 1751{ 1752 TRACE(("select_charset G%d size %d -> G%d size %d\n", 1753 sp->scstype, sp->scssize, 1754 type, size)); 1755 1756 sp->scstype = type; 1757 sp->scssize = size; 1758 if (size == 94) { 1759 sp->parsestate = scstable; 1760 } else { 1761 sp->parsestate = scs96table; 1762 } 1763} 1764/* *INDENT-OFF* */ 1765static const struct { 1766 DECNRCM_codes result; 1767 int prefix; 1768 int suffix; 1769 int min_level; 1770 int max_level; 1771 int need_nrc; 1772} scs_table[] = { 1773 { nrc_ASCII, 0, 'B', 1, 9, 0 }, 1774 { nrc_British, 0, 'A', 1, 9, 0 }, 1775 { nrc_DEC_Spec_Graphic, 0, '0', 1, 9, 0 }, 1776 { nrc_DEC_Alt_Chars, 0, '1', 1, 1, 0 }, 1777 { nrc_DEC_Alt_Graphics, 0, '2', 1, 1, 0 }, 1778 /* VT2xx */ 1779 { nrc_DEC_Supp, 0, '<', 2, 9, 0 }, 1780 { nrc_Dutch, 0, '4', 2, 9, 1 }, 1781 { nrc_Finnish, 0, '5', 2, 9, 1 }, 1782 { nrc_Finnish2, 0, 'C', 2, 9, 1 }, 1783 { nrc_French, 0, 'R', 2, 9, 1 }, 1784 { nrc_French2, 0, 'f', 2, 9, 1 }, 1785 { nrc_French_Canadian, 0, 'Q', 2, 9, 1 }, 1786 { nrc_German, 0, 'K', 2, 9, 1 }, 1787 { nrc_Italian, 0, 'Y', 2, 9, 1 }, 1788 { nrc_Norwegian_Danish2, 0, 'E', 2, 9, 1 }, 1789 { nrc_Norwegian_Danish3, 0, '6', 2, 9, 1 }, 1790 { nrc_Spanish, 0, 'Z', 2, 9, 1 }, 1791 { nrc_Swedish, 0, '7', 2, 9, 1 }, 1792 { nrc_Swedish2, 0, 'H', 2, 9, 1 }, 1793 { nrc_Swiss, 0, '=', 2, 9, 1 }, 1794 /* VT3xx */ 1795 { nrc_British_Latin_1, 0, 'A', 3, 9, 1 }, 1796 { nrc_DEC_Supp_Graphic, '%', '5', 3, 9, 0 }, 1797 { nrc_DEC_Technical, 0, '>', 3, 9, 0 }, 1798 { nrc_French_Canadian2, 0, '9', 3, 9, 1 }, 1799 { nrc_Norwegian_Danish, 0, '`', 3, 9, 1 }, 1800 { nrc_Portugese, '%', '6', 3, 9, 1 }, 1801 { nrc_ISO_Latin_1_Supp, 0, 'A', 3, 9, 0 }, 1802 /* VT5xx */ 1803 { nrc_Greek, '"', '>', 5, 9, 1 }, 1804 { nrc_Hebrew, '%', '=', 5, 9, 1 }, 1805 { nrc_Turkish, '%', '2', 5, 9, 1 }, 1806 { nrc_DEC_Cyrillic, '&', '4', 5, 9, 0 }, 1807 { nrc_DEC_Greek_Supp, '"', '?', 5, 9, 0 }, 1808 { nrc_DEC_Hebrew_Supp, '"', '4', 5, 9, 0 }, 1809 { nrc_DEC_Turkish_Supp, '%', '0', 5, 9, 0 }, 1810 { nrc_ISO_Greek_Supp, 0, 'F', 5, 9, 0 }, 1811 { nrc_ISO_Hebrew_Supp, 0, 'H', 5, 9, 0 }, 1812 { nrc_ISO_Latin_2_Supp, 0, 'B', 5, 9, 0 }, 1813 { nrc_ISO_Latin_5_Supp, 0, 'M', 5, 9, 0 }, 1814 { nrc_ISO_Latin_Cyrillic,0, 'L', 5, 9, 0 }, 1815 /* VT5xx (not implemented) */ 1816#if 0 1817 { nrc_Russian, '&', '5', 5, 9, 1 }, 1818 { nrc_SCS_NRCS, '%', '3', 5, 9, 0 }, 1819#endif 1820}; 1821/* *INDENT-ON* */ 1822 1823#if OPT_DEC_RECTOPS 1824static char * 1825encode_scs(DECNRCM_codes value) 1826{ 1827 static char buffer[3]; 1828 Cardinal n; 1829 char *result = buffer; 1830 for (n = 0; n < XtNumber(scs_table); ++n) { 1831 if (scs_table[n].result == value) { 1832 if (scs_table[n].prefix) 1833 *result++ = (char) scs_table[n].prefix; 1834 if (scs_table[n].suffix) 1835 *result++ = (char) scs_table[n].suffix; 1836 break; 1837 } 1838 } 1839 *result = '\0'; 1840 return buffer; 1841} 1842#endif 1843 1844void 1845xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix) 1846{ 1847 TScreen *screen = TScreenOf(xw); 1848 Cardinal n; 1849 DECNRCM_codes result = nrc_Unknown; 1850 1851 suffix &= 0x7f; 1852 for (n = 0; n < XtNumber(scs_table); ++n) { 1853 if (prefix == scs_table[n].prefix 1854 && suffix == scs_table[n].suffix 1855 && sgroup == scs_table[n].min_level 1856 && screen->vtXX_level >= scs_table[n].min_level 1857 && screen->vtXX_level <= scs_table[n].max_level 1858 && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) { 1859 result = scs_table[n].result; 1860 break; 1861 } 1862 } 1863 if (result != nrc_Unknown) { 1864 initCharset(screen, which, result); 1865 TRACE(("setting G%d to table #%d %s", 1866 which, n, visibleScsCode((int) result))); 1867 } else { 1868 TRACE(("...unknown GSET")); 1869 initCharset(screen, which, nrc_ASCII); 1870 } 1871#if OPT_TRACE 1872 TRACE((" (")); 1873 if (prefix) 1874 TRACE(("prefix='%c', ", prefix)); 1875 TRACE(("suffix='%c', sgroup=%d", suffix, sgroup)); 1876 TRACE((")\n")); 1877#endif 1878} 1879 1880/* 1881 * Given a parameter number, and subparameter (starting in each case from zero) 1882 * return the corresponding index into the parameter array. If the combination 1883 * is not found, return -1. 1884 */ 1885static int 1886subparam_index(int p, int s) 1887{ 1888 int result = -1; 1889 int j, p2, s2; 1890 1891 for (j = p2 = 0; j < nparam; ++j, ++p2) { 1892 if (parms.is_sub[j]) { 1893 s2 = 0; 1894 1895 do { 1896 if ((p == p2) && (s == s2)) { 1897 result = j; 1898 break; 1899 } 1900 ++s2; 1901 } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])); 1902 1903 if (result >= 0) 1904 break; 1905 1906 --j; /* undo the last "while" */ 1907 } else if (p == p2) { 1908 if (s == 0) { 1909 result = j; 1910 } 1911 break; 1912 } 1913 } 1914 TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result)); 1915 return result; 1916} 1917 1918/* 1919 * Check if the given item in the parameter array has subparameters. 1920 * If so, return the number of subparameters to use as a loop limit, etc. 1921 */ 1922static int 1923param_has_subparams(int item) 1924{ 1925 int result = 0; 1926 if (parms.has_subparams) { 1927 int n = subparam_index(item, 0); 1928 if (n >= 0 && parms.is_sub[n]) { 1929 while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) { 1930 result++; 1931 } 1932 } 1933 } 1934 TRACE(("...param_has_subparams(%d) ->%d\n", item, result)); 1935 return result; 1936} 1937 1938#if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS 1939/* 1940 * Given an index into the parameter array, return the corresponding parameter 1941 * number (starting from zero). 1942 */ 1943static int 1944param_number(int item) 1945{ 1946 int result = -1; 1947 int j, p; 1948 1949 for (j = p = 0; j < nparam; ++j, ++p) { 1950 if (p >= item) { 1951 result = j; 1952 break; 1953 } 1954 if (parms.is_sub[j]) { 1955 while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) { 1956 /* EMPTY */ 1957 } 1958 --j; 1959 } 1960 } 1961 1962 TRACE2(("...param_number(%d) = %d\n", item, result)); 1963 return result; 1964} 1965 1966static int 1967get_subparam(int p, int s) 1968{ 1969 int item = subparam_index(p, s); 1970 int result = (item >= 0) ? parms.params[item] : DEFAULT; 1971 TRACE(("...get_subparam[%d] = %d\n", item, result)); 1972 return result; 1973} 1974 1975/* 1976 * Some background - 1977 * 1978 * Todd Larason provided the initial changes to support 256-colors in July 1999. 1979 * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and 1980 * was unsure if there would be some standard using those codes. His response 1981 * was that this was documented (it turns out, in equally vague terms) in ITU 1982 * T.416 1983 * 1984 * Discussing this with Todd Larason in mid-1999, my point was that given the 1985 * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going 1986 * to be effective (more than $100 then, more than $200 in 2012) 1987 * 1988 * We overlooked the detail about ":" as a subparameter delimiter (documented 1989 * in 5.4.2 in ECMA-48). Some discussion in KDE in mid-2006 led Lars Doelle 1990 * to discuss the issue with me. Lars' initial concern dealt with the fact 1991 * that a sequence such as 1992 * CSI 38 ; 5 ; 1 m 1993 * violated the principle that SGR parameters could be used in any order. 1994 * Further discussion (see KDE #107487) resolved that the standard expected 1995 * that the sequence would look like 1996 * CSI 38 ; 5 : 1 m 1997 * which still violates that principle, since the "5:1" parameter has to 1998 * follow the "38" to be useful. 1999 * 2000 * This function accepts either format (per request by Paul Leonerd Evans). 2001 * It also accepts 2002 * CSI 38 : 5 : 1 m 2003 * according to Lars' original assumption. While implementing that, I added 2004 * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value. 2005 * ISO-8613-6 documents that as "direct color". 2006 * 2007 * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's 2008 * quirk in the description of direct color: it mentions a color space 2009 * identifier parameter which should follow the "2" (as parameter 1). In the 2010 * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as 2011 * well as parameters 7 and 8. Like parameter 1, parameters 7 and 8 are not 2012 * defined clearly in the standard, and a close reading indicates they are 2013 * optional, saying they "may be used". This implementation ignores parameters 2014 * 6 (and above), and provides for the color space identifier by checking the 2015 * number of parameters: 2016 * 3 after "2" (no color space identifier) 2017 * 4 or more after "2" (color space identifier) 2018 * 2019 * By the way - all of the parameters are decimal integers, and missing 2020 * parameters represent a default value. ISO-8613-6 is clear about that. 2021 * 2022 * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter. 2023 * ECMA-48 says only: 2024 * 2025 * 5.4.2 Parameter string format 2026 * 2027 * A parameter string which does not start with a bit combination in the 2028 * range 03/12 to 03/15 shall have the following format: 2029 * 2030 * a) A parameter string consists of one or more parameter 2031 * sub-strings, each of which represents a number in decimal 2032 * notation. 2033 * 2034 * b) Each parameter sub-string consists of one or more bit 2035 * combinations from 03/00 to 03/10; the bit combinations from 2036 * 03/00 to 03/09 represent the digits ZERO to NINE; bit 2037 * combination 03/10 may be used as a separator in a parameter 2038 * sub-string, for example, to separate the fractional part of a 2039 * decimal number from the integer part of that number. 2040 * 2041 * That is, there is no mention in ECMA-48 of the possibility that a parameter 2042 * string might be a list of parameters, as done in ISO-8613-3 (nor does 2043 * ECMA-48 provide an example where the ":" separator might be used). Because 2044 * of this, xterm treats other cases than those needed for ISO-8613-3 as an 2045 * error, and stops interpreting the sequence. 2046 */ 2047#define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0)) 2048static Boolean 2049parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended) 2050{ 2051 Boolean result = False; 2052 int item = *itemp; 2053 int next = item; 2054 int base = param_number(item); 2055 int code = -1; 2056 int values[3]; /* maximum number of subparameters */ 2057 int need = 0; /* number of subparameters needed */ 2058 int have; 2059 int n; 2060 2061 /* 2062 * On entry, 'item' points to the 38/48 code in the parameter array. 2063 * If that has subparameters, we will expect all of the values to 2064 * be subparameters of that item. 2065 */ 2066 if ((have = param_has_subparams(item)) != 0) { 2067 /* accept CSI 38 : 5 : 1 m */ 2068 /* accept CSI 38 : 2 : 1 : 2 : 3 m */ 2069 code = get_subparam(base, 1); 2070 need = extended_colors_limit(code); 2071 next = item + have; 2072 for (n = 0; n < need && n < 3; ++n) { 2073 values[n] = get_subparam(base, 2 + n + (have > 4)); 2074 } 2075 } else if (++item < nparam) { 2076 ++base; 2077 if ((have = param_has_subparams(item)) != 0) { 2078 /* accept CSI 38 ; 5 : 1 m */ 2079 /* accept CSI 38 ; 2 : 1 : 2 : 3 m */ 2080 code = get_subparam(base, 0); 2081 need = extended_colors_limit(code); 2082 next = base + have; 2083 for (n = 0; n < need && n < 3; ++n) { 2084 values[n] = get_subparam(base, 1 + n + (have > 3)); 2085 } 2086 } else { 2087 /* accept CSI 38 ; 5 ; 1 m */ 2088 /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */ 2089 code = GetParam(item); 2090 need = extended_colors_limit(code); 2091 next = item + need; 2092 for (n = 0; n < need && n < 3; ++n) { 2093 values[n] = GetParam(item + 1 + n); 2094 } 2095 } 2096 } 2097 item = next; 2098 2099 *extended = False; 2100 switch (code) { 2101 case 2: 2102 /* direct color in rgb space */ 2103 if ((values[0] >= 0 && values[0] < 256) && 2104 (values[1] >= 0 && values[1] < 256) && 2105 (values[2] >= 0 && values[2] < 256)) { 2106#if OPT_DIRECT_COLOR 2107 if (TScreenOf(xw)->direct_color && xw->has_rgb) { 2108 *colorp = getDirectColor(xw, values[0], values[1], values[2]); 2109 result = True; 2110 *extended = True; 2111 } else 2112#endif 2113 { 2114 *colorp = xtermClosestColor(xw, values[0], values[1], values[2]); 2115 result = okIndexedColor(*colorp); 2116 } 2117 } else { 2118 *colorp = -1; 2119 } 2120 break; 2121 case 5: 2122 /* indexed color */ 2123 *colorp = values[0]; 2124 result = okIndexedColor(*colorp); 2125 break; 2126 default: 2127 *colorp = -1; 2128 break; 2129 } 2130 2131 TRACE(("...resulting color %d/%d %s\n", 2132 *colorp, NUM_ANSI_COLORS, 2133 result ? "OK" : "ERR")); 2134 2135 *itemp = item; 2136 return result; 2137} 2138#endif /* ...extended_colors */ 2139 2140static int 2141optional_param(int which) 2142{ 2143 return (nparam > which) ? GetParam(which) : DEFAULT; 2144} 2145 2146static int 2147zero_if_default(int which) 2148{ 2149 int result = (nparam > which) ? GetParam(which) : 0; 2150 if (result <= 0) 2151 result = 0; 2152 return result; 2153} 2154 2155static int 2156one_if_default(int which) 2157{ 2158 int result = (nparam > which) ? GetParam(which) : 0; 2159 if (result <= 0) 2160 result = 1; 2161 return result; 2162} 2163 2164/* 2165 * Color palette changes using the OSC controls require a repaint of the 2166 * screen - but not immediately. Do the repaint as soon as we detect a 2167 * state which will not lead to another color palette change. 2168 */ 2169static void 2170repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp) 2171{ 2172 Boolean ignore = False; 2173 2174 switch (sp->nextstate) { 2175 case CASE_ESC: 2176 ignore = ((sp->parsestate == ansi_table) || 2177 (sp->parsestate == sos_table)); 2178#if USE_DOUBLE_BUFFER 2179 if (resource.buffered && TScreenOf(xw)->needSwap) { 2180 ignore = False; 2181 } 2182#endif 2183 break; 2184 case CASE_OSC: 2185 ignore = ((sp->parsestate == ansi_table) || 2186 (sp->parsestate == esc_table)); 2187 break; 2188 case CASE_IGNORE: 2189 ignore = (sp->parsestate == sos_table); 2190 break; 2191 case CASE_ST: 2192 ignore = ((sp->parsestate == esc_table) || 2193 (sp->parsestate == sos_table)); 2194 break; 2195 case CASE_ESC_DIGIT: 2196 ignore = (sp->parsestate == csi_table); 2197 break; 2198 case CASE_ESC_SEMI: 2199 ignore = (sp->parsestate == csi2_table); 2200 break; 2201 } 2202 2203 if (!ignore) { 2204 TRACE(("repaintWhenPaletteChanged\n")); 2205 xw->work.palette_changed = False; 2206 xtermRepaint(xw); 2207 xtermFlushDbe(xw); 2208 } 2209} 2210 2211#if OPT_C1_PRINT || OPT_WIDE_CHARS 2212#define ParseSOS(screen) ((screen)->c1_printable == 0) 2213#else 2214#define ParseSOS(screen) 0 2215#endif 2216 2217#define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable 2218 2219static void 2220illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp) 2221{ 2222 ResetState(sp); 2223 sp->nextstate = sp->parsestate[E2A(c)]; 2224 Bell(xw, XkbBI_MinorError, 0); 2225} 2226 2227static void 2228init_parser(XtermWidget xw, struct ParseState *sp) 2229{ 2230 TScreen *screen = TScreenOf(xw); 2231 2232 memset(sp, 0, sizeof(*sp)); 2233 sp->scssize = 94; /* number of printable/nonspace ASCII */ 2234 sp->lastchar = -1; /* not a legal IChar */ 2235 sp->nextstate = -1; /* not a legal state */ 2236 2237 init_groundtable(screen, sp); 2238 ResetState(sp); 2239} 2240 2241static void 2242init_reply(unsigned type) 2243{ 2244 memset(&reply, 0, sizeof(reply)); 2245 reply.a_type = (Char) type; 2246} 2247 2248static void 2249deferparsing(unsigned c, struct ParseState *sp) 2250{ 2251 SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size); 2252 if (new_string == 0) { 2253 xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n", 2254 (unsigned long) new_length, c); 2255 return; 2256 } 2257 SafeFree(sp->defer_area, sp->defer_size); 2258 sp->defer_area[(sp->defer_used)++] = CharOf(c); 2259} 2260 2261#if OPT_VT52_MODE 2262static void 2263update_vt52_vt100_settings(void) 2264{ 2265 update_autowrap(); 2266 update_reversewrap(); 2267 update_autolinefeed(); 2268 update_appcursor(); 2269 update_appkeypad(); 2270 update_allow132(); 2271} 2272#endif 2273 2274static Boolean 2275doparsing(XtermWidget xw, unsigned c, struct ParseState *sp) 2276{ 2277 TScreen *screen = TScreenOf(xw); 2278 int item; 2279 int count; 2280 int value; 2281 int laststate; 2282 int thischar = -1; 2283 XTermRect myRect; 2284#if OPT_DEC_RECTOPS 2285 int thispage = 1; 2286#endif 2287 2288 if (sp->check_recur) { 2289 /* Defer parsing when parser is already running as the parser is not 2290 * safe to reenter. 2291 */ 2292 deferparsing(c, sp); 2293 return True; 2294 } 2295 sp->check_recur++; 2296 2297 do { 2298#if OPT_WIDE_CHARS 2299 int this_is_wide = 0; 2300 2301 /* 2302 * Handle zero-width combining characters. Make it faster by noting 2303 * that according to the Unicode charts, the majority of Western 2304 * character sets do not use this feature. There are some unassigned 2305 * codes at 0x242, but no zero-width characters until past 0x300. 2306 */ 2307 if (c >= 0x300 2308 && screen->wide_chars 2309 && CharWidth(c) == 0 2310 && !isWideControl(c)) { 2311 int prev, test; 2312 Boolean used = True; 2313 int use_row; 2314 int use_col; 2315 2316 WriteNow(); 2317 use_row = (screen->char_was_written 2318 ? screen->last_written_row 2319 : screen->cur_row); 2320 use_col = (screen->char_was_written 2321 ? screen->last_written_col 2322 : screen->cur_col); 2323 2324 /* 2325 * Check if the latest data can be added to the base character. 2326 * If there is already a combining character stored for the cell, 2327 * we cannot, since that would change the order. 2328 */ 2329 if (screen->normalized_c 2330 && !IsCellCombined(screen, use_row, use_col)) { 2331 prev = (int) XTERM_CELL(use_row, use_col); 2332 test = do_precomposition(prev, (int) c); 2333 TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n", 2334 prev, CharWidth(prev), 2335 (int) c, CharWidth(c), 2336 test, CharWidth(test))); 2337 } else { 2338 prev = -1; 2339 test = -1; 2340 } 2341 2342 /* substitute combined character with precomposed character 2343 * only if it does not change the width of the base character 2344 */ 2345 if (test != -1 2346 && CharWidth(test) == CharWidth(prev)) { 2347 putXtermCell(screen, use_row, use_col, test); 2348 } else if (screen->char_was_written 2349 || getXtermCell(screen, use_row, use_col) >= ' ') { 2350 addXtermCombining(screen, use_row, use_col, c); 2351 } else { 2352 /* 2353 * none of the above... we will add the combining character as 2354 * a base character. 2355 */ 2356 used = False; 2357 } 2358 2359 if (used) { 2360 if (!screen->scroll_amt) 2361 ScrnUpdate(xw, use_row, use_col, 1, 1, 1); 2362 continue; 2363 } 2364 } 2365#endif 2366 2367 /* Intercept characters for printer controller mode */ 2368 if (PrinterOf(screen).printer_controlmode == 2) { 2369 if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0) 2370 continue; 2371 } 2372 2373 /* 2374 * VT52 is a little ugly in the one place it has a parameterized 2375 * control sequence, since the parameter falls after the character 2376 * that denotes the type of sequence. 2377 */ 2378#if OPT_VT52_MODE 2379 if (sp->vt52_cup) { 2380 if (nparam < NPARAM - 1) { 2381 SetParam(nparam++, (int) (c & 0x7f) - 32); 2382 parms.is_sub[nparam] = 0; 2383 } 2384 if (nparam < 2) 2385 continue; 2386 sp->vt52_cup = False; 2387 CursorSet(screen, zero_if_default(0), zero_if_default(1), xw->flags); 2388 sp->parsestate = vt52_table; 2389 SetParam(0, 0); 2390 SetParam(1, 0); 2391 continue; 2392 } 2393#endif 2394 2395 laststate = sp->nextstate; 2396 if (c == ANSI_DEL 2397 && sp->parsestate == sp->groundtable 2398 && sp->scssize == 96 2399 && sp->scstype != 0) { 2400 /* 2401 * Handle special case of shifts for 96-character sets by checking 2402 * if we have a DEL. The other special case for SPACE will always 2403 * be printable. 2404 */ 2405 sp->nextstate = CASE_PRINT; 2406 } else 2407#if OPT_WIDE_CHARS 2408 if (c > 255) { 2409 /* 2410 * The parsing tables all have 256 entries. If we're supporting 2411 * wide characters, we handle them by treating them the same as 2412 * printing characters. 2413 */ 2414 if (sp->parsestate == sp->groundtable) { 2415 sp->nextstate = CASE_PRINT; 2416 } else if (sp->parsestate == sos_table) { 2417 c &= WIDEST_ICHAR; 2418 if (c > 255) { 2419 TRACE(("Found code > 255 while in SOS state: %04X\n", c)); 2420 c = BAD_ASCII; 2421 } 2422 } else { 2423 sp->nextstate = CASE_GROUND_STATE; 2424 } 2425 } else 2426#endif 2427 sp->nextstate = sp->parsestate[E2A(c)]; 2428 2429#if OPT_BROKEN_OSC 2430 /* 2431 * Linux console palette escape sequences start with an OSC, but do 2432 * not terminate correctly. Some scripts do not check before writing 2433 * them, making xterm appear to hang (it's awaiting a valid string 2434 * terminator). Just ignore these if we see them - there's no point 2435 * in emulating bad code. 2436 */ 2437 if (screen->brokenLinuxOSC 2438 && sp->parsestate == sos_table) { 2439 if (sp->string_used) { 2440 switch (sp->string_area[0]) { 2441 case 'P': 2442 if (sp->string_used <= 7) 2443 break; 2444 /* FALLTHRU */ 2445 case 'R': 2446 illegal_parse(xw, c, sp); 2447 TRACE(("Reset to ground state (brokenLinuxOSC)\n")); 2448 break; 2449 } 2450 } 2451 } 2452#endif 2453 2454#if OPT_BROKEN_ST 2455 /* 2456 * Before patch #171, carriage control embedded within an OSC string 2457 * would terminate it. Some (buggy, of course) applications rely on 2458 * this behavior. Accommodate them by allowing one to compile xterm 2459 * and emulate the old behavior. 2460 */ 2461 if (screen->brokenStringTerm 2462 && sp->parsestate == sos_table 2463 && c < 32) { 2464 switch (c) { 2465 case ANSI_EOT: /* FALLTHRU */ 2466 case ANSI_BS: /* FALLTHRU */ 2467 case ANSI_HT: /* FALLTHRU */ 2468 case ANSI_LF: /* FALLTHRU */ 2469 case ANSI_VT: /* FALLTHRU */ 2470 case ANSI_FF: /* FALLTHRU */ 2471 case ANSI_CR: /* FALLTHRU */ 2472 case ANSI_SO: /* FALLTHRU */ 2473 case ANSI_SI: /* FALLTHRU */ 2474 case ANSI_XON: /* FALLTHRU */ 2475 case ANSI_CAN: 2476 illegal_parse(xw, c, sp); 2477 TRACE(("Reset to ground state (brokenStringTerm)\n")); 2478 break; 2479 } 2480 } 2481#endif 2482 2483#if OPT_C1_PRINT 2484 /* 2485 * This is not completely foolproof, but will allow an application 2486 * with values in the C1 range to use them as printable characters, 2487 * provided that they are not intermixed with an escape sequence. 2488 */ 2489 if (screen->c1_printable 2490 && (c >= 128 && c < 256)) { 2491 sp->nextstate = (sp->parsestate == esc_table 2492 ? CASE_ESC_IGNORE 2493 : sp->parsestate[E2A(160)]); 2494 TRACE(("allowC1Printable %04X %s ->%s\n", 2495 c, which_table(sp->parsestate), 2496 visibleVTparse(sp->nextstate))); 2497 } 2498#endif 2499 2500#if OPT_WIDE_CHARS 2501 /* 2502 * If we have a C1 code and the c1_printable flag is not set, simply 2503 * ignore it when it was translated from UTF-8. That is because the 2504 * value could not have been present as-is in the UTF-8. 2505 * 2506 * To see that CASE_IGNORE is a consistent value, note that it is 2507 * always used for NUL and other uninteresting C0 controls. 2508 */ 2509#if OPT_C1_PRINT 2510 if (!screen->c1_printable) 2511#endif 2512 if (screen->wide_chars 2513 && (c >= 128 && c < 160)) { 2514 sp->nextstate = CASE_IGNORE; 2515 } 2516 2517 /* 2518 * If this character is a different width than the last one, put the 2519 * previous text into the buffer and draw it now. 2520 */ 2521 this_is_wide = isWide((int) c); 2522 if (this_is_wide != sp->last_was_wide) { 2523 WriteNow(); 2524 } 2525#endif 2526 2527 /* 2528 * Accumulate string for printable text. This may be 8/16-bit 2529 * characters. 2530 */ 2531 if (sp->nextstate == CASE_PRINT) { 2532 SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size); 2533 if (new_string == 0) { 2534 xtermWarning("Cannot allocate %lu bytes for printable text\n", 2535 (unsigned long) new_length); 2536 continue; 2537 } 2538 SafeFree(sp->print_area, sp->print_size); 2539#if OPT_VT52_MODE 2540 /* 2541 * Strip output text to 7-bits for VT52. We should do this for 2542 * VT100 also (which is a 7-bit device), but xterm has been 2543 * doing this for so long we shouldn't change this behavior. 2544 */ 2545 if (screen->vtXX_level < 1) 2546 c &= 0x7f; 2547#endif 2548 sp->print_area[sp->print_used++] = (IChar) c; 2549 sp->lastchar = thischar = (int) c; 2550#if OPT_WIDE_CHARS 2551 sp->last_was_wide = this_is_wide; 2552#endif 2553 if (morePtyData(screen, VTbuffer)) { 2554 continue; 2555 } 2556 } 2557 2558 if (sp->nextstate == CASE_PRINT 2559 || (laststate == CASE_PRINT && sp->print_used)) { 2560 WriteNow(); 2561 } 2562 2563 /* 2564 * Accumulate string for APC, DCS, PM, OSC, SOS controls 2565 * This should always be 8-bit characters. 2566 */ 2567 if (sp->parsestate == sos_table) { 2568 SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size); 2569 if (new_string == 0) { 2570 xtermWarning("Cannot allocate %lu bytes for string mode %d\n", 2571 (unsigned long) new_length, sp->string_mode); 2572 continue; 2573 } 2574 SafeFree(sp->string_area, sp->string_size); 2575#if OPT_WIDE_CHARS 2576 /* 2577 * We cannot display codes above 255, but let's try to 2578 * accommodate the application a little by not aborting the 2579 * string. 2580 */ 2581 if ((c & WIDEST_ICHAR) > 255) { 2582 sp->nextstate = CASE_PRINT; 2583 c = BAD_ASCII; 2584 } 2585#endif 2586 sp->string_area[(sp->string_used)++] = CharOf(c); 2587 } else if (sp->parsestate != esc_table) { 2588 /* if we were accumulating, we're not any more */ 2589 sp->string_mode = 0; 2590 sp->string_used = 0; 2591 } 2592 2593 DumpParams(); 2594 TRACE(("parse %04X -> %s %s (used=%lu)\n", 2595 c, visibleVTparse(sp->nextstate), 2596 which_table(sp->parsestate), 2597 (unsigned long) sp->string_used)); 2598 2599 /* 2600 * If the parameter list has subparameters (tokens separated by ":") 2601 * reject any controls that do not accept subparameters. 2602 */ 2603 if (parms.has_subparams) { 2604 switch (sp->nextstate) { 2605 case CASE_GROUND_STATE: 2606 case CASE_CSI_IGNORE: 2607 /* FALLTHRU */ 2608 2609 case CASE_ESC_DIGIT: 2610 case CASE_ESC_SEMI: 2611 case CASE_ESC_COLON: 2612 /* these states are required to parse parameter lists */ 2613 break; 2614 2615 case CASE_SGR: 2616 TRACE(("...possible subparam usage\n")); 2617 break; 2618 2619 case CASE_CSI_DEC_DOLLAR_STATE: 2620 case CASE_CSI_DOLLAR_STATE: 2621 case CASE_CSI_HASH_STATE: 2622 case CASE_CSI_EX_STATE: 2623 case CASE_CSI_QUOTE_STATE: 2624 case CASE_CSI_SPACE_STATE: 2625 case CASE_CSI_STAR_STATE: 2626 case CASE_CSI_TICK_STATE: 2627 case CASE_DEC2_STATE: 2628 case CASE_DEC3_STATE: 2629 case CASE_DEC_STATE: 2630 /* use this branch when we do not yet have the final character */ 2631 TRACE(("...unexpected subparam usage\n")); 2632 InitParams(); 2633 sp->nextstate = CASE_CSI_IGNORE; 2634 break; 2635 2636 default: 2637 /* use this branch for cases where we have the final character 2638 * in the table that processed the parameter list. 2639 */ 2640 TRACE(("...unexpected subparam usage\n")); 2641 ResetState(sp); 2642 continue; 2643 } 2644 } 2645 2646 if (xw->work.palette_changed) { 2647 repaintWhenPaletteChanged(xw, sp); 2648 } 2649 2650 switch (sp->nextstate) { 2651 case CASE_PRINT: 2652 TRACE(("CASE_PRINT - printable characters\n")); 2653 break; 2654 2655 case CASE_GROUND_STATE: 2656 TRACE(("CASE_GROUND_STATE - exit ignore mode\n")); 2657 ResetState(sp); 2658 break; 2659 2660 case CASE_IGNORE: 2661 TRACE(("CASE_IGNORE - Ignore character %02X\n", c)); 2662 break; 2663 2664 case CASE_ENQ: 2665 TRACE(("CASE_ENQ - answerback\n")); 2666 if (((xw->keyboard.flags & MODE_SRM) == 0) 2667 ? (sp->check_recur == 0) 2668 : (sp->check_recur <= 1)) { 2669 for (count = 0; screen->answer_back[count] != 0; count++) 2670 unparseputc(xw, screen->answer_back[count]); 2671 unparse_end(xw); 2672 } 2673 break; 2674 2675 case CASE_BELL: 2676 TRACE(("CASE_BELL - bell\n")); 2677 if (sp->string_mode == ANSI_OSC) { 2678 if (sp->string_used) 2679 sp->string_area[--(sp->string_used)] = '\0'; 2680 if (sp->check_recur <= 1) 2681 do_osc(xw, sp->string_area, sp->string_used, (int) c); 2682 ResetState(sp); 2683 } else { 2684 /* bell */ 2685 Bell(xw, XkbBI_TerminalBell, 0); 2686 } 2687 break; 2688 2689 case CASE_BS: 2690 TRACE(("CASE_BS - backspace\n")); 2691 CursorBack(xw, 1); 2692 break; 2693 2694 case CASE_CR: 2695 TRACE(("CASE_CR\n")); 2696 CarriageReturn(xw); 2697 break; 2698 2699 case CASE_ESC: 2700 if_OPT_VT52_MODE(screen, { 2701 sp->parsestate = vt52_esc_table; 2702 break; 2703 }); 2704 sp->parsestate = esc_table; 2705 break; 2706 2707#if OPT_VT52_MODE 2708 case CASE_VT52_CUP: 2709 TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n")); 2710 sp->vt52_cup = True; 2711 ResetState(sp); 2712 break; 2713 2714 case CASE_VT52_IGNORE: 2715 TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n")); 2716 sp->parsestate = vt52_ignore_table; 2717 break; 2718#endif 2719 2720 case CASE_VMOT: 2721 TRACE(("CASE_VMOT\n")); 2722 /* 2723 * form feed, line feed, vertical tab 2724 */ 2725 xtermAutoPrint(xw, c); 2726 xtermIndex(xw, 1); 2727 if (xw->flags & LINEFEED) 2728 CarriageReturn(xw); 2729 else 2730 do_xevents(xw); 2731 break; 2732 2733 case CASE_CBT: 2734 TRACE(("CASE_CBT\n")); 2735 /* cursor backward tabulation */ 2736 count = one_if_default(0); 2737 while ((count-- > 0) 2738 && (TabToPrevStop(xw))) ; 2739 ResetState(sp); 2740 break; 2741 2742 case CASE_CHT: 2743 TRACE(("CASE_CHT\n")); 2744 /* cursor forward tabulation */ 2745 count = one_if_default(0); 2746 while ((count-- > 0) 2747 && (TabToNextStop(xw))) ; 2748 ResetState(sp); 2749 break; 2750 2751 case CASE_TAB: 2752 /* tab */ 2753 TabToNextStop(xw); 2754 break; 2755 2756 case CASE_SI: 2757 screen->curgl = 0; 2758 if_OPT_VT52_MODE(screen, { 2759 ResetState(sp); 2760 }); 2761 break; 2762 2763 case CASE_SO: 2764 screen->curgl = 1; 2765 if_OPT_VT52_MODE(screen, { 2766 ResetState(sp); 2767 }); 2768 break; 2769 2770 case CASE_DECDHL: 2771 xterm_DECDHL(xw, c == '3'); 2772 ResetState(sp); 2773 break; 2774 2775 case CASE_DECSWL: 2776 xterm_DECSWL(xw); 2777 ResetState(sp); 2778 break; 2779 2780 case CASE_DECDWL: 2781 xterm_DECDWL(xw); 2782 ResetState(sp); 2783 break; 2784 2785 case CASE_SCR_STATE: 2786 /* enter scr state */ 2787 sp->parsestate = scrtable; 2788 break; 2789 2790 case CASE_SCS0_STATE: 2791 /* enter scs state 0 */ 2792 select_charset(sp, 0, 94); 2793 break; 2794 2795 case CASE_SCS1_STATE: 2796 /* enter scs state 1 */ 2797 select_charset(sp, 1, 94); 2798 break; 2799 2800 case CASE_SCS2_STATE: 2801 /* enter scs state 2 */ 2802 select_charset(sp, 2, 94); 2803 break; 2804 2805 case CASE_SCS3_STATE: 2806 /* enter scs state 3 */ 2807 select_charset(sp, 3, 94); 2808 break; 2809 2810 case CASE_SCS1A_STATE: 2811 /* enter scs state 1 */ 2812 select_charset(sp, 1, 96); 2813 break; 2814 2815 case CASE_SCS2A_STATE: 2816 /* enter scs state 2 */ 2817 select_charset(sp, 2, 96); 2818 break; 2819 2820 case CASE_SCS3A_STATE: 2821 /* enter scs state 3 */ 2822 select_charset(sp, 3, 96); 2823 break; 2824 2825 case CASE_ESC_IGNORE: 2826 /* unknown escape sequence */ 2827 sp->parsestate = eigtable; 2828 break; 2829 2830 case CASE_ESC_DIGIT: 2831 /* digit in csi or dec mode */ 2832 if (nparam > 0) { 2833 value = zero_if_default(nparam - 1); 2834 SetParam(nparam - 1, (10 * value) + ((int) c - '0')); 2835 if (GetParam(nparam - 1) > MAX_I_PARAM) 2836 SetParam(nparam - 1, MAX_I_PARAM); 2837 if (sp->parsestate == csi_table) 2838 sp->parsestate = csi2_table; 2839 } 2840 break; 2841 2842 case CASE_ESC_SEMI: 2843 /* semicolon in csi or dec mode */ 2844 if (nparam < NPARAM) { 2845 parms.is_sub[nparam] = 0; 2846 SetParam(nparam++, DEFAULT); 2847 } 2848 if (sp->parsestate == csi_table) 2849 sp->parsestate = csi2_table; 2850 break; 2851 2852 /* 2853 * A _few_ commands accept colon-separated subparameters. 2854 * Mark the parameter list so that we can exclude (most) bogus 2855 * commands with simple/fast checks. 2856 */ 2857 case CASE_ESC_COLON: 2858 if (nparam < NPARAM) { 2859 parms.has_subparams = 1; 2860 if (nparam == 0) { 2861 parms.is_sub[nparam] = 1; 2862 SetParam(nparam++, DEFAULT); 2863 } else if (parms.is_sub[nparam - 1] == 0) { 2864 parms.is_sub[nparam - 1] = 1; 2865 parms.is_sub[nparam] = 2; 2866 parms.params[nparam] = 0; 2867 ++nparam; 2868 } else { 2869 parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1]; 2870 parms.params[nparam] = 0; 2871 ++nparam; 2872 } 2873 } 2874 break; 2875 2876 case CASE_DEC_STATE: 2877 /* enter dec mode */ 2878 sp->parsestate = dec_table; 2879 break; 2880 2881 case CASE_DEC2_STATE: 2882 /* enter dec2 mode */ 2883 sp->parsestate = dec2_table; 2884 break; 2885 2886 case CASE_DEC3_STATE: 2887 /* enter dec3 mode */ 2888 sp->parsestate = dec3_table; 2889 break; 2890 2891 case CASE_ICH: 2892 TRACE(("CASE_ICH - insert char\n")); 2893 InsertChar(xw, (unsigned) one_if_default(0)); 2894 ResetState(sp); 2895 break; 2896 2897 case CASE_CUU: 2898 TRACE(("CASE_CUU - cursor up\n")); 2899 CursorUp(screen, one_if_default(0)); 2900 ResetState(sp); 2901 break; 2902 2903 case CASE_CUD: 2904 TRACE(("CASE_CUD - cursor down\n")); 2905 CursorDown(screen, one_if_default(0)); 2906 ResetState(sp); 2907 break; 2908 2909 case CASE_CUF: 2910 TRACE(("CASE_CUF - cursor forward\n")); 2911 CursorForward(xw, one_if_default(0)); 2912 ResetState(sp); 2913 break; 2914 2915 case CASE_CUB: 2916 TRACE(("CASE_CUB - cursor backward\n")); 2917 CursorBack(xw, one_if_default(0)); 2918 ResetState(sp); 2919 break; 2920 2921 case CASE_CUP: 2922 TRACE(("CASE_CUP - cursor position\n")); 2923 if_OPT_XMC_GLITCH(screen, { 2924 Jump_XMC(xw); 2925 }); 2926 CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags); 2927 ResetState(sp); 2928 break; 2929 2930 case CASE_VPA: 2931 TRACE(("CASE_VPA - vertical position absolute\n")); 2932 CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags); 2933 ResetState(sp); 2934 break; 2935 2936 case CASE_HPA: 2937 TRACE(("CASE_HPA - horizontal position absolute\n")); 2938 CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags); 2939 ResetState(sp); 2940 break; 2941 2942 case CASE_VPR: 2943 TRACE(("CASE_VPR - vertical position relative\n")); 2944 CursorSet(screen, 2945 CursorRow(xw) + one_if_default(0), 2946 CursorCol(xw), 2947 xw->flags); 2948 ResetState(sp); 2949 break; 2950 2951 case CASE_HPR: 2952 TRACE(("CASE_HPR - horizontal position relative\n")); 2953 CursorSet(screen, 2954 CursorRow(xw), 2955 CursorCol(xw) + one_if_default(0), 2956 xw->flags); 2957 ResetState(sp); 2958 break; 2959 2960 case CASE_HP_BUGGY_LL: 2961 TRACE(("CASE_HP_BUGGY_LL\n")); 2962 /* Some HP-UX applications have the bug that they 2963 assume ESC F goes to the lower left corner of 2964 the screen, regardless of what terminfo says. */ 2965 if (screen->hp_ll_bc) 2966 CursorSet(screen, screen->max_row, 0, xw->flags); 2967 ResetState(sp); 2968 break; 2969 2970 case CASE_ED: 2971 TRACE(("CASE_ED - erase display\n")); 2972 do_cd_xtra_scroll(xw); 2973 do_erase_display(xw, zero_if_default(0), OFF_PROTECT); 2974 ResetState(sp); 2975 break; 2976 2977 case CASE_EL: 2978 TRACE(("CASE_EL - erase line\n")); 2979 do_erase_line(xw, zero_if_default(0), OFF_PROTECT); 2980 ResetState(sp); 2981 break; 2982 2983 case CASE_ECH: 2984 TRACE(("CASE_ECH - erase char\n")); 2985 /* ECH */ 2986 do_erase_char(xw, one_if_default(0), OFF_PROTECT); 2987 ResetState(sp); 2988 break; 2989 2990 case CASE_IL: 2991 TRACE(("CASE_IL - insert line\n")); 2992 InsertLine(xw, one_if_default(0)); 2993 ResetState(sp); 2994 break; 2995 2996 case CASE_DL: 2997 TRACE(("CASE_DL - delete line\n")); 2998 DeleteLine(xw, one_if_default(0)); 2999 ResetState(sp); 3000 break; 3001 3002 case CASE_DCH: 3003 TRACE(("CASE_DCH - delete char\n")); 3004 DeleteChar(xw, (unsigned) one_if_default(0)); 3005 ResetState(sp); 3006 break; 3007 3008 case CASE_TRACK_MOUSE: 3009 /* 3010 * A single parameter other than zero is always scroll-down. 3011 * A zero-parameter is used to reset the mouse mode, and is 3012 * not useful for scrolling anyway. 3013 */ 3014 if (nparam > 1 || GetParam(0) == 0) { 3015 CELL start; 3016 3017 TRACE(("CASE_TRACK_MOUSE\n")); 3018 /* Track mouse as long as in window and between 3019 * specified rows 3020 */ 3021 start.row = one_if_default(2) - 1; 3022 start.col = GetParam(1) - 1; 3023 TrackMouse(xw, 3024 GetParam(0), 3025 &start, 3026 GetParam(3) - 1, GetParam(4) - 2); 3027 } else { 3028 TRACE(("CASE_SD - scroll down\n")); 3029 /* SD */ 3030 RevScroll(xw, one_if_default(0)); 3031 do_xevents(xw); 3032 } 3033 ResetState(sp); 3034 break; 3035 3036 case CASE_SD: 3037 /* 3038 * Cater to ECMA-48's typographical error... 3039 */ 3040 TRACE(("CASE_SD - scroll down\n")); 3041 RevScroll(xw, one_if_default(0)); 3042 do_xevents(xw); 3043 ResetState(sp); 3044 break; 3045 3046 case CASE_DECID: 3047 TRACE(("CASE_DECID\n")); 3048 if_OPT_VT52_MODE(screen, { 3049 unparseputc(xw, ANSI_ESC); 3050 unparseputc(xw, '/'); 3051 unparseputc(xw, 'Z'); 3052 unparse_end(xw); 3053 ResetState(sp); 3054 break; 3055 }); 3056 SetParam(0, DEFAULT); /* Default ID parameter */ 3057 /* FALLTHRU */ 3058 case CASE_DA1: 3059 TRACE(("CASE_DA1\n")); 3060 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 3061 count = 0; 3062 init_reply(ANSI_CSI); 3063 reply.a_pintro = '?'; 3064 3065 /* 3066 * The first parameter corresponds to the highest operating 3067 * level (i.e., service level) of the emulation. A DEC 3068 * terminal can be setup to respond with a different DA 3069 * response, but there's no control sequence that modifies 3070 * this. We set it via a resource. 3071 */ 3072 if (screen->terminal_id < 200) { 3073 switch (screen->terminal_id) { 3074 case 132: 3075 reply.a_param[count++] = 4; /* VT132 */ 3076#if OPT_REGIS_GRAPHICS 3077 reply.a_param[count++] = 6; /* no STP, AVO, GPO (ReGIS) */ 3078#else 3079 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */ 3080#endif 3081 break; 3082 case 131: 3083 reply.a_param[count++] = 7; /* VT131 */ 3084 break; 3085 case 125: 3086 reply.a_param[count++] = 12; /* VT125 */ 3087#if OPT_REGIS_GRAPHICS 3088 reply.a_param[count++] = 0 | 2 | 1; /* no STP, AVO, GPO (ReGIS) */ 3089#else 3090 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */ 3091#endif 3092 reply.a_param[count++] = 0; /* no printer */ 3093 reply.a_param[count++] = XTERM_PATCH; /* ROM version */ 3094 break; 3095 case 102: 3096 reply.a_param[count++] = 6; /* VT102 */ 3097 break; 3098 case 101: 3099 reply.a_param[count++] = 1; /* VT101 */ 3100 reply.a_param[count++] = 0; /* no options */ 3101 break; 3102 default: /* VT100 */ 3103 reply.a_param[count++] = 1; /* VT100 */ 3104 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */ 3105 break; 3106 } 3107 } else { 3108 reply.a_param[count++] = (ParmType) (60 3109 + screen->terminal_id 3110 / 100); 3111 reply.a_param[count++] = 1; /* 132-columns */ 3112 reply.a_param[count++] = 2; /* printer */ 3113#if OPT_REGIS_GRAPHICS 3114 if (optRegisGraphics(screen)) { 3115 reply.a_param[count++] = 3; /* ReGIS graphics */ 3116 } 3117#endif 3118#if OPT_SIXEL_GRAPHICS 3119 if (optSixelGraphics(screen)) { 3120 reply.a_param[count++] = 4; /* sixel graphics */ 3121 } 3122#endif 3123 reply.a_param[count++] = 6; /* selective-erase */ 3124#if OPT_SUNPC_KBD 3125 if (xw->keyboard.type == keyboardIsVT220) 3126#endif 3127 reply.a_param[count++] = 8; /* user-defined-keys */ 3128 reply.a_param[count++] = 9; /* national replacement charsets */ 3129 reply.a_param[count++] = 15; /* technical characters */ 3130 reply.a_param[count++] = 16; /* locator port */ 3131 if (screen->terminal_id >= 400) { 3132 reply.a_param[count++] = 17; /* terminal state interrogation */ 3133 reply.a_param[count++] = 18; /* windowing extension */ 3134 reply.a_param[count++] = 21; /* horizontal scrolling */ 3135 } 3136 if_OPT_ISO_COLORS(screen, { 3137 reply.a_param[count++] = 22; /* ANSI color, VT525 */ 3138 }); 3139 reply.a_param[count++] = 28; /* rectangular editing */ 3140#if OPT_DEC_LOCATOR 3141 reply.a_param[count++] = 29; /* ANSI text locator */ 3142#endif 3143 } 3144 reply.a_nparam = (ParmType) count; 3145 reply.a_inters = 0; 3146 reply.a_final = 'c'; 3147 unparseseq(xw, &reply); 3148 } 3149 ResetState(sp); 3150 break; 3151 3152 case CASE_DA2: 3153 TRACE(("CASE_DA2\n")); 3154 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 3155 count = 0; 3156 init_reply(ANSI_CSI); 3157 reply.a_pintro = '>'; 3158 3159 if (screen->terminal_id >= 200) { 3160 switch (screen->terminal_id) { 3161 case 220: 3162 default: 3163 reply.a_param[count++] = 1; /* VT220 */ 3164 break; 3165 case 240: 3166 case 241: 3167 /* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */ 3168 reply.a_param[count++] = 2; /* VT240 */ 3169 break; 3170 case 320: 3171 /* http://www.vt100.net/docs/vt320-uu/appendixe.html */ 3172 reply.a_param[count++] = 24; /* VT320 */ 3173 break; 3174 case 330: 3175 reply.a_param[count++] = 18; /* VT330 */ 3176 break; 3177 case 340: 3178 reply.a_param[count++] = 19; /* VT340 */ 3179 break; 3180 case 382: 3181 reply.a_param[count++] = 32; /* VT382 */ 3182 break; 3183 case 420: 3184 reply.a_param[count++] = 41; /* VT420 */ 3185 break; 3186 case 510: 3187 /* http://www.vt100.net/docs/vt510-rm/DA2 */ 3188 reply.a_param[count++] = 61; /* VT510 */ 3189 break; 3190 case 520: 3191 reply.a_param[count++] = 64; /* VT520 */ 3192 break; 3193 case 525: 3194 reply.a_param[count++] = 65; /* VT525 */ 3195 break; 3196 } 3197 } else { 3198 reply.a_param[count++] = 0; /* VT100 (nonstandard) */ 3199 } 3200 reply.a_param[count++] = XTERM_PATCH; /* Version */ 3201 reply.a_param[count++] = 0; /* options (none) */ 3202 reply.a_nparam = (ParmType) count; 3203 reply.a_inters = 0; 3204 reply.a_final = 'c'; 3205 unparseseq(xw, &reply); 3206 } 3207 ResetState(sp); 3208 break; 3209 3210 case CASE_DECRPTUI: 3211 TRACE(("CASE_DECRPTUI\n")); 3212 if ((screen->vtXX_level >= 4) 3213 && (GetParam(0) <= 0)) { /* less than means DEFAULT */ 3214 unparseputc1(xw, ANSI_DCS); 3215 unparseputc(xw, '!'); 3216 unparseputc(xw, '|'); 3217 /* report the "terminal unit id" as 4 pairs of hexadecimal 3218 * digits -- meaningless for a terminal emulator, but some 3219 * host may care about the format. 3220 */ 3221 for (count = 0; count < 8; ++count) { 3222 unparseputc(xw, '0'); 3223 } 3224 unparseputc1(xw, ANSI_ST); 3225 unparse_end(xw); 3226 } 3227 ResetState(sp); 3228 break; 3229 3230 case CASE_TBC: 3231 TRACE(("CASE_TBC - tab clear\n")); 3232 if ((value = GetParam(0)) <= 0) /* less than means default */ 3233 TabClear(xw->tabs, screen->cur_col); 3234 else if (value == 3) 3235 TabZonk(xw->tabs); 3236 ResetState(sp); 3237 break; 3238 3239 case CASE_SET: 3240 TRACE(("CASE_SET - set mode\n")); 3241 ansi_modes(xw, bitset); 3242 ResetState(sp); 3243 break; 3244 3245 case CASE_RST: 3246 TRACE(("CASE_RST - reset mode\n")); 3247 ansi_modes(xw, bitclr); 3248 ResetState(sp); 3249 break; 3250 3251 case CASE_SGR: 3252 for (item = 0; item < nparam; ++item) { 3253 int op = GetParam(item); 3254 int skip; 3255 3256 if_OPT_XMC_GLITCH(screen, { 3257 Mark_XMC(xw, op); 3258 }); 3259 TRACE(("CASE_SGR %d\n", op)); 3260 3261 /* 3262 * Only SGR 38/48 accept subparameters, and in those cases 3263 * the values will not be seen at this point. 3264 */ 3265 if ((skip = param_has_subparams(item))) { 3266 switch (op) { 3267 case 38: 3268 /* FALLTHRU */ 3269 case 48: 3270 if_OPT_ISO_COLORS(screen, { 3271 break; 3272 }); 3273 /* FALLTHRU */ 3274 default: 3275 TRACE(("...unexpected subparameter in SGR\n")); 3276 item += skip; /* ignore this */ 3277 op = NPARAM; /* will never use this, anyway */ 3278 break; 3279 } 3280 } 3281 3282 switch (op) { 3283 case DEFAULT: 3284 /* FALLTHRU */ 3285 case 0: 3286 resetRendition(xw); 3287 if_OPT_ISO_COLORS(screen, { 3288 reset_SGR_Colors(xw); 3289 }); 3290 break; 3291 case 1: /* Bold */ 3292 UIntSet(xw->flags, BOLD); 3293 if_OPT_ISO_COLORS(screen, { 3294 setExtendedFG(xw); 3295 }); 3296 break; 3297#if OPT_WIDE_ATTRS 3298 case 2: /* faint, decreased intensity or second colour */ 3299 UIntSet(xw->flags, ATR_FAINT); 3300 if_OPT_ISO_COLORS(screen, { 3301 setExtendedFG(xw); 3302 }); 3303 break; 3304 case 3: /* italicized */ 3305 setItalicFont(xw, UseItalicFont(screen)); 3306 UIntSet(xw->flags, ATR_ITALIC); 3307 if_OPT_ISO_COLORS(screen, { 3308 setExtendedFG(xw); 3309 }); 3310 break; 3311#endif 3312 case 4: /* Underscore */ 3313 UIntSet(xw->flags, UNDERLINE); 3314 if_OPT_ISO_COLORS(screen, { 3315 setExtendedFG(xw); 3316 }); 3317 break; 3318 case 5: /* Blink (less than 150 per minute) */ 3319 /* FALLTHRU */ 3320 case 6: /* Blink (150 per minute, or more) */ 3321 UIntSet(xw->flags, BLINK); 3322 StartBlinking(xw); 3323 if_OPT_ISO_COLORS(screen, { 3324 setExtendedFG(xw); 3325 }); 3326 break; 3327 case 7: 3328 UIntSet(xw->flags, INVERSE); 3329 if_OPT_ISO_COLORS(screen, { 3330 setExtendedBG(xw); 3331 }); 3332 break; 3333 case 8: 3334 UIntSet(xw->flags, INVISIBLE); 3335 break; 3336#if OPT_WIDE_ATTRS 3337 case 9: /* crossed-out characters */ 3338 UIntSet(xw->flags, ATR_STRIKEOUT); 3339 break; 3340#endif 3341#if OPT_WIDE_ATTRS 3342 case 21: /* doubly-underlined */ 3343 UIntSet(xw->flags, ATR_DBL_UNDER); 3344 break; 3345#endif 3346 case 22: /* reset 'bold' */ 3347 UIntClr(xw->flags, BOLD); 3348#if OPT_WIDE_ATTRS 3349 UIntClr(xw->flags, ATR_FAINT); 3350#endif 3351 if_OPT_ISO_COLORS(screen, { 3352 setExtendedFG(xw); 3353 }); 3354 break; 3355#if OPT_WIDE_ATTRS 3356 case 23: /* not italicized */ 3357 ResetItalics(xw); 3358 if_OPT_ISO_COLORS(screen, { 3359 setExtendedFG(xw); 3360 }); 3361 break; 3362#endif 3363 case 24: 3364 UIntClr(xw->flags, UNDERLINE); 3365#if OPT_WIDE_ATTRS 3366 UIntClr(xw->flags, ATR_DBL_UNDER); 3367#endif 3368 if_OPT_ISO_COLORS(screen, { 3369 setExtendedFG(xw); 3370 }); 3371 break; 3372 case 25: /* reset 'blink' */ 3373 UIntClr(xw->flags, BLINK); 3374 if_OPT_ISO_COLORS(screen, { 3375 setExtendedFG(xw); 3376 }); 3377 break; 3378 case 27: 3379 UIntClr(xw->flags, INVERSE); 3380 if_OPT_ISO_COLORS(screen, { 3381 setExtendedBG(xw); 3382 }); 3383 break; 3384 case 28: 3385 UIntClr(xw->flags, INVISIBLE); 3386 break; 3387#if OPT_WIDE_ATTRS 3388 case 29: /* not crossed out */ 3389 UIntClr(xw->flags, ATR_STRIKEOUT); 3390 break; 3391#endif 3392 case 30: 3393 /* FALLTHRU */ 3394 case 31: 3395 /* FALLTHRU */ 3396 case 32: 3397 /* FALLTHRU */ 3398 case 33: 3399 /* FALLTHRU */ 3400 case 34: 3401 /* FALLTHRU */ 3402 case 35: 3403 /* FALLTHRU */ 3404 case 36: 3405 /* FALLTHRU */ 3406 case 37: 3407 if_OPT_ISO_COLORS(screen, { 3408 xw->sgr_foreground = (op - 30); 3409 xw->sgr_38_xcolors = False; 3410 clrDirectFG(xw->flags); 3411 setExtendedFG(xw); 3412 }); 3413 break; 3414 case 38: 3415 /* This is more complicated than I'd like, but it should 3416 * properly eat all the parameters for unsupported modes. 3417 */ 3418 if_OPT_ISO_COLORS(screen, { 3419 Boolean extended; 3420 if (parse_extended_colors(xw, &value, &item, 3421 &extended)) { 3422 xw->sgr_foreground = value; 3423 xw->sgr_38_xcolors = True; 3424 setDirectFG(xw->flags, extended); 3425 setExtendedFG(xw); 3426 } 3427 }); 3428 break; 3429 case 39: 3430 if_OPT_ISO_COLORS(screen, { 3431 reset_SGR_Foreground(xw); 3432 }); 3433 break; 3434 case 40: 3435 /* FALLTHRU */ 3436 case 41: 3437 /* FALLTHRU */ 3438 case 42: 3439 /* FALLTHRU */ 3440 case 43: 3441 /* FALLTHRU */ 3442 case 44: 3443 /* FALLTHRU */ 3444 case 45: 3445 /* FALLTHRU */ 3446 case 46: 3447 /* FALLTHRU */ 3448 case 47: 3449 if_OPT_ISO_COLORS(screen, { 3450 xw->sgr_background = (op - 40); 3451 clrDirectBG(xw->flags); 3452 setExtendedBG(xw); 3453 }); 3454 break; 3455 case 48: 3456 if_OPT_ISO_COLORS(screen, { 3457 Boolean extended; 3458 if (parse_extended_colors(xw, &value, &item, 3459 &extended)) { 3460 xw->sgr_background = value; 3461 setDirectBG(xw->flags, extended); 3462 setExtendedBG(xw); 3463 } 3464 }); 3465 break; 3466 case 49: 3467 if_OPT_ISO_COLORS(screen, { 3468 reset_SGR_Background(xw); 3469 }); 3470 break; 3471 case 90: 3472 /* FALLTHRU */ 3473 case 91: 3474 /* FALLTHRU */ 3475 case 92: 3476 /* FALLTHRU */ 3477 case 93: 3478 /* FALLTHRU */ 3479 case 94: 3480 /* FALLTHRU */ 3481 case 95: 3482 /* FALLTHRU */ 3483 case 96: 3484 /* FALLTHRU */ 3485 case 97: 3486 if_OPT_AIX_COLORS(screen, { 3487 xw->sgr_foreground = (op - 90 + 8); 3488 clrDirectFG(xw->flags); 3489 setExtendedFG(xw); 3490 }); 3491 break; 3492 case 100: 3493#if !OPT_AIX_COLORS 3494 if_OPT_ISO_COLORS(screen, { 3495 reset_SGR_Foreground(xw); 3496 reset_SGR_Background(xw); 3497 }); 3498 break; 3499#endif 3500 case 101: 3501 /* FALLTHRU */ 3502 case 102: 3503 /* FALLTHRU */ 3504 case 103: 3505 /* FALLTHRU */ 3506 case 104: 3507 /* FALLTHRU */ 3508 case 105: 3509 /* FALLTHRU */ 3510 case 106: 3511 /* FALLTHRU */ 3512 case 107: 3513 if_OPT_AIX_COLORS(screen, { 3514 xw->sgr_background = (op - 100 + 8); 3515 clrDirectBG(xw->flags); 3516 setExtendedBG(xw); 3517 }); 3518 break; 3519 default: 3520 /* later: skip += NPARAM; */ 3521 break; 3522 } 3523 } 3524 ResetState(sp); 3525 break; 3526 3527 /* DSR (except for the '?') is a superset of CPR */ 3528 case CASE_DSR: 3529 sp->private_function = True; 3530 3531 /* FALLTHRU */ 3532 case CASE_CPR: 3533 TRACE(("CASE_DSR - device status report\n")); 3534 count = 0; 3535 init_reply(ANSI_CSI); 3536 reply.a_pintro = CharOf(sp->private_function ? '?' : 0); 3537 reply.a_inters = 0; 3538 reply.a_final = 'n'; 3539 3540 switch (GetParam(0)) { 3541 case 5: 3542 TRACE(("...request operating status\n")); 3543 /* operating status */ 3544 reply.a_param[count++] = 0; /* (no malfunction ;-) */ 3545 break; 3546 case 6: 3547 TRACE(("...request %s\n", 3548 (sp->private_function 3549 ? "DECXCPR" 3550 : "CPR"))); 3551 /* CPR */ 3552 /* DECXCPR (with page=1) */ 3553 value = (screen->cur_row + 1); 3554 if ((xw->flags & ORIGIN) != 0) { 3555 value -= screen->top_marg; 3556 } 3557 reply.a_param[count++] = (ParmType) value; 3558 3559 value = (screen->cur_col + 1); 3560 if ((xw->flags & ORIGIN) != 0) { 3561 value -= screen->lft_marg; 3562 } 3563 reply.a_param[count++] = (ParmType) value; 3564 3565 if (sp->private_function 3566 && screen->vtXX_level >= 4) { /* VT420 */ 3567 reply.a_param[count++] = 1; 3568 } 3569 reply.a_final = 'R'; 3570 break; 3571 case 15: 3572 TRACE(("...request printer status\n")); 3573 if (sp->private_function 3574 && screen->vtXX_level >= 2) { /* VT220 */ 3575 reply.a_param[count++] = 13; /* no printer detected */ 3576 } 3577 break; 3578 case 25: 3579 TRACE(("...request UDK status\n")); 3580 if (sp->private_function 3581 && screen->vtXX_level >= 2) { /* VT220 */ 3582 reply.a_param[count++] = 20; /* UDK always unlocked */ 3583 } 3584 break; 3585 case 26: 3586 TRACE(("...request keyboard status\n")); 3587 if (sp->private_function 3588 && screen->vtXX_level >= 2) { /* VT220 */ 3589 reply.a_param[count++] = 27; 3590 reply.a_param[count++] = 1; /* North American */ 3591 if (screen->vtXX_level >= 3) { /* VT320 */ 3592 reply.a_param[count++] = 0; /* ready */ 3593 } 3594 if (screen->vtXX_level >= 4) { /* VT420 */ 3595 reply.a_param[count++] = 0; /* LK201 */ 3596 } 3597 } 3598 break; 3599 case 53: /* according to existing xterm handling */ 3600 /* FALLTHRU */ 3601 case 55: /* according to the VT330/VT340 Text Programming Manual */ 3602 TRACE(("...request locator status\n")); 3603 if (sp->private_function 3604 && screen->vtXX_level >= 3) { /* VT330 */ 3605#if OPT_DEC_LOCATOR 3606 reply.a_param[count++] = 50; /* locator ready */ 3607#else 3608 reply.a_param[count++] = 53; /* no locator */ 3609#endif 3610 } 3611 break; 3612 case 56: 3613 TRACE(("...request locator type\n")); 3614 if (sp->private_function 3615 && screen->vtXX_level >= 3) { /* VT330 */ 3616 reply.a_param[count++] = 57; 3617#if OPT_DEC_LOCATOR 3618 reply.a_param[count++] = 1; /* mouse */ 3619#else 3620 reply.a_param[count++] = 0; /* unknown */ 3621#endif 3622 } 3623 break; 3624 case 62: 3625 TRACE(("...request DECMSR - macro space\n")); 3626 if (sp->private_function 3627 && screen->vtXX_level >= 4) { /* VT420 */ 3628 reply.a_pintro = 0; 3629 reply.a_radix[count] = 16; /* no data */ 3630 reply.a_param[count++] = 0; /* no space for macros */ 3631 reply.a_inters = '*'; 3632 reply.a_final = L_CURL; 3633 } 3634 break; 3635 case 63: 3636 TRACE(("...request DECCKSR - memory checksum\n")); 3637 /* DECCKSR - Memory checksum */ 3638 if (sp->private_function 3639 && screen->vtXX_level >= 4) { /* VT420 */ 3640 init_reply(ANSI_DCS); 3641 reply.a_param[count++] = (ParmType) GetParam(1); /* PID */ 3642 reply.a_delim = "!~"; /* delimiter */ 3643 reply.a_radix[count] = 16; /* use hex */ 3644 reply.a_param[count++] = 0; /* no data */ 3645 } 3646 break; 3647 case 75: 3648 TRACE(("...request data integrity\n")); 3649 if (sp->private_function 3650 && screen->vtXX_level >= 4) { /* VT420 */ 3651 reply.a_param[count++] = 70; /* no errors */ 3652 } 3653 break; 3654 case 85: 3655 TRACE(("...request multi-session configuration\n")); 3656 if (sp->private_function 3657 && screen->vtXX_level >= 4) { /* VT420 */ 3658 reply.a_param[count++] = 83; /* not configured */ 3659 } 3660 break; 3661 default: 3662 break; 3663 } 3664 3665 if ((reply.a_nparam = (ParmType) count) != 0) 3666 unparseseq(xw, &reply); 3667 3668 ResetState(sp); 3669 sp->private_function = False; 3670 break; 3671 3672 case CASE_MC: 3673 TRACE(("CASE_MC - media control\n")); 3674 xtermMediaControl(xw, GetParam(0), False); 3675 ResetState(sp); 3676 break; 3677 3678 case CASE_DEC_MC: 3679 TRACE(("CASE_DEC_MC - DEC media control\n")); 3680 xtermMediaControl(xw, GetParam(0), True); 3681 ResetState(sp); 3682 break; 3683 3684 case CASE_HP_MEM_LOCK: 3685 /* FALLTHRU */ 3686 case CASE_HP_MEM_UNLOCK: 3687 TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK) 3688 ? "CASE_HP_MEM_LOCK" 3689 : "CASE_HP_MEM_UNLOCK"))); 3690 if (screen->scroll_amt) 3691 FlushScroll(xw); 3692 if (sp->parsestate[c] == CASE_HP_MEM_LOCK) 3693 set_tb_margins(screen, screen->cur_row, screen->bot_marg); 3694 else 3695 set_tb_margins(screen, 0, screen->bot_marg); 3696 ResetState(sp); 3697 break; 3698 3699 case CASE_DECSTBM: 3700 TRACE(("CASE_DECSTBM - set scrolling region\n")); 3701 { 3702 int top; 3703 int bot; 3704 top = one_if_default(0); 3705 if (nparam < 2 || (bot = GetParam(1)) == DEFAULT 3706 || bot > MaxRows(screen) 3707 || bot == 0) 3708 bot = MaxRows(screen); 3709 if (bot > top) { 3710 if (screen->scroll_amt) 3711 FlushScroll(xw); 3712 set_tb_margins(screen, top - 1, bot - 1); 3713 CursorSet(screen, 0, 0, xw->flags); 3714 } 3715 ResetState(sp); 3716 } 3717 break; 3718 3719 case CASE_DECREQTPARM: 3720 TRACE(("CASE_DECREQTPARM\n")); 3721 if (screen->terminal_id < 200) { /* VT102 */ 3722 value = zero_if_default(0); 3723 if (value == 0 || value == 1) { 3724 init_reply(ANSI_CSI); 3725 reply.a_pintro = 0; 3726 reply.a_nparam = 7; 3727 reply.a_param[0] = (ParmType) (value + 2); 3728 reply.a_param[1] = 1; /* no parity */ 3729 reply.a_param[2] = 1; /* eight bits */ 3730 reply.a_param[3] = 128; /* transmit 38.4k baud */ 3731 reply.a_param[4] = 128; /* receive 38.4k baud */ 3732 reply.a_param[5] = 1; /* clock multiplier ? */ 3733 reply.a_param[6] = 0; /* STP flags ? */ 3734 reply.a_inters = 0; 3735 reply.a_final = 'x'; 3736 unparseseq(xw, &reply); 3737 } 3738 } 3739 ResetState(sp); 3740 break; 3741 3742 case CASE_DECSET: 3743 /* DECSET */ 3744#if OPT_VT52_MODE 3745 if (screen->vtXX_level != 0) 3746#endif 3747 dpmodes(xw, bitset); 3748 ResetState(sp); 3749#if OPT_TEK4014 3750 if (TEK4014_ACTIVE(xw)) { 3751 TRACE(("Tek4014 is now active...\n")); 3752 if (sp->check_recur) 3753 sp->check_recur--; 3754 return False; 3755 } 3756#endif 3757 break; 3758 3759 case CASE_DECRST: 3760 /* DECRST */ 3761 dpmodes(xw, bitclr); 3762 init_groundtable(screen, sp); 3763 ResetState(sp); 3764 break; 3765 3766 case CASE_DECALN: 3767 TRACE(("CASE_DECALN - alignment test\n")); 3768 if (screen->cursor_state) 3769 HideCursor(xw); 3770 /* 3771 * DEC STD 070 does not mention left/right margins. Likely the 3772 * text was for VT100, and not updated for VT420. 3773 */ 3774 resetRendition(xw); 3775 resetMargins(xw); 3776 CursorSet(screen, 0, 0, xw->flags); 3777 xtermParseRect(xw, 0, 0, &myRect); 3778 ScrnFillRectangle(xw, &myRect, 'E', 0, False); 3779 ResetState(sp); 3780 break; 3781 3782 case CASE_GSETS5: 3783 if (screen->vtXX_level >= 5) { 3784 TRACE(("CASE_GSETS5(%d) = '%c'\n", sp->scstype, c)); 3785 xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c); 3786 } 3787 ResetState(sp); 3788 break; 3789 3790 case CASE_GSETS3: 3791 if (screen->vtXX_level >= 3) { 3792 TRACE(("CASE_GSETS3(%d) = '%c'\n", sp->scstype, c)); 3793 xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c); 3794 } 3795 ResetState(sp); 3796 break; 3797 3798 case CASE_GSETS: 3799 if (strchr("012AB", (int) c) != 0) { 3800 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c)); 3801 xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c); 3802 } else if (screen->vtXX_level >= 2) { 3803 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c)); 3804 xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c); 3805 } 3806 ResetState(sp); 3807 break; 3808 3809 case CASE_ANSI_SC: 3810 if (IsLeftRightMode(xw)) { 3811 int left; 3812 int right; 3813 3814 TRACE(("CASE_DECSLRM - set left and right margin\n")); 3815 left = one_if_default(0); 3816 if (nparam < 2 || (right = GetParam(1)) == DEFAULT 3817 || right > MaxCols(screen) 3818 || right == 0) 3819 right = MaxCols(screen); 3820 if (right > left) { 3821 set_lr_margins(screen, left - 1, right - 1); 3822 CursorSet(screen, 0, 0, xw->flags); 3823 } 3824 } else { 3825 TRACE(("CASE_ANSI_SC - save cursor\n")); 3826 CursorSave(xw); 3827 } 3828 ResetState(sp); 3829 break; 3830 3831 case CASE_DECSC: 3832 TRACE(("CASE_DECSC - save cursor\n")); 3833 CursorSave(xw); 3834 ResetState(sp); 3835 break; 3836 3837 case CASE_ANSI_RC: 3838 /* FALLTHRU */ 3839 case CASE_DECRC: 3840 TRACE(("CASE_%sRC - restore cursor\n", 3841 (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_")); 3842 CursorRestore(xw); 3843 if_OPT_ISO_COLORS(screen, { 3844 setExtendedFG(xw); 3845 }); 3846 ResetState(sp); 3847 break; 3848 3849 case CASE_DECKPAM: 3850 TRACE(("CASE_DECKPAM\n")); 3851 xw->keyboard.flags |= MODE_DECKPAM; 3852 update_appkeypad(); 3853 ResetState(sp); 3854 break; 3855 3856 case CASE_DECKPNM: 3857 TRACE(("CASE_DECKPNM\n")); 3858 UIntClr(xw->keyboard.flags, MODE_DECKPAM); 3859 update_appkeypad(); 3860 ResetState(sp); 3861 break; 3862 3863 case CASE_CSI_QUOTE_STATE: 3864 sp->parsestate = csi_quo_table; 3865 break; 3866 3867#if OPT_BLINK_CURS 3868 case CASE_CSI_SPACE_STATE: 3869 sp->parsestate = csi_sp_table; 3870 break; 3871 3872 case CASE_DECSCUSR: 3873 TRACE(("CASE_DECSCUSR\n")); 3874 { 3875 Boolean change = True; 3876 int blinks = screen->cursor_blink_esc; 3877 3878 HideCursor(xw); 3879 3880 switch (GetParam(0)) { 3881 case DEFAULT: 3882 /* FALLTHRU */ 3883 case DEFAULT_STYLE: 3884 /* FALLTHRU */ 3885 case BLINK_BLOCK: 3886 blinks = True; 3887 screen->cursor_shape = CURSOR_BLOCK; 3888 break; 3889 case STEADY_BLOCK: 3890 blinks = False; 3891 screen->cursor_shape = CURSOR_BLOCK; 3892 break; 3893 case BLINK_UNDERLINE: 3894 blinks = True; 3895 screen->cursor_shape = CURSOR_UNDERLINE; 3896 break; 3897 case STEADY_UNDERLINE: 3898 blinks = False; 3899 screen->cursor_shape = CURSOR_UNDERLINE; 3900 break; 3901 case BLINK_BAR: 3902 blinks = True; 3903 screen->cursor_shape = CURSOR_BAR; 3904 break; 3905 case STEADY_BAR: 3906 blinks = False; 3907 screen->cursor_shape = CURSOR_BAR; 3908 break; 3909 default: 3910 change = False; 3911 break; 3912 } 3913 TRACE(("cursor_shape:%d blinks:%s\n", 3914 screen->cursor_shape, BtoS(blinks))); 3915 if (change) { 3916 xtermSetCursorBox(screen); 3917 screen->cursor_blink_esc = blinks; 3918 UpdateCursorBlink(xw); 3919 } 3920 } 3921 ResetState(sp); 3922 break; 3923#endif 3924 3925#if OPT_SCROLL_LOCK 3926 case CASE_DECLL: 3927 TRACE(("CASE_DECLL\n")); 3928 if (nparam > 0) { 3929 for (count = 0; count < nparam; ++count) { 3930 int op = zero_if_default(count); 3931 switch (op) { 3932 case 0: 3933 case DEFAULT: 3934 xtermClearLEDs(screen); 3935 break; 3936 case 1: 3937 /* FALLTHRU */ 3938 case 2: 3939 /* FALLTHRU */ 3940 case 3: 3941 xtermShowLED(screen, 3942 (Cardinal) op, 3943 True); 3944 break; 3945 case 21: 3946 /* FALLTHRU */ 3947 case 22: 3948 /* FALLTHRU */ 3949 case 23: 3950 xtermShowLED(screen, 3951 (Cardinal) (op - 20), 3952 True); 3953 break; 3954 } 3955 } 3956 } else { 3957 xtermClearLEDs(screen); 3958 } 3959 ResetState(sp); 3960 break; 3961#endif 3962 3963#if OPT_VT52_MODE 3964 case CASE_VT52_FINISH: 3965 TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n", 3966 screen->terminal_id, 3967 screen->vtXX_level)); 3968 if (screen->terminal_id >= 100 3969 && screen->vtXX_level == 0) { 3970 sp->groundtable = 3971 sp->parsestate = ansi_table; 3972 /* 3973 * On restore, the terminal does not recognize DECRQSS for 3974 * DECSCL (per vttest). 3975 */ 3976 screen->vtXX_level = 1; 3977 xw->flags = screen->vt52_save_flags; 3978 screen->curgl = screen->vt52_save_curgl; 3979 screen->curgr = screen->vt52_save_curgr; 3980 screen->curss = screen->vt52_save_curss; 3981 restoreCharsets(screen, screen->vt52_save_gsets); 3982 update_vt52_vt100_settings(); 3983 } 3984 break; 3985#endif 3986 3987 case CASE_ANSI_LEVEL_1: 3988 TRACE(("CASE_ANSI_LEVEL_1\n")); 3989 set_ansi_conformance(screen, 1); 3990 ResetState(sp); 3991 break; 3992 3993 case CASE_ANSI_LEVEL_2: 3994 TRACE(("CASE_ANSI_LEVEL_2\n")); 3995 set_ansi_conformance(screen, 2); 3996 ResetState(sp); 3997 break; 3998 3999 case CASE_ANSI_LEVEL_3: 4000 TRACE(("CASE_ANSI_LEVEL_3\n")); 4001 set_ansi_conformance(screen, 3); 4002 ResetState(sp); 4003 break; 4004 4005 case CASE_DECSCL: 4006 TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1))); 4007 /* 4008 * This changes the emulation level, and is not recognized by 4009 * VT100s. However, a VT220 or above can be set to conformance 4010 * level 1 to act like a VT100. 4011 */ 4012 if (screen->terminal_id >= 200) { 4013 /* 4014 * Disallow unrecognized parameters, as well as attempts to set 4015 * the operating level higher than the given terminal-id. 4016 */ 4017 if (GetParam(0) >= 61 4018 && GetParam(0) <= 60 + (screen->terminal_id / 100)) { 4019 int new_vtXX_level = GetParam(0) - 60; 4020 int case_value = zero_if_default(1); 4021 /* 4022 * Note: 4023 * 4024 * The VT300, VT420, VT520 manuals claim that DECSCL does a 4025 * hard reset (RIS). 4026 * 4027 * Both the VT220 manual and DEC STD 070 (which documents 4028 * levels 1-4 in detail) state that it is a soft reset. 4029 * 4030 * Perhaps both sets of manuals are right (unlikely). 4031 * Kermit says it's soft. 4032 */ 4033 ReallyReset(xw, False, False); 4034 init_parser(xw, sp); 4035 screen->vtXX_level = new_vtXX_level; 4036 if (new_vtXX_level > 1) { 4037 switch (case_value) { 4038 case 1: 4039 show_8bit_control(False); 4040 break; 4041 case 0: 4042 case 2: 4043 show_8bit_control(True); 4044 break; 4045 } 4046 } 4047 } 4048 } 4049 ResetState(sp); 4050 break; 4051 4052 case CASE_DECSCA: 4053 TRACE(("CASE_DECSCA\n")); 4054 screen->protected_mode = DEC_PROTECT; 4055 if (GetParam(0) <= 0 || GetParam(0) == 2) { 4056 UIntClr(xw->flags, PROTECTED); 4057 TRACE(("...clear PROTECTED\n")); 4058 } else if (GetParam(0) == 1) { 4059 xw->flags |= PROTECTED; 4060 TRACE(("...set PROTECTED\n")); 4061 } 4062 ResetState(sp); 4063 break; 4064 4065 case CASE_DECSED: 4066 TRACE(("CASE_DECSED\n")); 4067 do_erase_display(xw, zero_if_default(0), DEC_PROTECT); 4068 ResetState(sp); 4069 break; 4070 4071 case CASE_DECSEL: 4072 TRACE(("CASE_DECSEL\n")); 4073 do_erase_line(xw, zero_if_default(0), DEC_PROTECT); 4074 ResetState(sp); 4075 break; 4076 4077 case CASE_GRAPHICS_ATTRIBUTES: 4078#if OPT_GRAPHICS 4079 TRACE(("CASE_GRAPHICS_ATTRIBUTES\n")); 4080 { 4081 /* request: item, action, value */ 4082 /* reply: item, status, value */ 4083 if (nparam != 3) { 4084 TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam)); 4085 } else { 4086 int status = 3; /* assume failure */ 4087 int result = 0; 4088 int result2 = 0; 4089 4090 TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n", 4091 GetParam(0), GetParam(1), GetParam(2))); 4092 switch (GetParam(0)) { 4093 case 1: /* color register count */ 4094 switch (GetParam(1)) { 4095 case 1: /* read */ 4096 status = 0; /* success */ 4097 result = (int) get_color_register_count(screen); 4098 break; 4099 case 2: /* reset */ 4100 screen->numcolorregisters = 0; 4101 status = 0; /* success */ 4102 result = (int) get_color_register_count(screen); 4103 break; 4104 case 3: /* set */ 4105 if (GetParam(2) > 1 && 4106 (unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) { 4107 screen->numcolorregisters = GetParam(2); 4108 status = 0; /* success */ 4109 result = (int) get_color_register_count(screen); 4110 } 4111 break; 4112 case 4: /* read maximum */ 4113 status = 0; /* success */ 4114 result = MAX_COLOR_REGISTERS; 4115 break; 4116 default: 4117 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n", 4118 GetParam(1))); 4119 status = 2; /* error in Pa */ 4120 break; 4121 } 4122 break; 4123 case 2: /* graphics geometry */ 4124 switch (GetParam(1)) { 4125 case 1: /* read */ 4126 TRACE(("Get sixel graphics geometry\n")); 4127 status = 0; /* success */ 4128 result = Min(Width(screen), (int) screen->graphics_max_wide); 4129 result2 = Min(Height(screen), (int) screen->graphics_max_high); 4130 break; 4131 case 2: /* reset */ 4132 /* FALLTHRU */ 4133 case 3: /* set */ 4134 break; 4135 case 4: /* read maximum */ 4136 status = 0; /* success */ 4137 result = screen->graphics_max_wide; 4138 result2 = screen->graphics_max_high; 4139 break; 4140 default: 4141 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n", 4142 GetParam(1))); 4143 status = 2; /* error in Pa */ 4144 break; 4145 } 4146 break; 4147# if OPT_REGIS_GRAPHICS 4148 case 3: /* ReGIS geometry */ 4149 switch (GetParam(1)) { 4150 case 1: /* read */ 4151 status = 0; /* success */ 4152 result = screen->graphics_regis_def_wide; 4153 result2 = screen->graphics_regis_def_high; 4154 break; 4155 case 2: /* reset */ 4156 /* FALLTHRU */ 4157 case 3: /* set */ 4158 /* FALLTHRU */ 4159 case 4: /* read maximum */ 4160 /* not implemented */ 4161 break; 4162 default: 4163 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n", 4164 GetParam(1))); 4165 status = 2; /* error in Pa */ 4166 break; 4167 } 4168 break; 4169#endif 4170 default: 4171 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n", 4172 GetParam(0))); 4173 status = 1; 4174 break; 4175 } 4176 4177 init_reply(ANSI_CSI); 4178 reply.a_pintro = '?'; 4179 count = 0; 4180 reply.a_param[count++] = (ParmType) GetParam(0); 4181 reply.a_param[count++] = (ParmType) status; 4182 reply.a_param[count++] = (ParmType) result; 4183 if (GetParam(0) >= 2) 4184 reply.a_param[count++] = (ParmType) result2; 4185 reply.a_nparam = (ParmType) count; 4186 reply.a_inters = 0; 4187 reply.a_final = 'S'; 4188 unparseseq(xw, &reply); 4189 } 4190 } 4191#endif 4192 ResetState(sp); 4193 break; 4194 4195 case CASE_ST: 4196 TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n", 4197 (unsigned long) sp->string_used, 4198 sp->string_mode)); 4199 ResetState(sp); 4200 if (!sp->string_used) 4201 break; 4202 sp->string_area[--(sp->string_used)] = '\0'; 4203 if (sp->check_recur <= 1) 4204 switch (sp->string_mode) { 4205 case ANSI_APC: 4206 /* ignored */ 4207 break; 4208 case ANSI_DCS: 4209 do_dcs(xw, sp->string_area, sp->string_used); 4210 break; 4211 case ANSI_OSC: 4212 do_osc(xw, sp->string_area, sp->string_used, ANSI_ST); 4213 break; 4214 case ANSI_PM: 4215 /* ignored */ 4216 break; 4217 case ANSI_SOS: 4218 /* ignored */ 4219 break; 4220 default: 4221 TRACE(("unknown mode\n")); 4222 break; 4223 } 4224 break; 4225 4226 case CASE_SOS: 4227 TRACE(("CASE_SOS: Start of String\n")); 4228 if (ParseSOS(screen)) { 4229 sp->string_mode = ANSI_SOS; 4230 sp->parsestate = sos_table; 4231 } else { 4232 illegal_parse(xw, c, sp); 4233 } 4234 break; 4235 4236 case CASE_PM: 4237 TRACE(("CASE_PM: Privacy Message\n")); 4238 if (ParseSOS(screen)) { 4239 sp->string_mode = ANSI_PM; 4240 sp->parsestate = sos_table; 4241 } else { 4242 illegal_parse(xw, c, sp); 4243 } 4244 break; 4245 4246 case CASE_DCS: 4247 TRACE(("CASE_DCS: Device Control String\n")); 4248 sp->string_mode = ANSI_DCS; 4249 sp->parsestate = sos_table; 4250 break; 4251 4252 case CASE_APC: 4253 TRACE(("CASE_APC: Application Program Command\n")); 4254 if (ParseSOS(screen)) { 4255 sp->string_mode = ANSI_APC; 4256 sp->parsestate = sos_table; 4257 } else { 4258 illegal_parse(xw, c, sp); 4259 } 4260 break; 4261 4262 case CASE_SPA: 4263 TRACE(("CASE_SPA - start protected area\n")); 4264 screen->protected_mode = ISO_PROTECT; 4265 xw->flags |= PROTECTED; 4266 ResetState(sp); 4267 break; 4268 4269 case CASE_EPA: 4270 TRACE(("CASE_EPA - end protected area\n")); 4271 UIntClr(xw->flags, PROTECTED); 4272 ResetState(sp); 4273 break; 4274 4275 case CASE_SU: 4276 TRACE(("CASE_SU - scroll up\n")); 4277 xtermScroll(xw, one_if_default(0)); 4278 ResetState(sp); 4279 break; 4280 4281 case CASE_SL: /* ISO 6429, non-DEC */ 4282 TRACE(("CASE_SL - scroll left\n")); 4283 xtermScrollLR(xw, one_if_default(0), True); 4284 ResetState(sp); 4285 break; 4286 4287 case CASE_SR: /* ISO 6429, non-DEC */ 4288 TRACE(("CASE_SR - scroll right\n")); 4289 xtermScrollLR(xw, one_if_default(0), False); 4290 ResetState(sp); 4291 break; 4292 4293 case CASE_DECDC: 4294 TRACE(("CASE_DC - delete column\n")); 4295 if (screen->vtXX_level >= 4) { 4296 xtermColScroll(xw, one_if_default(0), True, screen->cur_col); 4297 } 4298 ResetState(sp); 4299 break; 4300 4301 case CASE_DECIC: 4302 TRACE(("CASE_IC - insert column\n")); 4303 if (screen->vtXX_level >= 4) { 4304 xtermColScroll(xw, one_if_default(0), False, screen->cur_col); 4305 } 4306 ResetState(sp); 4307 break; 4308 4309 case CASE_DECBI: 4310 TRACE(("CASE_BI - back index\n")); 4311 if (screen->vtXX_level >= 4) { 4312 xtermColIndex(xw, True); 4313 } 4314 ResetState(sp); 4315 break; 4316 4317 case CASE_DECFI: 4318 TRACE(("CASE_FI - forward index\n")); 4319 if (screen->vtXX_level >= 4) { 4320 xtermColIndex(xw, False); 4321 } 4322 ResetState(sp); 4323 break; 4324 4325 case CASE_IND: 4326 TRACE(("CASE_IND - index\n")); 4327 xtermIndex(xw, 1); 4328 do_xevents(xw); 4329 ResetState(sp); 4330 break; 4331 4332 case CASE_CPL: 4333 TRACE(("CASE_CPL - cursor prev line\n")); 4334 CursorPrevLine(xw, one_if_default(0)); 4335 ResetState(sp); 4336 break; 4337 4338 case CASE_CNL: 4339 TRACE(("CASE_CNL - cursor next line\n")); 4340 CursorNextLine(xw, one_if_default(0)); 4341 ResetState(sp); 4342 break; 4343 4344 case CASE_NEL: 4345 TRACE(("CASE_NEL\n")); 4346 xtermIndex(xw, 1); 4347 CarriageReturn(xw); 4348 ResetState(sp); 4349 break; 4350 4351 case CASE_HTS: 4352 TRACE(("CASE_HTS - horizontal tab set\n")); 4353 TabSet(xw->tabs, screen->cur_col); 4354 ResetState(sp); 4355 break; 4356 4357 case CASE_REPORT_VERSION: 4358 TRACE(("CASE_REPORT_VERSION - report terminal version\n")); 4359 if (GetParam(0) <= 0) { 4360 unparseputc1(xw, ANSI_DCS); 4361 unparseputc(xw, '>'); 4362 unparseputc(xw, '|'); 4363 unparseputs(xw, xtermVersion()); 4364 unparseputc1(xw, ANSI_ST); 4365 unparse_end(xw); 4366 } 4367 ResetState(sp); 4368 break; 4369 4370 case CASE_RI: 4371 TRACE(("CASE_RI - reverse index\n")); 4372 RevIndex(xw, 1); 4373 ResetState(sp); 4374 break; 4375 4376 case CASE_SS2: 4377 TRACE(("CASE_SS2\n")); 4378 screen->curss = 2; 4379 ResetState(sp); 4380 break; 4381 4382 case CASE_SS3: 4383 TRACE(("CASE_SS3\n")); 4384 screen->curss = 3; 4385 ResetState(sp); 4386 break; 4387 4388 case CASE_CSI_STATE: 4389 /* enter csi state */ 4390 InitParams(); 4391 SetParam(nparam++, DEFAULT); 4392 sp->parsestate = csi_table; 4393 break; 4394 4395 case CASE_ESC_SP_STATE: 4396 /* esc space */ 4397 sp->parsestate = esc_sp_table; 4398 break; 4399 4400 case CASE_CSI_EX_STATE: 4401 /* csi exclamation */ 4402 sp->parsestate = csi_ex_table; 4403 break; 4404 4405 case CASE_CSI_TICK_STATE: 4406 /* csi tick (') */ 4407 sp->parsestate = csi_tick_table; 4408 break; 4409 4410#if OPT_DEC_LOCATOR 4411 case CASE_DECEFR: 4412 TRACE(("CASE_DECEFR - Enable Filter Rectangle\n")); 4413 if (okSendMousePos(xw) == DEC_LOCATOR) { 4414 MotionOff(screen, xw); 4415 if ((screen->loc_filter_top = GetParam(0)) < 1) 4416 screen->loc_filter_top = LOC_FILTER_POS; 4417 if (nparam < 2 4418 || (screen->loc_filter_left = GetParam(1)) < 1) 4419 screen->loc_filter_left = LOC_FILTER_POS; 4420 if (nparam < 3 4421 || (screen->loc_filter_bottom = GetParam(2)) < 1) 4422 screen->loc_filter_bottom = LOC_FILTER_POS; 4423 if (nparam < 4 4424 || (screen->loc_filter_right = GetParam(3)) < 1) 4425 screen->loc_filter_right = LOC_FILTER_POS; 4426 InitLocatorFilter(xw); 4427 } 4428 ResetState(sp); 4429 break; 4430 4431 case CASE_DECELR: 4432 MotionOff(screen, xw); 4433 if (GetParam(0) <= 0 || GetParam(0) > 2) { 4434 screen->send_mouse_pos = MOUSE_OFF; 4435 TRACE(("DECELR - Disable Locator Reports\n")); 4436 } else { 4437 TRACE(("DECELR - Enable Locator Reports\n")); 4438 screen->send_mouse_pos = DEC_LOCATOR; 4439 xtermShowPointer(xw, True); 4440 if (GetParam(0) == 2) { 4441 screen->locator_reset = True; 4442 } else { 4443 screen->locator_reset = False; 4444 } 4445 if (nparam < 2 || GetParam(1) != 1) { 4446 screen->locator_pixels = False; 4447 } else { 4448 screen->locator_pixels = True; 4449 } 4450 screen->loc_filter = False; 4451 } 4452 ResetState(sp); 4453 break; 4454 4455 case CASE_DECSLE: 4456 TRACE(("DECSLE - Select Locator Events\n")); 4457 for (count = 0; count < nparam; ++count) { 4458 switch (zero_if_default(count)) { 4459 case 0: 4460 MotionOff(screen, xw); 4461 screen->loc_filter = False; 4462 screen->locator_events = 0; 4463 break; 4464 case 1: 4465 screen->locator_events |= LOC_BTNS_DN; 4466 break; 4467 case 2: 4468 UIntClr(screen->locator_events, LOC_BTNS_DN); 4469 break; 4470 case 3: 4471 screen->locator_events |= LOC_BTNS_UP; 4472 break; 4473 case 4: 4474 UIntClr(screen->locator_events, LOC_BTNS_UP); 4475 break; 4476 } 4477 } 4478 ResetState(sp); 4479 break; 4480 4481 case CASE_DECRQLP: 4482 TRACE(("DECRQLP - Request Locator Position\n")); 4483 if (GetParam(0) < 2) { 4484 /* Issue DECLRP Locator Position Report */ 4485 GetLocatorPosition(xw); 4486 } 4487 ResetState(sp); 4488 break; 4489#endif /* OPT_DEC_LOCATOR */ 4490 4491#if OPT_DEC_RECTOPS 4492 case CASE_CSI_DOLLAR_STATE: 4493 TRACE(("CASE_CSI_DOLLAR_STATE\n")); 4494 /* csi dollar ($) */ 4495 if (screen->vtXX_level >= 3) 4496 sp->parsestate = csi_dollar_table; 4497 else 4498 sp->parsestate = eigtable; 4499 break; 4500 4501 case CASE_CSI_STAR_STATE: 4502 TRACE(("CASE_CSI_STAR_STATE\n")); 4503 /* csi star (*) */ 4504 if (screen->vtXX_level >= 4) 4505 sp->parsestate = csi_star_table; 4506 else 4507 sp->parsestate = eigtable; 4508 break; 4509 4510 case CASE_DECRQCRA: 4511 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) { 4512 int checksum; 4513 int pid; 4514 4515 TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n")); 4516 xtermCheckRect(xw, ParamPair(0), &checksum); 4517 init_reply(ANSI_DCS); 4518 count = 0; 4519 checksum &= 0xffff; 4520 pid = GetParam(0); 4521 reply.a_param[count++] = (ParmType) pid; 4522 reply.a_delim = "!~"; /* delimiter */ 4523 reply.a_radix[count] = 16; 4524 reply.a_param[count++] = (ParmType) checksum; 4525 reply.a_nparam = (ParmType) count; 4526 TRACE(("...checksum(%d) = %04X\n", pid, checksum)); 4527 unparseseq(xw, &reply); 4528 } 4529 ResetState(sp); 4530 break; 4531 4532 case CASE_DECCRA: 4533 if (screen->vtXX_level >= 4) { 4534 TRACE(("CASE_DECCRA - Copy rectangular area\n")); 4535 xtermParseRect(xw, ParamPair(0), &myRect); 4536 ScrnCopyRectangle(xw, &myRect, ParamPair(5)); 4537 } 4538 ResetState(sp); 4539 break; 4540 4541 case CASE_DECERA: 4542 if (screen->vtXX_level >= 4) { 4543 TRACE(("CASE_DECERA - Erase rectangular area\n")); 4544 xtermParseRect(xw, ParamPair(0), &myRect); 4545 ScrnFillRectangle(xw, &myRect, ' ', xw->flags, True); 4546 } 4547 ResetState(sp); 4548 break; 4549 4550 case CASE_DECFRA: 4551 if (screen->vtXX_level >= 4) { 4552 value = zero_if_default(0); 4553 4554 TRACE(("CASE_DECFRA - Fill rectangular area\n")); 4555 if (nparam > 0 && CharWidth(value) > 0) { 4556 xtermParseRect(xw, ParamPair(1), &myRect); 4557 ScrnFillRectangle(xw, &myRect, value, xw->flags, True); 4558 } 4559 } 4560 ResetState(sp); 4561 break; 4562 4563 case CASE_DECSERA: 4564 if (screen->vtXX_level >= 4) { 4565 TRACE(("CASE_DECSERA - Selective erase rectangular area\n")); 4566 xtermParseRect(xw, ParamPair(0), &myRect); 4567 ScrnWipeRectangle(xw, &myRect); 4568 } 4569 ResetState(sp); 4570 break; 4571 4572 case CASE_DECSACE: 4573 TRACE(("CASE_DECSACE - Select attribute change extent\n")); 4574 screen->cur_decsace = zero_if_default(0); 4575 ResetState(sp); 4576 break; 4577 4578 case CASE_DECCARA: 4579 if (screen->vtXX_level >= 4) { 4580 TRACE(("CASE_DECCARA - Change attributes in rectangular area\n")); 4581 xtermParseRect(xw, ParamPair(0), &myRect); 4582 ScrnMarkRectangle(xw, &myRect, False, ParamPair(4)); 4583 } 4584 ResetState(sp); 4585 break; 4586 4587 case CASE_DECRARA: 4588 if (screen->vtXX_level >= 4) { 4589 TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n")); 4590 xtermParseRect(xw, ParamPair(0), &myRect); 4591 ScrnMarkRectangle(xw, &myRect, True, ParamPair(4)); 4592 } 4593 ResetState(sp); 4594 break; 4595 4596 case CASE_DECSCPP: 4597 if (screen->vtXX_level >= 3) { 4598 TRACE(("CASE_DECSCPP\n")); 4599 /* default and 0 are "80", with "132" as the other legal choice */ 4600 switch (zero_if_default(0)) { 4601 case 0: 4602 case 80: 4603 value = 80; 4604 break; 4605 case 132: 4606 value = 132; 4607 break; 4608 default: 4609 value = -1; 4610 break; 4611 } 4612 if (value > 0) { 4613 if (screen->cur_col + 1 > value) 4614 CursorSet(screen, screen->cur_row, value - 1, xw->flags); 4615 UIntClr(xw->flags, IN132COLUMNS); 4616 if (value == 132) 4617 UIntSet(xw->flags, IN132COLUMNS); 4618 RequestResize(xw, -1, value, True); 4619 } 4620 } 4621 ResetState(sp); 4622 break; 4623 4624 case CASE_DECSNLS: 4625 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetWinLines)) { 4626 TRACE(("CASE_DECSNLS\n")); 4627 value = zero_if_default(0); 4628 if (value >= 1 && value <= 255) { 4629 RequestResize(xw, value, -1, True); 4630 } 4631 } 4632 ResetState(sp); 4633 break; 4634 4635 case CASE_DECRQPSR: 4636#define reply_char(n,c) do { reply.a_radix[(n)] = 1; reply.a_param[(n)++] = (ParmType)(c); } while (0) 4637#define reply_bit(n,c) ((n) ? (c) : 0) 4638 if (screen->vtXX_level >= 3) { 4639 TRACE(("CASE_DECRQPSR\n")); 4640 switch (GetParam(0)) { 4641 case 1: 4642 TRACE(("...DECCIR\n")); 4643 init_reply(ANSI_DCS); 4644 count = 0; 4645 reply_char(count, '1'); 4646 reply_char(count, '$'); 4647 reply_char(count, 'u'); 4648 reply.a_param[count++] = (ParmType) (screen->cur_row + 1); 4649 reply.a_param[count++] = (ParmType) (screen->cur_col + 1); 4650 reply.a_param[count++] = (ParmType) thispage; 4651 reply_char(count, ';'); 4652 reply_char(count, (0x40 4653 | reply_bit(xw->flags & INVERSE, 8) 4654 | reply_bit(xw->flags & BLINK, 4) 4655 | reply_bit(xw->flags & UNDERLINE, 2) 4656 | reply_bit(xw->flags & BOLD, 1) 4657 )); 4658 reply_char(count, ';'); 4659 reply_char(count, 0x40 | 4660 reply_bit(screen->protected_mode & 4661 DEC_PROTECT, 1) 4662 ); 4663 reply_char(count, ';'); 4664 reply_char(count, (0x40 4665 | reply_bit(screen->do_wrap, 8) 4666 | reply_bit((screen->curss == 3), 4) 4667 | reply_bit((screen->curss == 2), 2) 4668 | reply_bit(xw->flags & ORIGIN, 1) 4669 )); 4670 reply_char(count, ';'); 4671 reply.a_param[count++] = screen->curgl; 4672 reply.a_param[count++] = screen->curgr; 4673 reply_char(count, ';'); 4674 reply_char(count, 0x4f); /* assert all 96's */ 4675 reply_char(count, ';'); 4676 for (item = 0; item < NUM_GSETS; ++item) { 4677 char *temp = encode_scs(screen->gsets[item]); 4678 while (*temp != '\0') { 4679 reply_char(count, *temp++); 4680 } 4681 } 4682 reply.a_nparam = (ParmType) count; 4683 unparseseq(xw, &reply); 4684 break; 4685 case 2: 4686 TRACE(("...DECTABSR\n")); 4687 init_reply(ANSI_DCS); 4688 reply.a_delim = "/"; 4689 count = 0; 4690 reply_char(count, '2'); 4691 reply_char(count, '$'); 4692 reply_char(count, 'u'); 4693 for (item = 0; item < MAX_TABS; ++item) { 4694 if (count + 1 >= NPARAM) 4695 break; 4696 if (TabIsSet(xw->tabs, item)) { 4697 reply.a_param[count++] = (ParmType) (item + 1); 4698 } 4699 if (item > screen->max_col) 4700 break; 4701 } 4702 reply.a_nparam = (ParmType) count; 4703 unparseseq(xw, &reply); 4704 break; 4705 } 4706 } 4707 ResetState(sp); 4708 break; 4709 4710 case CASE_RQM: 4711 TRACE(("CASE_RQM\n")); 4712 do_ansi_rqm(xw, ParamPair(0)); 4713 ResetState(sp); 4714 break; 4715 4716 case CASE_DECRQM: 4717 TRACE(("CASE_DECRQM\n")); 4718 do_dec_rqm(xw, ParamPair(0)); 4719 ResetState(sp); 4720 break; 4721 4722 case CASE_CSI_DEC_DOLLAR_STATE: 4723 TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n")); 4724 /* csi ? dollar ($) */ 4725 sp->parsestate = csi_dec_dollar_table; 4726 break; 4727#else 4728 case CASE_CSI_DOLLAR_STATE: 4729 /* csi dollar ($) */ 4730 sp->parsestate = eigtable; 4731 break; 4732 4733 case CASE_CSI_STAR_STATE: 4734 /* csi dollar (*) */ 4735 sp->parsestate = eigtable; 4736 break; 4737 4738 case CASE_CSI_DEC_DOLLAR_STATE: 4739 /* csi ? dollar ($) */ 4740 sp->parsestate = eigtable; 4741 break; 4742#endif /* OPT_DEC_RECTOPS */ 4743 4744#if OPT_XTERM_SGR 4745 case CASE_CSI_HASH_STATE: 4746 TRACE(("CASE_CSI_HASH_STATE\n")); 4747 /* csi hash (#) */ 4748 sp->parsestate = csi_hash_table; 4749 break; 4750 4751 case CASE_XTERM_CHECKSUM: 4752#if OPT_DEC_RECTOPS 4753 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) { 4754 TRACE(("CASE_XTERM_CHECKSUM\n")); 4755 screen->checksum_ext = zero_if_default(0); 4756 } 4757#endif 4758 ResetState(sp); 4759 break; 4760 4761 case CASE_XTERM_PUSH_SGR: 4762 TRACE(("CASE_XTERM_PUSH_SGR\n")); 4763 value = 0; 4764 if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) { 4765 value = DEFAULT; 4766 } else if (nparam > 0) { 4767 for (count = 0; count < nparam; ++count) { 4768 item = zero_if_default(count); 4769 /* deprecated - for compatibility */ 4770#if OPT_ISO_COLORS 4771 if (item == psFG_COLOR_obs) { 4772 item = psFG_COLOR; 4773 } else if (item == psBG_COLOR_obs) { 4774 item = psBG_COLOR; 4775 } 4776#endif 4777 if (item > 0 && item < MAX_PUSH_SGR) { 4778 value |= (1 << (item - 1)); 4779 } 4780 } 4781 } 4782 xtermPushSGR(xw, value); 4783 ResetState(sp); 4784 break; 4785 4786 case CASE_XTERM_REPORT_SGR: 4787 TRACE(("CASE_XTERM_REPORT_SGR\n")); 4788 xtermParseRect(xw, ParamPair(0), &myRect); 4789 xtermReportSGR(xw, &myRect); 4790 ResetState(sp); 4791 break; 4792 4793 case CASE_XTERM_POP_SGR: 4794 TRACE(("CASE_XTERM_POP_SGR\n")); 4795 xtermPopSGR(xw); 4796 ResetState(sp); 4797 break; 4798 4799 case CASE_XTERM_PUSH_COLORS: 4800 TRACE(("CASE_XTERM_PUSH_COLORS\n")); 4801 if (nparam == 0) { 4802 xtermPushColors(xw, DEFAULT); 4803 } else { 4804 for (count = 0; count < nparam; ++count) { 4805 xtermPushColors(xw, GetParam(count)); 4806 } 4807 } 4808 ResetState(sp); 4809 break; 4810 4811 case CASE_XTERM_POP_COLORS: 4812 TRACE(("CASE_XTERM_POP_COLORS\n")); 4813 if (nparam == 0) { 4814 xtermPopColors(xw, DEFAULT); 4815 } else { 4816 for (count = 0; count < nparam; ++count) { 4817 xtermPopColors(xw, GetParam(count)); 4818 } 4819 } 4820 ResetState(sp); 4821 break; 4822 4823 case CASE_XTERM_REPORT_COLORS: 4824 TRACE(("CASE_XTERM_REPORT_COLORS\n")); 4825 xtermReportColors(xw); 4826 ResetState(sp); 4827 break; 4828#endif 4829 4830 case CASE_S7C1T: 4831 TRACE(("CASE_S7C1T\n")); 4832 if (screen->vtXX_level >= 2) { 4833 show_8bit_control(False); 4834 ResetState(sp); 4835 } 4836 break; 4837 4838 case CASE_S8C1T: 4839 TRACE(("CASE_S8C1T\n")); 4840 if (screen->vtXX_level >= 2) { 4841 show_8bit_control(True); 4842 ResetState(sp); 4843 } 4844 break; 4845 4846 case CASE_OSC: 4847 TRACE(("CASE_OSC: Operating System Command\n")); 4848 sp->parsestate = sos_table; 4849 sp->string_mode = ANSI_OSC; 4850 break; 4851 4852 case CASE_RIS: 4853 TRACE(("CASE_RIS\n")); 4854 VTReset(xw, True, True); 4855 /* NOTREACHED */ 4856 4857 case CASE_DECSTR: 4858 TRACE(("CASE_DECSTR\n")); 4859 VTReset(xw, False, False); 4860 /* NOTREACHED */ 4861 4862 case CASE_REP: 4863 TRACE(("CASE_REP\n")); 4864 if (CharWidth(sp->lastchar) > 0) { 4865 IChar repeated[2]; 4866 count = one_if_default(0); 4867 repeated[0] = (IChar) sp->lastchar; 4868 while (count-- > 0) { 4869 dotext(xw, 4870 screen->gsets[(int) (screen->curgl)], 4871 repeated, 1); 4872 } 4873 } 4874 ResetState(sp); 4875 break; 4876 4877 case CASE_LS2: 4878 TRACE(("CASE_LS2\n")); 4879 screen->curgl = 2; 4880 ResetState(sp); 4881 break; 4882 4883 case CASE_LS3: 4884 TRACE(("CASE_LS3\n")); 4885 screen->curgl = 3; 4886 ResetState(sp); 4887 break; 4888 4889 case CASE_LS3R: 4890 TRACE(("CASE_LS3R\n")); 4891 screen->curgr = 3; 4892 ResetState(sp); 4893 break; 4894 4895 case CASE_LS2R: 4896 TRACE(("CASE_LS2R\n")); 4897 screen->curgr = 2; 4898 ResetState(sp); 4899 break; 4900 4901 case CASE_LS1R: 4902 TRACE(("CASE_LS1R\n")); 4903 screen->curgr = 1; 4904 ResetState(sp); 4905 break; 4906 4907 case CASE_XTERM_SAVE: 4908 savemodes(xw); 4909 ResetState(sp); 4910 break; 4911 4912 case CASE_XTERM_RESTORE: 4913 restoremodes(xw); 4914 ResetState(sp); 4915 break; 4916 4917 case CASE_XTERM_WINOPS: 4918 TRACE(("CASE_XTERM_WINOPS\n")); 4919 window_ops(xw); 4920 ResetState(sp); 4921 break; 4922#if OPT_WIDE_CHARS 4923 case CASE_ESC_PERCENT: 4924 TRACE(("CASE_ESC_PERCENT\n")); 4925 sp->parsestate = esc_pct_table; 4926 break; 4927 4928 case CASE_UTF8: 4929 /* If we did not set UTF-8 mode from resource or the 4930 * command-line, allow it to be enabled/disabled by 4931 * control sequence. 4932 */ 4933 TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n", 4934 screen->wide_chars, 4935 screen->utf8_mode, 4936 BtoS(c == 'G'))); 4937 if ((!screen->wide_chars) && (c == 'G')) { 4938 WriteNow(); 4939 ChangeToWide(xw); 4940 } 4941 if (screen->wide_chars 4942 && !screen->utf8_always) { 4943 switchPtyData(screen, c == 'G'); 4944 TRACE(("UTF8 mode %s\n", 4945 BtoS(screen->utf8_mode))); 4946 } else { 4947 TRACE(("UTF8 mode NOT turned %s (%s)\n", 4948 BtoS(c == 'G'), 4949 (screen->utf8_mode == uAlways) 4950 ? "UTF-8 mode set from command-line" 4951 : "wideChars resource was not set")); 4952 } 4953 ResetState(sp); 4954 break; 4955 4956 case CASE_SCS_DQUOTE: 4957 TRACE(("CASE_SCS_DQUOTE\n")); 4958 sp->parsestate = scs_2qt_table; 4959 break; 4960 4961 case CASE_GSETS_DQUOTE: 4962 if (screen->vtXX_level >= 5) { 4963 TRACE(("CASE_GSETS_DQUOTE(%d) = '%c'\n", sp->scstype, c)); 4964 xtermDecodeSCS(xw, sp->scstype, 5, '"', (int) c); 4965 } 4966 ResetState(sp); 4967 break; 4968 4969 case CASE_SCS_AMPRSND: 4970 TRACE(("CASE_SCS_AMPRSND\n")); 4971 sp->parsestate = scs_amp_table; 4972 break; 4973 4974 case CASE_GSETS_AMPRSND: 4975 if (screen->vtXX_level >= 5) { 4976 TRACE(("CASE_GSETS_AMPRSND(%d) = '%c'\n", sp->scstype, c)); 4977 xtermDecodeSCS(xw, sp->scstype, 5, '&', (int) c); 4978 } 4979 ResetState(sp); 4980 break; 4981 4982 case CASE_SCS_PERCENT: 4983 TRACE(("CASE_SCS_PERCENT\n")); 4984 sp->parsestate = scs_pct_table; 4985 break; 4986 4987 case CASE_GSETS_PERCENT: 4988 if (screen->vtXX_level >= 3) { 4989 TRACE(("CASE_GSETS_PERCENT(%d) = '%c'\n", sp->scstype, c)); 4990 switch (c) { 4991 case '0': /* DEC Turkish */ 4992 case '2': /* Turkish */ 4993 case '=': /* Hebrew */ 4994 value = 5; 4995 break; 4996 case '5': /* DEC Supplemental Graphics */ 4997 case '6': /* Portuguese */ 4998 default: 4999 value = 3; 5000 break; 5001 } 5002 xtermDecodeSCS(xw, sp->scstype, value, '%', (int) c); 5003 } 5004 ResetState(sp); 5005 break; 5006#endif 5007 case CASE_XTERM_SHIFT_ESCAPE: 5008 TRACE(("CASE_XTERM_SHIFT_ESCAPE\n")); 5009 value = ((nparam == 0) 5010 ? 0 5011 : one_if_default(0)); 5012 if (value >= 0 && value <= 1) 5013 xw->keyboard.shift_escape = value; 5014 ResetState(sp); 5015 break; 5016 5017#if OPT_MOD_FKEYS 5018 case CASE_SET_MOD_FKEYS: 5019 TRACE(("CASE_SET_MOD_FKEYS\n")); 5020 if (nparam >= 1) { 5021 set_mod_fkeys(xw, 5022 GetParam(0), 5023 ((nparam > 1) 5024 ? GetParam(1) 5025 : DEFAULT), 5026 True); 5027 } else { 5028 for (value = 1; value <= 5; ++value) 5029 set_mod_fkeys(xw, value, DEFAULT, True); 5030 } 5031 ResetState(sp); 5032 break; 5033 5034 case CASE_SET_MOD_FKEYS0: 5035 TRACE(("CASE_SET_MOD_FKEYS0\n")); 5036 if (nparam >= 1 && GetParam(0) != DEFAULT) { 5037 set_mod_fkeys(xw, GetParam(0), -1, False); 5038 } else { 5039 xw->keyboard.modify_now.function_keys = -1; 5040 } 5041 ResetState(sp); 5042 break; 5043#endif 5044 case CASE_HIDE_POINTER: 5045 TRACE(("CASE_HIDE_POINTER\n")); 5046 if (nparam >= 1 && GetParam(0) != DEFAULT) { 5047 screen->pointer_mode = GetParam(0); 5048 } else { 5049 screen->pointer_mode = DEF_POINTER_MODE; 5050 } 5051 ResetState(sp); 5052 break; 5053 5054 case CASE_XTERM_SM_TITLE: 5055 TRACE(("CASE_XTERM_SM_TITLE\n")); 5056 if (nparam >= 1) { 5057 int n; 5058 for (n = 0; n < nparam; ++n) { 5059 if (GetParam(n) != DEFAULT) 5060 screen->title_modes |= (1 << GetParam(n)); 5061 } 5062 } else { 5063 screen->title_modes = DEF_TITLE_MODES; 5064 } 5065 TRACE(("...title_modes %#x\n", screen->title_modes)); 5066 ResetState(sp); 5067 break; 5068 5069 case CASE_XTERM_RM_TITLE: 5070 TRACE(("CASE_XTERM_RM_TITLE\n")); 5071 if (nparam >= 1) { 5072 int n; 5073 for (n = 0; n < nparam; ++n) { 5074 if (GetParam(n) != DEFAULT) 5075 screen->title_modes &= ~(1 << GetParam(n)); 5076 } 5077 } else { 5078 screen->title_modes = DEF_TITLE_MODES; 5079 } 5080 TRACE(("...title_modes %#x\n", screen->title_modes)); 5081 ResetState(sp); 5082 break; 5083 5084 case CASE_CSI_IGNORE: 5085 sp->parsestate = cigtable; 5086 break; 5087 5088 case CASE_DECSWBV: 5089 TRACE(("CASE_DECSWBV\n")); 5090 switch (zero_if_default(0)) { 5091 case 2: 5092 /* FALLTHRU */ 5093 case 3: 5094 /* FALLTHRU */ 5095 case 4: 5096 screen->warningVolume = bvLow; 5097 break; 5098 case 5: 5099 /* FALLTHRU */ 5100 case 6: 5101 /* FALLTHRU */ 5102 case 7: 5103 /* FALLTHRU */ 5104 case 8: 5105 screen->warningVolume = bvHigh; 5106 break; 5107 default: 5108 screen->warningVolume = bvOff; 5109 break; 5110 } 5111 TRACE(("...warningVolume %d\n", screen->warningVolume)); 5112 ResetState(sp); 5113 break; 5114 5115 case CASE_DECSMBV: 5116 TRACE(("CASE_DECSMBV\n")); 5117 switch (zero_if_default(0)) { 5118 case 2: 5119 /* FALLTHRU */ 5120 case 3: 5121 /* FALLTHRU */ 5122 case 4: 5123 screen->marginVolume = bvLow; 5124 break; 5125 case 0: 5126 /* FALLTHRU */ 5127 case 5: 5128 /* FALLTHRU */ 5129 case 6: 5130 /* FALLTHRU */ 5131 case 7: 5132 /* FALLTHRU */ 5133 case 8: 5134 screen->marginVolume = bvHigh; 5135 break; 5136 default: 5137 screen->marginVolume = bvOff; 5138 break; 5139 } 5140 TRACE(("...marginVolume %d\n", screen->marginVolume)); 5141 ResetState(sp); 5142 break; 5143 } 5144 if (sp->parsestate == sp->groundtable) 5145 sp->lastchar = thischar; 5146 } while (0); 5147 5148#if OPT_WIDE_CHARS 5149 screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse) 5150 && (sp->parsestate != sos_table)); 5151#endif 5152 5153 if (sp->check_recur) 5154 sp->check_recur--; 5155 return True; 5156} 5157 5158static void 5159VTparse(XtermWidget xw) 5160{ 5161 Boolean keep_running; 5162 5163 /* We longjmp back to this point in VTReset() */ 5164 (void) setjmp(vtjmpbuf); 5165 init_parser(xw, &myState); 5166 5167 do { 5168 keep_running = doparsing(xw, doinput(xw), &myState); 5169 if (myState.check_recur == 0 && myState.defer_used != 0) { 5170 while (myState.defer_used) { 5171 Char *deferred = myState.defer_area; 5172 size_t len = myState.defer_used; 5173 size_t i; 5174 myState.defer_area = NULL; 5175 myState.defer_size = 0; 5176 myState.defer_used = 0; 5177 for (i = 0; i < len; i++) { 5178 (void) doparsing(xw, deferred[i], &myState); 5179 } 5180 free(deferred); 5181 } 5182 } else { 5183 free(myState.defer_area); 5184 } 5185 myState.defer_area = NULL; 5186 myState.defer_size = 0; 5187 myState.defer_used = 0; 5188 } while (keep_running); 5189} 5190 5191static Char *v_buffer; /* pointer to physical buffer */ 5192static Char *v_bufstr = NULL; /* beginning of area to write */ 5193static Char *v_bufptr; /* end of area to write */ 5194static Char *v_bufend; /* end of physical buffer */ 5195 5196/* Write data to the pty as typed by the user, pasted with the mouse, 5197 or generated by us in response to a query ESC sequence. */ 5198 5199void 5200v_write(int f, const Char *data, unsigned len) 5201{ 5202 TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len))); 5203 if (v_bufstr == NULL) { 5204 if (len > 0) { 5205 v_buffer = (Char *) XtMalloc((Cardinal) len); 5206 v_bufstr = v_buffer; 5207 v_bufptr = v_buffer; 5208 v_bufend = v_buffer + len; 5209 } 5210 if (v_bufstr == NULL) { 5211 return; 5212 } 5213 } 5214 if_DEBUG({ 5215 fprintf(stderr, "v_write called with %u bytes (%ld left over)", 5216 len, (long) (v_bufptr - v_bufstr)); 5217 if (len > 1 && len < 10) 5218 fprintf(stderr, " \"%.*s\"", len, (const char *) data); 5219 fprintf(stderr, "\n"); 5220 }); 5221 5222#ifdef VMS 5223 if ((1 << f) != pty_mask) { 5224 tt_write((const char *) data, len); 5225 return; 5226 } 5227#else /* VMS */ 5228 if (!FD_ISSET(f, &pty_mask)) { 5229 IGNORE_RC(write(f, (const char *) data, (size_t) len)); 5230 return; 5231 } 5232#endif /* VMS */ 5233 5234 /* 5235 * Append to the block we already have. 5236 * Always doing this simplifies the code, and 5237 * isn't too bad, either. If this is a short 5238 * block, it isn't too expensive, and if this is 5239 * a long block, we won't be able to write it all 5240 * anyway. 5241 */ 5242 5243 if (len > 0) { 5244#if OPT_DABBREV 5245 TScreenOf(term)->dabbrev_working = False; /* break dabbrev sequence */ 5246#endif 5247 if (v_bufend < v_bufptr + len) { /* we've run out of room */ 5248 if (v_bufstr != v_buffer) { 5249 /* there is unused space, move everything down */ 5250 /* possibly overlapping memmove here */ 5251 if_DEBUG({ 5252 fprintf(stderr, "moving data down %ld\n", 5253 (long) (v_bufstr - v_buffer)); 5254 }); 5255 memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr)); 5256 v_bufptr -= v_bufstr - v_buffer; 5257 v_bufstr = v_buffer; 5258 } 5259 if (v_bufend < v_bufptr + len) { 5260 /* still won't fit: get more space */ 5261 /* Don't use XtRealloc because an error is not fatal. */ 5262 unsigned size = (unsigned) (v_bufptr - v_buffer); 5263 v_buffer = TypeRealloc(Char, size + len, v_buffer); 5264 if (v_buffer) { 5265 if_DEBUG({ 5266 fprintf(stderr, "expanded buffer to %u\n", 5267 size + len); 5268 }); 5269 v_bufstr = v_buffer; 5270 v_bufptr = v_buffer + size; 5271 v_bufend = v_bufptr + len; 5272 } else { 5273 /* no memory: ignore entire write request */ 5274 xtermWarning("cannot allocate buffer space\n"); 5275 v_buffer = v_bufstr; /* restore clobbered pointer */ 5276 } 5277 } 5278 } 5279 if (v_bufend >= v_bufptr + len) { 5280 /* new stuff will fit */ 5281 memmove(v_bufptr, data, (size_t) len); 5282 v_bufptr += len; 5283 } 5284 } 5285 5286 /* 5287 * Write out as much of the buffer as we can. 5288 * Be careful not to overflow the pty's input silo. 5289 * We are conservative here and only write 5290 * a small amount at a time. 5291 * 5292 * If we can't push all the data into the pty yet, we expect write 5293 * to return a non-negative number less than the length requested 5294 * (if some data written) or -1 and set errno to EAGAIN, 5295 * EWOULDBLOCK, or EINTR (if no data written). 5296 * 5297 * (Not all systems do this, sigh, so the code is actually 5298 * a little more forgiving.) 5299 */ 5300 5301#define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */ 5302 5303 if (v_bufptr > v_bufstr) { 5304 int riten; 5305 5306#ifdef VMS 5307 riten = tt_write(v_bufstr, 5308 ((v_bufptr - v_bufstr <= VMS_TERM_BUFFER_SIZE) 5309 ? v_bufptr - v_bufstr 5310 : VMS_TERM_BUFFER_SIZE)); 5311 if (riten == 0) 5312 return (riten); 5313#else /* VMS */ 5314 riten = (int) write(f, v_bufstr, 5315 (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE) 5316 ? v_bufptr - v_bufstr 5317 : MAX_PTY_WRITE)); 5318 if (riten < 0) 5319#endif /* VMS */ 5320 { 5321 if_DEBUG({ 5322 perror("write"); 5323 }); 5324 riten = 0; 5325 } 5326 if_DEBUG({ 5327 fprintf(stderr, "write called with %ld, wrote %d\n", 5328 ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE) 5329 ? (long) (v_bufptr - v_bufstr) 5330 : MAX_PTY_WRITE), 5331 riten); 5332 }); 5333 v_bufstr += riten; 5334 if (v_bufstr >= v_bufptr) /* we wrote it all */ 5335 v_bufstr = v_bufptr = v_buffer; 5336 } 5337 5338 /* 5339 * If we have lots of unused memory allocated, return it 5340 */ 5341 if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */ 5342 /* save pointers across realloc */ 5343 int start = (int) (v_bufstr - v_buffer); 5344 int size = (int) (v_bufptr - v_buffer); 5345 unsigned allocsize = (unsigned) (size ? size : 1); 5346 5347 v_buffer = TypeRealloc(Char, allocsize, v_buffer); 5348 if (v_buffer) { 5349 v_bufstr = v_buffer + start; 5350 v_bufptr = v_buffer + size; 5351 v_bufend = v_buffer + allocsize; 5352 if_DEBUG({ 5353 fprintf(stderr, "shrunk buffer to %u\n", allocsize); 5354 }); 5355 } else { 5356 /* should we print a warning if couldn't return memory? */ 5357 v_buffer = v_bufstr - start; /* restore clobbered pointer */ 5358 } 5359 } 5360} 5361 5362static void 5363updateCursor(XtermWidget xw) 5364{ 5365 TScreen *screen = TScreenOf(xw); 5366 5367 if (screen->cursor_set != screen->cursor_state) { 5368 if (screen->cursor_set) 5369 ShowCursor(xw); 5370 else 5371 HideCursor(xw); 5372 } 5373} 5374 5375#if OPT_BLINK_CURS || OPT_BLINK_TEXT 5376static void 5377reallyStopBlinking(XtermWidget xw) 5378{ 5379 TScreen *screen = TScreenOf(xw); 5380 5381 if (screen->cursor_state == BLINKED_OFF) { 5382 /* force cursor to display if it is enabled */ 5383 screen->cursor_state = !screen->cursor_set; 5384 updateCursor(xw); 5385 xevents(xw); 5386 } 5387} 5388#endif 5389 5390static void 5391update_the_screen(XtermWidget xw) 5392{ 5393 TScreen *screen = TScreenOf(xw); 5394 Boolean moved; 5395 5396 if (screen->scroll_amt) 5397 FlushScroll(xw); 5398 moved = CursorMoved(screen); 5399 if (screen->cursor_set && moved) { 5400 if (screen->cursor_state) 5401 HideCursor(xw); 5402 ShowCursor(xw); 5403#if OPT_INPUT_METHOD 5404 PreeditPosition(xw); 5405#endif 5406 } else { 5407#if OPT_INPUT_METHOD 5408 if (moved) 5409 PreeditPosition(xw); 5410#endif 5411 updateCursor(xw); 5412 } 5413} 5414 5415#ifdef VMS 5416#define ptymask() (v_bufptr > v_bufstr ? pty_mask : 0) 5417 5418static void 5419in_put(XtermWidget xw) 5420{ 5421 static PtySelect select_mask; 5422 static PtySelect write_mask; 5423 int update = VTbuffer->update; 5424 int size; 5425 5426 int status; 5427 Dimension replyWidth, replyHeight; 5428 XtGeometryResult stat; 5429 5430 TScreen *screen = TScreenOf(xw); 5431 char *cp; 5432 int i; 5433 5434 select_mask = pty_mask; /* force initial read */ 5435 for (;;) { 5436 5437 /* if the terminal changed size, resize the widget */ 5438 if (tt_changed) { 5439 tt_changed = False; 5440 5441 stat = REQ_RESIZE((Widget) xw, 5442 ((Dimension) FontWidth(screen) 5443 * (tt_width) 5444 + 2 * screen->border 5445 + screen->fullVwin.sb_info.width), 5446 ((Dimension) FontHeight(screen) 5447 * (tt_length) 5448 + 2 * screen->border), 5449 &replyWidth, &replyHeight); 5450 5451 if (stat == XtGeometryYes || stat == XtGeometryDone) { 5452 xw->core.width = replyWidth; 5453 xw->core.height = replyHeight; 5454 5455 ScreenResize(xw, replyWidth, replyHeight, &xw->flags); 5456 } 5457 repairSizeHints(); 5458 } 5459 5460 if (screen->eventMode == NORMAL 5461 && readPtyData(xw, &select_mask, VTbuffer)) { 5462 if (screen->scrollWidget 5463 && screen->scrollttyoutput 5464 && screen->topline < 0) 5465 /* Scroll to bottom */ 5466 WindowScroll(xw, 0, False); 5467 break; 5468 } 5469 update_the_screen(xw); 5470 5471 if (QLength(screen->display)) { 5472 select_mask = X_mask; 5473 } else { 5474 write_mask = ptymask(); 5475 XFlush(screen->display); 5476 select_mask = Select_mask; 5477 if (screen->eventMode != NORMAL) 5478 select_mask = X_mask; 5479 } 5480 if (write_mask & ptymask()) { 5481 v_write(screen->respond, 0, 0); /* flush buffer */ 5482 } 5483 5484 if (select_mask & X_mask) { 5485 xevents(xw); 5486 if (VTbuffer->update != update) 5487 break; 5488 } 5489 } 5490} 5491#else /* VMS */ 5492 5493static void 5494in_put(XtermWidget xw) 5495{ 5496 static PtySelect select_mask; 5497 static PtySelect write_mask; 5498 5499 TScreen *screen = TScreenOf(xw); 5500 int i; 5501 int update = VTbuffer->update; 5502#if USE_DOUBLE_BUFFER 5503 int should_wait = 1; 5504#endif 5505 5506 static struct timeval select_timeout; 5507 5508#if OPT_BLINK_CURS 5509 /* 5510 * Compute the timeout for the blinking cursor to be much smaller than 5511 * the "on" or "off" interval. 5512 */ 5513 int tick = ((screen->blink_on < screen->blink_off) 5514 ? screen->blink_on 5515 : screen->blink_off); 5516 tick *= (1000 / 8); /* 1000 for msec/usec, 8 for "much" smaller */ 5517 if (tick < 1) 5518 tick = 1; 5519#endif 5520 5521 for (;;) { 5522 int size; 5523 int time_select; 5524 5525 if (screen->eventMode == NORMAL 5526 && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) { 5527 if (screen->scrollWidget 5528 && screen->scrollttyoutput 5529 && screen->topline < 0) 5530 WindowScroll(xw, 0, False); /* Scroll to bottom */ 5531 /* stop speed reading at some point to look for X stuff */ 5532 TRACE(("VTbuffer uses %ld/%d\n", 5533 (long) (VTbuffer->last - VTbuffer->buffer), 5534 BUF_SIZE)); 5535 if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) { 5536 FD_CLR(screen->respond, &select_mask); 5537 break; 5538 } 5539#if USE_DOUBLE_BUFFER 5540 if (resource.buffered && should_wait) { 5541 /* wait for potential extra data (avoids some flickering) */ 5542 usleep((unsigned) DbeMsecs(xw)); 5543 should_wait = 0; 5544 } 5545#endif 5546#if defined(HAVE_SCHED_YIELD) 5547 /* 5548 * If we've read a full (small/fragment) buffer, let the operating 5549 * system have a turn, and we'll resume reading until we've either 5550 * read only a fragment of the buffer, or we've filled the large 5551 * buffer (see above). Doing this helps keep up with large bursts 5552 * of output. 5553 */ 5554 if (size == FRG_SIZE) { 5555 select_timeout.tv_sec = 0; 5556 i = Select(max_plus1, &select_mask, &write_mask, 0, 5557 &select_timeout); 5558 if (i > 0 && FD_ISSET(screen->respond, &select_mask)) { 5559 sched_yield(); 5560 } else 5561 break; 5562 } else { 5563 break; 5564 } 5565#else 5566 (void) size; /* unused in this branch */ 5567 break; 5568#endif 5569 } 5570 update_the_screen(xw); 5571 5572 XFlush(screen->display); /* always flush writes before waiting */ 5573 5574 /* Update the masks and, unless X events are already in the queue, 5575 wait for I/O to be possible. */ 5576 XFD_COPYSET(&Select_mask, &select_mask); 5577 /* in selection mode xterm does not read pty */ 5578 if (screen->eventMode != NORMAL) 5579 FD_CLR(screen->respond, &select_mask); 5580 5581 if (v_bufptr > v_bufstr) { 5582 XFD_COPYSET(&pty_mask, &write_mask); 5583 } else 5584 FD_ZERO(&write_mask); 5585 select_timeout.tv_sec = 0; 5586 time_select = 0; 5587 5588 /* 5589 * if there's either an XEvent or an XtTimeout pending, just take 5590 * a quick peek, i.e. timeout from the select() immediately. If 5591 * there's nothing pending, let select() block a little while, but 5592 * for a shorter interval than the arrow-style scrollbar timeout. 5593 * The blocking is optional, because it tends to increase the load 5594 * on the host. 5595 */ 5596 if (xtermAppPending()) { 5597 select_timeout.tv_usec = 0; 5598 time_select = 1; 5599 } else if (screen->awaitInput) { 5600 select_timeout.tv_usec = 50000; 5601 time_select = 1; 5602#if OPT_BLINK_CURS 5603 } else if ((screen->blink_timer != 0 && 5604 ((screen->select & FOCUS) || screen->always_highlight)) || 5605 (screen->cursor_state == BLINKED_OFF)) { 5606 select_timeout.tv_usec = tick; 5607 while (select_timeout.tv_usec > 1000000) { 5608 select_timeout.tv_usec -= 1000000; 5609 select_timeout.tv_sec++; 5610 } 5611 time_select = 1; 5612#endif 5613#if OPT_SESSION_MGT 5614 } else if (resource.sessionMgt) { 5615 if (ice_fd >= 0) 5616 FD_SET(ice_fd, &select_mask); 5617#endif 5618 } 5619 if (need_cleanup) 5620 NormalExit(); 5621 xtermFlushDbe(xw); 5622 i = Select(max_plus1, &select_mask, &write_mask, 0, 5623 (time_select ? &select_timeout : 0)); 5624 if (i < 0) { 5625 if (errno != EINTR) 5626 SysError(ERROR_SELECT); 5627 continue; 5628 } 5629 5630 /* if there is room to write more data to the pty, go write more */ 5631 if (FD_ISSET(screen->respond, &write_mask)) { 5632 v_write(screen->respond, (Char *) 0, 0); /* flush buffer */ 5633 } 5634 5635 /* if there are X events already in our queue, it 5636 counts as being readable */ 5637 if (xtermAppPending() || 5638 FD_ISSET(ConnectionNumber(screen->display), &select_mask)) { 5639 xevents(xw); 5640 if (VTbuffer->update != update) /* HandleInterpret */ 5641 break; 5642 } 5643 5644 } 5645} 5646#endif /* VMS */ 5647 5648static IChar 5649doinput(XtermWidget xw) 5650{ 5651 TScreen *screen = TScreenOf(xw); 5652 5653 while (!morePtyData(screen, VTbuffer)) 5654 in_put(xw); 5655 return nextPtyData(screen, VTbuffer); 5656} 5657 5658#if OPT_INPUT_METHOD 5659/* 5660 * For OverTheSpot, client has to inform the position for XIM preedit. 5661 */ 5662static void 5663PreeditPosition(XtermWidget xw) 5664{ 5665 TInput *input = lookupTInput(xw, (Widget) xw); 5666 TScreen *screen = TScreenOf(xw); 5667 CLineData *ld; 5668 XPoint spot; 5669 XVaNestedList list; 5670 5671 if (input && input->xic 5672 && (ld = getLineData(screen, screen->cur_row)) != 0) { 5673 spot.x = (short) LineCursorX(screen, ld, screen->cur_col); 5674 spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent); 5675 list = XVaCreateNestedList(0, 5676 XNSpotLocation, &spot, 5677 XNForeground, T_COLOR(screen, TEXT_FG), 5678 XNBackground, T_COLOR(screen, TEXT_BG), 5679 (void *) 0); 5680 XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0); 5681 XFree(list); 5682 } 5683} 5684#endif 5685 5686static void 5687WrapLine(XtermWidget xw) 5688{ 5689 TScreen *screen = TScreenOf(xw); 5690 LineData *ld = getLineData(screen, screen->cur_row); 5691 5692 if (ld != 0) { 5693 /* mark that we had to wrap this line */ 5694 LineSetFlag(ld, LINEWRAPPED); 5695 ShowWrapMarks(xw, screen->cur_row, ld); 5696 xtermAutoPrint(xw, '\n'); 5697 xtermIndex(xw, 1); 5698 set_cur_col(screen, ScrnLeftMargin(xw)); 5699 } 5700} 5701 5702/* 5703 * Process a string of characters according to the character set indicated by 5704 * charset. Worry about end of line conditions (wraparound if selected). 5705 * 5706 * It is possible to use CUP, etc., to move outside margins. In that case, the 5707 * right-margin is ineffective until the text (may) wrap and get within the 5708 * margins. 5709 */ 5710void 5711dotext(XtermWidget xw, 5712 DECNRCM_codes charset, 5713 IChar *buf, /* start of characters to process */ 5714 Cardinal len) /* end */ 5715{ 5716 TScreen *screen = TScreenOf(xw); 5717#if OPT_WIDE_CHARS 5718 Cardinal chars_chomped = 1; 5719 int next_col = screen->cur_col; 5720#else 5721 int next_col, this_col; /* must be signed */ 5722#endif 5723 Cardinal offset; 5724 int rmargin = ScrnRightMargin(xw); 5725 5726#if OPT_WIDE_CHARS 5727 if (screen->vt100_graphics) 5728#endif 5729 if (!(len = (Cardinal) xtermCharSetOut(xw, buf, buf + len, charset))) 5730 return; 5731 5732 if_OPT_XMC_GLITCH(screen, { 5733 Cardinal n; 5734 if (charset != '?') { 5735 for (n = 0; n < len; n++) { 5736 if (buf[n] == XMC_GLITCH) 5737 buf[n] = XMC_GLITCH + 1; 5738 } 5739 } 5740 }); 5741 5742#if OPT_WIDE_CHARS 5743 for (offset = 0; 5744 offset < len && (chars_chomped > 0 || screen->do_wrap); 5745 offset += chars_chomped) { 5746 int width_here = 0; 5747 int last_chomp = 0; 5748 Boolean force_wrap; 5749 5750 chars_chomped = 0; 5751 do { 5752 int right = ((screen->cur_col > rmargin) 5753 ? screen->max_col 5754 : rmargin); 5755 int width_available = right + 1 - screen->cur_col; 5756 Boolean need_wrap = False; 5757 Boolean did_wrap = False; 5758 5759 force_wrap = False; 5760 5761 if (screen->do_wrap) { 5762 screen->do_wrap = False; 5763 if ((xw->flags & WRAPAROUND)) { 5764 WrapLine(xw); 5765 right = ((screen->cur_col > rmargin) 5766 ? screen->max_col 5767 : rmargin); 5768 width_available = right + 1 - screen->cur_col; 5769 next_col = screen->cur_col; 5770 did_wrap = True; 5771 } 5772 } 5773 5774 /* 5775 * This can happen with left/right margins... 5776 */ 5777 if (width_available <= 0) { 5778 break; 5779 } 5780 5781 /* 5782 * Regarding the soft-hyphen aberration, see 5783 * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html 5784 */ 5785 while (width_here <= width_available 5786 && chars_chomped < (len - offset)) { 5787 Cardinal n = chars_chomped + offset; 5788 if (!screen->utf8_mode 5789 || (screen->vt100_graphics && charset == '0')) { 5790 last_chomp = 1; 5791 } else if (screen->c1_printable && 5792 buf[n] >= 0x80 && 5793 buf[n] <= 0xa0) { 5794 last_chomp = 1; 5795 } else { 5796 last_chomp = CharWidth(buf[n]); 5797 if (last_chomp <= 0) { 5798 IChar ch = buf[n]; 5799 Bool eat_it = !screen->utf8_mode && (ch > 127); 5800 if (ch == 0xad) { 5801 /* 5802 * Only display soft-hyphen if it happens to be at 5803 * the right-margin. While that means that only 5804 * the displayed character could be selected for 5805 * pasting, a well-behaved application would never 5806 * send this, anyway... 5807 */ 5808 if (width_here < width_available - 1) { 5809 eat_it = True; 5810 } else { 5811 last_chomp = 1; 5812 eat_it = False; 5813 } 5814 TRACE(("...will%s display soft-hyphen\n", 5815 eat_it ? " not" : "")); 5816 } 5817 /* 5818 * Supposedly we dealt with combining characters and 5819 * control characters in doparse(). Anything left over 5820 * is junk that we will not attempt to display. 5821 */ 5822 if (eat_it) { 5823 TRACE(("...will not display U+%04X\n", ch)); 5824 --len; 5825 while (n < len) { 5826 buf[n] = buf[n + 1]; 5827 ++n; 5828 } 5829 last_chomp = 0; 5830 chars_chomped--; 5831 } 5832 } 5833 } 5834 width_here += last_chomp; 5835 chars_chomped++; 5836 } 5837 5838 if (width_here > width_available) { 5839 if (last_chomp > right + 1) { 5840 break; /* give up - it is too big */ 5841 } else if (chars_chomped-- == 0) { 5842 /* This can happen with left/right margins... */ 5843 break; 5844 } 5845 width_here -= last_chomp; 5846 if (chars_chomped > 0) { 5847 if (!(xw->flags & WRAPAROUND)) { 5848 buf[chars_chomped + offset - 1] = buf[len - 1]; 5849 } else { 5850 need_wrap = True; 5851 } 5852 } 5853 } else if (width_here == width_available) { 5854 need_wrap = True; 5855 } else if (chars_chomped != (len - offset)) { 5856 need_wrap = True; 5857 } 5858 5859 if (chars_chomped != 0 && next_col <= screen->max_col) { 5860 WriteText(xw, buf + offset, chars_chomped); 5861 } else if (!did_wrap 5862 && len > 0 5863 && (xw->flags & WRAPAROUND) 5864 && screen->cur_col > ScrnLeftMargin(xw)) { 5865 force_wrap = True; 5866 need_wrap = True; 5867 } 5868 next_col += width_here; 5869 screen->do_wrap = need_wrap; 5870 } while (force_wrap); 5871 } 5872 5873 /* 5874 * Remember that we wrote something to the screen, for use as a base of 5875 * combining characters. The logic above may have called cursor-forward 5876 * or carriage-return operations which resets this flag, so we set it at 5877 * the very end. 5878 */ 5879 screen->char_was_written = True; 5880#else /* ! OPT_WIDE_CHARS */ 5881 5882 for (offset = 0; offset < len; offset += (Cardinal) this_col) { 5883#if OPT_DEC_CHRSET 5884 CLineData *ld = getLineData(screen, screen->cur_row); 5885#endif 5886 int right = ((screen->cur_col > rmargin) 5887 ? screen->max_col 5888 : rmargin); 5889 5890 int last_col = LineMaxCol(screen, ld); 5891 if (last_col > right) 5892 last_col = right; 5893 this_col = last_col - screen->cur_col + 1; 5894 if (screen->do_wrap) { 5895 screen->do_wrap = False; 5896 if ((xw->flags & WRAPAROUND)) { 5897 WrapLine(xw); 5898 } 5899 this_col = 1; 5900 } 5901 if (offset + (Cardinal) this_col > len) { 5902 this_col = (int) (len - offset); 5903 } 5904 next_col = screen->cur_col + this_col; 5905 5906 WriteText(xw, buf + offset, (unsigned) this_col); 5907 5908 /* 5909 * The call to WriteText updates screen->cur_col. 5910 * If screen->cur_col is less than next_col, we must have 5911 * hit the right margin - so set the do_wrap flag. 5912 */ 5913 screen->do_wrap = (Boolean) (screen->cur_col < next_col); 5914 } 5915 5916#endif /* OPT_WIDE_CHARS */ 5917} 5918 5919#if OPT_WIDE_CHARS 5920unsigned 5921visual_width(const IChar *str, Cardinal len) 5922{ 5923 /* returns the visual width of a string (doublewide characters count 5924 as 2, normalwide characters count as 1) */ 5925 unsigned my_len = 0; 5926 while (len) { 5927 int ch = (int) *str++; 5928 if (isWide(ch)) 5929 my_len += 2; 5930 else 5931 my_len++; 5932 len--; 5933 } 5934 return my_len; 5935} 5936#endif 5937 5938#if HANDLE_STRUCT_NOTIFY 5939/* Flag icon name with "***" on window output when iconified. 5940 */ 5941static void 5942HandleStructNotify(Widget w GCC_UNUSED, 5943 XtPointer closure GCC_UNUSED, 5944 XEvent *event, 5945 Boolean *cont GCC_UNUSED) 5946{ 5947 XtermWidget xw = term; 5948 TScreen *screen = TScreenOf(xw); 5949 5950 (void) screen; 5951 TRACE_EVENT("HandleStructNotify", event, NULL, 0); 5952 switch (event->type) { 5953 case MapNotify: 5954 resetZIconBeep(xw); 5955 mapstate = !IsUnmapped; 5956 break; 5957 case UnmapNotify: 5958 mapstate = IsUnmapped; 5959 break; 5960 case MappingNotify: 5961 XRefreshKeyboardMapping(&(event->xmapping)); 5962 VTInitModifiers(xw); 5963 break; 5964 case ConfigureNotify: 5965 if (event->xconfigure.window == XtWindow(toplevel)) { 5966#if !OPT_TOOLBAR 5967 int height = event->xconfigure.height; 5968 int width = event->xconfigure.width; 5969#endif 5970 5971#if USE_DOUBLE_BUFFER 5972 discardRenderDraw(screen); 5973#endif /* USE_DOUBLE_BUFFER */ 5974#if OPT_TOOLBAR 5975 /* 5976 * The notification is for the top-level widget, but we care about 5977 * vt100 (ignore the tek4014 window). 5978 */ 5979 if (screen->Vshow) { 5980 VTwin *Vwin = WhichVWin(screen); 5981 TbInfo *info = &(Vwin->tb_info); 5982 TbInfo save = *info; 5983 5984 if (info->menu_bar) { 5985 XtVaGetValues(info->menu_bar, 5986 XtNheight, &info->menu_height, 5987 XtNborderWidth, &info->menu_border, 5988 (XtPointer) 0); 5989 5990 if (save.menu_height != info->menu_height 5991 || save.menu_border != info->menu_border) { 5992 5993 TRACE(("...menu_height %d\n", info->menu_height)); 5994 TRACE(("...menu_border %d\n", info->menu_border)); 5995 TRACE(("...had height %d, border %d\n", 5996 save.menu_height, 5997 save.menu_border)); 5998 5999 /* 6000 * Window manager still may be using the old values. 6001 * Try to fool it. 6002 */ 6003 REQ_RESIZE((Widget) xw, 6004 screen->fullVwin.fullwidth, 6005 (Dimension) (info->menu_height 6006 - save.menu_height 6007 + screen->fullVwin.fullheight), 6008 NULL, NULL); 6009 repairSizeHints(); 6010 } 6011 } 6012 } 6013#else 6014 if (!xw->work.doing_resize 6015#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 6016 && !(resource.buffered && UsingRenderFont(xw)) /* buggyXft */ 6017#endif 6018 && (height != xw->hints.height 6019 || width != xw->hints.width)) { 6020 /* 6021 * This is a special case: other calls to RequestResize that 6022 * could set the screensize arbitrarily are via escape 6023 * sequences, and we've limited resizing. But a configure 6024 * notify is from the window manager, presumably under control 6025 * of the interactive user (ignoring abuse of wmctrl). Ignore 6026 * the limit for this case. 6027 */ 6028 int saved_limit = xw->misc.limit_resize; 6029 xw->misc.limit_resize = 0; 6030 RequestResize(xw, height, width, False); 6031 xw->misc.limit_resize = saved_limit; 6032 } 6033#endif /* OPT_TOOLBAR */ 6034 } 6035 break; 6036 } 6037} 6038#endif /* HANDLE_STRUCT_NOTIFY */ 6039 6040#if OPT_BLINK_CURS 6041static int 6042DoStartBlinking(TScreen *screen) 6043{ 6044 int actual = ((screen->cursor_blink == cbTrue || 6045 screen->cursor_blink == cbAlways) 6046 ? 1 6047 : 0); 6048 int wanted = screen->cursor_blink_esc ? 1 : 0; 6049 int result; 6050 if (screen->cursor_blink_xor) { 6051 result = actual ^ wanted; 6052 } else { 6053 result = actual | wanted; 6054 } 6055 return result; 6056} 6057 6058static void 6059SetCursorBlink(XtermWidget xw, BlinkOps enable) 6060{ 6061 TScreen *screen = TScreenOf(xw); 6062 6063 if (SettableCursorBlink(screen)) { 6064 screen->cursor_blink = enable; 6065 } 6066 if (DoStartBlinking(screen)) { 6067 StartBlinking(xw); 6068 } else { 6069 /* EMPTY */ 6070#if OPT_BLINK_TEXT 6071 reallyStopBlinking(xw); 6072#else 6073 StopBlinking(xw); 6074#endif 6075 } 6076 update_cursorblink(); 6077} 6078 6079void 6080ToggleCursorBlink(XtermWidget xw) 6081{ 6082 TScreen *screen = TScreenOf(xw); 6083 6084 if (screen->cursor_blink == cbTrue) { 6085 SetCursorBlink(xw, cbFalse); 6086 } else if (screen->cursor_blink == cbFalse) { 6087 SetCursorBlink(xw, cbTrue); 6088 } 6089} 6090#endif 6091 6092/* 6093 * process ANSI modes set, reset 6094 */ 6095static void 6096ansi_modes(XtermWidget xw, BitFunc func) 6097{ 6098 int i; 6099 6100 for (i = 0; i < nparam; ++i) { 6101 switch (GetParam(i)) { 6102 case 2: /* KAM (if set, keyboard locked */ 6103 (*func) (&xw->keyboard.flags, MODE_KAM); 6104 break; 6105 6106 case 4: /* IRM */ 6107 (*func) (&xw->flags, INSERT); 6108 break; 6109 6110 case 12: /* SRM (if set, local echo */ 6111 (*func) (&xw->keyboard.flags, MODE_SRM); 6112 break; 6113 6114 case 20: /* LNM */ 6115 (*func) (&xw->flags, LINEFEED); 6116 update_autolinefeed(); 6117 break; 6118 } 6119 } 6120} 6121 6122#define IsSM() (func == bitset) 6123 6124#define set_bool_mode(flag) \ 6125 flag = (Boolean) IsSM() 6126 6127static void 6128really_set_mousemode(XtermWidget xw, 6129 Bool enabled, 6130 XtermMouseModes mode) 6131{ 6132 TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF; 6133 if (okSendMousePos(xw) != MOUSE_OFF) 6134 xtermShowPointer(xw, True); 6135} 6136 6137#define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode) 6138 6139#if OPT_PASTE64 || OPT_READLINE 6140#define set_mouseflag(f) \ 6141 (IsSM() \ 6142 ? SCREEN_FLAG_set(screen, f) \ 6143 : SCREEN_FLAG_unset(screen, f)) 6144#endif 6145 6146/* 6147 * process DEC private modes set, reset 6148 */ 6149static void 6150dpmodes(XtermWidget xw, BitFunc func) 6151{ 6152 TScreen *screen = TScreenOf(xw); 6153 int i, j; 6154 unsigned myflags; 6155 6156 TRACE(("changing %d DEC private modes\n", nparam)); 6157 for (i = 0; i < nparam; ++i) { 6158 int code = GetParam(i); 6159 6160 TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code)); 6161 switch ((DECSET_codes) code) { 6162 case srm_DECCKM: 6163 (*func) (&xw->keyboard.flags, MODE_DECCKM); 6164 update_appcursor(); 6165 break; 6166 case srm_DECANM: /* ANSI/VT52 mode */ 6167 if (IsSM()) { /* ANSI (VT100) */ 6168 /* 6169 * Setting DECANM should have no effect, since this function 6170 * cannot be reached from vt52 mode. 6171 */ 6172 /* EMPTY */ ; 6173 } 6174#if OPT_VT52_MODE 6175 else if (screen->terminal_id >= 100) { /* VT52 */ 6176 TRACE(("DECANM terminal_id %d, vtXX_level %d\n", 6177 screen->terminal_id, 6178 screen->vtXX_level)); 6179 /* 6180 * According to DEC STD 070 section A.5.5, the various VT100 6181 * modes have undefined behavior when entering/exiting VT52 6182 * mode. xterm saves/restores/initializes the most commonly 6183 * used settings, but a real VT100 or VT520 may differ. 6184 * 6185 * For instance, DEC's documentation goes on to comment that 6186 * while the VT52 uses hardware tabs (8 columns), the emulation 6187 * (e.g., a VT420) does not alter those tab settings when 6188 * switching modes. 6189 */ 6190 screen->vtXX_level = 0; 6191 screen->vt52_save_flags = xw->flags; 6192 xw->flags = 0; 6193 screen->vt52_save_curgl = screen->curgl; 6194 screen->vt52_save_curgr = screen->curgr; 6195 screen->vt52_save_curss = screen->curss; 6196 saveCharsets(screen, screen->vt52_save_gsets); 6197 resetCharsets(screen); 6198 InitParams(); /* ignore the remaining params, if any */ 6199 update_vt52_vt100_settings(); 6200 RequestResize(xw, -1, 80, True); 6201 } 6202#endif 6203 break; 6204 case srm_DECCOLM: 6205 if (screen->c132) { 6206 Boolean willResize = ((j = IsSM() 6207 ? 132 6208 : 80) 6209 != ((xw->flags & IN132COLUMNS) 6210 ? 132 6211 : 80) 6212 || j != MaxCols(screen)); 6213 if (!(xw->flags & NOCLEAR_COLM)) 6214 ClearScreen(xw); 6215 if (willResize) 6216 RequestResize(xw, -1, j, True); 6217 (*func) (&xw->flags, IN132COLUMNS); 6218 resetMargins(xw); 6219 CursorSet(screen, 0, 0, xw->flags); 6220 } 6221 break; 6222 case srm_DECSCLM: /* (slow scroll) */ 6223 if (IsSM()) { 6224 screen->jumpscroll = 0; 6225 if (screen->scroll_amt) 6226 FlushScroll(xw); 6227 } else 6228 screen->jumpscroll = 1; 6229 (*func) (&xw->flags, SMOOTHSCROLL); 6230 update_jumpscroll(); 6231 break; 6232 case srm_DECSCNM: 6233 myflags = xw->flags; 6234 (*func) (&xw->flags, REVERSE_VIDEO); 6235 if ((xw->flags ^ myflags) & REVERSE_VIDEO) 6236 ReverseVideo(xw); 6237 /* update_reversevideo done in RevVid */ 6238 break; 6239 6240 case srm_DECOM: 6241 (*func) (&xw->flags, ORIGIN); 6242 CursorSet(screen, 0, 0, xw->flags); 6243 break; 6244 6245 case srm_DECAWM: 6246 (*func) (&xw->flags, WRAPAROUND); 6247 update_autowrap(); 6248 break; 6249 case srm_DECARM: 6250 /* ignore autorepeat 6251 * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only 6252 * for the whole display - not limited to a given window. 6253 */ 6254 break; 6255 case srm_X10_MOUSE: /* MIT bogus sequence */ 6256 MotionOff(screen, xw); 6257 set_mousemode(X10_MOUSE); 6258 break; 6259#if OPT_TOOLBAR 6260 case srm_RXVT_TOOLBAR: 6261 ShowToolbar(IsSM()); 6262 break; 6263#endif 6264#if OPT_BLINK_CURS 6265 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 6266 if (SettableCursorBlink(screen)) { 6267 set_bool_mode(screen->cursor_blink_esc); 6268 UpdateCursorBlink(xw); 6269 } 6270 break; 6271 case srm_CURSOR_BLINK_OPS: 6272 /* intentionally ignored (this is user-preference) */ 6273 break; 6274 case srm_XOR_CURSOR_BLINKS: 6275 /* intentionally ignored (this is user-preference) */ 6276 break; 6277#endif 6278 case srm_DECPFF: /* print form feed */ 6279 set_bool_mode(PrinterOf(screen).printer_formfeed); 6280 break; 6281 case srm_DECPEX: /* print extent */ 6282 set_bool_mode(PrinterOf(screen).printer_extent); 6283 break; 6284 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 6285 set_bool_mode(screen->cursor_set); 6286 break; 6287 case srm_RXVT_SCROLLBAR: 6288 if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF)) 6289 ToggleScrollBar(xw); 6290 break; 6291#if OPT_SHIFT_FONTS 6292 case srm_RXVT_FONTSIZE: 6293 set_bool_mode(xw->misc.shift_fonts); 6294 break; 6295#endif 6296#if OPT_TEK4014 6297 case srm_DECTEK: 6298 if (IsSM() && !(screen->inhibit & I_TEK)) { 6299 FlushLog(xw); 6300 TEK4014_ACTIVE(xw) = True; 6301 TRACE(("Tek4014 is now active...\n")); 6302 update_vttekmode(); 6303 } 6304 break; 6305#endif 6306 case srm_132COLS: /* 132 column mode */ 6307 set_bool_mode(screen->c132); 6308 update_allow132(); 6309 break; 6310 case srm_CURSES_HACK: 6311 set_bool_mode(screen->curses); 6312 update_cursesemul(); 6313 break; 6314 case srm_DECNRCM: /* national charset (VT220) */ 6315 if (screen->vtXX_level >= 2) { 6316 if ((*func) (&xw->flags, NATIONAL)) { 6317 modified_DECNRCM(xw); 6318 } 6319 } 6320 break; 6321#if OPT_PRINT_GRAPHICS 6322 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 6323 set_bool_mode(screen->graphics_expanded_print_mode); 6324 break; 6325#endif 6326 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 6327 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_mode)) { 6328 set_bool_mode(screen->marginbell); 6329 if (!screen->marginbell) 6330 screen->bellArmed = -1; 6331 update_marginbell(); 6332 } 6333 break; 6334 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 6335 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_syntax)) { 6336 (*func) (&xw->flags, REVERSEWRAP); 6337 update_reversewrap(); 6338 } 6339 break; 6340#ifdef ALLOWLOGGING 6341 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 6342 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_background_mode)) { 6343#ifdef ALLOWLOGFILEONOFF 6344 /* 6345 * if this feature is enabled, logging may be 6346 * enabled and disabled via escape sequences. 6347 */ 6348 if (IsSM()) 6349 StartLog(xw); 6350 else 6351 CloseLog(xw); 6352#else 6353 Bell(xw, XkbBI_Info, 0); 6354 Bell(xw, XkbBI_Info, 0); 6355#endif /* ALLOWLOGFILEONOFF */ 6356 } 6357 break; 6358#elif OPT_PRINT_GRAPHICS 6359 case srm_DECGPBM: /* Graphics Print Background Mode */ 6360 set_bool_mode(screen->graphics_print_background_mode); 6361 break; 6362#endif /* ALLOWLOGGING */ 6363 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 6364 if (!xw->misc.titeInhibit) { 6365 if (IsSM()) { 6366 CursorSave(xw); 6367 ToAlternate(xw, True); 6368 ClearScreen(xw); 6369 } else { 6370 FromAlternate(xw); 6371 CursorRestore(xw); 6372 } 6373 } else if (IsSM()) { 6374 do_ti_xtra_scroll(xw); 6375 } 6376 break; 6377 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 6378 if (!xw->misc.titeInhibit) { 6379 if (IsSM()) { 6380 ToAlternate(xw, False); 6381 } else { 6382 if (screen->whichBuf) 6383 ClearScreen(xw); 6384 FromAlternate(xw); 6385 } 6386 } else if (IsSM()) { 6387 do_ti_xtra_scroll(xw); 6388 } 6389 break; 6390 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 6391 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_rotated_print_mode)) { 6392 if (!xw->misc.titeInhibit) { 6393 if (IsSM()) { 6394 ToAlternate(xw, False); 6395 } else { 6396 FromAlternate(xw); 6397 } 6398 } else if (IsSM()) { 6399 do_ti_xtra_scroll(xw); 6400 } 6401 } 6402 break; 6403 case srm_DECNKM: 6404 (*func) (&xw->keyboard.flags, MODE_DECKPAM); 6405 update_appkeypad(); 6406 break; 6407 case srm_DECBKM: 6408 /* back-arrow mapped to backspace or delete(D) */ 6409 (*func) (&xw->keyboard.flags, MODE_DECBKM); 6410 TRACE(("DECSET DECBKM %s\n", 6411 BtoS(xw->keyboard.flags & MODE_DECBKM))); 6412 update_decbkm(); 6413 break; 6414 case srm_DECLRMM: 6415 if (screen->vtXX_level >= 4) { /* VT420 */ 6416 (*func) (&xw->flags, LEFT_RIGHT); 6417 if (IsLeftRightMode(xw)) { 6418 xterm_ResetDouble(xw); 6419 } else { 6420 reset_lr_margins(screen); 6421 } 6422 } 6423 break; 6424#if OPT_SIXEL_GRAPHICS 6425 case srm_DECSDM: /* sixel scrolling */ 6426 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 6427 (*func) (&xw->keyboard.flags, MODE_DECSDM); 6428 TRACE(("DECSET/DECRST DECSDM %s (resource default is %d)\n", 6429 BtoS(xw->keyboard.flags & MODE_DECSDM), 6430 TScreenOf(xw)->sixel_scrolling)); 6431 update_decsdm(); 6432 } 6433 break; 6434#endif 6435 case srm_DECNCSM: 6436 if (screen->vtXX_level >= 5) { /* VT510 */ 6437 (*func) (&xw->flags, NOCLEAR_COLM); 6438 } 6439 break; 6440 case srm_VT200_MOUSE: /* xterm bogus sequence */ 6441 MotionOff(screen, xw); 6442 set_mousemode(VT200_MOUSE); 6443 break; 6444 case srm_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */ 6445 MotionOff(screen, xw); 6446 set_mousemode(VT200_HIGHLIGHT_MOUSE); 6447 break; 6448 case srm_BTN_EVENT_MOUSE: 6449 MotionOff(screen, xw); 6450 set_mousemode(BTN_EVENT_MOUSE); 6451 break; 6452 case srm_ANY_EVENT_MOUSE: 6453 set_mousemode(ANY_EVENT_MOUSE); 6454 if (screen->send_mouse_pos == MOUSE_OFF) { 6455 MotionOff(screen, xw); 6456 } else { 6457 MotionOn(screen, xw); 6458 } 6459 break; 6460#if OPT_FOCUS_EVENT 6461 case srm_FOCUS_EVENT_MOUSE: 6462 set_bool_mode(screen->send_focus_pos); 6463 break; 6464#endif 6465 case srm_EXT_MODE_MOUSE: 6466 /* FALLTHRU */ 6467 case srm_SGR_EXT_MODE_MOUSE: 6468 /* FALLTHRU */ 6469 case srm_URXVT_EXT_MODE_MOUSE: 6470 /* FALLTHRU */ 6471 case srm_PIXEL_POSITION_MOUSE: 6472 /* 6473 * Rather than choose an arbitrary precedence among the coordinate 6474 * modes, they are mutually exclusive. For consistency, a reset is 6475 * only effective against the matching mode. 6476 */ 6477 if (IsSM()) { 6478 screen->extend_coords = code; 6479 } else if (screen->extend_coords == code) { 6480 screen->extend_coords = 0; 6481 } 6482 break; 6483 case srm_ALTERNATE_SCROLL: 6484 set_bool_mode(screen->alternateScroll); 6485 break; 6486 case srm_RXVT_SCROLL_TTY_OUTPUT: 6487 set_bool_mode(screen->scrollttyoutput); 6488 update_scrollttyoutput(); 6489 break; 6490 case srm_RXVT_SCROLL_TTY_KEYPRESS: 6491 set_bool_mode(screen->scrollkey); 6492 update_scrollkey(); 6493 break; 6494 case srm_EIGHT_BIT_META: 6495 if (screen->eight_bit_meta != ebNever) { 6496 set_bool_mode(screen->eight_bit_meta); 6497 } 6498 break; 6499#if OPT_NUM_LOCK 6500 case srm_REAL_NUMLOCK: 6501 set_bool_mode(xw->misc.real_NumLock); 6502 update_num_lock(); 6503 break; 6504 case srm_META_SENDS_ESC: 6505 set_bool_mode(screen->meta_sends_esc); 6506 update_meta_esc(); 6507 break; 6508#endif 6509 case srm_DELETE_IS_DEL: 6510 set_bool_mode(screen->delete_is_del); 6511 update_delete_del(); 6512 break; 6513#if OPT_NUM_LOCK 6514 case srm_ALT_SENDS_ESC: 6515 set_bool_mode(screen->alt_sends_esc); 6516 update_alt_esc(); 6517 break; 6518#endif 6519 case srm_KEEP_SELECTION: 6520 set_bool_mode(screen->keepSelection); 6521 update_keepSelection(); 6522 break; 6523 case srm_SELECT_TO_CLIPBOARD: 6524 set_bool_mode(screen->selectToClipboard); 6525 update_selectToClipboard(); 6526 break; 6527 case srm_BELL_IS_URGENT: 6528 set_bool_mode(screen->bellIsUrgent); 6529 update_bellIsUrgent(); 6530 break; 6531 case srm_POP_ON_BELL: 6532 set_bool_mode(screen->poponbell); 6533 update_poponbell(); 6534 break; 6535 case srm_KEEP_CLIPBOARD: 6536 set_bool_mode(screen->keepClipboard); 6537 update_keepClipboard(); 6538 break; 6539 case srm_ALLOW_ALTBUF: 6540 if (IsSM()) { 6541 xw->misc.titeInhibit = False; 6542 } else if (!xw->misc.titeInhibit) { 6543 xw->misc.titeInhibit = True; 6544 FromAlternate(xw); 6545 } 6546 update_titeInhibit(); 6547 break; 6548 case srm_SAVE_CURSOR: 6549 if (!xw->misc.titeInhibit) { 6550 if (IsSM()) 6551 CursorSave(xw); 6552 else 6553 CursorRestore(xw); 6554 } 6555 break; 6556#if OPT_TCAP_FKEYS 6557 case srm_TCAP_FKEYS: 6558 set_keyboard_type(xw, keyboardIsTermcap, IsSM()); 6559 break; 6560#endif 6561#if OPT_SUN_FUNC_KEYS 6562 case srm_SUN_FKEYS: 6563 set_keyboard_type(xw, keyboardIsSun, IsSM()); 6564 break; 6565#endif 6566#if OPT_HP_FUNC_KEYS 6567 case srm_HP_FKEYS: 6568 set_keyboard_type(xw, keyboardIsHP, IsSM()); 6569 break; 6570#endif 6571#if OPT_SCO_FUNC_KEYS 6572 case srm_SCO_FKEYS: 6573 set_keyboard_type(xw, keyboardIsSCO, IsSM()); 6574 break; 6575#endif 6576 case srm_LEGACY_FKEYS: 6577 set_keyboard_type(xw, keyboardIsLegacy, IsSM()); 6578 break; 6579#if OPT_SUNPC_KBD 6580 case srm_VT220_FKEYS: 6581 set_keyboard_type(xw, keyboardIsVT220, IsSM()); 6582 break; 6583#endif 6584#if OPT_PASTE64 || OPT_READLINE 6585 case srm_PASTE_IN_BRACKET: 6586 set_mouseflag(paste_brackets); 6587 break; 6588#endif 6589#if OPT_READLINE 6590 case srm_BUTTON1_MOVE_POINT: 6591 set_mouseflag(click1_moves); 6592 break; 6593 case srm_BUTTON2_MOVE_POINT: 6594 set_mouseflag(paste_moves); 6595 break; 6596 case srm_DBUTTON3_DELETE: 6597 set_mouseflag(dclick3_deletes); 6598 break; 6599 case srm_PASTE_QUOTE: 6600 set_mouseflag(paste_quotes); 6601 break; 6602 case srm_PASTE_LITERAL_NL: 6603 set_mouseflag(paste_literal_nl); 6604 break; 6605#endif /* OPT_READLINE */ 6606#if OPT_GRAPHICS 6607 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 6608 TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n", 6609 BtoS(screen->privatecolorregisters), 6610 BtoS(TScreenOf(xw)->privatecolorregisters))); 6611 set_bool_mode(screen->privatecolorregisters); 6612 update_privatecolorregisters(); 6613 break; 6614#endif 6615#if OPT_SIXEL_GRAPHICS 6616 case srm_SIXEL_SCROLLS_RIGHT: /* sixel scrolling moves cursor to right */ 6617 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 6618 set_bool_mode(screen->sixel_scrolls_right); 6619 TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n", 6620 BtoS(screen->sixel_scrolls_right), 6621 BtoS(TScreenOf(xw)->sixel_scrolls_right))); 6622 } 6623 break; 6624#endif 6625 default: 6626 TRACE(("DATA_ERROR: unknown private code %d\n", code)); 6627 break; 6628 } 6629 } 6630} 6631 6632/* 6633 * process xterm private modes save 6634 */ 6635static void 6636savemodes(XtermWidget xw) 6637{ 6638 TScreen *screen = TScreenOf(xw); 6639 int i; 6640 6641 for (i = 0; i < nparam; i++) { 6642 int code = GetParam(i); 6643 6644 TRACE(("savemodes %d\n", code)); 6645 switch ((DECSET_codes) code) { 6646 case srm_DECCKM: 6647 DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM); 6648 break; 6649 case srm_DECANM: /* ANSI/VT52 mode */ 6650 /* no effect */ 6651 break; 6652 case srm_DECCOLM: 6653 if (screen->c132) 6654 DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS); 6655 break; 6656 case srm_DECSCLM: /* (slow scroll) */ 6657 DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL); 6658 break; 6659 case srm_DECSCNM: 6660 DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO); 6661 break; 6662 case srm_DECOM: 6663 DoSM(DP_DECOM, xw->flags & ORIGIN); 6664 break; 6665 case srm_DECAWM: 6666 DoSM(DP_DECAWM, xw->flags & WRAPAROUND); 6667 break; 6668 case srm_DECARM: 6669 /* ignore autorepeat */ 6670 break; 6671 case srm_X10_MOUSE: /* mouse bogus sequence */ 6672 DoSM(DP_X_X10MSE, screen->send_mouse_pos); 6673 break; 6674#if OPT_TOOLBAR 6675 case srm_RXVT_TOOLBAR: 6676 DoSM(DP_TOOLBAR, resource.toolBar); 6677 break; 6678#endif 6679#if OPT_BLINK_CURS 6680 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 6681 if (SettableCursorBlink(screen)) { 6682 DoSM(DP_CRS_BLINK, screen->cursor_blink_esc); 6683 } 6684 break; 6685 case srm_CURSOR_BLINK_OPS: 6686 /* intentionally ignored (this is user-preference) */ 6687 break; 6688 case srm_XOR_CURSOR_BLINKS: 6689 /* intentionally ignored (this is user-preference) */ 6690 break; 6691#endif 6692 case srm_DECPFF: /* print form feed */ 6693 DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 6694 break; 6695 case srm_DECPEX: /* print extent */ 6696 DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 6697 break; 6698 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 6699 DoSM(DP_CRS_VISIBLE, screen->cursor_set); 6700 break; 6701 case srm_RXVT_SCROLLBAR: 6702 DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0)); 6703 break; 6704#if OPT_SHIFT_FONTS 6705 case srm_RXVT_FONTSIZE: 6706 DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 6707 break; 6708#endif 6709#if OPT_TEK4014 6710 case srm_DECTEK: 6711 DoSM(DP_DECTEK, TEK4014_ACTIVE(xw)); 6712 break; 6713#endif 6714 case srm_132COLS: /* 132 column mode */ 6715 DoSM(DP_X_DECCOLM, screen->c132); 6716 break; 6717 case srm_CURSES_HACK: /* curses hack */ 6718 DoSM(DP_X_MORE, screen->curses); 6719 break; 6720 case srm_DECNRCM: /* national charset (VT220) */ 6721 if (screen->vtXX_level >= 2) { 6722 DoSM(DP_DECNRCM, xw->flags & NATIONAL); 6723 } 6724 break; 6725#if OPT_PRINT_GRAPHICS 6726 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 6727 DoSM(DP_DECGEPM, screen->graphics_expanded_print_mode); 6728 break; 6729#endif 6730 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 6731 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCM, screen->graphics_print_color_mode)) { 6732 DoSM(DP_X_MARGIN, screen->marginbell); 6733 } 6734 break; 6735 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 6736 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 6737 DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP); 6738 } 6739 break; 6740#ifdef ALLOWLOGGING 6741 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 6742 if_PRINT_GRAPHICS2(DoSM(DP_DECGPBM, screen->graphics_print_background_mode)) { 6743#ifdef ALLOWLOGFILEONOFF 6744 DoSM(DP_X_LOGGING, screen->logging); 6745#endif /* ALLOWLOGFILEONOFF */ 6746 } 6747 break; 6748#elif OPT_PRINT_GRAPHICS 6749 case srm_DECGPBM: /* Graphics Print Background Mode */ 6750 DoSM(DP_DECGPBM, screen->graphics_print_background_mode); 6751 break; 6752#endif /* ALLOWLOGGING */ 6753 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 6754 /* FALLTHRU */ 6755 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 6756 DoSM(DP_X_ALTBUF, screen->whichBuf); 6757 break; 6758 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 6759 if_PRINT_GRAPHICS2(DoSM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 6760 DoSM(DP_X_ALTBUF, screen->whichBuf); 6761 } 6762 break; 6763 case srm_DECNKM: 6764 DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM); 6765 break; 6766 case srm_DECBKM: /* backarrow mapping */ 6767 DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM); 6768 break; 6769 case srm_DECLRMM: /* left-right */ 6770 DoSM(DP_X_LRMM, LEFT_RIGHT); 6771 break; 6772#if OPT_SIXEL_GRAPHICS 6773 case srm_DECSDM: /* sixel scrolling */ 6774 DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM); 6775 update_decsdm(); 6776 break; 6777#endif 6778 case srm_DECNCSM: /* noclear */ 6779 DoSM(DP_X_NCSM, NOCLEAR_COLM); 6780 break; 6781 case srm_VT200_MOUSE: /* mouse bogus sequence */ 6782 /* FALLTHRU */ 6783 case srm_VT200_HIGHLIGHT_MOUSE: 6784 /* FALLTHRU */ 6785 case srm_BTN_EVENT_MOUSE: 6786 /* FALLTHRU */ 6787 case srm_ANY_EVENT_MOUSE: 6788 DoSM(DP_X_MOUSE, screen->send_mouse_pos); 6789 break; 6790#if OPT_FOCUS_EVENT 6791 case srm_FOCUS_EVENT_MOUSE: 6792 DoSM(DP_X_FOCUS, screen->send_focus_pos); 6793 break; 6794#endif 6795 case srm_EXT_MODE_MOUSE: 6796 /* FALLTHRU */ 6797 case srm_SGR_EXT_MODE_MOUSE: 6798 /* FALLTHRU */ 6799 case srm_URXVT_EXT_MODE_MOUSE: 6800 /* FALLTHRU */ 6801 case srm_PIXEL_POSITION_MOUSE: 6802 DoSM(DP_X_EXT_MOUSE, screen->extend_coords); 6803 break; 6804 case srm_ALTERNATE_SCROLL: 6805 DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 6806 break; 6807 case srm_RXVT_SCROLL_TTY_OUTPUT: 6808 DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 6809 break; 6810 case srm_RXVT_SCROLL_TTY_KEYPRESS: 6811 DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 6812 break; 6813 case srm_EIGHT_BIT_META: 6814 DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 6815 break; 6816#if OPT_NUM_LOCK 6817 case srm_REAL_NUMLOCK: 6818 DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 6819 break; 6820 case srm_META_SENDS_ESC: 6821 DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc); 6822 break; 6823#endif 6824 case srm_DELETE_IS_DEL: 6825 DoSM(DP_DELETE_IS_DEL, screen->delete_is_del); 6826 break; 6827#if OPT_NUM_LOCK 6828 case srm_ALT_SENDS_ESC: 6829 DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 6830 break; 6831#endif 6832 case srm_KEEP_SELECTION: 6833 DoSM(DP_KEEP_SELECTION, screen->keepSelection); 6834 break; 6835 case srm_SELECT_TO_CLIPBOARD: 6836 DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 6837 break; 6838 case srm_BELL_IS_URGENT: 6839 DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 6840 break; 6841 case srm_POP_ON_BELL: 6842 DoSM(DP_POP_ON_BELL, screen->poponbell); 6843 break; 6844 case srm_KEEP_CLIPBOARD: 6845 DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 6846 break; 6847#if OPT_TCAP_FKEYS 6848 case srm_TCAP_FKEYS: 6849 /* FALLTHRU */ 6850#endif 6851#if OPT_SUN_FUNC_KEYS 6852 case srm_SUN_FKEYS: 6853 /* FALLTHRU */ 6854#endif 6855#if OPT_HP_FUNC_KEYS 6856 case srm_HP_FKEYS: 6857 /* FALLTHRU */ 6858#endif 6859#if OPT_SCO_FUNC_KEYS 6860 case srm_SCO_FKEYS: 6861 /* FALLTHRU */ 6862#endif 6863#if OPT_SUNPC_KBD 6864 case srm_VT220_FKEYS: 6865 /* FALLTHRU */ 6866#endif 6867 case srm_LEGACY_FKEYS: 6868 DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type); 6869 break; 6870 case srm_ALLOW_ALTBUF: 6871 DoSM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 6872 break; 6873 case srm_SAVE_CURSOR: 6874 if (!xw->misc.titeInhibit) { 6875 CursorSave(xw); 6876 } 6877 break; 6878#if OPT_PASTE64 || OPT_READLINE 6879 case srm_PASTE_IN_BRACKET: 6880 SCREEN_FLAG_save(screen, paste_brackets); 6881 break; 6882#endif 6883#if OPT_READLINE 6884 case srm_BUTTON1_MOVE_POINT: 6885 SCREEN_FLAG_save(screen, click1_moves); 6886 break; 6887 case srm_BUTTON2_MOVE_POINT: 6888 SCREEN_FLAG_save(screen, paste_moves); 6889 break; 6890 case srm_DBUTTON3_DELETE: 6891 SCREEN_FLAG_save(screen, dclick3_deletes); 6892 break; 6893 case srm_PASTE_QUOTE: 6894 SCREEN_FLAG_save(screen, paste_quotes); 6895 break; 6896 case srm_PASTE_LITERAL_NL: 6897 SCREEN_FLAG_save(screen, paste_literal_nl); 6898 break; 6899#endif /* OPT_READLINE */ 6900#if OPT_GRAPHICS 6901 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 6902 TRACE(("save PRIVATE_COLOR_REGISTERS %s\n", 6903 BtoS(screen->privatecolorregisters))); 6904 DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 6905 update_privatecolorregisters(); 6906 break; 6907#endif 6908#if OPT_SIXEL_GRAPHICS 6909 case srm_SIXEL_SCROLLS_RIGHT: 6910 TRACE(("save SIXEL_SCROLLS_RIGHT %s\n", 6911 BtoS(screen->sixel_scrolls_right))); 6912 DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 6913 break; 6914#endif 6915 } 6916 } 6917} 6918 6919/* 6920 * process xterm private modes restore 6921 */ 6922static void 6923restoremodes(XtermWidget xw) 6924{ 6925 TScreen *screen = TScreenOf(xw); 6926 int i, j; 6927 6928 for (i = 0; i < nparam; i++) { 6929 int code = GetParam(i); 6930 6931 TRACE(("restoremodes %d\n", code)); 6932 switch ((DECSET_codes) code) { 6933 case srm_DECCKM: 6934 bitcpy(&xw->keyboard.flags, 6935 screen->save_modes[DP_DECCKM], MODE_DECCKM); 6936 update_appcursor(); 6937 break; 6938 case srm_DECANM: /* ANSI/VT52 mode */ 6939 /* no effect */ 6940 break; 6941 case srm_DECCOLM: 6942 if (screen->c132) { 6943 if (!(xw->flags & NOCLEAR_COLM)) 6944 ClearScreen(xw); 6945 CursorSet(screen, 0, 0, xw->flags); 6946 if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS) 6947 ? 132 : 80) != ((xw->flags & IN132COLUMNS) 6948 ? 132 : 80) || j != MaxCols(screen)) 6949 RequestResize(xw, -1, j, True); 6950 bitcpy(&xw->flags, 6951 screen->save_modes[DP_DECCOLM], 6952 IN132COLUMNS); 6953 } 6954 break; 6955 case srm_DECSCLM: /* (slow scroll) */ 6956 if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) { 6957 screen->jumpscroll = 0; 6958 if (screen->scroll_amt) 6959 FlushScroll(xw); 6960 } else 6961 screen->jumpscroll = 1; 6962 bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL); 6963 update_jumpscroll(); 6964 break; 6965 case srm_DECSCNM: 6966 if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) { 6967 bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO); 6968 ReverseVideo(xw); 6969 /* update_reversevideo done in RevVid */ 6970 } 6971 break; 6972 case srm_DECOM: 6973 bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN); 6974 CursorSet(screen, 0, 0, xw->flags); 6975 break; 6976 6977 case srm_DECAWM: 6978 bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND); 6979 update_autowrap(); 6980 break; 6981 case srm_DECARM: 6982 /* ignore autorepeat */ 6983 break; 6984 case srm_X10_MOUSE: /* MIT bogus sequence */ 6985 DoRM0(DP_X_X10MSE, screen->send_mouse_pos); 6986 really_set_mousemode(xw, 6987 screen->send_mouse_pos != MOUSE_OFF, 6988 (XtermMouseModes) screen->send_mouse_pos); 6989 break; 6990#if OPT_TOOLBAR 6991 case srm_RXVT_TOOLBAR: 6992 DoRM(DP_TOOLBAR, resource.toolBar); 6993 ShowToolbar(resource.toolBar); 6994 break; 6995#endif 6996#if OPT_BLINK_CURS 6997 case srm_ATT610_BLINK: /* Start/stop blinking cursor */ 6998 if (SettableCursorBlink(screen)) { 6999 DoRM(DP_CRS_BLINK, screen->cursor_blink_esc); 7000 UpdateCursorBlink(xw); 7001 } 7002 break; 7003 case srm_CURSOR_BLINK_OPS: 7004 /* intentionally ignored (this is user-preference) */ 7005 break; 7006 case srm_XOR_CURSOR_BLINKS: 7007 /* intentionally ignored (this is user-preference) */ 7008 break; 7009#endif 7010 case srm_DECPFF: /* print form feed */ 7011 DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 7012 break; 7013 case srm_DECPEX: /* print extent */ 7014 DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 7015 break; 7016 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 7017 DoRM(DP_CRS_VISIBLE, screen->cursor_set); 7018 break; 7019 case srm_RXVT_SCROLLBAR: 7020 if ((screen->fullVwin.sb_info.width != 0) != 7021 screen->save_modes[DP_RXVT_SCROLLBAR]) { 7022 ToggleScrollBar(xw); 7023 } 7024 break; 7025#if OPT_SHIFT_FONTS 7026 case srm_RXVT_FONTSIZE: 7027 DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 7028 break; 7029#endif 7030#if OPT_TEK4014 7031 case srm_DECTEK: 7032 if (!(screen->inhibit & I_TEK) && 7033 (TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) { 7034 FlushLog(xw); 7035 TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK]; 7036 update_vttekmode(); 7037 } 7038 break; 7039#endif 7040 case srm_132COLS: /* 132 column mode */ 7041 DoRM(DP_X_DECCOLM, screen->c132); 7042 update_allow132(); 7043 break; 7044 case srm_CURSES_HACK: /* curses hack */ 7045 DoRM(DP_X_MORE, screen->curses); 7046 update_cursesemul(); 7047 break; 7048 case srm_DECNRCM: /* national charset (VT220) */ 7049 if (screen->vtXX_level >= 2) { 7050 if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL)) 7051 modified_DECNRCM(xw); 7052 } 7053 break; 7054#if OPT_PRINT_GRAPHICS 7055 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 7056 DoRM(DP_DECGEPM, screen->graphics_expanded_print_mode); 7057 break; 7058#endif 7059 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 7060 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCM, screen->graphics_print_color_mode)) { 7061 if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0) 7062 screen->bellArmed = -1; 7063 update_marginbell(); 7064 } 7065 break; 7066 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 7067 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 7068 bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP); 7069 update_reversewrap(); 7070 } 7071 break; 7072#ifdef ALLOWLOGGING 7073 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 7074 if_PRINT_GRAPHICS2(DoRM(DP_DECGPBM, screen->graphics_print_background_mode)) { 7075#ifdef ALLOWLOGFILEONOFF 7076 if (screen->save_modes[DP_X_LOGGING]) 7077 StartLog(xw); 7078 else 7079 CloseLog(xw); 7080#endif /* ALLOWLOGFILEONOFF */ 7081 /* update_logging done by StartLog and CloseLog */ 7082 } 7083 break; 7084#elif OPT_PRINT_GRAPHICS 7085 case srm_DECGPBM: /* Graphics Print Background Mode */ 7086 DoRM(DP_DECGPBM, screen->graphics_print_background_mode); 7087 break; 7088#endif /* ALLOWLOGGING */ 7089 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 7090 /* FALLTHRU */ 7091 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 7092 if (!xw->misc.titeInhibit) { 7093 if (screen->save_modes[DP_X_ALTBUF]) 7094 ToAlternate(xw, False); 7095 else 7096 FromAlternate(xw); 7097 /* update_altscreen done by ToAlt and FromAlt */ 7098 } else if (screen->save_modes[DP_X_ALTBUF]) { 7099 do_ti_xtra_scroll(xw); 7100 } 7101 break; 7102 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7103 if_PRINT_GRAPHICS2(DoRM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 7104 if (!xw->misc.titeInhibit) { 7105 if (screen->save_modes[DP_X_ALTBUF]) 7106 ToAlternate(xw, False); 7107 else 7108 FromAlternate(xw); 7109 /* update_altscreen done by ToAlt and FromAlt */ 7110 } else if (screen->save_modes[DP_X_ALTBUF]) { 7111 do_ti_xtra_scroll(xw); 7112 } 7113 } 7114 break; 7115 case srm_DECNKM: 7116 bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM); 7117 update_appkeypad(); 7118 break; 7119 case srm_DECBKM: /* backarrow mapping */ 7120 bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM); 7121 update_decbkm(); 7122 break; 7123 case srm_DECLRMM: /* left-right */ 7124 bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT); 7125 if (IsLeftRightMode(xw)) { 7126 xterm_ResetDouble(xw); 7127 } else { 7128 reset_lr_margins(screen); 7129 } 7130 break; 7131#if OPT_SIXEL_GRAPHICS 7132 case srm_DECSDM: /* sixel scrolling */ 7133 bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM); 7134 update_decsdm(); 7135 break; 7136#endif 7137 case srm_DECNCSM: /* noclear */ 7138 bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM); 7139 break; 7140 case srm_VT200_MOUSE: /* mouse bogus sequence */ 7141 /* FALLTHRU */ 7142 case srm_VT200_HIGHLIGHT_MOUSE: 7143 /* FALLTHRU */ 7144 case srm_BTN_EVENT_MOUSE: 7145 /* FALLTHRU */ 7146 case srm_ANY_EVENT_MOUSE: 7147 DoRM0(DP_X_MOUSE, screen->send_mouse_pos); 7148 really_set_mousemode(xw, 7149 screen->send_mouse_pos != MOUSE_OFF, 7150 (XtermMouseModes) screen->send_mouse_pos); 7151 break; 7152#if OPT_FOCUS_EVENT 7153 case srm_FOCUS_EVENT_MOUSE: 7154 DoRM(DP_X_FOCUS, screen->send_focus_pos); 7155 break; 7156#endif 7157 case srm_EXT_MODE_MOUSE: 7158 /* FALLTHRU */ 7159 case srm_SGR_EXT_MODE_MOUSE: 7160 /* FALLTHRU */ 7161 case srm_URXVT_EXT_MODE_MOUSE: 7162 /* FALLTHRU */ 7163 case srm_PIXEL_POSITION_MOUSE: 7164 DoRM(DP_X_EXT_MOUSE, screen->extend_coords); 7165 break; 7166 case srm_ALLOW_ALTBUF: 7167 DoRM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 7168 if (xw->misc.titeInhibit) 7169 FromAlternate(xw); 7170 update_titeInhibit(); 7171 break; 7172 case srm_SAVE_CURSOR: 7173 if (!xw->misc.titeInhibit) { 7174 CursorRestore(xw); 7175 } 7176 break; 7177 case srm_ALTERNATE_SCROLL: 7178 DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 7179 break; 7180 case srm_RXVT_SCROLL_TTY_OUTPUT: 7181 DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 7182 update_scrollttyoutput(); 7183 break; 7184 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7185 DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 7186 update_scrollkey(); 7187 break; 7188 case srm_EIGHT_BIT_META: 7189 DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 7190 break; 7191#if OPT_NUM_LOCK 7192 case srm_REAL_NUMLOCK: 7193 DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 7194 update_num_lock(); 7195 break; 7196 case srm_META_SENDS_ESC: 7197 DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc); 7198 update_meta_esc(); 7199 break; 7200#endif 7201 case srm_DELETE_IS_DEL: 7202 DoRM(DP_DELETE_IS_DEL, screen->delete_is_del); 7203 update_delete_del(); 7204 break; 7205#if OPT_NUM_LOCK 7206 case srm_ALT_SENDS_ESC: 7207 DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 7208 update_alt_esc(); 7209 break; 7210#endif 7211 case srm_KEEP_SELECTION: 7212 DoRM(DP_KEEP_SELECTION, screen->keepSelection); 7213 update_keepSelection(); 7214 break; 7215 case srm_SELECT_TO_CLIPBOARD: 7216 DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 7217 update_selectToClipboard(); 7218 break; 7219 case srm_BELL_IS_URGENT: 7220 DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 7221 update_bellIsUrgent(); 7222 break; 7223 case srm_POP_ON_BELL: 7224 DoRM(DP_POP_ON_BELL, screen->poponbell); 7225 update_poponbell(); 7226 break; 7227 case srm_KEEP_CLIPBOARD: 7228 DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 7229 update_keepClipboard(); 7230 break; 7231#if OPT_TCAP_FKEYS 7232 case srm_TCAP_FKEYS: 7233 /* FALLTHRU */ 7234#endif 7235#if OPT_SUN_FUNC_KEYS 7236 case srm_SUN_FKEYS: 7237 /* FALLTHRU */ 7238#endif 7239#if OPT_HP_FUNC_KEYS 7240 case srm_HP_FKEYS: 7241 /* FALLTHRU */ 7242#endif 7243#if OPT_SCO_FUNC_KEYS 7244 case srm_SCO_FKEYS: 7245 /* FALLTHRU */ 7246#endif 7247#if OPT_SUNPC_KBD 7248 case srm_VT220_FKEYS: 7249 /* FALLTHRU */ 7250#endif 7251 case srm_LEGACY_FKEYS: 7252 xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE]; 7253 break; 7254#if OPT_PASTE64 || OPT_READLINE 7255 case srm_PASTE_IN_BRACKET: 7256 SCREEN_FLAG_restore(screen, paste_brackets); 7257 break; 7258#endif 7259#if OPT_READLINE 7260 case srm_BUTTON1_MOVE_POINT: 7261 SCREEN_FLAG_restore(screen, click1_moves); 7262 break; 7263 case srm_BUTTON2_MOVE_POINT: 7264 SCREEN_FLAG_restore(screen, paste_moves); 7265 break; 7266 case srm_DBUTTON3_DELETE: 7267 SCREEN_FLAG_restore(screen, dclick3_deletes); 7268 break; 7269 case srm_PASTE_QUOTE: 7270 SCREEN_FLAG_restore(screen, paste_quotes); 7271 break; 7272 case srm_PASTE_LITERAL_NL: 7273 SCREEN_FLAG_restore(screen, paste_literal_nl); 7274 break; 7275#endif /* OPT_READLINE */ 7276#if OPT_GRAPHICS 7277 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 7278 TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n", 7279 BtoS(screen->privatecolorregisters))); 7280 DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 7281 TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n", 7282 BtoS(screen->privatecolorregisters))); 7283 update_privatecolorregisters(); 7284 break; 7285#endif 7286#if OPT_SIXEL_GRAPHICS 7287 case srm_SIXEL_SCROLLS_RIGHT: 7288 TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n", 7289 BtoS(screen->sixel_scrolls_right))); 7290 DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 7291 TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n", 7292 BtoS(screen->sixel_scrolls_right))); 7293 break; 7294#endif 7295 } 7296 } 7297} 7298 7299/* 7300 * Convert an XTextProperty to a string. 7301 * 7302 * This frees the data owned by the XTextProperty, and returns in its place the 7303 * string, which must be freed by the caller. 7304 */ 7305static char * 7306property_to_string(XtermWidget xw, XTextProperty * text) 7307{ 7308 TScreen *screen = TScreenOf(xw); 7309 Display *dpy = screen->display; 7310 char *result = 0; 7311 char **list = NULL; 7312 int length = 0; 7313 int rc; 7314 7315 TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n", 7316 text->value, 7317 TraceAtomName(dpy, text->encoding), 7318 text->format, 7319 text->nitems)); 7320 7321#if OPT_WIDE_CHARS 7322 /* 7323 * We will use the XmbTextPropertyToTextList call to extract UTF-8 data. 7324 * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to 7325 * ISO-8859-1. 7326 */ 7327 rc = -1; 7328 if ((text->format != 8) 7329 || IsTitleMode(xw, tmGetUtf8) 7330 || (text->encoding == XA_UTF8_STRING(dpy) && 7331 !(screen->wide_chars || screen->c1_printable) && 7332 (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0) 7333 || (rc < 0)) 7334#endif 7335 if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0) 7336 rc = XTextPropertyToStringList(text, &list, &length); 7337 7338 if (rc >= 0) { 7339 int n, c, pass; 7340 size_t need; 7341 7342 for (pass = 0; pass < 2; ++pass) { 7343 for (n = 0, need = 0; n < length; n++) { 7344 char *s = list[n]; 7345 while ((c = *s++) != '\0') { 7346 if (pass) 7347 result[need] = (char) c; 7348 ++need; 7349 } 7350 } 7351 if (pass) 7352 result[need] = '\0'; 7353 else 7354 result = malloc(need + 1); 7355 if (result == 0) 7356 break; 7357 } 7358 XFreeStringList(list); 7359 } 7360 if (text->value != 0) 7361 XFree(text->value); 7362 7363 return result; 7364} 7365 7366static char * 7367get_icon_label(XtermWidget xw) 7368{ 7369 XTextProperty text; 7370 char *result = 0; 7371 7372 if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 7373 result = property_to_string(xw, &text); 7374 } 7375 return result; 7376} 7377 7378static char * 7379get_window_label(XtermWidget xw) 7380{ 7381 XTextProperty text; 7382 char *result = 0; 7383 7384 if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 7385 result = property_to_string(xw, &text); 7386 } 7387 return result; 7388} 7389 7390/* 7391 * Report window label (icon or title) in dtterm protocol 7392 * ESC ] code label ESC backslash 7393 */ 7394static void 7395report_win_label(XtermWidget xw, 7396 int code, 7397 char *text) 7398{ 7399 unparseputc(xw, ANSI_ESC); 7400 unparseputc(xw, ']'); 7401 unparseputc(xw, code); 7402 7403 if (text != 0) { 7404 int copy = IsTitleMode(xw, tmGetBase16); 7405 if (copy) { 7406 TRACE(("Encoding hex:%s\n", text)); 7407 text = x_encode_hex(text); 7408 } 7409 unparseputs(xw, text); 7410 if (copy) 7411 free(text); 7412 } 7413 7414 unparseputc(xw, ANSI_ESC); 7415 unparseputc(xw, '\\'); /* should be ST */ 7416 unparse_end(xw); 7417} 7418 7419/* 7420 * Window operations (from CDE dtterm description, as well as extensions). 7421 * See also "allowWindowOps" resource. 7422 */ 7423static void 7424window_ops(XtermWidget xw) 7425{ 7426 TScreen *screen = TScreenOf(xw); 7427 XWindowChanges values; 7428 XWindowAttributes win_attrs; 7429#if OPT_MAXIMIZE 7430 unsigned root_width; 7431 unsigned root_height; 7432#endif 7433 int code = zero_if_default(0); 7434 char *label; 7435 7436 TRACE(("window_ops %d\n", code)); 7437 switch (code) { 7438 case ewRestoreWin: /* Restore (de-iconify) window */ 7439 if (AllowWindowOps(xw, ewRestoreWin)) { 7440 xtermDeiconify(xw); 7441 } 7442 break; 7443 7444 case ewMinimizeWin: /* Minimize (iconify) window */ 7445 if (AllowWindowOps(xw, ewMinimizeWin)) { 7446 xtermIconify(xw); 7447 } 7448 break; 7449 7450 case ewSetWinPosition: /* Move the window to the given position */ 7451 if (AllowWindowOps(xw, ewSetWinPosition)) { 7452 unsigned value_mask; 7453 7454 values.x = (Position) zero_if_default(1); 7455 values.y = (Position) zero_if_default(2); 7456 TRACE(("...move window to %d,%d\n", values.x, values.y)); 7457 value_mask = (CWX | CWY); 7458 XReconfigureWMWindow(screen->display, 7459 VShellWindow(xw), 7460 DefaultScreen(screen->display), 7461 value_mask, 7462 &values); 7463 } 7464 break; 7465 7466 case ewSetWinSizePixels: /* Resize the window to given size in pixels */ 7467 if (AllowWindowOps(xw, ewSetWinSizePixels)) { 7468 RequestResize(xw, optional_param(1), optional_param(2), False); 7469 } 7470 break; 7471 7472 case ewRaiseWin: /* Raise the window to the front of the stack */ 7473 if (AllowWindowOps(xw, ewRaiseWin)) { 7474 TRACE(("...raise window\n")); 7475 XRaiseWindow(screen->display, VShellWindow(xw)); 7476 } 7477 break; 7478 7479 case ewLowerWin: /* Lower the window to the bottom of the stack */ 7480 if (AllowWindowOps(xw, ewLowerWin)) { 7481 TRACE(("...lower window\n")); 7482 XLowerWindow(screen->display, VShellWindow(xw)); 7483 } 7484 break; 7485 7486 case ewRefreshWin: /* Refresh the window */ 7487 if (AllowWindowOps(xw, ewRefreshWin)) { 7488 TRACE(("...redraw window\n")); 7489 Redraw(); 7490 } 7491 break; 7492 7493 case ewSetWinSizeChars: /* Resize the text-area, in characters */ 7494 if (AllowWindowOps(xw, ewSetWinSizeChars)) { 7495 RequestResize(xw, optional_param(1), optional_param(2), True); 7496 } 7497 break; 7498 7499#if OPT_MAXIMIZE 7500 case ewMaximizeWin: /* Maximize or restore */ 7501 if (AllowWindowOps(xw, ewMaximizeWin)) { 7502 RequestMaximize(xw, zero_if_default(1)); 7503 } 7504 break; 7505 case ewFullscreenWin: /* Fullscreen or restore */ 7506 if (AllowWindowOps(xw, ewFullscreenWin)) { 7507 switch (zero_if_default(1)) { 7508 default: 7509 RequestMaximize(xw, 0); 7510 break; 7511 case 1: 7512 RequestMaximize(xw, 1); 7513 break; 7514 case 2: 7515 RequestMaximize(xw, !(screen->restore_data)); 7516 break; 7517 } 7518 } 7519 break; 7520#endif 7521 7522 case ewGetWinState: /* Report the window's state */ 7523 if (AllowWindowOps(xw, ewGetWinState)) { 7524 TRACE(("...get window attributes\n")); 7525 init_reply(ANSI_CSI); 7526 reply.a_pintro = 0; 7527 reply.a_nparam = 1; 7528 reply.a_param[0] = (ParmType) (xtermIsIconified(xw) ? 2 : 1); 7529 reply.a_inters = 0; 7530 reply.a_final = 't'; 7531 unparseseq(xw, &reply); 7532 } 7533 break; 7534 7535 case ewGetWinPosition: /* Report the window's position */ 7536 if (AllowWindowOps(xw, ewGetWinPosition)) { 7537 Window win; 7538 Window result_win; 7539 int result_y, result_x; 7540 7541 TRACE(("...get window position\n")); 7542 init_reply(ANSI_CSI); 7543 reply.a_pintro = 0; 7544 reply.a_nparam = 3; 7545 reply.a_param[0] = 3; 7546 switch (zero_if_default(1)) { 7547 case 2: /* report the text-window's position */ 7548 result_y = 0; 7549 result_x = 0; 7550 { 7551 Widget mw; 7552 for (mw = (Widget) xw; mw != 0; mw = XtParent(mw)) { 7553 result_x += mw->core.x; 7554 result_y += mw->core.y; 7555 if (mw == SHELL_OF(xw)) 7556 break; 7557 } 7558 } 7559 result_x += OriginX(screen); 7560 result_y += OriginY(screen); 7561 break; 7562 default: 7563 win = WMFrameWindow(xw); 7564 xtermGetWinAttrs(screen->display, 7565 win, 7566 &win_attrs); 7567 XTranslateCoordinates(screen->display, 7568 VShellWindow(xw), 7569 win_attrs.root, 7570 -win_attrs.border_width, 7571 -win_attrs.border_width, 7572 &result_x, &result_y, &result_win); 7573 TRACE(("translated position %d,%d vs %d,%d\n", 7574 result_y, result_x, 7575 win_attrs.y, win_attrs.x)); 7576 if (!discount_frame_extents(xw, &result_y, &result_x)) { 7577 TRACE(("...cancelled translation\n")); 7578 result_y = win_attrs.y; 7579 result_x = win_attrs.x; 7580 } 7581 break; 7582 } 7583 reply.a_param[1] = (ParmType) result_x; 7584 reply.a_param[2] = (ParmType) result_y; 7585 reply.a_inters = 0; 7586 reply.a_final = 't'; 7587 unparseseq(xw, &reply); 7588 } 7589 break; 7590 7591 case ewGetWinSizePixels: /* Report the window's size in pixels */ 7592 if (AllowWindowOps(xw, ewGetWinSizePixels)) { 7593 ParmType high = (ParmType) Height(screen); 7594 ParmType wide = (ParmType) Width(screen); 7595 7596 TRACE(("...get window size in pixels\n")); 7597 init_reply(ANSI_CSI); 7598 reply.a_pintro = 0; 7599 reply.a_nparam = 3; 7600 reply.a_param[0] = 4; 7601 switch (zero_if_default(1)) { 7602 case 2: /* report the shell-window's size */ 7603 xtermGetWinAttrs(screen->display, 7604 WMFrameWindow(xw), 7605 &win_attrs); 7606 high = (ParmType) win_attrs.height; 7607 wide = (ParmType) win_attrs.width; 7608 /* FALLTHRU */ 7609 default: 7610 reply.a_param[1] = high; 7611 reply.a_param[2] = wide; 7612 break; 7613 } 7614 reply.a_inters = 0; 7615 reply.a_final = 't'; 7616 unparseseq(xw, &reply); 7617 } 7618 break; 7619 7620#if OPT_MAXIMIZE 7621 case ewGetScreenSizePixels: /* Report the screen's size, in Pixels */ 7622 if (AllowWindowOps(xw, ewGetScreenSizePixels)) { 7623 TRACE(("...get screen size in pixels\n")); 7624 (void) QueryMaximize(xw, &root_width, &root_height); 7625 init_reply(ANSI_CSI); 7626 reply.a_pintro = 0; 7627 reply.a_nparam = 3; 7628 reply.a_param[0] = 5; 7629 reply.a_param[1] = (ParmType) root_height; 7630 reply.a_param[2] = (ParmType) root_width; 7631 reply.a_inters = 0; 7632 reply.a_final = 't'; 7633 unparseseq(xw, &reply); 7634 } 7635 break; 7636 case ewGetCharSizePixels: /* Report the font's size, in pixel */ 7637 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 7638 TRACE(("...get font size in pixels\n")); 7639 TRACE(("...using font size %dx%d\n", 7640 FontHeight(screen), 7641 FontWidth(screen))); 7642 init_reply(ANSI_CSI); 7643 reply.a_pintro = 0; 7644 reply.a_nparam = 3; 7645 reply.a_param[0] = 6; 7646 reply.a_param[1] = (ParmType) FontHeight(screen); 7647 reply.a_param[2] = (ParmType) FontWidth(screen); 7648 reply.a_inters = 0; 7649 reply.a_final = 't'; 7650 unparseseq(xw, &reply); 7651 } 7652 break; 7653#endif 7654 7655 case ewGetWinSizeChars: /* Report the text's size in characters */ 7656 if (AllowWindowOps(xw, ewGetWinSizeChars)) { 7657 TRACE(("...get window size in characters\n")); 7658 init_reply(ANSI_CSI); 7659 reply.a_pintro = 0; 7660 reply.a_nparam = 3; 7661 reply.a_param[0] = 8; 7662 reply.a_param[1] = (ParmType) MaxRows(screen); 7663 reply.a_param[2] = (ParmType) MaxCols(screen); 7664 reply.a_inters = 0; 7665 reply.a_final = 't'; 7666 unparseseq(xw, &reply); 7667 } 7668 break; 7669 7670#if OPT_MAXIMIZE 7671 case ewGetScreenSizeChars: /* Report the screen's size, in characters */ 7672 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 7673 TRACE(("...get screen size in characters\n")); 7674 TRACE(("...using font size %dx%d\n", 7675 FontHeight(screen), 7676 FontWidth(screen))); 7677 (void) QueryMaximize(xw, &root_width, &root_height); 7678 init_reply(ANSI_CSI); 7679 reply.a_pintro = 0; 7680 reply.a_nparam = 3; 7681 reply.a_param[0] = 9; 7682 reply.a_param[1] = (ParmType) (root_height 7683 / (unsigned) FontHeight(screen)); 7684 reply.a_param[2] = (ParmType) (root_width 7685 / (unsigned) FontWidth(screen)); 7686 reply.a_inters = 0; 7687 reply.a_final = 't'; 7688 unparseseq(xw, &reply); 7689 } 7690 break; 7691#endif 7692 7693 case ewGetIconTitle: /* Report the icon's label */ 7694 if (AllowWindowOps(xw, ewGetIconTitle)) { 7695 TRACE(("...get icon's label\n")); 7696 report_win_label(xw, 'L', label = get_icon_label(xw)); 7697 free(label); 7698 } 7699 break; 7700 7701 case ewGetWinTitle: /* Report the window's title */ 7702 if (AllowWindowOps(xw, ewGetWinTitle)) { 7703 TRACE(("...get window's label\n")); 7704 report_win_label(xw, 'l', label = get_window_label(xw)); 7705 free(label); 7706 } 7707 break; 7708 7709 case ewPushTitle: /* save the window's title(s) on stack */ 7710 if (AllowWindowOps(xw, ewPushTitle)) { 7711 SaveTitle *last = screen->save_title; 7712 SaveTitle *item = TypeCalloc(SaveTitle); 7713 7714 TRACE(("...push title onto stack\n")); 7715 if (item != 0) { 7716 switch (zero_if_default(1)) { 7717 case 0: 7718 item->iconName = get_icon_label(xw); 7719 item->windowName = get_window_label(xw); 7720 break; 7721 case 1: 7722 item->iconName = get_icon_label(xw); 7723 break; 7724 case 2: 7725 item->windowName = get_window_label(xw); 7726 break; 7727 } 7728 item->next = last; 7729 if (item->iconName == 0) { 7730 item->iconName = ((last == 0) 7731 ? get_icon_label(xw) 7732 : x_strdup(last->iconName)); 7733 } 7734 if (item->windowName == 0) { 7735 item->windowName = ((last == 0) 7736 ? get_window_label(xw) 7737 : x_strdup(last->windowName)); 7738 } 7739 screen->save_title = item; 7740 } 7741 } 7742 break; 7743 7744 case ewPopTitle: /* restore the window's title(s) from stack */ 7745 if (AllowWindowOps(xw, ewPopTitle)) { 7746 SaveTitle *item = screen->save_title; 7747 7748 TRACE(("...pop title off stack\n")); 7749 if (item != 0) { 7750 switch (zero_if_default(1)) { 7751 case 0: 7752 ChangeIconName(xw, item->iconName); 7753 ChangeTitle(xw, item->windowName); 7754 break; 7755 case 1: 7756 ChangeIconName(xw, item->iconName); 7757 break; 7758 case 2: 7759 ChangeTitle(xw, item->windowName); 7760 break; 7761 } 7762 screen->save_title = item->next; 7763 free(item->iconName); 7764 free(item->windowName); 7765 free(item); 7766 } 7767 } 7768 break; 7769 7770 default: /* DECSLPP (24, 25, 36, 48, 72, 144) */ 7771 if (AllowWindowOps(xw, ewSetWinLines)) { 7772 if (code >= 24) 7773 RequestResize(xw, code, -1, True); 7774 } 7775 break; 7776 } 7777} 7778 7779/* 7780 * set a bit in a word given a pointer to the word and a mask. 7781 */ 7782static int 7783bitset(unsigned *p, unsigned mask) 7784{ 7785 unsigned before = *p; 7786 *p |= mask; 7787 return (before != *p); 7788} 7789 7790/* 7791 * clear a bit in a word given a pointer to the word and a mask. 7792 */ 7793static int 7794bitclr(unsigned *p, unsigned mask) 7795{ 7796 unsigned before = *p; 7797 *p &= ~mask; 7798 return (before != *p); 7799} 7800 7801/* 7802 * Copy bits from one word to another, given a mask 7803 */ 7804static int 7805bitcpy(unsigned *p, unsigned q, unsigned mask) 7806{ 7807 unsigned before = *p; 7808 bitclr(p, mask); 7809 bitset(p, q & mask); 7810 return (before != *p); 7811} 7812 7813void 7814unparseputc1(XtermWidget xw, int c) 7815{ 7816 if (c >= 0x80 && c <= 0x9F) { 7817 if (!TScreenOf(xw)->control_eight_bits) { 7818 unparseputc(xw, A2E(ANSI_ESC)); 7819 c = A2E(c - 0x40); 7820 } 7821 } 7822 unparseputc(xw, c); 7823} 7824 7825void 7826unparseseq(XtermWidget xw, ANSI *ap) 7827{ 7828 int c; 7829 7830 assert(ap->a_nparam < NPARAM); 7831 unparseputc1(xw, c = ap->a_type); 7832 if (c == ANSI_ESC 7833 || c == ANSI_DCS 7834 || c == ANSI_CSI 7835 || c == ANSI_OSC 7836 || c == ANSI_PM 7837 || c == ANSI_APC 7838 || c == ANSI_SS3) { 7839 int i; 7840 int inters; 7841 char temp[8]; 7842 7843 if (ap->a_pintro != 0) 7844 unparseputc(xw, ap->a_pintro); 7845 for (i = 0; i < ap->a_nparam; ++i) { 7846 if (i != 0) { 7847 if (ap->a_radix[i] == 1 || ap->a_radix[i - 1] == 1) { 7848 ; 7849 } else if (ap->a_delim) { 7850 unparseputs(xw, ap->a_delim); 7851 } else { 7852 unparseputc(xw, ';'); 7853 } 7854 } 7855 switch (ap->a_radix[i]) { 7856 case 16: 7857 sprintf(temp, "%04X", ap->a_param[i] & 0xffff); 7858 unparseputs(xw, temp); 7859 break; 7860 case 1: 7861 unparseputc(xw, ap->a_param[i]); 7862 break; 7863 default: 7864 unparseputn(xw, (unsigned) (UParm) ap->a_param[i]); 7865 break; 7866 } 7867 } 7868 if ((inters = ap->a_inters) != 0) { 7869 for (i = 3; i >= 0; --i) { 7870 c = CharOf(inters >> (8 * i)); 7871 if (c != 0) 7872 unparseputc(xw, c); 7873 } 7874 } 7875 switch (ap->a_type) { 7876 case ANSI_DCS: 7877 /* FALLTHRU */ 7878 case ANSI_OSC: 7879 /* FALLTHRU */ 7880 case ANSI_PM: 7881 /* FALLTHRU */ 7882 case ANSI_APC: 7883 unparseputc1(xw, ANSI_ST); 7884 break; 7885 default: 7886 unparseputc(xw, (char) ap->a_final); 7887 break; 7888 } 7889 } 7890 unparse_end(xw); 7891} 7892 7893void 7894unparseputn(XtermWidget xw, unsigned n) 7895{ 7896 unsigned q; 7897 7898 q = n / 10; 7899 if (q != 0) 7900 unparseputn(xw, q); 7901 unparseputc(xw, (char) ('0' + (n % 10))); 7902} 7903 7904void 7905unparseputs(XtermWidget xw, const char *s) 7906{ 7907 if (s != 0) { 7908 while (*s) 7909 unparseputc(xw, *s++); 7910 } 7911} 7912 7913void 7914unparseputc(XtermWidget xw, int c) 7915{ 7916 TScreen *screen = TScreenOf(xw); 7917 IChar *buf = screen->unparse_bfr; 7918 unsigned len; 7919 7920 if ((screen->unparse_len + 2) >= screen->unparse_max) 7921 unparse_end(xw); 7922 7923 len = screen->unparse_len; 7924 7925#if OPT_TCAP_QUERY 7926 /* 7927 * If we're returning a termcap string, it has to be translated since 7928 * a DCS must not contain any characters except for the normal 7-bit 7929 * printable ASCII (counting tab, carriage return, etc). For now, 7930 * just use hexadecimal for the whole thing. 7931 */ 7932 if (screen->tc_query_code >= 0) { 7933 char tmp[3]; 7934 sprintf(tmp, "%02X", c & 0xFF); 7935 buf[len++] = CharOf(tmp[0]); 7936 buf[len++] = CharOf(tmp[1]); 7937 } else 7938#endif 7939 if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) { 7940 buf[len++] = '\n'; 7941 } 7942 7943 screen->unparse_len = len; 7944 7945 /* If send/receive mode is reset, we echo characters locally */ 7946 if ((xw->keyboard.flags & MODE_SRM) == 0) { 7947 doparsing(xw, (unsigned) c, &myState); 7948 } 7949} 7950 7951void 7952unparse_end(XtermWidget xw) 7953{ 7954 TScreen *screen = TScreenOf(xw); 7955 7956#if OPT_TCAP_QUERY 7957 /* 7958 * tcap-query works by simulating key-presses, which ordinarily would be 7959 * flushed out at the end of each key. For better efficiency, do not do 7960 * the flush unless we are about to fill the buffer used to capture the 7961 * response. 7962 */ 7963 if ((screen->tc_query_code >= 0) 7964 && (screen->unparse_len + 2 < screen->unparse_max)) { 7965 return; 7966 } 7967#endif 7968 if (screen->unparse_len) { 7969 TRACE(("unparse_end %u:%s\n", 7970 screen->unparse_len, 7971 visibleIChars(screen->unparse_bfr, screen->unparse_len))); 7972#ifdef VMS 7973 tt_write(screen->unparse_bfr, screen->unparse_len); 7974#else /* VMS */ 7975 writePtyData(screen->respond, screen->unparse_bfr, screen->unparse_len); 7976#endif /* VMS */ 7977 screen->unparse_len = 0; 7978 } 7979} 7980 7981void 7982ToggleAlternate(XtermWidget xw) 7983{ 7984 if (TScreenOf(xw)->whichBuf) 7985 FromAlternate(xw); 7986 else 7987 ToAlternate(xw, False); 7988} 7989 7990static void 7991ToAlternate(XtermWidget xw, Bool clearFirst) 7992{ 7993 TScreen *screen = TScreenOf(xw); 7994 7995 if (screen->whichBuf == 0) { 7996 TRACE(("ToAlternate\n")); 7997 if (!screen->editBuf_index[1]) 7998 screen->editBuf_index[1] = allocScrnBuf(xw, 7999 (unsigned) MaxRows(screen), 8000 (unsigned) MaxCols(screen), 8001 &screen->editBuf_data[1]); 8002 SwitchBufs(xw, 1, clearFirst); 8003#if OPT_SAVE_LINES 8004 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 8005#endif 8006 update_altscreen(); 8007 } 8008} 8009 8010static void 8011FromAlternate(XtermWidget xw) 8012{ 8013 TScreen *screen = TScreenOf(xw); 8014 8015 if (screen->whichBuf != 0) { 8016 TRACE(("FromAlternate\n")); 8017 if (screen->scroll_amt) 8018 FlushScroll(xw); 8019 SwitchBufs(xw, 0, False); 8020#if OPT_SAVE_LINES 8021 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 8022#endif 8023 update_altscreen(); 8024 } 8025} 8026 8027static void 8028SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst) 8029{ 8030 TScreen *screen = TScreenOf(xw); 8031 int rows, top; 8032 8033 screen->whichBuf = toBuf; 8034 if (screen->cursor_state) 8035 HideCursor(xw); 8036 8037 rows = MaxRows(screen); 8038 SwitchBufPtrs(screen, toBuf); 8039 8040 if ((top = INX2ROW(screen, 0)) < rows) { 8041 if (screen->scroll_amt) { 8042 FlushScroll(xw); 8043 } 8044 xtermClear2(xw, 8045 (int) OriginX(screen), 8046 (int) top * FontHeight(screen) + screen->border, 8047 (unsigned) Width(screen), 8048 (unsigned) ((rows - top) * FontHeight(screen))); 8049 if (clearFirst) { 8050 ClearBufRows(xw, top, rows); 8051 } 8052 } 8053 ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False); 8054} 8055 8056Bool 8057CheckBufPtrs(TScreen *screen) 8058{ 8059 return (screen->visbuf != 0 8060#if OPT_SAVE_LINES 8061 && screen->editBuf_index[0] != 0 8062#endif 8063 && screen->editBuf_index[1] != 0); 8064} 8065 8066/* 8067 * Swap buffer line pointers between alternate and regular screens. 8068 */ 8069void 8070SwitchBufPtrs(TScreen *screen, int toBuf) 8071{ 8072 if (CheckBufPtrs(screen)) { 8073#if OPT_SAVE_LINES 8074 screen->visbuf = screen->editBuf_index[toBuf]; 8075#else 8076 size_t len = ScrnPointers(screen, (size_t) MaxRows(screen)); 8077 8078 (void) toBuf; 8079 memcpy(screen->save_ptr, screen->visbuf, len); 8080 memcpy(screen->visbuf, screen->editBuf_index[1], len); 8081 memcpy(screen->editBuf_index[1], screen->save_ptr, len); 8082#endif 8083 } 8084} 8085 8086void 8087VTRun(XtermWidget xw) 8088{ 8089 TScreen *screen = TScreenOf(xw); 8090 8091 TRACE(("VTRun ...\n")); 8092 8093 if (!screen->Vshow) { 8094 set_vt_visibility(True); 8095 } 8096 update_vttekmode(); 8097 update_vtshow(); 8098 update_tekshow(); 8099 set_vthide_sensitivity(); 8100 8101 ScrnAllocBuf(xw); 8102 8103 screen->cursor_state = OFF; 8104 screen->cursor_set = ON; 8105#if OPT_BLINK_CURS 8106 if (DoStartBlinking(screen)) 8107 StartBlinking(xw); 8108#endif 8109 8110#if OPT_TEK4014 8111 if (Tpushb > Tpushback) { 8112 fillPtyData(xw, VTbuffer, (char *) Tpushback, (int) (Tpushb - Tpushback)); 8113 Tpushb = Tpushback; 8114 } 8115#endif 8116 screen->is_running = True; 8117 if (screen->embed_high && screen->embed_wide) { 8118 ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags)); 8119 } 8120#if OPT_MAXIMIZE 8121 else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways) 8122 FullScreen(xw, True); 8123#endif 8124 if (!setjmp(VTend)) 8125 VTparse(xw); 8126 StopBlinking(xw); 8127 HideCursor(xw); 8128 screen->cursor_set = OFF; 8129 TRACE(("... VTRun\n")); 8130} 8131 8132/*ARGSUSED*/ 8133static void 8134VTExpose(Widget w GCC_UNUSED, 8135 XEvent *event, 8136 Region region GCC_UNUSED) 8137{ 8138 DEBUG_MSG("Expose\n"); 8139 if (event->type == Expose) 8140 HandleExposure(term, event); 8141} 8142 8143static void 8144VTGraphicsOrNoExpose(XEvent *event) 8145{ 8146 XtermWidget xw = term; 8147 TScreen *screen = TScreenOf(xw); 8148 if (screen->incopy <= 0) { 8149 screen->incopy = 1; 8150 if (screen->scrolls > 0) 8151 screen->scrolls--; 8152 } 8153 if (event->type == GraphicsExpose) 8154 if (HandleExposure(xw, event)) 8155 screen->cursor_state = OFF; 8156 if ((event->type == NoExpose) 8157 || ((XGraphicsExposeEvent *) event)->count == 0) { 8158 if (screen->incopy <= 0 && screen->scrolls > 0) 8159 screen->scrolls--; 8160 if (screen->scrolls) 8161 screen->incopy = -1; 8162 else 8163 screen->incopy = 0; 8164 } 8165} 8166 8167/*ARGSUSED*/ 8168static void 8169VTNonMaskableEvent(Widget w GCC_UNUSED, 8170 XtPointer closure GCC_UNUSED, 8171 XEvent *event, 8172 Boolean *cont GCC_UNUSED) 8173{ 8174 switch (event->type) { 8175 case GraphicsExpose: 8176 /* FALLTHRU */ 8177 case NoExpose: 8178 VTGraphicsOrNoExpose(event); 8179 break; 8180 } 8181} 8182 8183static void 8184VTResize(Widget w) 8185{ 8186 if (XtIsRealized(w)) { 8187 XtermWidget xw = (XtermWidget) w; 8188 ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags); 8189 } 8190} 8191 8192#define okDimension(src,dst) ((src <= MAX_U_COORD) \ 8193 && ((dst = (Dimension) src) == src)) 8194 8195static void 8196RequestResize(XtermWidget xw, int rows, int cols, Bool text) 8197{ 8198 TScreen *screen = TScreenOf(xw); 8199 Dimension replyWidth, replyHeight; 8200 Dimension askedWidth, askedHeight; 8201 XtGeometryResult status; 8202 XWindowAttributes attrs; 8203#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8204 Boolean buggyXft = False; 8205 Cardinal ignore = 0; 8206#endif 8207 8208 TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text)); 8209 8210 /* check first if the row/column values fit into a Dimension */ 8211 if (cols > 0) { 8212 if ((int) (askedWidth = (Dimension) cols) < cols) { 8213 TRACE(("... cols too large for Dimension\n")); 8214 return; 8215 } 8216 } else { 8217 askedWidth = 0; 8218 } 8219 if (rows > 0) { 8220 if ((int) (askedHeight = (Dimension) rows) < rows) { 8221 TRACE(("... rows too large for Dimension\n")); 8222 return; 8223 } 8224 } else { 8225 askedHeight = 0; 8226 } 8227 8228 xw->work.doing_resize = True; 8229 8230#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8231 /* 8232 * Work around a bug seen when vttest switches from 132 columns back to 80 8233 * columns, while double-buffering is active. If Xft is active during the 8234 * resize, the screen will be blank thereafter. This workaround causes 8235 * some extra flickering, but that is preferable to a blank screen. 8236 * 8237 * Since the bitmap- and TrueType-fonts do not always have identical sizes, 8238 * do this switching early, to use the updated font-sizes in the request 8239 * for resizing the window. 8240 */ 8241#define ToggleXft() HandleRenderFont((Widget)xw, (XEvent *)0, (String *)0, &ignore) 8242 if (resource.buffered 8243 && UsingRenderFont(xw)) { 8244 ToggleXft(); 8245 buggyXft = True; 8246 } 8247#endif 8248 8249 /* 8250 * If the requested values will fit into a Dimension, and one or both are 8251 * zero, get the current corresponding screen dimension to use as a limit. 8252 */ 8253 if (askedHeight == 0 8254 || askedWidth == 0 8255 || xw->misc.limit_resize > 0) { 8256 xtermGetWinAttrs(XtDisplay(xw), 8257 RootWindowOfScreen(XtScreen(xw)), &attrs); 8258 } 8259 8260 /* 8261 * Using the current font metrics, translate the requested character 8262 * rows/columns into pixels. 8263 */ 8264 if (text) { 8265 unsigned long value; 8266 8267 if ((value = (unsigned long) rows) != 0) { 8268 if (rows < 0) 8269 value = (unsigned long) MaxRows(screen); 8270 value *= (unsigned long) FontHeight(screen); 8271 value += (unsigned long) (2 * screen->border); 8272 if (!okDimension(value, askedHeight)) 8273 goto give_up; 8274 } 8275 8276 if ((value = (unsigned long) cols) != 0) { 8277 if (cols < 0) 8278 value = (unsigned long) MaxCols(screen); 8279 value *= (unsigned long) FontWidth(screen); 8280 value += (unsigned long) ((2 * screen->border) 8281 + ScrollbarWidth(screen)); 8282 if (!okDimension(value, askedWidth)) 8283 goto give_up; 8284 } 8285 8286 } else { 8287 if (rows < 0) 8288 askedHeight = FullHeight(screen); 8289 if (cols < 0) 8290 askedWidth = FullWidth(screen); 8291 } 8292 8293 if (rows == 0) { 8294 askedHeight = (Dimension) attrs.height; 8295 } 8296 if (cols == 0) { 8297 askedWidth = (Dimension) attrs.width; 8298 } 8299 8300 if (xw->misc.limit_resize > 0) { 8301 Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height); 8302 Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width); 8303 if ((int) high < attrs.height) 8304 high = (Dimension) attrs.height; 8305 if (askedHeight > high) 8306 askedHeight = high; 8307 if ((int) wide < attrs.width) 8308 wide = (Dimension) attrs.width; 8309 if (askedWidth > wide) 8310 askedWidth = wide; 8311 } 8312#ifndef nothack 8313 getXtermSizeHints(xw); 8314#endif 8315 8316 TRACE(("...requesting resize %dx%d\n", askedHeight, askedWidth)); 8317 status = REQ_RESIZE((Widget) xw, 8318 askedWidth, askedHeight, 8319 &replyWidth, &replyHeight); 8320 8321 if (status == XtGeometryYes || 8322 status == XtGeometryDone) { 8323 ScreenResize(xw, replyWidth, replyHeight, &xw->flags); 8324 } 8325#ifndef nothack 8326 /* 8327 * XtMakeResizeRequest() has the undesirable side-effect of clearing 8328 * the window manager's hints, even on a failed request. This would 8329 * presumably be fixed if the shell did its own work. 8330 */ 8331 if (xw->hints.flags 8332 && replyHeight 8333 && replyWidth) { 8334 xw->hints.height = replyHeight; 8335 xw->hints.width = replyWidth; 8336 8337 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 8338 TRACE_HINTS(&xw->hints); 8339 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints); 8340 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 8341 TRACE_WM_HINTS(xw); 8342 } 8343#endif 8344 8345 XSync(screen->display, False); /* synchronize */ 8346 if (xtermAppPending()) { 8347 xevents(xw); 8348 } 8349 8350 give_up: 8351#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8352 if (buggyXft) { 8353 ToggleXft(); 8354 if (xtermAppPending()) { 8355 xevents(xw); 8356 } 8357 } 8358#endif 8359 8360 xw->work.doing_resize = False; 8361 8362 TRACE(("...RequestResize done\n")); 8363 return; 8364} 8365 8366static String xterm_trans = 8367"<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\ 8368 <MappingNotify>: KeyboardMapping()\n"; 8369 8370int 8371VTInit(XtermWidget xw) 8372{ 8373 Widget vtparent = SHELL_OF(xw); 8374 8375 TRACE(("VTInit " TRACE_L "\n")); 8376 8377 XtRealizeWidget(vtparent); 8378 XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans)); 8379 (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent), 8380 &wm_delete_window, 1); 8381 8382 if (IsEmpty(xw->keyboard.print_translations)) { 8383 TRACE_TRANS("shell", vtparent); 8384 TRACE_TRANS("vt100", (Widget) (xw)); 8385 xtermButtonInit(xw); 8386 } 8387 8388 ScrnAllocBuf(xw); 8389 8390 TRACE(("..." TRACE_R " VTInit\n")); 8391 return (1); 8392} 8393 8394static void 8395VTClassInit(void) 8396{ 8397 XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, 8398 (XtConvertArgList) NULL, (Cardinal) 0); 8399} 8400 8401#if OPT_COLOR_RES 8402/* 8403 * Override the use of XtDefaultForeground/XtDefaultBackground to make some 8404 * colors, such as cursor color, use the actual foreground/background value 8405 * if there is no explicit resource value used. 8406 */ 8407static Pixel 8408fill_Tres(XtermWidget target, XtermWidget source, int offset) 8409{ 8410 char *name; 8411 ScrnColors temp; 8412 TScreen *src = TScreenOf(source); 8413 TScreen *dst = TScreenOf(target); 8414 8415 dst->Tcolors[offset] = src->Tcolors[offset]; 8416 dst->Tcolors[offset].mode = False; 8417 8418 if ((name = x_strtrim(dst->Tcolors[offset].resource)) != 0) 8419 dst->Tcolors[offset].resource = name; 8420 8421 if (name == 0) { 8422 dst->Tcolors[offset].value = target->dft_foreground; 8423 } else if (isDefaultForeground(name)) { 8424 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 8425 ? target->dft_foreground 8426 : dst->Tcolors[TEXT_FG].value); 8427 } else if (isDefaultBackground(name)) { 8428 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 8429 ? target->dft_background 8430 : dst->Tcolors[TEXT_BG].value); 8431 } else { 8432 memset(&temp, 0, sizeof(temp)); 8433 if (AllocateTermColor(target, &temp, offset, name, True)) { 8434 if (COLOR_DEFINED(&(temp), offset)) 8435 free(temp.names[offset]); 8436 dst->Tcolors[offset].value = temp.colors[offset]; 8437 } else if (offset == TEXT_FG || offset == TEXT_BG) { 8438 free(name); 8439 dst->Tcolors[offset].resource = 0; 8440 } 8441 } 8442 return dst->Tcolors[offset].value; 8443} 8444 8445/* 8446 * If one or both of the foreground/background colors cannot be allocated, 8447 * e.g., due to gross misconfiguration, recover by setting both to the 8448 * display's default values. 8449 */ 8450static void 8451repairColors(XtermWidget target) 8452{ 8453 TScreen *screen = TScreenOf(target); 8454 8455 if (screen->Tcolors[TEXT_FG].resource == 0 || 8456 screen->Tcolors[TEXT_BG].resource == 0) { 8457 xtermWarning("unable to allocate fg/bg colors\n"); 8458 screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground); 8459 screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground); 8460 if (screen->Tcolors[TEXT_FG].resource == 0 || 8461 screen->Tcolors[TEXT_BG].resource == 0) { 8462 Exit(1); 8463 } 8464 screen->Tcolors[TEXT_FG].value = target->dft_foreground; 8465 screen->Tcolors[TEXT_BG].value = target->dft_background; 8466 } 8467} 8468#else 8469#define fill_Tres(target, source, offset) \ 8470 TScreenOf(target)->Tcolors[offset] = TScreenOf(source)->Tcolors[offset] 8471#define repairColors(target) /* nothing */ 8472#endif 8473 8474#if OPT_WIDE_CHARS 8475static void 8476set_utf8_feature(TScreen *screen, int *feature) 8477{ 8478 if (*feature == uDefault) { 8479 switch (screen->utf8_mode) { 8480 case uFalse: 8481 /* FALLTHRU */ 8482 case uTrue: 8483 *feature = screen->utf8_mode; 8484 break; 8485 case uDefault: 8486 /* should not happen */ 8487 *feature = uTrue; 8488 break; 8489 case uAlways: 8490 /* use this to disable menu entry */ 8491 break; 8492 } 8493 } 8494} 8495 8496static void 8497VTInitialize_locale(XtermWidget xw) 8498{ 8499 TScreen *screen = TScreenOf(xw); 8500 Bool is_utf8 = xtermEnvUTF8(); 8501 8502 TRACE(("VTInitialize_locale\n")); 8503 TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode)); 8504 TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts)); 8505 TRACE(("... request screen.utf8_title = %d\n", screen->utf8_title)); 8506 8507 screen->utf8_always = (screen->utf8_mode == uAlways); 8508 if (screen->utf8_mode < 0) 8509 screen->utf8_mode = uFalse; 8510 8511 if (screen->utf8_mode > 3) 8512 screen->utf8_mode = uDefault; 8513 8514 screen->latin9_mode = 0; 8515 screen->unicode_font = 0; 8516#if OPT_LUIT_PROG 8517 xw->misc.callfilter = 0; 8518 xw->misc.use_encoding = 0; 8519 8520 TRACE(("... setup for luit:\n")); 8521 TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str)); 8522 8523 if (screen->utf8_mode == uFalse) { 8524 TRACE(("... command-line +u8 overrides\n")); 8525 } else 8526#if OPT_MINI_LUIT 8527 if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) { 8528 int fl = (int) strlen(DefaultFontN(xw)); 8529 if (fl > 11 8530 && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) { 8531 screen->unicode_font = 1; 8532 /* unicode font, use True */ 8533#ifdef HAVE_LANGINFO_CODESET 8534 if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968") 8535 || !strcmp(xtermEnvEncoding(), "ISO-8859-1")) { 8536 if (screen->utf8_mode == uDefault) 8537 screen->utf8_mode = uFalse; 8538 } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) { 8539 if (screen->utf8_mode == uDefault) 8540 screen->utf8_mode = uFalse; 8541 screen->latin9_mode = 1; 8542 } else { 8543 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 8544 screen->utf8_mode = uAlways; 8545 } 8546#else 8547 xw->misc.callfilter = is_utf8 ? 0 : 1; 8548 screen->utf8_mode = uAlways; 8549#endif 8550 } else { 8551 /* other encoding, use False */ 8552 if (screen->utf8_mode == uDefault) { 8553 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 8554 } 8555 } 8556 } else 8557#endif /* OPT_MINI_LUIT */ 8558 if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 || 8559 x_strcasecmp(xw->misc.locale_str, "ON") == 0 || 8560 x_strcasecmp(xw->misc.locale_str, "YES") == 0 || 8561 x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 || 8562 strcmp(xw->misc.locale_str, "1") == 0) { 8563 /* when true ... fully obeying LC_CTYPE locale */ 8564 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 8565 screen->utf8_mode = uAlways; 8566 } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 || 8567 x_strcasecmp(xw->misc.locale_str, "OFF") == 0 || 8568 x_strcasecmp(xw->misc.locale_str, "NO") == 0 || 8569 strcmp(xw->misc.locale_str, "0") == 0) { 8570 /* when false ... original value of utf8_mode is effective */ 8571 if (screen->utf8_mode == uDefault) { 8572 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 8573 } 8574 } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 || 8575 x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) { 8576 /* when medium ... obeying locale only for UTF-8 and Asian */ 8577 if (is_utf8) { 8578 screen->utf8_mode = uAlways; 8579 } else if ( 8580#ifdef MB_CUR_MAX 8581 MB_CUR_MAX > 1 || 8582#else 8583 !strncmp(xtermEnvLocale(), "ja", (size_t) 2) || 8584 !strncmp(xtermEnvLocale(), "ko", (size_t) 2) || 8585 !strncmp(xtermEnvLocale(), "zh", (size_t) 2) || 8586#endif 8587 !strncmp(xtermEnvLocale(), "th", (size_t) 2) || 8588 !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) { 8589 xw->misc.callfilter = 1; 8590 screen->utf8_mode = uAlways; 8591 } else { 8592 screen->utf8_mode = uFalse; 8593 } 8594 } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 || 8595 x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) { 8596 /* when UTF-8 ... UTF-8 mode */ 8597 screen->utf8_mode = uAlways; 8598 } else { 8599 /* other words are regarded as encoding name passed to luit */ 8600 xw->misc.callfilter = 1; 8601 screen->utf8_mode = uAlways; 8602 xw->misc.use_encoding = 1; 8603 } 8604 TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter))); 8605 TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding))); 8606#else 8607 if (screen->utf8_mode == uDefault) { 8608 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 8609 } 8610#endif /* OPT_LUIT_PROG */ 8611 8612 set_utf8_feature(screen, &screen->utf8_fonts); 8613 set_utf8_feature(screen, &screen->utf8_title); 8614 8615 screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse); 8616 8617 TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode)); 8618 TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts)); 8619 TRACE(("... updated screen.utf8_title = %d\n", screen->utf8_title)); 8620 TRACE(("...VTInitialize_locale done\n")); 8621} 8622#endif 8623 8624void 8625lookupSelectUnit(XtermWidget xw, Cardinal item, String value) 8626{ 8627 /* *INDENT-OFF* */ 8628 static const struct { 8629 const char * name; 8630 SelectUnit code; 8631 } table[] = { 8632 { "char", Select_CHAR }, 8633 { "word", Select_WORD }, 8634 { "line", Select_LINE }, 8635 { "group", Select_GROUP }, 8636 { "page", Select_PAGE }, 8637 { "all", Select_ALL }, 8638#if OPT_SELECT_REGEX 8639 { "regex", Select_REGEX }, 8640#endif 8641 }; 8642 /* *INDENT-ON* */ 8643 8644 TScreen *screen = TScreenOf(xw); 8645 String next = x_skip_nonblanks(value); 8646 Cardinal n; 8647 8648 screen->selectMap[item] = NSELECTUNITS; 8649 for (n = 0; n < XtNumber(table); ++n) { 8650 if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) { 8651 screen->selectMap[item] = table[n].code; 8652#if OPT_SELECT_REGEX 8653 if (table[n].code == Select_REGEX) { 8654 screen->selectExpr[item] = x_strtrim(next); 8655 TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item])); 8656 } 8657#endif 8658 break; 8659 } 8660 } 8661} 8662 8663static void 8664ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item) 8665{ 8666 lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]); 8667} 8668 8669/* 8670 * Parse a comma-separated list, returning a string which the caller must 8671 * free, and updating the source pointer. 8672 */ 8673static char * 8674ParseList(const char **source) 8675{ 8676 const char *base = *source; 8677 const char *next; 8678 char *value = 0; 8679 char *result; 8680 8681 /* ignore empty values */ 8682 while (*base == ',') 8683 ++base; 8684 8685 if (*base != '\0') { 8686 size_t size; 8687 8688 next = base; 8689 while (*next != '\0' && *next != ',') 8690 ++next; 8691 size = (size_t) (1 + next - base); 8692 value = malloc(size); 8693 if (value != 0) { 8694 memcpy(value, base, size); 8695 value[size - 1] = '\0'; 8696 } 8697 *source = next; 8698 } else { 8699 *source = base; 8700 } 8701 result = x_strtrim(value); 8702 free(value); 8703 return result; 8704} 8705 8706static void 8707set_flags_from_list(char *target, 8708 const char *source, 8709 const FlagList * list) 8710{ 8711 Cardinal n; 8712 8713 while (!IsEmpty(source)) { 8714 char *next = ParseList(&source); 8715 Boolean found = False; 8716 char flag = 1; 8717 8718 if (next == 0) 8719 break; 8720 if (*next == '~') { 8721 flag = 0; 8722 next++; 8723 } 8724 if (isdigit(CharOf(*next))) { 8725 char *temp; 8726 int value = (int) strtol(next, &temp, 0); 8727 if (!FullS2L(next, temp)) { 8728 xtermWarning("Expected a number: %s\n", next); 8729 } else { 8730 for (n = 0; list[n].name != 0; ++n) { 8731 if (list[n].code == value) { 8732 target[value] = flag; 8733 found = True; 8734 TRACE(("...found %s (%d)\n", list[n].name, value)); 8735 break; 8736 } 8737 } 8738 } 8739 } else { 8740 for (n = 0; list[n].name != 0; ++n) { 8741 if (!x_wildstrcmp(next, list[n].name)) { 8742 int value = list[n].code; 8743 target[value] = flag; 8744 found = True; 8745 TRACE(("...found %s (%d)\n", list[n].name, value)); 8746 } 8747 } 8748 } 8749 if (!found) { 8750 xtermWarning("Unrecognized keyword: %s\n", next); 8751 } 8752 free(next); 8753 } 8754} 8755 8756#define InitCursorShape(target, source) \ 8757 target->cursor_shape = source->cursor_underline \ 8758 ? CURSOR_UNDERLINE \ 8759 : CURSOR_BLOCK 8760 8761#if OPT_XRES_QUERY 8762static XtResource * 8763findVT100Resource(const char *name) 8764{ 8765 Cardinal n; 8766 XtResource *result = 0; 8767 8768 if (!IsEmpty(name)) { 8769 XrmQuark quarkName = XrmPermStringToQuark(name); 8770 for (n = 0; n < XtNumber(xterm_resources); ++n) { 8771 if ((int) xterm_resources[n].resource_offset >= 0 8772 && !strcmp(xterm_resources[n].resource_name, name)) { 8773 result = &xterm_resources[n]; 8774 break; 8775 } else if (xterm_resources[n].resource_name 8776 == (String) (intptr_t) quarkName) { 8777 result = &xterm_resources[n]; 8778 break; 8779 } 8780 } 8781 } 8782 return result; 8783} 8784 8785static int 8786cmp_resources(const void *a, const void *b) 8787{ 8788 return strcmp((*(const String *) a), 8789 (*(const String *) b)); 8790} 8791 8792static void 8793reportResources(XtermWidget xw) 8794{ 8795 String *list = TypeMallocN(String, XtNumber(xterm_resources)); 8796 Cardinal n; 8797 int widest = 0; 8798 8799 if (list == NULL) 8800 return; 8801 8802 for (n = 0; n < XtNumber(xterm_resources); ++n) { 8803 int width; 8804 list[n] = (((int) xterm_resources[n].resource_offset < 0) 8805 ? XrmQuarkToString((XrmQuark) (intptr_t) 8806 xterm_resources[n].resource_name) 8807 : xterm_resources[n].resource_name); 8808 width = (int) strlen(list[n]); 8809 if (widest < width) 8810 widest = width; 8811 } 8812 qsort(list, (size_t) XtNumber(xterm_resources), sizeof(String), cmp_resources); 8813 for (n = 0; n < XtNumber(xterm_resources); ++n) { 8814 char *value = vt100ResourceToString(xw, list[n]); 8815 printf("%-*s : %s\n", widest, list[n], value ? value : "(skip)"); 8816 free(value); 8817 } 8818 free(list); 8819} 8820 8821char * 8822vt100ResourceToString(XtermWidget xw, const char *name) 8823{ 8824 XtResource *data; 8825 char *result = NULL; 8826 8827 if ((data = findVT100Resource(name)) != 0) { 8828 int fake_offset = (int) data->resource_offset; 8829 void *res_addr; 8830 int real_offset; 8831 String res_type; 8832 8833 /* 8834 * X Toolkit "compiles" the resource-list into quarks and changes the 8835 * resource-offset at the same time to a negative value. 8836 */ 8837 if (fake_offset < 0) { 8838 real_offset = -(fake_offset + 1); 8839 res_type = XrmQuarkToString((XrmQuark) (intptr_t) data->resource_type); 8840 } else { 8841 real_offset = fake_offset; 8842 res_type = data->resource_type; 8843 } 8844 res_addr = (void *) ((char *) xw + real_offset); 8845 8846 if (!strcmp(res_type, XtRString)) { 8847 char *value = *(char **) res_addr; 8848 if (value != NULL) { 8849 size_t need = strlen(value); 8850 if ((result = malloc(1 + need)) != 0) 8851 strcpy(result, value); 8852 } 8853 } else if (!strcmp(res_type, XtRInt)) { 8854 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0) 8855 sprintf(result, "%d", *(int *) res_addr); 8856 } else if (!strcmp(res_type, XtRFloat)) { 8857 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0) 8858 sprintf(result, "%f", (double) (*(float *) res_addr)); 8859 } else if (!strcmp(res_type, XtRBoolean)) { 8860 if ((result = malloc((size_t) 6)) != 0) 8861 strcpy(result, *(Boolean *) res_addr ? "true" : "false"); 8862 } 8863 } 8864 TRACE(("vt100ResourceToString(%s) %s\n", name, NonNull(result))); 8865 return result; 8866} 8867#endif /* OPT_XRES_QUERY */ 8868 8869/* 8870 * Decode a terminal-ID or graphics-terminal-ID, using the default terminal-ID 8871 * if the value is outside a (looser) range than limitedTerminalID. This uses 8872 * a wider range, to avoid being a nuisance when using X resources with 8873 * different configurations of xterm. 8874 */ 8875static int 8876decodeTerminalID(const char *value) 8877{ 8878 const char *s; 8879 char *t; 8880 long result; 8881 8882 for (s = value; *s; s++) { 8883 if (!isalpha(CharOf(*s))) 8884 break; 8885 } 8886 result = strtol(s, &t, 10); 8887 if (t == s || *t != '\0' || result <= 0L || result > 1000L) { 8888 xtermWarning("unexpected value for terminalID: \"%s\"\n", value); 8889 result = atoi(DFT_DECID); 8890 } 8891 TRACE(("decodeTerminalID \"%s\" ->%d\n", value, (int) result)); 8892 return (int) result; 8893} 8894 8895/* 8896 * Ensures that the value returned by decodeTerminalID is either in the range 8897 * of IDs matching a known terminal, or (failing that), set to the built-in 8898 * default. The DA response relies on having the ID being set to a known 8899 * value. 8900 */ 8901static int 8902limitedTerminalID(int terminal_id) 8903{ 8904 if (terminal_id < MIN_DECID) 8905 terminal_id = MIN_DECID; 8906 else if (terminal_id > MAX_DECID) 8907 terminal_id = MAX_DECID; 8908 else 8909 terminal_id = atoi(DFT_DECID); 8910 return terminal_id; 8911} 8912 8913/* ARGSUSED */ 8914static void 8915VTInitialize(Widget wrequest, 8916 Widget new_arg, 8917 ArgList args GCC_UNUSED, 8918 Cardinal *num_args GCC_UNUSED) 8919{ 8920#define Kolor(name) TScreenOf(wnew)->name.resource 8921#define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name)) 8922#define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name)) 8923#define DftFg(name) isDefaultForeground(Kolor(name)) 8924#define DftBg(name) isDefaultBackground(Kolor(name)) 8925 8926#define DATA_END { NULL, -1 } 8927 8928#if OPT_BLINK_CURS 8929#define DATA(name) { #name, cb##name } 8930 static const FlagList tblBlinkOps[] = 8931 { 8932 DATA(Always) 8933 ,DATA(Never) 8934 ,DATA_END 8935 }; 8936#undef DATA 8937#endif 8938 8939#define DATA(name) { #name, ec##name } 8940 static const FlagList tblColorOps[] = 8941 { 8942 DATA(SetColor) 8943 ,DATA(GetColor) 8944 ,DATA(GetAnsiColor) 8945 ,DATA_END 8946 }; 8947#undef DATA 8948 8949#define DATA(name) { #name, ef##name } 8950 static const FlagList tblFontOps[] = 8951 { 8952 DATA(SetFont) 8953 ,DATA(GetFont) 8954 ,DATA_END 8955 }; 8956#undef DATA 8957 8958#define DATA(name) { #name, em##name } 8959 static const FlagList tblMouseOps[] = 8960 { 8961 DATA(X10) 8962 ,DATA(Locator) 8963 ,DATA(VT200Click) 8964 ,DATA(VT200Hilite) 8965 ,DATA(AnyButton) 8966 ,DATA(AnyEvent) 8967 ,DATA(FocusEvent) 8968 ,DATA(Extended) 8969 ,DATA(SGR) 8970 ,DATA(URXVT) 8971 ,DATA(AlternateScroll) 8972 ,DATA_END 8973 }; 8974#undef DATA 8975 8976#define DATA(name) { #name, ep##name } 8977#define DATA2(alias,name) { #alias, ep##name } 8978 static const FlagList tblPasteControls[] = 8979 { 8980 DATA(NUL) 8981 ,DATA(SOH) 8982 ,DATA(STX) 8983 ,DATA(ETX) 8984 ,DATA(EOT) 8985 ,DATA(ENQ) 8986 ,DATA(ACK) 8987 ,DATA(BEL) 8988 ,DATA(BS) 8989 ,DATA(HT) 8990 ,DATA(LF) 8991 ,DATA(VT) 8992 ,DATA(FF) 8993 ,DATA(CR) 8994 ,DATA(SO) 8995 ,DATA(SI) 8996 ,DATA(DLE) 8997 ,DATA(DC1) 8998 ,DATA(DC2) 8999 ,DATA(DC3) 9000 ,DATA(DC4) 9001 ,DATA(NAK) 9002 ,DATA(SYN) 9003 ,DATA(ETB) 9004 ,DATA(CAN) 9005 ,DATA(EM) 9006 ,DATA(SUB) 9007 ,DATA(ESC) 9008 ,DATA(FS) 9009 ,DATA(GS) 9010 ,DATA(RS) 9011 ,DATA(US) 9012 /* aliases */ 9013 ,DATA2(NL, LF) 9014 ,DATA(C0) 9015 ,DATA(DEL) 9016 ,DATA_END 9017 }; 9018#undef DATA 9019#undef DATA2 9020 9021#define DATA(name) { #name, et##name } 9022 static const FlagList tblTcapOps[] = 9023 { 9024 DATA(SetTcap) 9025 ,DATA(GetTcap) 9026 ,DATA_END 9027 }; 9028#undef DATA 9029 9030#define DATA(name) { #name, ew##name } 9031 static const FlagList tblWindowOps[] = 9032 { 9033 DATA(RestoreWin) 9034 ,DATA(MinimizeWin) 9035 ,DATA(SetWinPosition) 9036 ,DATA(SetWinSizePixels) 9037 ,DATA(RaiseWin) 9038 ,DATA(LowerWin) 9039 ,DATA(RefreshWin) 9040 ,DATA(SetWinSizeChars) 9041#if OPT_MAXIMIZE 9042 ,DATA(MaximizeWin) 9043 ,DATA(FullscreenWin) 9044#endif 9045 ,DATA(GetWinState) 9046 ,DATA(GetWinPosition) 9047 ,DATA(GetWinSizePixels) 9048 ,DATA(GetWinSizeChars) 9049#if OPT_MAXIMIZE 9050 ,DATA(GetScreenSizeChars) 9051#endif 9052 ,DATA(GetIconTitle) 9053 ,DATA(GetWinTitle) 9054 ,DATA(PushTitle) 9055 ,DATA(PopTitle) 9056 /* this item uses all remaining numbers in the sequence */ 9057 ,DATA(SetWinLines) 9058 /* starting at this point, numbers do not apply */ 9059 ,DATA(SetXprop) 9060 ,DATA(GetSelection) 9061 ,DATA(SetSelection) 9062 ,DATA(GetChecksum) 9063 ,DATA(SetChecksum) 9064 ,DATA_END 9065 }; 9066#undef DATA 9067 9068#if OPT_RENDERFONT 9069#define DATA(name) { #name, er##name } 9070 static const FlagList tblRenderFont[] = 9071 { 9072 DATA(Default) 9073 ,DATA(DefaultOff) 9074 ,DATA_END 9075 }; 9076#undef DATA 9077#endif 9078 9079#define DATA(name) { #name, ss##name } 9080 static const FlagList tblShift2S[] = 9081 { 9082 DATA(Always) 9083 ,DATA(Never) 9084 ,DATA_END 9085 }; 9086#undef DATA 9087 9088#if OPT_WIDE_CHARS 9089#define DATA(name) { #name, u##name } 9090 static const FlagList tblUtf8Mode[] = 9091 { 9092 DATA(Always) 9093 ,DATA(Default) 9094 ,DATA_END 9095 }; 9096#undef DATA 9097#endif 9098 9099#ifndef NO_ACTIVE_ICON 9100#define DATA(name) { #name, ei##name } 9101 static const FlagList tblAIconOps[] = 9102 { 9103 DATA(Default) 9104 ,DATA_END 9105 }; 9106#undef DATA 9107#endif 9108 9109#define DATA(name) { #name, eb##name } 9110 static const FlagList tbl8BitMeta[] = 9111 { 9112 DATA(Never) 9113 ,DATA(Locale) 9114 ,DATA_END 9115 }; 9116#undef DATA 9117 9118 XtermWidget request = (XtermWidget) wrequest; 9119 XtermWidget wnew = (XtermWidget) new_arg; 9120 Widget my_parent = SHELL_OF(wnew); 9121 int i; 9122 9123#if OPT_ISO_COLORS 9124 Bool color_ok; 9125#endif 9126 9127#if OPT_ISO_COLORS && OPT_COLOR_RES2 9128 static XtResource fake_resources[] = 9129 { 9130#if OPT_256_COLORS 9131# include <256colres.h> 9132#elif OPT_88_COLORS 9133# include <88colres.h> 9134#endif 9135 }; 9136#endif /* OPT_COLOR_RES2 */ 9137 TScreen *screen = TScreenOf(wnew); 9138 char *saveLocale = xtermSetLocale(LC_NUMERIC, "C"); 9139#if OPT_BLINK_CURS 9140 int ebValue; 9141#endif 9142 9143#if OPT_TRACE 9144 check_bitmasks(); 9145 check_tables(); 9146#endif 9147 9148 TRACE(("VTInitialize wnew %p, %d / %d resources " TRACE_L "\n", 9149 (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES)); 9150 assert(XtNumber(xterm_resources) < MAXRESOURCES); 9151 9152 /* Zero out the entire "screen" component of "wnew" widget, then do 9153 * field-by-field assignment of "screen" fields that are named in the 9154 * resource list. 9155 */ 9156 memset(screen, 0, sizeof(wnew->screen)); 9157 9158 /* DESCO Sys#67660 9159 * Zero out the entire "keyboard" component of "wnew" widget. 9160 */ 9161 memset(&wnew->keyboard, 0, sizeof(wnew->keyboard)); 9162 9163 /* 9164 * The workspace has no resources - clear it. 9165 */ 9166 memset(&wnew->work, 0, sizeof(wnew->work)); 9167 9168 /* dummy values so that we don't try to Realize the parent shell with height 9169 * or width of 0, which is illegal in X. The real size is computed in the 9170 * xtermWidget's Realize proc, but the shell's Realize proc is called first, 9171 * and must see a valid size. 9172 */ 9173 wnew->core.height = wnew->core.width = 1; 9174 9175 /* 9176 * The definition of -rv now is that it changes the definition of 9177 * XtDefaultForeground and XtDefaultBackground. So, we no longer 9178 * need to do anything special. 9179 */ 9180 screen->display = wnew->core.screen->display; 9181 9182 /* prep getVisualInfo() */ 9183 wnew->visInfo = 0; 9184 wnew->numVisuals = 0; 9185 (void) getVisualInfo(wnew); 9186 9187 /* 9188 * We use the default foreground/background colors to compare/check if a 9189 * color-resource has been set. 9190 */ 9191#define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy)) 9192#define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy)) 9193 9194 if (request->misc.re_verse) { 9195 wnew->dft_foreground = MyWhitePixel(screen->display); 9196 wnew->dft_background = MyBlackPixel(screen->display); 9197 } else { 9198 wnew->dft_foreground = MyBlackPixel(screen->display); 9199 wnew->dft_background = MyWhitePixel(screen->display); 9200 } 9201 9202 init_Tres(TEXT_FG); 9203 init_Tres(TEXT_BG); 9204 repairColors(wnew); 9205 9206 wnew->old_foreground = T_COLOR(screen, TEXT_FG); 9207 wnew->old_background = T_COLOR(screen, TEXT_BG); 9208 9209 TRACE(("Color resource initialization:\n")); 9210 TRACE((" Default foreground 0x%06lx\n", wnew->dft_foreground)); 9211 TRACE((" Default background 0x%06lx\n", wnew->dft_background)); 9212 TRACE((" Screen foreground 0x%06lx\n", T_COLOR(screen, TEXT_FG))); 9213 TRACE((" Screen background 0x%06lx\n", T_COLOR(screen, TEXT_BG))); 9214 TRACE((" Actual foreground 0x%06lx\n", wnew->old_foreground)); 9215 TRACE((" Actual background 0x%06lx\n", wnew->old_background)); 9216 9217 screen->mouse_button = 0; 9218 screen->mouse_row = -1; 9219 screen->mouse_col = -1; 9220 9221#if OPT_BOX_CHARS 9222 init_Bres(screen.force_box_chars); 9223 init_Bres(screen.force_packed); 9224 init_Bres(screen.force_all_chars); 9225 init_Bres(screen.assume_all_chars); 9226#endif 9227 init_Bres(screen.free_bold_box); 9228 init_Bres(screen.allowBoldFonts); 9229 9230 init_Bres(screen.c132); 9231 init_Bres(screen.curses); 9232 init_Bres(screen.hp_ll_bc); 9233#if OPT_XMC_GLITCH 9234 init_Ires(screen.xmc_glitch); 9235 init_Ires(screen.xmc_attributes); 9236 init_Bres(screen.xmc_inline); 9237 init_Bres(screen.move_sgr_ok); 9238#endif 9239#if OPT_BLINK_CURS 9240 init_Sres(screen.cursor_blink_s); 9241 ebValue = extendedBoolean(wnew->screen.cursor_blink_s, tblBlinkOps, cbLAST); 9242 wnew->screen.cursor_blink = (BlinkOps) ebValue; 9243 init_Bres(screen.cursor_blink_xor); 9244 init_Ires(screen.blink_on); 9245 init_Ires(screen.blink_off); 9246 screen->cursor_blink_i = screen->cursor_blink; 9247#endif 9248 init_Bres(screen.cursor_underline); 9249 /* resources allow for underline or block, not (yet) bar */ 9250 InitCursorShape(screen, TScreenOf(request)); 9251#if OPT_BLINK_CURS 9252 TRACE(("cursor_shape:%d blinks:%d\n", 9253 screen->cursor_shape, 9254 screen->cursor_blink)); 9255#endif 9256#if OPT_BLINK_TEXT 9257 init_Ires(screen.blink_as_bold); 9258#endif 9259 init_Ires(screen.border); 9260 init_Bres(screen.jumpscroll); 9261 init_Bres(screen.fastscroll); 9262 9263 init_Bres(screen.old_fkeys); 9264 wnew->screen.old_fkeys0 = wnew->screen.old_fkeys; 9265 wnew->keyboard.type = screen->old_fkeys 9266 ? keyboardIsLegacy 9267 : keyboardIsDefault; 9268 9269 init_Mres(screen.delete_is_del); 9270#ifdef ALLOWLOGGING 9271 init_Bres(misc.logInhibit); 9272 init_Bres(misc.log_on); 9273 init_Sres(screen.logfile); 9274#endif 9275 init_Bres(screen.bellIsUrgent); 9276 init_Bres(screen.bellOnReset); 9277 init_Bres(screen.marginbell); 9278 init_Bres(screen.multiscroll); 9279 init_Ires(screen.nmarginbell); 9280 init_Ires(screen.savelines); 9281 init_Ires(screen.scrollBarBorder); 9282 init_Ires(screen.scrolllines); 9283 init_Bres(screen.alternateScroll); 9284 init_Bres(screen.scrollttyoutput); 9285 init_Bres(screen.scrollkey); 9286 9287 init_Dres(screen.scale_height); 9288 if (screen->scale_height < MIN_SCALE_HEIGHT) 9289 screen->scale_height = MIN_SCALE_HEIGHT; 9290 if (screen->scale_height > MAX_SCALE_HEIGHT) 9291 screen->scale_height = MAX_SCALE_HEIGHT; 9292 9293 init_Bres(misc.autoWrap); 9294 init_Bres(misc.login_shell); 9295 init_Bres(misc.reverseWrap); 9296 init_Bres(misc.scrollbar); 9297 init_Sres(misc.geo_metry); 9298 init_Sres(misc.T_geometry); 9299 9300 init_Sres(screen.term_id); 9301 screen->terminal_id = decodeTerminalID(TScreenOf(request)->term_id); 9302 /* 9303 * (1) If a known terminal model, and not a graphical terminal, preserve 9304 * the terminal id. 9305 * (2) Otherwise, if ReGIS or sixel graphics are enabled, preserve the ID, 9306 * even if it is not a known terminal. 9307 * (3) Otherwise force the terminal ID to the min, max, or VT420 depending 9308 * on the input. 9309 */ 9310 switch (screen->terminal_id) { 9311 case 52: /* MIN_DECID */ 9312 case 100: 9313 case 101: 9314 case 102: 9315 case 131: 9316 case 132: 9317 case 220: 9318 case 320: 9319 case 420: /* DFT_DECID, unless overridden in configure */ 9320 case 510: 9321 case 520: 9322 case 525: /* MAX_DECID */ 9323 break; 9324 default: 9325#if OPT_REGIS_GRAPHICS 9326 if (optRegisGraphics(screen)) 9327 break; 9328#endif 9329#if OPT_SIXEL_GRAPHICS 9330 if (optSixelGraphics(screen)) 9331 break; 9332#endif 9333 screen->terminal_id = limitedTerminalID(screen->terminal_id); 9334 break; 9335 } 9336 TRACE(("term_id '%s' -> terminal_id %d\n", 9337 screen->term_id, 9338 screen->terminal_id)); 9339 9340 screen->vtXX_level = (screen->terminal_id / 100); 9341 9342 init_Ires(screen.title_modes); 9343 screen->title_modes0 = screen->title_modes; 9344 9345 init_Ires(screen.nextEventDelay); 9346 if (screen->nextEventDelay <= 0) 9347 screen->nextEventDelay = 1; 9348 9349 init_Bres(screen.visualbell); 9350 init_Bres(screen.flash_line); 9351 init_Ires(screen.visualBellDelay); 9352 init_Bres(screen.poponbell); 9353 9354 init_Bres(screen.eraseSavedLines0); 9355 screen->eraseSavedLines = screen->eraseSavedLines0; 9356 9357 init_Ires(misc.limit_resize); 9358 9359#if OPT_NUM_LOCK 9360 init_Bres(misc.real_NumLock); 9361 init_Bres(misc.alwaysUseMods); 9362#endif 9363 9364#if OPT_INPUT_METHOD 9365 init_Bres(misc.open_im); 9366 init_Ires(misc.retry_im); 9367 init_Sres(misc.f_x); 9368 init_Sres(misc.input_method); 9369 init_Sres(misc.preedit_type); 9370#endif 9371 9372#if OPT_SHIFT_FONTS 9373 init_Bres(misc.shift_fonts); 9374#endif 9375#if OPT_SUNPC_KBD 9376 init_Ires(misc.ctrl_fkeys); 9377#endif 9378#if OPT_TEK4014 9379 TEK4014_SHOWN(wnew) = False; /* not a resource... */ 9380 init_Bres(misc.tekInhibit); 9381 init_Bres(misc.tekSmall); 9382 init_Bres(misc.TekEmu); 9383#endif 9384#if OPT_TCAP_QUERY 9385 screen->tc_query_code = -1; 9386#endif 9387 wnew->misc.re_verse0 = request->misc.re_verse; 9388 init_Bres(misc.re_verse); 9389 init_Ires(screen.multiClickTime); 9390 init_Ires(screen.bellSuppressTime); 9391 init_Sres(screen.charClass); 9392 9393 init_Bres(screen.always_highlight); 9394 init_Bres(screen.brokenSelections); 9395 init_Bres(screen.cutNewline); 9396 init_Bres(screen.cutToBeginningOfLine); 9397 init_Bres(screen.highlight_selection); 9398 init_Bres(screen.show_wrap_marks); 9399 init_Bres(screen.i18nSelections); 9400 init_Bres(screen.keepClipboard); 9401 init_Bres(screen.keepSelection); 9402 init_Bres(screen.selectToClipboard); 9403 init_Bres(screen.trim_selection); 9404 9405 screen->pointer_cursor = TScreenOf(request)->pointer_cursor; 9406 init_Ires(screen.pointer_mode); 9407 wnew->screen.pointer_mode0 = wnew->screen.pointer_mode; 9408 9409 init_Sres(screen.answer_back); 9410 9411 wnew->SPS.printer_checked = False; 9412 init_Sres(SPS.printer_command); 9413 init_Bres(SPS.printer_autoclose); 9414 init_Bres(SPS.printer_extent); 9415 init_Bres(SPS.printer_formfeed); 9416 init_Bres(SPS.printer_newline); 9417 init_Ires(SPS.printer_controlmode); 9418#if OPT_PRINT_COLORS 9419 init_Ires(SPS.print_attributes); 9420#endif 9421 9422 init_Sres(screen.keyboard_dialect); 9423 9424 init_Sres(screen.cursor_font_name); 9425 init_Sres(screen.pointer_shape); 9426 9427 init_Bres(screen.input_eight_bits); 9428 init_Bres(screen.output_eight_bits); 9429 init_Bres(screen.control_eight_bits); 9430 init_Bres(screen.backarrow_key); 9431 init_Bres(screen.alt_is_not_meta); 9432 init_Bres(screen.alt_sends_esc); 9433 init_Bres(screen.meta_sends_esc); 9434 9435 init_Bres(screen.allowPasteControl0); 9436 init_Bres(screen.allowSendEvent0); 9437 init_Bres(screen.allowColorOp0); 9438 init_Bres(screen.allowFontOp0); 9439 init_Bres(screen.allowMouseOp0); 9440 init_Bres(screen.allowTcapOp0); 9441 init_Bres(screen.allowTitleOp0); 9442 init_Bres(screen.allowWindowOp0); 9443 9444#if OPT_SCROLL_LOCK 9445 init_Bres(screen.allowScrollLock0); 9446 init_Bres(screen.autoScrollLock); 9447#endif 9448 9449 init_Sres(screen.disallowedColorOps); 9450 9451 set_flags_from_list(screen->disallow_color_ops, 9452 screen->disallowedColorOps, 9453 tblColorOps); 9454 9455 init_Sres(screen.disallowedFontOps); 9456 9457 set_flags_from_list(screen->disallow_font_ops, 9458 screen->disallowedFontOps, 9459 tblFontOps); 9460 9461 init_Sres(screen.disallowedMouseOps); 9462 9463 set_flags_from_list(screen->disallow_mouse_ops, 9464 screen->disallowedMouseOps, 9465 tblMouseOps); 9466 9467 init_Sres(screen.disallowedPasteControls); 9468 9469 set_flags_from_list(screen->disallow_paste_controls, 9470 screen->disallowedPasteControls, 9471 tblPasteControls); 9472 9473 init_Sres(screen.disallowedTcapOps); 9474 9475 set_flags_from_list(screen->disallow_tcap_ops, 9476 screen->disallowedTcapOps, 9477 tblTcapOps); 9478 9479 init_Sres(screen.disallowedWinOps); 9480 9481 set_flags_from_list(screen->disallow_win_ops, 9482 screen->disallowedWinOps, 9483 tblWindowOps); 9484 9485 init_Sres(screen.default_string); 9486 init_Sres(screen.eightbit_select_types); 9487#if OPT_WIDE_CHARS 9488 init_Sres(screen.utf8_select_types); 9489#endif 9490 9491 /* make a copy so that editres cannot change the resource after startup */ 9492 screen->allowPasteControls = screen->allowPasteControl0; 9493 screen->allowSendEvents = screen->allowSendEvent0; 9494 screen->allowColorOps = screen->allowColorOp0; 9495 screen->allowFontOps = screen->allowFontOp0; 9496 screen->allowMouseOps = screen->allowMouseOp0; 9497 screen->allowTcapOps = screen->allowTcapOp0; 9498 screen->allowTitleOps = screen->allowTitleOp0; 9499 screen->allowWindowOps = screen->allowWindowOp0; 9500 9501#if OPT_SCROLL_LOCK 9502 screen->allowScrollLock = screen->allowScrollLock0; 9503#endif 9504 9505 init_Bres(screen.quiet_grab); 9506 9507#ifndef NO_ACTIVE_ICON 9508 init_Sres(screen.icon_fontname); 9509 getIconicFont(screen)->fs = xtermLoadQueryFont(wnew, 9510 screen->icon_fontname); 9511 TRACE(("iconFont '%s' %sloaded successfully\n", 9512 screen->icon_fontname, 9513 getIconicFont(screen)->fs ? "" : "NOT ")); 9514 init_Sres(misc.active_icon_s); 9515 wnew->work.active_icon = 9516 (Boolean) extendedBoolean(wnew->misc.active_icon_s, 9517 tblAIconOps, eiLAST); 9518 init_Ires(misc.icon_border_width); 9519 wnew->misc.icon_border_pixel = request->misc.icon_border_pixel; 9520#endif /* NO_ACTIVE_ICON */ 9521 9522 init_Bres(misc.signalInhibit); 9523 init_Bres(misc.titeInhibit); 9524 init_Bres(misc.tiXtraScroll); 9525 init_Bres(misc.cdXtraScroll); 9526 init_Bres(misc.color_inner_border); 9527 init_Bres(misc.dynamicColors); 9528 init_Bres(misc.resizeByPixel); 9529 9530#if OPT_DEC_CHRSET 9531 for (i = 0; i < NUM_CHRSET; i++) { 9532 screen->double_fonts[i].warn = fwResource; 9533 } 9534#endif 9535 for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) { 9536 init_Sres2(screen.MenuFontName, i); 9537 } 9538 for (i = 0; i < fMAX; i++) { 9539 screen->fnts[i].warn = fwResource; 9540#if OPT_WIDE_ATTRS 9541 screen->ifnts[i].warn = fwResource; 9542#endif 9543 } 9544#ifndef NO_ACTIVE_ICON 9545 screen->fnt_icon.warn = fwResource; 9546#endif 9547 9548 init_Ires(misc.fontWarnings); 9549 9550 initFontLists(wnew); 9551 9552#define DefaultFontNames screen->menu_font_names[fontMenu_default] 9553 9554 /* 9555 * Process Xft font resources first, since faceName may contain X11 fonts 9556 * that should override the "font" resource. 9557 */ 9558#if OPT_RENDERFONT 9559 init_Bres(screen.force_xft_height); 9560 for (i = 0; i <= fontMenu_lastBuiltin; ++i) { 9561 init_Dres2(misc.face_size, i); 9562 } 9563 9564#define ALLOC_FONTLIST(name,which,field) \ 9565 init_Sres(misc.default_xft.field);\ 9566 allocFontList(wnew,\ 9567 name,\ 9568 &(wnew->work.fonts),\ 9569 which,\ 9570 wnew->misc.default_xft.field,\ 9571 True) 9572 9573 ALLOC_FONTLIST(XtNfaceName, fNorm, f_n); 9574 9575#if OPT_WIDE_CHARS 9576 ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w); 9577#endif 9578 9579#undef ALLOC_FONTLIST 9580 9581#endif 9582 9583 /* 9584 * Process X11 (XLFD) font specifications. 9585 */ 9586#define ALLOC_FONTLIST(name,which,field) \ 9587 init_Sres(misc.default_font.field);\ 9588 allocFontList(wnew,\ 9589 name,\ 9590 &(wnew->work.fonts),\ 9591 which,\ 9592 wnew->misc.default_font.field,\ 9593 False) 9594 9595 ALLOC_FONTLIST(XtNfont, fNorm, f_n); 9596 ALLOC_FONTLIST(XtNboldFont, fBold, f_b); 9597 9598 DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew)); 9599 DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew)); 9600 9601#if OPT_WIDE_CHARS 9602 ALLOC_FONTLIST(XtNwideFont, fWide, f_w); 9603 ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb); 9604 9605 DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew)); 9606 DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew)); 9607#endif 9608 9609#undef ALLOC_FONTLIST 9610 9611 screen->EscapeFontName() = NULL; 9612 screen->SelectFontName() = NULL; 9613 9614 screen->menu_font_number = fontMenu_default; 9615 init_Sres(screen.initial_font); 9616 if (screen->initial_font != 0) { 9617 int result = xtermGetFont(screen->initial_font); 9618 if (result >= 0) 9619 screen->menu_font_number = result; 9620 } 9621#if OPT_BROKEN_OSC 9622 init_Bres(screen.brokenLinuxOSC); 9623#endif 9624 9625#if OPT_BROKEN_ST 9626 init_Bres(screen.brokenStringTerm); 9627#endif 9628 9629#if OPT_C1_PRINT 9630 init_Bres(screen.c1_printable); 9631#endif 9632 9633#if OPT_CLIP_BOLD 9634 init_Bres(screen.use_border_clipping); 9635 init_Bres(screen.use_clipping); 9636#endif 9637 9638#if OPT_DEC_CHRSET 9639 init_Bres(screen.font_doublesize); 9640 init_Ires(screen.cache_doublesize); 9641 if (screen->cache_doublesize > NUM_CHRSET) 9642 screen->cache_doublesize = NUM_CHRSET; 9643 if (screen->cache_doublesize == 0) 9644 screen->font_doublesize = False; 9645 TRACE(("Doublesize%s enabled, up to %d fonts\n", 9646 screen->font_doublesize ? "" : " not", 9647 screen->cache_doublesize)); 9648#endif 9649#if OPT_DEC_RECTOPS 9650 init_Ires(screen.checksum_ext0); 9651 screen->checksum_ext = screen->checksum_ext0; 9652#endif 9653 9654#if OPT_ISO_COLORS 9655 init_Ires(screen.veryBoldColors); 9656 init_Bres(screen.boldColors); 9657 init_Bres(screen.colorAttrMode); 9658 init_Bres(screen.colorBDMode); 9659 init_Bres(screen.colorBLMode); 9660 init_Bres(screen.colorMode); 9661 init_Bres(screen.colorULMode); 9662 init_Bres(screen.italicULMode); 9663 init_Bres(screen.colorRVMode); 9664 9665#if OPT_WIDE_ATTRS 9666 init_Bres(screen.colorITMode); 9667#endif 9668#if OPT_DIRECT_COLOR 9669 init_Bres(screen.direct_color); 9670#endif 9671 9672#if OPT_COLOR_RES2 9673 TRACE(("...will fake resources for color%d to color%d\n", 9674 MIN_ANSI_COLORS, 9675 NUM_ANSI_COLORS - 1)); 9676#endif 9677 for (i = 0, color_ok = False; i < MAXCOLORS; i++) { 9678 9679#if OPT_COLOR_RES2 9680 /* 9681 * Xt has a hardcoded limit on the maximum number of resources that can 9682 * be used in a widget. If we configure both luit (which implies 9683 * wide-characters) and 256-colors, it goes over that limit. Most 9684 * people would not need a resource-file with 256-colors; the default 9685 * values in our table are sufficient. In that case, fake the resource 9686 * setting by copying the default value from the table. The #define's 9687 * can be overridden to make these true resources. 9688 */ 9689 if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) { 9690 screen->Acolors[i].resource = 9691 x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr); 9692 if (screen->Acolors[i].resource == 0) 9693 screen->Acolors[i].resource = XtDefaultForeground; 9694 } else 9695#endif /* OPT_COLOR_RES2 */ 9696 { 9697 screen->Acolors[i] = TScreenOf(request)->Acolors[i]; 9698 screen->Acolors[i].resource = 9699 x_strtrim(screen->Acolors[i].resource); 9700 } 9701 9702#if OPT_COLOR_RES 9703 TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource)); 9704 screen->Acolors[i].mode = False; 9705 if (DftFg(Acolors[i])) { 9706 screen->Acolors[i].value = T_COLOR(screen, TEXT_FG); 9707 screen->Acolors[i].mode = True; 9708 } else if (DftBg(Acolors[i])) { 9709 screen->Acolors[i].value = T_COLOR(screen, TEXT_BG); 9710 screen->Acolors[i].mode = True; 9711 } else { 9712 color_ok = True; 9713 } 9714#else 9715 TRACE(("Acolors[%d] = %#lx\n", i, TScreenOf(request)->Acolors[i])); 9716 if (screen->Acolors[i] != wnew->dft_foreground && 9717 screen->Acolors[i] != T_COLOR(screen, TEXT_FG) && 9718 screen->Acolors[i] != T_COLOR(screen, TEXT_BG)) 9719 color_ok = True; 9720#endif 9721 } 9722 9723 /* 9724 * Check if we're trying to use color in a monochrome screen. Disable 9725 * color in that case, since that would make ANSI colors unusable. A 4-bit 9726 * or 8-bit display is usable, so we do not have to check for anything more 9727 * specific. 9728 */ 9729 if (color_ok) { 9730 if (getVisualDepth(wnew) <= 1) { 9731 TRACE(("disabling color since screen is monochrome\n")); 9732 color_ok = False; 9733 } 9734 } 9735 9736 /* If none of the colors are anything other than the foreground or 9737 * background, we'll assume this isn't color, no matter what the colorMode 9738 * resource says. (There doesn't seem to be any good way to determine if 9739 * the resource lookup failed versus the user having misconfigured this). 9740 */ 9741 if (!color_ok) { 9742 screen->colorMode = False; 9743 TRACE(("All colors are foreground or background: disable colorMode\n")); 9744 } 9745 wnew->sgr_foreground = -1; 9746 wnew->sgr_background = -1; 9747 wnew->sgr_38_xcolors = False; 9748 clrDirectFG(wnew->flags); 9749 clrDirectFG(wnew->flags); 9750#endif /* OPT_ISO_COLORS */ 9751 9752 /* 9753 * Decode the resources that control the behavior on multiple mouse clicks. 9754 * A single click is always bound to normal character selection, but the 9755 * other flavors can be changed. 9756 */ 9757 for (i = 0; i < NSELECTUNITS; ++i) { 9758 int ck = (i + 1); 9759 screen->maxClicks = ck; 9760 if (i == Select_CHAR) 9761 screen->selectMap[i] = Select_CHAR; 9762 else if (TScreenOf(request)->onClick[i] != 0) 9763 ParseOnClicks(wnew, request, (unsigned) i); 9764 else if (i <= Select_LINE) 9765 screen->selectMap[i] = (SelectUnit) i; 9766 else 9767 break; 9768#if OPT_XRES_QUERY 9769 init_Sres(screen.onClick[i]); 9770#endif 9771 TRACE(("on%dClicks %s=%d\n", ck, 9772 NonNull(TScreenOf(request)->onClick[i]), 9773 screen->selectMap[i])); 9774 if (screen->selectMap[i] == NSELECTUNITS) 9775 break; 9776 } 9777 TRACE(("maxClicks %d\n", screen->maxClicks)); 9778 9779 init_Tres(MOUSE_FG); 9780 init_Tres(MOUSE_BG); 9781 init_Tres(TEXT_CURSOR); 9782#if OPT_HIGHLIGHT_COLOR 9783 init_Tres(HIGHLIGHT_BG); 9784 init_Tres(HIGHLIGHT_FG); 9785 init_Bres(screen.hilite_reverse); 9786 init_Mres(screen.hilite_color); 9787 if (screen->hilite_color == Maybe) { 9788 screen->hilite_color = False; 9789#if OPT_COLOR_RES 9790 /* 9791 * If the highlight text/background are both set, and if they are 9792 * not equal to either the text/background or background/text, then 9793 * set the highlightColorMode automatically. 9794 */ 9795 if (!DftFg(Tcolors[HIGHLIGHT_BG]) 9796 && !DftBg(Tcolors[HIGHLIGHT_FG]) 9797 && !TxtFg(Tcolors[HIGHLIGHT_BG]) 9798 && !TxtBg(Tcolors[HIGHLIGHT_FG]) 9799 && !TxtBg(Tcolors[HIGHLIGHT_BG]) 9800 && !TxtFg(Tcolors[HIGHLIGHT_FG])) { 9801 TRACE(("...setting hilite_color automatically\n")); 9802 screen->hilite_color = True; 9803 } 9804#endif 9805 } 9806#endif 9807 9808#if OPT_TEK4014 9809 /* 9810 * The Tek4014 window has no separate resources for foreground, background 9811 * and cursor color. Since xterm always creates the vt100 widget first, we 9812 * can set the Tektronix colors here. That lets us use escape sequences to 9813 * set its dynamic colors and get consistent behavior whether or not the 9814 * window is displayed. 9815 */ 9816 screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG]; 9817 screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG]; 9818 screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR]; 9819#endif 9820 9821#ifdef SCROLLBAR_RIGHT 9822 init_Bres(misc.useRight); 9823#endif 9824 9825#if OPT_RENDERFONT 9826 init_Ires(misc.limit_fontsets); 9827 wnew->work.max_fontsets = (unsigned) wnew->misc.limit_fontsets; 9828 9829 init_Sres(misc.render_font_s); 9830 wnew->work.render_font = 9831 (Boolean) extendedBoolean(wnew->misc.render_font_s, 9832 tblRenderFont, erLast); 9833 if (wnew->work.render_font == erDefault) { 9834 if (IsEmpty(CurrentXftFont(wnew))) { 9835 free((void *) CurrentXftFont(wnew)); 9836 CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO); 9837 TRACE(("will allow runtime switch to render_font using \"%s\"\n", 9838 CurrentXftFont(wnew))); 9839 } else { 9840 wnew->work.render_font = erTrue; 9841 TRACE(("initially using TrueType font\n")); 9842 } 9843 } else if (wnew->work.render_font == erDefaultOff) { 9844 wnew->work.render_font = erFalse; 9845 } 9846 /* minor tweak to make debug traces consistent: */ 9847 if (wnew->work.render_font) { 9848 if (IsEmpty(CurrentXftFont(wnew))) { 9849 wnew->work.render_font = False; 9850 TRACE(("reset render_font since there is no face_name\n")); 9851 } 9852 } 9853#endif 9854 9855#if OPT_WIDE_CHARS 9856 /* setup data for next call */ 9857 init_Sres(screen.utf8_mode_s); 9858 request->screen.utf8_mode = 9859 extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast); 9860 9861 init_Sres(screen.utf8_fonts_s); 9862 request->screen.utf8_fonts = 9863 extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast); 9864 9865 init_Sres(screen.utf8_title_s); 9866 request->screen.utf8_title = 9867 extendedBoolean(request->screen.utf8_title_s, tblUtf8Mode, uLast); 9868 9869 /* 9870 * Make a copy in the input/request so that DefaultFontN() works for 9871 * the "CHECKFONT" option. 9872 */ 9873 copyFontList(&(request->work.fonts.x11.list_n), 9874 wnew->work.fonts.x11.list_n); 9875 9876 VTInitialize_locale(request); 9877 init_Bres(screen.normalized_c); 9878 init_Bres(screen.utf8_latin1); 9879 init_Bres(screen.utf8_weblike); 9880 9881#if OPT_LUIT_PROG 9882 init_Bres(misc.callfilter); 9883 init_Bres(misc.use_encoding); 9884 init_Sres(misc.locale_str); 9885 init_Sres(misc.localefilter); 9886#endif 9887 9888 init_Ires(screen.utf8_inparse); 9889 init_Ires(screen.utf8_mode); 9890 init_Ires(screen.utf8_fonts); 9891 init_Ires(screen.utf8_title); 9892 init_Ires(screen.max_combining); 9893 9894 init_Ires(screen.utf8_always); /* from utf8_mode, used in doparse */ 9895 9896 if (screen->max_combining < 0) { 9897 screen->max_combining = 0; 9898 } 9899 if (screen->max_combining > 5) { 9900 screen->max_combining = 5; 9901 } 9902 9903 init_Bres(screen.vt100_graphics); 9904 init_Bres(screen.wide_chars); 9905 init_Bres(misc.mk_width); 9906 init_Bres(misc.cjk_width); 9907 9908 init_Ires(misc.mk_samplesize); 9909 init_Ires(misc.mk_samplepass); 9910 9911 if (wnew->misc.mk_samplesize > 0xffff) 9912 wnew->misc.mk_samplesize = 0xffff; 9913 if (wnew->misc.mk_samplesize < 0) 9914 wnew->misc.mk_samplesize = 0; 9915 9916 if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize) 9917 wnew->misc.mk_samplepass = wnew->misc.mk_samplesize; 9918 if (wnew->misc.mk_samplepass < 0) 9919 wnew->misc.mk_samplepass = 0; 9920 9921 if (TScreenOf(request)->utf8_mode) { 9922 TRACE(("setting wide_chars on\n")); 9923 screen->wide_chars = True; 9924 } else { 9925 TRACE(("setting utf8_mode to 0\n")); 9926 screen->utf8_mode = uFalse; 9927 } 9928 mk_wcwidth_init(screen->utf8_mode); 9929 TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode)); 9930 9931#if OPT_MINI_LUIT 9932 if (TScreenOf(request)->latin9_mode) { 9933 screen->latin9_mode = True; 9934 } 9935 if (TScreenOf(request)->unicode_font) { 9936 screen->unicode_font = True; 9937 } 9938 TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode)); 9939 TRACE(("initialized unicode_font to %d\n", screen->unicode_font)); 9940#endif 9941 9942 decode_wcwidth(wnew); 9943 xtermSaveVTFonts(wnew); 9944#endif /* OPT_WIDE_CHARS */ 9945 9946 init_Sres(screen.eight_bit_meta_s); 9947 wnew->screen.eight_bit_meta = 9948 extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, ebLast); 9949 if (wnew->screen.eight_bit_meta == ebLocale) { 9950#if OPT_WIDE_CHARS 9951 if (xtermEnvUTF8()) { 9952 wnew->screen.eight_bit_meta = ebFalse; 9953 TRACE(("...eightBitMeta is false due to locale\n")); 9954 } else 9955#endif /* OPT_WIDE_CHARS */ 9956 { 9957 wnew->screen.eight_bit_meta = ebTrue; 9958 TRACE(("...eightBitMeta is true due to locale\n")); 9959 } 9960 } 9961 9962 init_Bres(screen.always_bold_mode); 9963 init_Bres(screen.bold_mode); 9964 init_Bres(screen.underline); 9965 9966 wnew->cur_foreground = 0; 9967 wnew->cur_background = 0; 9968 9969 wnew->keyboard.flags = MODE_SRM; 9970 9971 if (screen->backarrow_key) 9972 wnew->keyboard.flags |= MODE_DECBKM; 9973 TRACE(("initialized DECBKM %s\n", 9974 BtoS(wnew->keyboard.flags & MODE_DECBKM))); 9975 9976#if OPT_SIXEL_GRAPHICS 9977 init_Bres(screen.sixel_scrolling); 9978 if (screen->sixel_scrolling) 9979 wnew->keyboard.flags |= MODE_DECSDM; 9980 TRACE(("initialized DECSDM %s\n", 9981 BtoS(wnew->keyboard.flags & MODE_DECSDM))); 9982#endif 9983 9984#if OPT_GRAPHICS 9985 init_Sres(screen.graph_termid); 9986 screen->graphics_termid = decodeTerminalID(TScreenOf(request)->graph_termid); 9987 switch (screen->graphics_termid) { 9988 case 125: 9989 case 240: 9990 case 241: 9991 case 330: 9992 case 340: 9993 case 382: 9994 break; 9995 default: 9996 screen->graphics_termid = 0; 9997 break; 9998 } 9999 TRACE(("graph_termid '%s' -> graphics_termid %d\n", 10000 screen->graph_termid, 10001 screen->graphics_termid)); 10002 10003 init_Ires(screen.numcolorregisters); 10004 TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n", 10005 screen->numcolorregisters)); 10006 10007 init_Bres(screen.privatecolorregisters); /* FIXME: should this be off unconditionally here? */ 10008 TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n", 10009 BtoS(screen->privatecolorregisters))); 10010#endif 10011 10012#if OPT_GRAPHICS 10013 { 10014 int native_w, native_h; 10015 10016 switch (GraphicsTermId(screen)) { 10017 case 125: 10018 native_w = 768; 10019 native_h = 460; 10020 break; 10021 case 240: 10022 /* FALLTHRU */ 10023 case 241: 10024 native_w = 800; 10025 native_h = 460; 10026 break; 10027 case 330: 10028 /* FALLTHRU */ 10029 case 340: 10030 native_w = 800; 10031 native_h = 480; 10032 break; 10033 default: 10034 native_w = 800; 10035 native_h = 480; 10036 break; 10037 case 382: 10038 native_w = 960; 10039 native_h = 750; 10040 break; 10041 } 10042 10043# if OPT_REGIS_GRAPHICS 10044 init_Sres(screen.graphics_regis_default_font); 10045 TRACE(("default ReGIS font: %s\n", 10046 screen->graphics_regis_default_font)); 10047 10048 init_Sres(screen.graphics_regis_screensize); 10049 screen->graphics_regis_def_high = 1000; 10050 screen->graphics_regis_def_wide = 1000; 10051 if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) { 10052 TRACE(("setting default ReGIS screensize based on graphics_id %d\n", 10053 GraphicsTermId(screen))); 10054 screen->graphics_regis_def_high = (Dimension) native_h; 10055 screen->graphics_regis_def_wide = (Dimension) native_w; 10056 } else { 10057 int conf_high; 10058 int conf_wide; 10059 char ignore; 10060 10061 if (sscanf(screen->graphics_regis_screensize, 10062 "%dx%d%c", 10063 &conf_wide, 10064 &conf_high, 10065 &ignore) == 2) { 10066 if (conf_high > 0 && conf_wide > 0) { 10067 screen->graphics_regis_def_high = 10068 (Dimension) conf_high; 10069 screen->graphics_regis_def_wide = 10070 (Dimension) conf_wide; 10071 } else { 10072 TRACE(("ignoring invalid regisScreenSize %s\n", 10073 screen->graphics_regis_screensize)); 10074 } 10075 } else { 10076 TRACE(("ignoring invalid regisScreenSize %s\n", 10077 screen->graphics_regis_screensize)); 10078 } 10079 } 10080 TRACE(("default ReGIS graphics screensize %dx%d\n", 10081 (int) screen->graphics_regis_def_wide, 10082 (int) screen->graphics_regis_def_high)); 10083# endif 10084 10085 init_Sres(screen.graphics_max_size); 10086 screen->graphics_max_high = 1000; 10087 screen->graphics_max_wide = 1000; 10088 if (!x_strcasecmp(screen->graphics_max_size, "auto")) { 10089 TRACE(("setting max graphics screensize based on graphics_id %d\n", 10090 GraphicsTermId(screen))); 10091 screen->graphics_max_high = (Dimension) native_h; 10092 screen->graphics_max_wide = (Dimension) native_w; 10093 } else { 10094 int conf_high; 10095 int conf_wide; 10096 char ignore; 10097 10098 if (sscanf(screen->graphics_max_size, 10099 "%dx%d%c", 10100 &conf_wide, 10101 &conf_high, 10102 &ignore) == 2) { 10103 if (conf_high > 0 && conf_wide > 0) { 10104 screen->graphics_max_high = (Dimension) conf_high; 10105 screen->graphics_max_wide = (Dimension) conf_wide; 10106 } else { 10107 TRACE(("ignoring invalid maxGraphicSize %s\n", 10108 screen->graphics_max_size)); 10109 } 10110 } else { 10111 TRACE(("ignoring invalid maxGraphicSize %s\n", 10112 screen->graphics_max_size)); 10113 } 10114 } 10115# if OPT_REGIS_GRAPHICS 10116 /* Make sure the max is large enough for the default ReGIS size. */ 10117 if (screen->graphics_regis_def_high > 10118 screen->graphics_max_high) { 10119 screen->graphics_max_high = 10120 screen->graphics_regis_def_high; 10121 } 10122 if (screen->graphics_regis_def_wide > 10123 screen->graphics_max_wide) { 10124 screen->graphics_max_wide = 10125 screen->graphics_regis_def_wide; 10126 } 10127# endif 10128 TRACE(("max graphics screensize %dx%d\n", 10129 (int) screen->graphics_max_wide, 10130 (int) screen->graphics_max_high)); 10131 } 10132#endif 10133 10134#if OPT_SIXEL_GRAPHICS 10135 init_Bres(screen.sixel_scrolls_right); 10136#endif 10137#if OPT_PRINT_GRAPHICS 10138 init_Bres(screen.graphics_print_to_host); 10139 init_Bres(screen.graphics_expanded_print_mode); 10140 init_Bres(screen.graphics_print_color_mode); 10141 init_Bres(screen.graphics_print_color_syntax); 10142 init_Bres(screen.graphics_print_background_mode); 10143 init_Bres(screen.graphics_rotated_print_mode); 10144#endif 10145 10146 /* look for focus related events on the shell, because we need 10147 * to care about the shell's border being part of our focus. 10148 */ 10149 TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent)); 10150 XtAddEventHandler(my_parent, EnterWindowMask, False, 10151 HandleEnterWindow, (Opaque) NULL); 10152 XtAddEventHandler(my_parent, LeaveWindowMask, False, 10153 HandleLeaveWindow, (Opaque) NULL); 10154 XtAddEventHandler(my_parent, FocusChangeMask, False, 10155 HandleFocusChange, (Opaque) NULL); 10156 XtAddEventHandler((Widget) wnew, 0L, True, 10157 VTNonMaskableEvent, (Opaque) NULL); 10158 XtAddEventHandler((Widget) wnew, PropertyChangeMask, False, 10159 HandleBellPropertyChange, (Opaque) NULL); 10160 10161#if HANDLE_STRUCT_NOTIFY 10162#if OPT_TOOLBAR 10163 wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar); 10164 init_Ires(VT100_TB_INFO(menu_height)); 10165#endif 10166 XtAddEventHandler(my_parent, MappingNotify | StructureNotifyMask, False, 10167 HandleStructNotify, (Opaque) 0); 10168#endif /* HANDLE_STRUCT_NOTIFY */ 10169 10170 screen->bellInProgress = False; 10171 10172 set_character_class(screen->charClass); 10173#if OPT_REPORT_CCLASS 10174 if (resource.reportCClass) 10175 report_char_class(wnew); 10176#endif 10177 10178 /* create it, but don't realize it */ 10179 ScrollBarOn(wnew, True); 10180 10181 /* make sure that the resize gravity acceptable */ 10182 if (!GravityIsNorthWest(wnew) && 10183 !GravityIsSouthWest(wnew)) { 10184 char value[80]; 10185 String temp[2]; 10186 Cardinal nparams = 1; 10187 10188 sprintf(value, "%d", wnew->misc.resizeGravity); 10189 temp[0] = value; 10190 temp[1] = 0; 10191 XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError", 10192 "unsupported resizeGravity resource value (%s)", 10193 temp, &nparams); 10194 wnew->misc.resizeGravity = SouthWestGravity; 10195 } 10196#ifndef NO_ACTIVE_ICON 10197 screen->whichVwin = &screen->fullVwin; 10198#endif /* NO_ACTIVE_ICON */ 10199 10200 init_Ires(screen.unparse_max); 10201 if ((int) screen->unparse_max < 256) 10202 screen->unparse_max = 256; 10203 screen->unparse_bfr = (IChar *) (void *) XtCalloc(screen->unparse_max, 10204 (Cardinal) sizeof(IChar)); 10205 10206 if (screen->savelines < 0) 10207 screen->savelines = 0; 10208 10209 init_Bres(screen.awaitInput); 10210 10211 wnew->flags = 0; 10212 if (!screen->jumpscroll) 10213 wnew->flags |= SMOOTHSCROLL; 10214 if (wnew->misc.reverseWrap) 10215 wnew->flags |= REVERSEWRAP; 10216 if (wnew->misc.autoWrap) 10217 wnew->flags |= WRAPAROUND; 10218 if (wnew->misc.re_verse != wnew->misc.re_verse0) 10219 wnew->flags |= REVERSE_VIDEO; 10220 if (screen->c132) 10221 wnew->flags |= IN132COLUMNS; 10222 10223 wnew->initflags = wnew->flags; 10224 10225 init_Sres(keyboard.shift_escape_s); 10226 wnew->keyboard.shift_escape = 10227 extendedBoolean(wnew->keyboard.shift_escape_s, tblShift2S, ssLAST); 10228 10229#if OPT_MOD_FKEYS 10230 init_Ires(keyboard.modify_1st.allow_keys); 10231 init_Ires(keyboard.modify_1st.cursor_keys); 10232 init_Ires(keyboard.modify_1st.function_keys); 10233 init_Ires(keyboard.modify_1st.keypad_keys); 10234 init_Ires(keyboard.modify_1st.other_keys); 10235 init_Ires(keyboard.modify_1st.string_keys); 10236 init_Ires(keyboard.format_keys); 10237 wnew->keyboard.modify_now = wnew->keyboard.modify_1st; 10238#endif 10239 10240 init_Ires(misc.appcursorDefault); 10241 if (wnew->misc.appcursorDefault) 10242 wnew->keyboard.flags |= MODE_DECCKM; 10243 10244 init_Ires(misc.appkeypadDefault); 10245 if (wnew->misc.appkeypadDefault) 10246 wnew->keyboard.flags |= MODE_DECKPAM; 10247 10248 initLineData(wnew); 10249#if OPT_WIDE_CHARS 10250 freeFontList(&(request->work.fonts.x11.list_n)); 10251#endif 10252#if OPT_XRES_QUERY 10253 if (resource.reportXRes) 10254 reportResources(wnew); 10255#endif 10256 xtermResetLocale(LC_NUMERIC, saveLocale); 10257 TRACE(("" TRACE_R " VTInitialize\n")); 10258 return; 10259} 10260 10261void 10262releaseCursorGCs(XtermWidget xw) 10263{ 10264 TScreen *screen = TScreenOf(xw); 10265 VTwin *win = WhichVWin(screen); 10266 int n; 10267 10268 for_each_curs_gc(n) { 10269 freeCgs(xw, win, (CgsEnum) n); 10270 } 10271} 10272 10273void 10274releaseWindowGCs(XtermWidget xw, VTwin *win) 10275{ 10276 int n; 10277 10278 for_each_text_gc(n) { 10279 switch (n) { 10280 case gcBorder: 10281 case gcFiller: 10282 break; 10283 default: 10284 freeCgs(xw, win, (CgsEnum) n); 10285 break; 10286 } 10287 } 10288} 10289 10290#define TRACE_FREE_LEAK(name) \ 10291 if (name) { \ 10292 TRACE(("freed " #name ": %p\n", (const void *) name)); \ 10293 FreeAndNull(name); \ 10294 } 10295 10296#define TRACE_FREE_GC(name,part) \ 10297 if (part) { \ 10298 TRACE(("freed %s " #part ": %p\n", name, (const void *) part)); \ 10299 XFreeGC(dpy, part); \ 10300 part = 0; \ 10301 } 10302 10303#if OPT_INPUT_METHOD 10304static void 10305cleanupInputMethod(XtermWidget xw) 10306{ 10307 TInput *input = lookupTInput(xw, (Widget) xw); 10308 10309 if (input && input->xim) { 10310 XCloseIM(input->xim); 10311 input->xim = 0; 10312 TRACE(("freed screen->xim\n")); 10313 } 10314} 10315#else 10316#define cleanupInputMethod(xw) /* nothing */ 10317#endif 10318 10319#ifdef NO_LEAKS 10320#define FREE_VT_WIN(name) freeVTwin(dpy, #name, &(screen->name)) 10321static void 10322freeVTwin(Display *dpy, const char *whichWin, VTwin *win) 10323{ 10324 TRACE_FREE_GC(whichWin, win->filler_gc); 10325 TRACE_FREE_GC(whichWin, win->border_gc); 10326 TRACE_FREE_GC(whichWin, win->marker_gc[0]); 10327 TRACE_FREE_GC(whichWin, win->marker_gc[1]); 10328} 10329#endif 10330 10331static void 10332VTDestroy(Widget w GCC_UNUSED) 10333{ 10334#ifdef NO_LEAKS 10335 XtermWidget xw = (XtermWidget) w; 10336 TScreen *screen = TScreenOf(xw); 10337 Display *dpy = screen->display; 10338 Cardinal n, k; 10339 10340 StopBlinking(xw); 10341 10342 if (screen->scrollWidget) { 10343 XtUninstallTranslations(screen->scrollWidget); 10344 XtDestroyWidget(screen->scrollWidget); 10345 } 10346#if OPT_FIFO_LINES 10347 while (screen->saved_fifo > 0) { 10348 deleteScrollback(screen); 10349 } 10350#endif 10351 while (screen->save_title != 0) { 10352 SaveTitle *last = screen->save_title; 10353 screen->save_title = last->next; 10354 free(last->iconName); 10355 free(last->windowName); 10356 free(last); 10357 } 10358#ifndef NO_ACTIVE_ICON 10359 TRACE_FREE_LEAK(xw->misc.active_icon_s); 10360#endif 10361#if OPT_ISO_COLORS 10362 TRACE_FREE_LEAK(screen->cmap_data); 10363 for (n = 0; n < MAXCOLORS; n++) { 10364 TRACE_FREE_LEAK(screen->Acolors[n].resource); 10365 } 10366 for (n = 0; n < MAX_SAVED_SGR; n++) { 10367 TRACE_FREE_LEAK(xw->saved_colors.palettes[n]); 10368 } 10369#endif 10370#if OPT_COLOR_RES 10371 for (n = 0; n < NCOLORS; n++) { 10372 switch (n) { 10373#if OPT_TEK4014 10374 case TEK_BG: 10375 /* FALLTHRU */ 10376 case TEK_FG: 10377 /* FALLTHRU */ 10378 case TEK_CURSOR: 10379 break; 10380#endif 10381 default: 10382 TRACE_FREE_LEAK(screen->Tcolors[n].resource); 10383 break; 10384 } 10385 } 10386#endif 10387 FreeMarkGCs(xw); 10388 TRACE_FREE_LEAK(screen->unparse_bfr); 10389 TRACE_FREE_LEAK(screen->save_ptr); 10390 TRACE_FREE_LEAK(screen->saveBuf_data); 10391 TRACE_FREE_LEAK(screen->saveBuf_index); 10392 for (n = 0; n < 2; ++n) { 10393 TRACE_FREE_LEAK(screen->editBuf_data[n]); 10394 TRACE_FREE_LEAK(screen->editBuf_index[n]); 10395 } 10396 TRACE_FREE_LEAK(screen->keyboard_dialect); 10397 TRACE_FREE_LEAK(screen->cursor_font_name); 10398 TRACE_FREE_LEAK(screen->pointer_shape); 10399 TRACE_FREE_LEAK(screen->term_id); 10400#if OPT_WIDE_CHARS 10401 TRACE_FREE_LEAK(screen->utf8_mode_s); 10402 TRACE_FREE_LEAK(screen->utf8_fonts_s); 10403 TRACE_FREE_LEAK(screen->utf8_title_s); 10404#if OPT_LUIT_PROG 10405 TRACE_FREE_LEAK(xw->misc.locale_str); 10406 TRACE_FREE_LEAK(xw->misc.localefilter); 10407#endif 10408#endif 10409 TRACE_FREE_LEAK(xw->misc.T_geometry); 10410 TRACE_FREE_LEAK(xw->misc.geo_metry); 10411#if OPT_INPUT_METHOD 10412 cleanupInputMethod(xw); 10413 TRACE_FREE_LEAK(xw->misc.f_x); 10414 TRACE_FREE_LEAK(xw->misc.input_method); 10415 TRACE_FREE_LEAK(xw->misc.preedit_type); 10416#endif 10417 releaseCursorGCs(xw); 10418 releaseWindowGCs(xw, &(screen->fullVwin)); 10419#ifndef NO_ACTIVE_ICON 10420 XFreeFont(screen->display, getIconicFont(screen)->fs); 10421 releaseWindowGCs(xw, &(screen->iconVwin)); 10422#endif 10423 XtUninstallTranslations((Widget) xw); 10424#if OPT_TOOLBAR 10425 XtUninstallTranslations((Widget) XtParent(xw)); 10426#endif 10427 XtUninstallTranslations((Widget) SHELL_OF(xw)); 10428 10429 if (screen->hidden_cursor) 10430 XFreeCursor(screen->display, screen->hidden_cursor); 10431 10432 xtermCloseFonts(xw, screen->fnts); 10433#if OPT_WIDE_ATTRS 10434 xtermCloseFonts(xw, screen->ifnts); 10435#endif 10436 noleaks_cachedCgs(xw); 10437 free_termcap(xw); 10438 10439 FREE_VT_WIN(fullVwin); 10440#ifndef NO_ACTIVE_ICON 10441 FREE_VT_WIN(iconVwin); 10442#endif /* NO_ACTIVE_ICON */ 10443 10444 TRACE_FREE_LEAK(screen->selection_targets_8bit); 10445#if OPT_SELECT_REGEX 10446 for (n = 0; n < NSELECTUNITS; ++n) { 10447 if (screen->selectMap[n] == Select_REGEX) { 10448 TRACE_FREE_LEAK(screen->selectExpr[n]); 10449 } 10450 } 10451#endif 10452 10453#if OPT_RENDERFONT 10454 for (n = 0; n < NMENUFONTS; ++n) { 10455 int e; 10456 for (e = 0; e < fMAX; ++e) { 10457 xtermCloseXft(screen, getMyXftFont(xw, e, (int) n)); 10458 } 10459 } 10460 discardRenderDraw(screen); 10461 { 10462 ListXftFonts *p; 10463 while ((p = screen->list_xft_fonts) != 0) { 10464 screen->list_xft_fonts = p->next; 10465 free(p); 10466 } 10467 } 10468#endif 10469 10470 /* free things allocated via init_Sres or Init_Sres2 */ 10471#ifndef NO_ACTIVE_ICON 10472 TRACE_FREE_LEAK(screen->icon_fontname); 10473#endif 10474#ifdef ALLOWLOGGING 10475 TRACE_FREE_LEAK(screen->logfile); 10476#endif 10477 TRACE_FREE_LEAK(screen->eight_bit_meta_s); 10478 TRACE_FREE_LEAK(screen->charClass); 10479 TRACE_FREE_LEAK(screen->answer_back); 10480 TRACE_FREE_LEAK(screen->printer_state.printer_command); 10481 TRACE_FREE_LEAK(screen->disallowedColorOps); 10482 TRACE_FREE_LEAK(screen->disallowedFontOps); 10483 TRACE_FREE_LEAK(screen->disallowedMouseOps); 10484 TRACE_FREE_LEAK(screen->disallowedPasteControls); 10485 TRACE_FREE_LEAK(screen->disallowedTcapOps); 10486 TRACE_FREE_LEAK(screen->disallowedWinOps); 10487 TRACE_FREE_LEAK(screen->default_string); 10488 TRACE_FREE_LEAK(screen->eightbit_select_types); 10489 10490#if OPT_WIDE_CHARS 10491 TRACE_FREE_LEAK(screen->utf8_select_types); 10492#endif 10493 10494#if 0 10495 for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) { 10496 TRACE_FREE_LEAK(screen->MenuFontName(n)); 10497 } 10498#endif 10499 10500 TRACE_FREE_LEAK(screen->initial_font); 10501 10502#if OPT_LUIT_PROG 10503 TRACE_FREE_LEAK(xw->misc.locale_str); 10504 TRACE_FREE_LEAK(xw->misc.localefilter); 10505#endif 10506 10507#if OPT_RENDERFONT 10508 TRACE_FREE_LEAK(xw->misc.default_xft.f_n); 10509#if OPT_WIDE_CHARS 10510 TRACE_FREE_LEAK(xw->misc.default_xft.f_w); 10511#endif 10512 TRACE_FREE_LEAK(xw->misc.render_font_s); 10513#endif 10514 10515 TRACE_FREE_LEAK(xw->misc.default_font.f_n); 10516 TRACE_FREE_LEAK(xw->misc.default_font.f_b); 10517 10518#if OPT_WIDE_CHARS 10519 TRACE_FREE_LEAK(xw->misc.default_font.f_w); 10520 TRACE_FREE_LEAK(xw->misc.default_font.f_wb); 10521#endif 10522 10523 TRACE_FREE_LEAK(xw->work.wm_name); 10524 freeFontLists(&(xw->work.fonts.x11)); 10525#if OPT_RENDERFONT 10526 freeFontLists(&(xw->work.fonts.xft)); 10527#endif 10528 10529 xtermFontName(NULL); 10530#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 10531 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n); 10532 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b); 10533#if OPT_WIDE_CHARS 10534 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w); 10535 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb); 10536#endif 10537 freeFontLists(&(screen->cacheVTFonts.fonts.x11)); 10538 for (n = 0; n < NMENUFONTS; ++n) { 10539 for (k = 0; k < fMAX; ++k) { 10540 if (screen->menu_font_names[n][k] != 10541 screen->cacheVTFonts.menu_font_names[n][k]) { 10542 if (screen->menu_font_names[n][k] != _Font_Selected_) { 10543 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 10544 } 10545 TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]); 10546 } else { 10547 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 10548 } 10549 } 10550 } 10551#endif 10552 10553#if OPT_BLINK_CURS 10554 TRACE_FREE_LEAK(screen->cursor_blink_s); 10555#endif 10556 10557#if OPT_REGIS_GRAPHICS 10558 TRACE_FREE_LEAK(screen->graphics_regis_default_font); 10559 TRACE_FREE_LEAK(screen->graphics_regis_screensize); 10560#endif 10561#if OPT_GRAPHICS 10562 TRACE_FREE_LEAK(screen->graph_termid); 10563 TRACE_FREE_LEAK(screen->graphics_max_size); 10564#endif 10565 10566 for (n = 0; n < NSELECTUNITS; ++n) { 10567#if OPT_SELECT_REGEX 10568 TRACE_FREE_LEAK(screen->selectExpr[n]); 10569#endif 10570#if OPT_XRES_QUERY 10571 TRACE_FREE_LEAK(screen->onClick[n]); 10572#endif 10573 } 10574 10575 XtFree((void *) (screen->selection_atoms)); 10576 10577 for (n = 0; n < MAX_SELECTIONS; ++n) { 10578 free(screen->selected_cells[n].data_buffer); 10579 } 10580 10581 if (defaultTranslations != xtermClassRec.core_class.tm_table) { 10582 TRACE_FREE_LEAK(defaultTranslations); 10583 } 10584 TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table); 10585 TRACE_FREE_LEAK(xw->keyboard.shift_escape_s); 10586 TRACE_FREE_LEAK(xw->keyboard.extra_translations); 10587 TRACE_FREE_LEAK(xw->keyboard.shell_translations); 10588 TRACE_FREE_LEAK(xw->keyboard.xterm_translations); 10589 TRACE_FREE_LEAK(xw->keyboard.print_translations); 10590 UnmapSelections(xw); 10591 10592 XtFree((void *) (xw->visInfo)); 10593 10594#if OPT_WIDE_CHARS 10595 FreeTypedBuffer(XChar2b); 10596 FreeTypedBuffer(char); 10597#endif 10598#if OPT_RENDERFONT 10599#if OPT_RENDERWIDE 10600 FreeTypedBuffer(XftCharSpec); 10601#else 10602 FreeTypedBuffer(XftChar8); 10603#endif 10604#endif 10605 10606 TRACE_FREE_LEAK(myState.print_area); 10607 TRACE_FREE_LEAK(myState.string_area); 10608 memset(&myState, 0, sizeof(myState)); 10609 10610#endif /* defined(NO_LEAKS) */ 10611} 10612 10613#ifndef NO_ACTIVE_ICON 10614static void * 10615getProperty(Display *dpy, 10616 Window w, 10617 Atom req_type, 10618 const char *prop_name) 10619{ 10620 Atom property; 10621 Atom actual_return_type; 10622 int actual_format_return = 0; 10623 unsigned long nitems_return = 0; 10624 unsigned long bytes_after_return = 0; 10625 unsigned char *prop_return = 0; 10626 long long_length = 1024; 10627 size_t limit; 10628 char *result = 0; 10629 10630 TRACE(("getProperty %s(%s)\n", prop_name, 10631 req_type ? TraceAtomName(dpy, req_type) : "?")); 10632 property = XInternAtom(dpy, prop_name, False); 10633 10634 if (!xtermGetWinProp(dpy, 10635 w, 10636 property, 10637 0L, 10638 long_length, 10639 req_type, 10640 &actual_return_type, 10641 &actual_format_return, 10642 &nitems_return, 10643 &bytes_after_return, 10644 &prop_return)) { 10645 TRACE((".. Cannot get %s property.\n", prop_name)); 10646 } else if (prop_return != 0) { 10647 10648 if (nitems_return != 0 && 10649 actual_format_return != 0 && 10650 actual_return_type == req_type) { 10651 /* 10652 * Null-terminate the result to make string handling easier. 10653 * The format==8 corresponds to strings, and the number of items 10654 * is the number of characters. 10655 */ 10656 if (actual_format_return == 8) { 10657 limit = nitems_return; 10658 } else { 10659 /* manpage is misleading - X really uses 'long', not 32-bits */ 10660 limit = sizeof(long) * nitems_return; 10661 } 10662 if ((result = malloc(limit + 1)) != 0) { 10663 memcpy(result, prop_return, limit); 10664 result[limit] = '\0'; 10665 } 10666 TRACE(("... result %s\n", result ? ("ok") : "null")); 10667 } 10668 XFree(prop_return); 10669 } else { 10670 TRACE((".. no property returned\n")); 10671 } 10672 return (void *) result; 10673} 10674 10675/* 10676 * Active icons are supported by fvwm. This feature is not supported by 10677 * metacity (gnome) or kwin (kde). Both metacity and kwin support (in 10678 * incompatible ways, e.g., one uses the icon theme as a fallback for window 10679 * decorations but the other does not, etc, ...) an icon as part of the window 10680 * decoration (usually on the upper-left of the window). 10681 * 10682 * In either case, xterm's icon will only be shown in the window decorations if 10683 * xterm does not use the active icon feature. 10684 * 10685 * This function (tries to) determine the window manager's name, so that we can 10686 * provide a useful automatic default for active icons. It is based on reading 10687 * wmctrl, which covers most of EWMH and ICCM. 10688 */ 10689static char * 10690getWindowManagerName(XtermWidget xw) 10691{ 10692 TScreen *screen = TScreenOf(xw); 10693 Display *dpy = screen->display; 10694 Window *sup_window = NULL; 10695 char *result = 0; 10696 10697 TRACE(("getWindowManagerName\n")); 10698#define getWinProp(type, name) \ 10699 (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name) 10700 if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == 0) { 10701 sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK"); 10702 } 10703 10704 /* 10705 * If we found the supporting window, get the property containing the 10706 * window manager's name. EWMH defines _NET_WM_NAME, while ICCM defines 10707 * WM_CLASS. There is no standard for the names stored there; 10708 * conventionally it is mixed case. In practice, the former is more often 10709 * set; the latter is not given (or is a lowercased version of the former). 10710 */ 10711 if (sup_window != 0) { 10712#define getStringProp(type,name) \ 10713 (char *)getProperty(dpy, *sup_window, type, name) 10714 if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == 0 10715 && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == 0 10716 && (result = getStringProp(XA_STRING, "WM_CLASS")) == 0) { 10717 TRACE(("... window manager does not tell its name\n")); 10718 } 10719 free(sup_window); 10720 } else { 10721 TRACE(("... Cannot get window manager info properties\n")); 10722 } 10723 if (result == 0) 10724 result = x_strdup("unknown"); 10725 TRACE(("... window manager name is %s\n", result)); 10726 return result; 10727} 10728 10729static Boolean 10730discount_frame_extents(XtermWidget xw, int *high, int *wide) 10731{ 10732 TScreen *screen = TScreenOf(xw); 10733 Display *dpy = screen->display; 10734 10735 Atom atom_supported = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False); 10736 Atom actual_type; 10737 int actual_format; 10738 long long_offset = 0; 10739 long long_length = 128; /* number of items to ask for at a time */ 10740 unsigned long nitems; 10741 unsigned long bytes_after; 10742 unsigned char *args; 10743 Boolean rc; 10744 10745 rc = xtermGetWinProp(dpy, 10746 VShellWindow(xw), 10747 atom_supported, 10748 long_offset, 10749 long_length, 10750 XA_CARDINAL, /* req_type */ 10751 &actual_type, /* actual_type_return */ 10752 &actual_format, /* actual_format_return */ 10753 &nitems, /* nitems_return */ 10754 &bytes_after, /* bytes_after_return */ 10755 &args /* prop_return */ 10756 ); 10757 10758 if (rc && args && (nitems == 4) && (actual_format == 32)) { 10759 long *extents = (long *) (void *) args; 10760 10761 TRACE(("_NET_FRAME_EXTENTS:\n")); 10762 TRACE((" left: %ld\n", extents[0])); 10763 TRACE((" right: %ld\n", extents[1])); 10764 TRACE((" top: %ld\n", extents[2])); 10765 TRACE((" bottom: %ld\n", extents[3])); 10766 10767 if (!x_strncasecmp(xw->work.wm_name, "gnome shell", 11)) { 10768 *wide -= (int) (extents[0] + extents[1]); /* -= (left+right) */ 10769 *high -= (int) (extents[2] + extents[3]); /* -= (top+bottom) */ 10770 TRACE(("...applied extents %d,%d\n", *high, *wide)); 10771 } else if (!x_strncasecmp(xw->work.wm_name, "compiz", 6)) { 10772 /* Ubuntu 16.04 is really off-by-one */ 10773 *wide -= (int) (extents[0] + extents[1] - 1); 10774 *high -= (int) (extents[2] + extents[3] - 1); 10775 TRACE(("...applied extents %d,%d\n", *high, *wide)); 10776 } else if (!x_strncasecmp(xw->work.wm_name, "fvwm", 4)) { 10777 TRACE(("...skipping extents\n")); 10778 } else { 10779 TRACE(("...ignoring extents\n")); 10780 rc = False; 10781 } 10782 } else { 10783 rc = False; 10784 } 10785 return rc; 10786} 10787#endif /* !NO_ACTIVE_ICON */ 10788 10789void 10790initBorderGC(XtermWidget xw, VTwin *win) 10791{ 10792 TScreen *screen = TScreenOf(xw); 10793 Pixel filler; 10794 10795 TRACE(("initBorderGC(%s) core bg %#lx, bd %#lx text fg %#lx, bg %#lx %s\n", 10796 (win == &(screen->fullVwin)) ? "full" : "icon", 10797 xw->core.background_pixel, 10798 xw->core.border_pixel, 10799 T_COLOR(screen, TEXT_FG), 10800 T_COLOR(screen, TEXT_BG), 10801 xw->misc.re_verse ? "reverse" : "normal")); 10802 if (xw->misc.color_inner_border 10803 && (xw->core.background_pixel != xw->core.border_pixel)) { 10804 /* 10805 * By default, try to match the inner window's background. 10806 */ 10807 if ((xw->core.background_pixel == T_COLOR(screen, TEXT_BG)) && 10808 (xw->core.border_pixel == T_COLOR(screen, TEXT_FG))) { 10809 filler = T_COLOR(screen, TEXT_BG); 10810 } else { 10811 filler = xw->core.border_pixel; 10812 } 10813 TRACE((" border %#lx\n", filler)); 10814 setCgsFore(xw, win, gcBorder, filler); 10815 setCgsBack(xw, win, gcBorder, filler); 10816 win->border_gc = getCgsGC(xw, win, gcBorder); 10817 } 10818#if USE_DOUBLE_BUFFER 10819 else if (resource.buffered) { 10820 filler = T_COLOR(screen, TEXT_BG); 10821 TRACE((" border %#lx (buffered)\n", filler)); 10822 setCgsFore(xw, win, gcBorder, filler); 10823 setCgsBack(xw, win, gcBorder, filler); 10824 win->border_gc = getCgsGC(xw, win, gcBorder); 10825 } 10826#endif 10827 else { 10828 TRACE((" border unused\n")); 10829 win->border_gc = 0; 10830 } 10831 10832 /* 10833 * Initialize a GC for double-buffering, needed for XFillRectangle call 10834 * in xtermClear2(). When not double-buffering, the XClearArea call works, 10835 * without requiring a separate GC. 10836 */ 10837#if USE_DOUBLE_BUFFER 10838 if (resource.buffered) { 10839 filler = (((xw->flags & BG_COLOR) && (xw->cur_background >= 0)) 10840 ? getXtermBG(xw, xw->flags, xw->cur_background) 10841 : T_COLOR(screen, TEXT_BG)); 10842 10843 TRACE((" filler %#lx %s\n", 10844 filler, 10845 xw->misc.re_verse ? "reverse" : "normal")); 10846 10847 setCgsFore(xw, win, gcFiller, filler); 10848 setCgsBack(xw, win, gcFiller, filler); 10849 10850 win->filler_gc = getCgsGC(xw, win, gcFiller); 10851 } 10852#endif 10853} 10854#if USE_DOUBLE_BUFFER 10855static Boolean 10856allocateDbe(XtermWidget xw, VTwin *target) 10857{ 10858 TScreen *screen = TScreenOf(xw); 10859 Boolean result = False; 10860 10861 target->drawable = target->window; 10862 10863 if (resource.buffered) { 10864 Window win = target->window; 10865 Drawable d; 10866 int major, minor; 10867 if (XdbeQueryExtension(XtDisplay(xw), &major, &minor)) { 10868 d = XdbeAllocateBackBufferName(XtDisplay(xw), win, 10869 (XdbeSwapAction) XdbeCopied); 10870 if (d == None) { 10871 fprintf(stderr, "Couldn't allocate a back buffer!\n"); 10872 exit(3); 10873 } 10874 target->drawable = d; 10875 screen->needSwap = 1; 10876 TRACE(("initialized double-buffering\n")); 10877 result = True; 10878 } else { 10879 resource.buffered = False; 10880 } 10881 } 10882 return result; 10883} 10884#endif /* USE_DOUBLE_BUFFER */ 10885 10886/*ARGSUSED*/ 10887static void 10888VTRealize(Widget w, 10889 XtValueMask * valuemask, 10890 XSetWindowAttributes * values) 10891{ 10892 XtermWidget xw = (XtermWidget) w; 10893 TScreen *screen = TScreenOf(xw); 10894 10895 const VTFontNames *myfont; 10896 struct Xinerama_geometry pos; 10897 int pr; 10898 Atom pid_atom; 10899 int i; 10900 10901 TRACE(("VTRealize " TRACE_L "\n")); 10902 10903 TabReset(xw->tabs); 10904 10905 if (screen->menu_font_number == fontMenu_default) { 10906 myfont = defaultVTFontNames(xw); 10907 } else { 10908 myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number)); 10909 } 10910 memset(screen->fnts, 0, sizeof(screen->fnts)); 10911 10912 if (!xtermLoadFont(xw, 10913 myfont, 10914 False, 10915 screen->menu_font_number)) { 10916 if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) { 10917 char *use_font = x_strdup(DEFFONT); 10918 xtermWarning("unable to open font \"%s\", trying \"%s\"....\n", 10919 myfont->f_n, use_font); 10920 (void) xtermLoadFont(xw, 10921 xtermFontName(use_font), 10922 False, 10923 screen->menu_font_number); 10924 screen->MenuFontName(screen->menu_font_number) = use_font; 10925 } 10926 } 10927 10928 /* really screwed if we couldn't open default font */ 10929 if (!GetNormalFont(screen, fNorm)->fs) { 10930 xtermWarning("unable to locate a suitable font\n"); 10931 Exit(1); 10932 } 10933#if OPT_WIDE_CHARS 10934 if (screen->utf8_mode) { 10935 TRACE(("check if this is a wide font, if not try again\n")); 10936 if (xtermLoadWideFonts(xw, False)) { 10937 SetVTFont(xw, screen->menu_font_number, True, NULL); 10938 /* we will not be able to switch to ISO-8859-1 */ 10939 if (!screen->mergedVTFonts) { 10940 screen->utf8_fonts = uAlways; 10941 update_font_utf8_fonts(); 10942 } 10943 } 10944 } 10945#endif 10946 10947 xtermSetupPointer(xw, screen->pointer_shape); 10948 10949 /* set defaults */ 10950 pos.x = 1; 10951 pos.y = 1; 10952 pos.w = 80; 10953 pos.h = 24; 10954 10955 TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry))); 10956 pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos); 10957 TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w)); 10958 10959 set_max_col(screen, (int) (pos.w - 1)); /* units in character cells */ 10960 set_max_row(screen, (int) (pos.h - 1)); /* units in character cells */ 10961 xtermUpdateFontInfo(xw, False); 10962 10963 pos.w = screen->fullVwin.fullwidth; 10964 pos.h = screen->fullVwin.fullheight; 10965 10966 TRACE(("... BorderWidth: widget %d parent %d shell %d\n", 10967 BorderWidth(xw), 10968 BorderWidth(XtParent(xw)), 10969 BorderWidth(SHELL_OF(xw)))); 10970 10971 if ((pr & XValue) && (XNegative & pr)) { 10972 pos.x = (Position) (pos.x + (pos.scr_w 10973 - (int) pos.w 10974 - (BorderWidth(XtParent(xw)) * 2))); 10975 } 10976 if ((pr & YValue) && (YNegative & pr)) { 10977 pos.y = (Position) (pos.y + (pos.scr_h 10978 - (int) pos.h 10979 - (BorderWidth(XtParent(xw)) * 2))); 10980 } 10981 pos.x = (Position) (pos.x + pos.scr_x); 10982 pos.y = (Position) (pos.y + pos.scr_y); 10983 10984 /* set up size hints for window manager; min 1 char by 1 char */ 10985 getXtermSizeHints(xw); 10986 xtermSizeHints(xw, (xw->misc.scrollbar 10987 ? (screen->scrollWidget->core.width 10988 + BorderWidth(screen->scrollWidget)) 10989 : 0)); 10990 10991 xw->hints.x = pos.x; 10992 xw->hints.y = pos.y; 10993#if OPT_MAXIMIZE 10994 /* assure single-increment resize for fullscreen */ 10995 if (xw->work.ewmh[0].mode) { 10996 xw->hints.width_inc = 1; 10997 xw->hints.height_inc = 1; 10998 } 10999#endif 11000 if ((XValue & pr) || (YValue & pr)) { 11001 xw->hints.flags |= USSize | USPosition; 11002 xw->hints.flags |= PWinGravity; 11003 switch (pr & (XNegative | YNegative)) { 11004 case 0: 11005 xw->hints.win_gravity = NorthWestGravity; 11006 break; 11007 case XNegative: 11008 xw->hints.win_gravity = NorthEastGravity; 11009 break; 11010 case YNegative: 11011 xw->hints.win_gravity = SouthWestGravity; 11012 break; 11013 default: 11014 xw->hints.win_gravity = SouthEastGravity; 11015 break; 11016 } 11017 } else { 11018 /* set a default size, but do *not* set position */ 11019 xw->hints.flags |= PSize; 11020 } 11021 xw->hints.height = xw->hints.base_height 11022 + xw->hints.height_inc * MaxRows(screen); 11023 xw->hints.width = xw->hints.base_width 11024 + xw->hints.width_inc * MaxCols(screen); 11025 11026 if ((WidthValue & pr) || (HeightValue & pr)) 11027 xw->hints.flags |= USSize; 11028 else 11029 xw->hints.flags |= PSize; 11030 11031 /* 11032 * Note that the size-hints are for the shell, while the resize-request 11033 * is for the vt100 widget. They are not the same size. 11034 */ 11035 (void) REQ_RESIZE((Widget) xw, 11036 (Dimension) pos.w, (Dimension) pos.h, 11037 &xw->core.width, &xw->core.height); 11038 11039 /* XXX This is bogus. We are parsing geometries too late. This 11040 * is information that the shell widget ought to have before we get 11041 * realized, so that it can do the right thing. 11042 */ 11043 if (xw->hints.flags & USPosition) 11044 XMoveWindow(XtDisplay(xw), VShellWindow(xw), 11045 xw->hints.x, xw->hints.y); 11046 11047 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 11048 TRACE_HINTS(&xw->hints); 11049 XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints); 11050 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 11051 TRACE_WM_HINTS(xw); 11052 11053 if ((pid_atom = XInternAtom(XtDisplay(xw), "_NET_WM_PID", False)) != None) { 11054 /* XChangeProperty format 32 really is "long" */ 11055 unsigned long pid_l = (unsigned long) getpid(); 11056 TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l)); 11057 XChangeProperty(XtDisplay(xw), VShellWindow(xw), 11058 pid_atom, XA_CARDINAL, 32, PropModeReplace, 11059 (unsigned char *) &pid_l, 1); 11060 } 11061 11062 XFlush(XtDisplay(xw)); /* get it out to window manager */ 11063 11064 /* use ForgetGravity instead of SouthWestGravity because translating 11065 the Expose events for ConfigureNotifys is too hard */ 11066 values->bit_gravity = (GravityIsNorthWest(xw) 11067 ? NorthWestGravity 11068 : ForgetGravity); 11069 screen->fullVwin.window = XtWindow(xw) = 11070 XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)), 11071 xw->core.x, xw->core.y, 11072 xw->core.width, xw->core.height, BorderWidth(xw), 11073 (int) xw->core.depth, 11074 InputOutput, CopyFromParent, 11075 *valuemask | CWBitGravity, values); 11076#if USE_DOUBLE_BUFFER 11077 if (allocateDbe(xw, &(screen->fullVwin))) { 11078 screen->needSwap = 1; 11079 TRACE(("initialized full double-buffering\n")); 11080 } else { 11081 resource.buffered = False; 11082 screen->fullVwin.drawable = screen->fullVwin.window; 11083 } 11084#endif /* USE_DOUBLE_BUFFER */ 11085 screen->event_mask = values->event_mask; 11086 11087#ifndef NO_ACTIVE_ICON 11088 /* 11089 * Normally, the font-number for icon fonts does not correspond with any of 11090 * the menu-selectable fonts. If we cannot load the font given for the 11091 * iconFont resource, try with font1 aka "Unreadable". 11092 */ 11093 screen->icon_fontnum = -1; 11094 if (getIconicFont(screen)->fs == 0) { 11095 getIconicFont(screen)->fs = 11096 xtermLoadQueryFont(xw, screen->MenuFontName(fontMenu_font1)); 11097 ReportIcons(("%susing font1 '%s' as iconFont\n", 11098 (getIconicFont(screen)->fs 11099 ? "" 11100 : "NOT "), 11101 screen->MenuFontName(fontMenu_font1))); 11102 } 11103#if OPT_RENDERFONT 11104 /* 11105 * If we still have no result from iconFont resource (perhaps because fonts 11106 * are missing) but are using Xft, try to use that instead. We prefer 11107 * bitmap fonts in any case, since scaled fonts are usually less readable, 11108 * particularly at small sizes. 11109 */ 11110 if (UsingRenderFont(xw) 11111 && getIconicFont(screen)->fs == 0) { 11112 screen->icon_fontnum = fontMenu_default; 11113 getIconicFont(screen)->fs = GetNormalFont(screen, fNorm)->fs; /* need for next-if */ 11114 ReportIcons(("using TrueType font as iconFont\n")); 11115 } 11116#endif 11117 xw->work.wm_name = getWindowManagerName(xw); 11118 if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) { 11119 ReportIcons(("window manager name is %s\n", xw->work.wm_name)); 11120 if (x_strncasecmp(xw->work.wm_name, "fvwm", 4) && 11121 x_strncasecmp(xw->work.wm_name, "window maker", 12)) { 11122 xw->work.active_icon = eiFalse; 11123 TRACE(("... disable active_icon\n")); 11124 } 11125 } 11126 TRACE((".. if active_icon (%d), get its font\n", xw->work.active_icon)); 11127 if (xw->work.active_icon && getIconicFont(screen)->fs) { 11128 int iconX = 0, iconY = 0; 11129 Widget shell = SHELL_OF(xw); 11130 VTwin *win = &(screen->iconVwin); 11131 int save_fontnum = screen->menu_font_number; 11132 11133 ReportIcons(("initializing active-icon %d\n", screen->icon_fontnum)); 11134 screen->menu_font_number = screen->icon_fontnum; 11135 XtVaGetValues(shell, 11136 XtNiconX, &iconX, 11137 XtNiconY, &iconY, 11138 (XtPointer) 0); 11139 xtermComputeFontInfo(xw, &(screen->iconVwin), 11140 getIconicFont(screen)->fs, 0); 11141 screen->menu_font_number = save_fontnum; 11142 11143 /* since only one client is permitted to select for Button 11144 * events, we have to let the window manager get 'em... 11145 */ 11146 values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask); 11147 values->border_pixel = xw->misc.icon_border_pixel; 11148 11149 screen->iconVwin.window = 11150 XCreateWindow(XtDisplay(xw), 11151 RootWindowOfScreen(XtScreen(shell)), 11152 iconX, iconY, 11153 screen->iconVwin.fullwidth, 11154 screen->iconVwin.fullheight, 11155 xw->misc.icon_border_width, 11156 (int) xw->core.depth, 11157 InputOutput, CopyFromParent, 11158 *valuemask | CWBitGravity | CWBorderPixel, 11159 values); 11160#if USE_DOUBLE_BUFFER 11161 if (allocateDbe(xw, &(screen->iconVwin))) { 11162 TRACE(("initialized icon double-buffering\n")); 11163 } else { 11164 resource.buffered = False; 11165 screen->iconVwin.drawable = screen->iconVwin.window; 11166 screen->fullVwin.drawable = screen->fullVwin.window; 11167 } 11168#endif /* USE_DOUBLE_BUFFER */ 11169 XtVaSetValues(shell, 11170 XtNiconWindow, screen->iconVwin.window, 11171 (XtPointer) 0); 11172 XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w); 11173 11174 setCgsFont(xw, win, gcNorm, getIconicFont(screen)); 11175 setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG)); 11176 setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG)); 11177 11178 copyCgs(xw, win, gcBold, gcNorm); 11179 11180 setCgsFont(xw, win, gcNormReverse, getIconicFont(screen)); 11181 setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG)); 11182 setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG)); 11183 11184 copyCgs(xw, win, gcBoldReverse, gcNormReverse); 11185 11186 initBorderGC(xw, win); 11187 11188#if OPT_TOOLBAR 11189 /* 11190 * Toolbar is initialized before we get here. Enable the menu item 11191 * and set it properly. 11192 */ 11193 SetItemSensitivity(vtMenuEntries[vtMenu_activeicon].widget, True); 11194 update_activeicon(); 11195#endif 11196 } else { 11197 ReportIcons(("disabled active-icon\n")); 11198 xw->work.active_icon = eiFalse; 11199 } 11200#endif /* NO_ACTIVE_ICON */ 11201 11202#if OPT_INPUT_METHOD 11203 VTInitI18N(xw); 11204#endif 11205#if OPT_NUM_LOCK 11206 VTInitModifiers(xw); 11207#if OPT_EXTRA_PASTE 11208 if (xw->keyboard.extra_translations) { 11209 XtOverrideTranslations((Widget) xw, 11210 XtParseTranslationTable(xw->keyboard.extra_translations)); 11211 } 11212#endif 11213#endif 11214 11215 set_cursor_gcs(xw); 11216 initBorderGC(xw, &(screen->fullVwin)); 11217 11218 /* Reset variables used by ANSI emulation. */ 11219 11220 resetCharsets(screen); 11221 11222 XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor); 11223 11224 set_cur_col(screen, 0); 11225 set_cur_row(screen, 0); 11226 set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1); 11227 set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1); 11228 resetMargins(xw); 11229 11230 memset(screen->sc, 0, sizeof(screen->sc)); 11231 11232 /* Mark screen buffer as unallocated. We wait until the run loop so 11233 that the child process does not fork and exec with all the dynamic 11234 memory it will never use. If we were to do it here, the 11235 swap space for new process would be huge for huge savelines. */ 11236#if OPT_TEK4014 11237 if (!tekWidget) /* if not called after fork */ 11238#endif 11239 { 11240 screen->visbuf = NULL; 11241 screen->saveBuf_index = NULL; 11242 } 11243 11244 ResetWrap(screen); 11245 screen->scrolls = screen->incopy = 0; 11246 xtermSetCursorBox(screen); 11247 11248 screen->savedlines = 0; 11249 11250 for (i = 0; i < 2; ++i) { 11251 screen->whichBuf = !screen->whichBuf; 11252 CursorSave(xw); 11253 } 11254 11255#ifndef NO_ACTIVE_ICON 11256 if (!xw->work.active_icon) 11257#endif 11258 xtermLoadIcon(xw, resource.icon_hint); 11259 11260 /* 11261 * Do this last, since it may change the layout via a resize. 11262 */ 11263 if (xw->misc.scrollbar) { 11264 screen->fullVwin.sb_info.width = 0; 11265 ScrollBarOn(xw, False); 11266 } 11267 11268 xtermSetWinSize(xw); 11269 TRACE(("" TRACE_R " VTRealize\n")); 11270} 11271 11272#if OPT_INPUT_METHOD 11273 11274/* limit this feature to recent XFree86 since X11R6.x core dumps */ 11275#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING) 11276#define USE_XIM_INSTANTIATE_CB 11277 11278static void 11279xim_instantiate_cb(Display *display, 11280 XPointer client_data GCC_UNUSED, 11281 XPointer call_data GCC_UNUSED) 11282{ 11283 XtermWidget xw = term; 11284 11285 TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data)); 11286 11287 if (display == XtDisplay(xw)) { 11288 VTInitI18N(xw); 11289 } 11290} 11291 11292static void 11293xim_destroy_cb(XIM im GCC_UNUSED, 11294 XPointer client_data GCC_UNUSED, 11295 XPointer call_data GCC_UNUSED) 11296{ 11297 XtermWidget xw = term; 11298 TInput *input = lookupTInput(xw, (Widget) xw); 11299 11300 TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n", 11301 (long) im, client_data, call_data)); 11302 if (input) 11303 input->xic = NULL; 11304 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 11305 xim_instantiate_cb, NULL); 11306} 11307#endif /* X11R6+ */ 11308 11309static Boolean 11310xim_create_fs(XtermWidget xw) 11311{ 11312 XFontStruct **fonts; 11313 char **font_name_list; 11314 char **missing_charset_list; 11315 char *def_string; 11316 int missing_charset_count; 11317 unsigned i, j; 11318 11319 if (xw->work.xim_fs == 0) { 11320 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 11321 xw->misc.f_x, 11322 &missing_charset_list, 11323 &missing_charset_count, 11324 &def_string); 11325 if (xw->work.xim_fs == NULL) { 11326 xtermWarning("Preparation of font set " 11327 "\"%s\" for XIM failed.\n", xw->misc.f_x); 11328 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 11329 DEFXIMFONT, 11330 &missing_charset_list, 11331 &missing_charset_count, 11332 &def_string); 11333 } 11334 } 11335 if (xw->work.xim_fs == NULL) { 11336 xtermWarning("Preparation of default font set " 11337 "\"%s\" for XIM failed.\n", DEFXIMFONT); 11338 cleanupInputMethod(xw); 11339 xw->work.cannot_im = True; 11340 } else { 11341 (void) XExtentsOfFontSet(xw->work.xim_fs); 11342 j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list); 11343 for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) { 11344 if (xw->work.xim_fs_ascent < (*fonts)->ascent) 11345 xw->work.xim_fs_ascent = (*fonts)->ascent; 11346 } 11347 } 11348 return (Boolean) !(xw->work.cannot_im); 11349} 11350 11351static void 11352xim_create_xic(XtermWidget xw, Widget theInput) 11353{ 11354 Display *myDisplay = XtDisplay(theInput); 11355 Window myWindow = XtWindow(theInput); 11356 unsigned i, j; 11357 char *p = NULL, *s, *t, *ns, *end, buf[32]; 11358 XIMStyles *xim_styles; 11359 XIMStyle input_style = 0; 11360 Bool found; 11361 static struct { 11362 const char *name; 11363 unsigned long code; 11364 } known_style[] = { 11365 { 11366 "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing) 11367 }, 11368 { 11369 "OffTheSpot", (XIMPreeditArea | XIMStatusArea) 11370 }, 11371 { 11372 "Root", (XIMPreeditNothing | XIMStatusNothing) 11373 }, 11374 }; 11375 TInput *input = lookupTInput(xw, theInput); 11376 11377 if (xw->work.cannot_im) { 11378 return; 11379 } 11380 11381 if (input == 0) { 11382 for (i = 0; i < NINPUTWIDGETS; ++i) { 11383 if (xw->work.inputs[i].w == 0) { 11384 input = xw->work.inputs + i; 11385 input->w = theInput; 11386 break; 11387 } 11388 } 11389 } 11390 11391 if (input == 0) { 11392 xtermWarning("attempted to add too many input widgets\n"); 11393 return; 11394 } 11395 11396 TRACE(("xim_real_init\n")); 11397 11398 if (IsEmpty(xw->misc.input_method)) { 11399 if ((p = XSetLocaleModifiers("")) != NULL && *p) { 11400 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 11401 } 11402 } else { 11403 s = xw->misc.input_method; 11404 i = 5 + (unsigned) strlen(s); 11405 11406 t = (char *) MyStackAlloc(i, buf); 11407 if (t == NULL) { 11408 SysError(ERROR_VINIT); 11409 } else { 11410 11411 for (ns = s; ns && *s;) { 11412 while (*s && isspace(CharOf(*s))) 11413 s++; 11414 if (!*s) 11415 break; 11416 if ((ns = end = strchr(s, ',')) == 0) 11417 end = s + strlen(s); 11418 while ((end != s) && isspace(CharOf(end[-1]))) 11419 end--; 11420 11421 if (end != s) { 11422 strcpy(t, "@im="); 11423 strncat(t, s, (size_t) (end - s)); 11424 11425 if ((p = XSetLocaleModifiers(t)) != 0 && *p 11426 && (input->xim = XOpenIM(myDisplay, 11427 NULL, 11428 NULL, 11429 NULL)) != 0) { 11430 break; 11431 } 11432 11433 } 11434 s = ns + 1; 11435 } 11436 MyStackFree(t, buf); 11437 } 11438 } 11439 11440 if (input->xim == NULL 11441 && (p = XSetLocaleModifiers("@im=none")) != NULL 11442 && *p) { 11443 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 11444 } 11445 11446 if (!input->xim) { 11447 xtermWarning("Failed to open input method\n"); 11448 return; 11449 } 11450 TRACE(("VTInitI18N opened input method:%s\n", NonNull(p))); 11451 11452 if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0) 11453 || !xim_styles 11454 || !xim_styles->count_styles) { 11455 xtermWarning("input method doesn't support any style\n"); 11456 cleanupInputMethod(xw); 11457 xw->work.cannot_im = True; 11458 return; 11459 } 11460 11461 found = False; 11462 for (s = xw->misc.preedit_type; s && !found;) { 11463 while (*s && isspace(CharOf(*s))) 11464 s++; 11465 if (!*s) 11466 break; 11467 if ((ns = end = strchr(s, ',')) != 0) 11468 ns++; 11469 else 11470 end = s + strlen(s); 11471 while ((end != s) && isspace(CharOf(end[-1]))) 11472 end--; 11473 11474 if (end != s) { /* just in case we have a spurious comma */ 11475 TRACE(("looking for style '%.*s'\n", (int) (end - s), s)); 11476 for (i = 0; i < XtNumber(known_style); i++) { 11477 if ((int) strlen(known_style[i].name) == (end - s) 11478 && !strncmp(s, known_style[i].name, (size_t) (end - s))) { 11479 input_style = known_style[i].code; 11480 for (j = 0; j < xim_styles->count_styles; j++) { 11481 if (input_style == xim_styles->supported_styles[j]) { 11482 found = True; 11483 break; 11484 } 11485 } 11486 if (found) 11487 break; 11488 } 11489 } 11490 } 11491 11492 s = ns; 11493 } 11494 XFree(xim_styles); 11495 11496 if (!found) { 11497 xtermWarning("input method doesn't support my preedit type (%s)\n", 11498 xw->misc.preedit_type); 11499 cleanupInputMethod(xw); 11500 xw->work.cannot_im = True; 11501 return; 11502 } 11503 11504 /* 11505 * Check for styles we do not yet support. 11506 */ 11507 TRACE(("input_style %#lx\n", input_style)); 11508 if (input_style == (XIMPreeditArea | XIMStatusArea)) { 11509 xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n"); 11510 cleanupInputMethod(xw); 11511 xw->work.cannot_im = True; 11512 return; 11513 } 11514 11515 /* 11516 * For XIMPreeditPosition (or OverTheSpot), XIM client has to 11517 * prepare a font. 11518 * The font has to be locale-dependent XFontSet, whereas 11519 * XTerm use Unicode font. This leads a problem that the 11520 * same font cannot be used for XIM preedit. 11521 */ 11522 if (input_style != (XIMPreeditNothing | XIMStatusNothing)) { 11523 XVaNestedList p_list; 11524 XPoint spot = 11525 {0, 0}; 11526 11527 if (xim_create_fs(xw)) { 11528 p_list = XVaCreateNestedList(0, 11529 XNSpotLocation, &spot, 11530 XNFontSet, xw->work.xim_fs, 11531 (void *) 0); 11532 input->xic = XCreateIC(input->xim, 11533 XNInputStyle, input_style, 11534 XNClientWindow, myWindow, 11535 XNFocusWindow, myWindow, 11536 XNPreeditAttributes, p_list, 11537 (void *) 0); 11538 } 11539 } else { 11540 input->xic = XCreateIC(input->xim, XNInputStyle, input_style, 11541 XNClientWindow, myWindow, 11542 XNFocusWindow, myWindow, 11543 (void *) 0); 11544 } 11545 11546 if (!input->xic) { 11547 xtermWarning("Failed to create input context\n"); 11548 cleanupInputMethod(xw); 11549 } 11550#if defined(USE_XIM_INSTANTIATE_CB) 11551 else { 11552 XIMCallback destroy_cb; 11553 11554 destroy_cb.callback = xim_destroy_cb; 11555 destroy_cb.client_data = NULL; 11556 if (XSetIMValues(input->xim, 11557 XNDestroyCallback, 11558 &destroy_cb, 11559 (void *) 0)) { 11560 xtermWarning("Could not set destroy callback to IM\n"); 11561 } 11562 } 11563#endif 11564 11565 return; 11566} 11567 11568static void 11569xim_real_init(XtermWidget xw) 11570{ 11571 xim_create_xic(xw, (Widget) xw); 11572} 11573 11574static void 11575VTInitI18N(XtermWidget xw) 11576{ 11577 if (xw->misc.open_im) { 11578 xim_real_init(xw); 11579 11580#if defined(USE_XIM_INSTANTIATE_CB) 11581 if (lookupTInput(xw, (Widget) xw) == NULL 11582 && !xw->work.cannot_im 11583 && xw->misc.retry_im-- > 0) { 11584 sleep(3); 11585 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 11586 xim_instantiate_cb, NULL); 11587 } 11588#endif 11589 } 11590} 11591 11592TInput * 11593lookupTInput(XtermWidget xw, Widget w) 11594{ 11595 TInput *result = 0; 11596 unsigned n; 11597 11598 for (n = 0; n < NINPUTWIDGETS; ++n) { 11599 if (xw->work.inputs[n].w == w) { 11600 result = xw->work.inputs + n; 11601 break; 11602 } 11603 } 11604 11605 return result; 11606} 11607#endif /* OPT_INPUT_METHOD */ 11608 11609static void 11610set_cursor_outline_gc(XtermWidget xw, 11611 Bool filled, 11612 Pixel fg, 11613 Pixel bg, 11614 Pixel cc) 11615{ 11616 TScreen *screen = TScreenOf(xw); 11617 VTwin *win = WhichVWin(screen); 11618 CgsEnum cgsId = gcVTcursOutline; 11619 11620 if (cc == bg) 11621 cc = fg; 11622 11623 if (filled) { 11624 setCgsFore(xw, win, cgsId, bg); 11625 setCgsBack(xw, win, cgsId, cc); 11626 } else { 11627 setCgsFore(xw, win, cgsId, cc); 11628 setCgsBack(xw, win, cgsId, bg); 11629 } 11630} 11631 11632static Boolean 11633VTSetValues(Widget cur, 11634 Widget request GCC_UNUSED, 11635 Widget wnew, 11636 ArgList args GCC_UNUSED, 11637 Cardinal *num_args GCC_UNUSED) 11638{ 11639 XtermWidget curvt = (XtermWidget) cur; 11640 XtermWidget newvt = (XtermWidget) wnew; 11641 Boolean refresh_needed = False; 11642 Boolean fonts_redone = False; 11643 11644 if ((T_COLOR(TScreenOf(curvt), TEXT_BG) != 11645 T_COLOR(TScreenOf(newvt), TEXT_BG)) || 11646 (T_COLOR(TScreenOf(curvt), TEXT_FG) != 11647 T_COLOR(TScreenOf(newvt), TEXT_FG)) || 11648 (TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) != 11649 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) || 11650 strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 11651 if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 11652 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt); 11653 } 11654 if (xtermLoadFont(newvt, 11655 xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)), 11656 True, TScreenOf(newvt)->menu_font_number)) { 11657 /* resizing does the redisplay, so don't ask for it here */ 11658 refresh_needed = True; 11659 fonts_redone = True; 11660 } else if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 11661 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt); 11662 } 11663 } 11664 if (!fonts_redone 11665 && (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) != 11666 T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) { 11667 if (set_cursor_gcs(newvt)) 11668 refresh_needed = True; 11669 } 11670 if (curvt->misc.re_verse != newvt->misc.re_verse) { 11671 newvt->flags ^= REVERSE_VIDEO; 11672 ReverseVideo(newvt); 11673 /* ReverseVideo toggles */ 11674 newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse); 11675 refresh_needed = True; 11676 } 11677 if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) != 11678 T_COLOR(TScreenOf(newvt), MOUSE_FG)) || 11679 (T_COLOR(TScreenOf(curvt), MOUSE_BG) != 11680 T_COLOR(TScreenOf(newvt), MOUSE_BG))) { 11681 recolor_cursor(TScreenOf(newvt), 11682 TScreenOf(newvt)->pointer_cursor, 11683 T_COLOR(TScreenOf(newvt), MOUSE_FG), 11684 T_COLOR(TScreenOf(newvt), MOUSE_BG)); 11685 refresh_needed = True; 11686 } 11687 if (curvt->misc.scrollbar != newvt->misc.scrollbar) { 11688 ToggleScrollBar(newvt); 11689 } 11690 11691 return refresh_needed; 11692} 11693 11694/* 11695 * Given a font-slot and information about selection/reverse, find the 11696 * corresponding cached-GC slot. 11697 */ 11698#if OPT_WIDE_ATTRS 11699static int 11700reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font) 11701{ 11702 TScreen *screen = TScreenOf(xw); 11703 CgsEnum result = gcMAX; 11704 11705 (void) screen; 11706 if (ReverseOrHilite(screen, attr_flags, hilite)) { 11707 switch (font) { 11708 case fNorm: 11709 result = gcNormReverse; 11710 break; 11711 case fBold: 11712 result = gcBoldReverse; 11713 break; 11714#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 11715 case fItal: 11716 result = gcNormReverse; /* FIXME */ 11717 break; 11718#endif 11719#if OPT_WIDE_CHARS 11720 case fWide: 11721 result = gcWideReverse; 11722 break; 11723 case fWBold: 11724 result = gcWBoldReverse; 11725 break; 11726 case fWItal: 11727 result = gcWideReverse; /* FIXME */ 11728 break; 11729#endif 11730 } 11731 } else { 11732 switch (font) { 11733 case fNorm: 11734 result = gcNorm; 11735 break; 11736 case fBold: 11737 result = gcBold; 11738 break; 11739#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 11740 case fItal: 11741 result = gcNorm; /* FIXME */ 11742 break; 11743#endif 11744#if OPT_WIDE_CHARS 11745 case fWide: 11746 result = gcWide; 11747 break; 11748 case fWBold: 11749 result = gcWBold; 11750 break; 11751 case fWItal: 11752 result = gcWide; /* FIXME */ 11753 break; 11754#endif 11755 } 11756 } 11757 return (int) result; 11758} 11759#endif 11760 11761#define setGC(code) set_at = __LINE__, currentCgs = code 11762 11763#define OutsideSelection(screen,srow,scol) \ 11764 ((srow) > (screen)->endH.row || \ 11765 ((srow) == (screen)->endH.row && \ 11766 (scol) >= (screen)->endH.col) || \ 11767 (srow) < (screen)->startH.row || \ 11768 ((srow) == (screen)->startH.row && \ 11769 (scol) < (screen)->startH.col)) 11770 11771/* 11772 * Shows cursor at new cursor position in screen. 11773 */ 11774void 11775ShowCursor(XtermWidget xw) 11776{ 11777 TScreen *screen = TScreenOf(xw); 11778 XTermDraw params; 11779 IChar base; 11780 unsigned flags; 11781 CellColor fg_bg = initCColor; 11782 GC currentGC; 11783 GC outlineGC; 11784 CgsEnum currentCgs = gcMAX; 11785 VTwin *currentWin = WhichVWin(screen); 11786 int set_at; 11787 Bool in_selection; 11788 Bool reversed; 11789 Bool filled; 11790 Pixel fg_pix; 11791 Pixel bg_pix; 11792 Pixel tmp; 11793#if OPT_HIGHLIGHT_COLOR 11794 Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG); 11795 Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG); 11796 Boolean use_selbg; 11797 Boolean use_selfg; 11798#endif 11799#if OPT_WIDE_CHARS 11800 int my_col = 0; 11801#endif 11802 int cursor_col; 11803 CLineData *ld = 0; 11804 11805 if (screen->cursor_state == BLINKED_OFF) 11806 return; 11807 11808 if (screen->eventMode != NORMAL) 11809 return; 11810 11811 if (INX2ROW(screen, screen->cur_row) > screen->max_row) 11812 return; 11813 11814 screen->cursorp.row = screen->cur_row; 11815 cursor_col = screen->cursorp.col = screen->cur_col; 11816 screen->cursor_moved = False; 11817 11818#ifndef NO_ACTIVE_ICON 11819 if (IsIcon(screen)) { 11820 screen->cursor_state = ON; 11821 return; 11822 } 11823#endif /* NO_ACTIVE_ICON */ 11824 11825 ld = getLineData(screen, screen->cur_row); 11826 11827 base = ld->charData[cursor_col]; 11828 flags = ld->attribs[cursor_col]; 11829 11830 if_OPT_WIDE_CHARS(screen, { 11831 if (base == HIDDEN_CHAR && cursor_col > 0) { 11832 /* if cursor points to non-initial part of wide character, 11833 * back it up 11834 */ 11835 --cursor_col; 11836 base = ld->charData[cursor_col]; 11837 } 11838 my_col = cursor_col; 11839 if (base == 0) 11840 base = ' '; 11841 if (isWide((int) base)) 11842 my_col += 1; 11843 }); 11844 11845 if (base == 0) { 11846 base = ' '; 11847 } 11848#if OPT_ISO_COLORS 11849#ifdef EXP_BOGUS_FG 11850 /* 11851 * If the cursor happens to be on blanks, and we have not set both 11852 * foreground and background color, do not treat it as a colored cell. 11853 */ 11854 if (base == ' ') { 11855 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 11856 TRACE(("ShowCursor - do not treat as a colored cell\n")); 11857 flags &= ~(FG_COLOR | BG_COLOR); 11858 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 11859 TRACE(("ShowCursor - should we treat as a colored cell?\n")); 11860 if (!(xw->flags & FG_COLOR)) { 11861 if (CheckBogusForeground(screen, "ShowCursor")) { 11862 flags &= ~(FG_COLOR | BG_COLOR); 11863 } 11864 } 11865 } 11866 } 11867#else /* !EXP_BOGUS_FG */ 11868 /* 11869 * If the cursor happens to be on blanks, and the foreground color is set 11870 * but not the background, do not treat it as a colored cell. 11871 */ 11872 if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR 11873 && base == ' ') { 11874 flags &= ~TERM_COLOR_FLAGS(xw); 11875 } 11876#endif 11877#endif 11878 11879 /* 11880 * Compare the current cell to the last set of colors used for the 11881 * cursor and update the GC's if needed. 11882 */ 11883 (void) fg_bg; 11884 if_OPT_ISO_COLORS(screen, { 11885 fg_bg = ld->color[cursor_col]; 11886 }); 11887 11888 fg_pix = getXtermFG(xw, flags, (int) extract_fg(xw, fg_bg, flags)); 11889 bg_pix = getXtermBG(xw, flags, (int) extract_bg(xw, fg_bg, flags)); 11890 11891 /* 11892 * If we happen to have the same foreground/background colors, choose 11893 * a workable foreground color from which we can obtain a visible cursor. 11894 */ 11895 if (fg_pix == bg_pix) { 11896 long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG)); 11897 long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG)); 11898 if (bg_diff < 0) 11899 bg_diff = -bg_diff; 11900 if (fg_diff < 0) 11901 fg_diff = -fg_diff; 11902 if (bg_diff < fg_diff) { 11903 fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG); 11904 } else { 11905 fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG); 11906 } 11907 } 11908 11909 if (OutsideSelection(screen, screen->cur_row, screen->cur_col)) 11910 in_selection = False; 11911 else 11912 in_selection = True; 11913 11914 reversed = ReverseOrHilite(screen, flags, in_selection); 11915 11916 /* This is like updatedXtermGC(), except that we have to worry about 11917 * whether the window has focus, since in that case we want just an 11918 * outline for the cursor. 11919 */ 11920 filled = (screen->select || screen->always_highlight) && isCursorBlock(screen); 11921#if OPT_HIGHLIGHT_COLOR 11922 use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix); 11923 use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix); 11924#endif 11925 if (filled) { 11926 if (reversed) { /* text is reverse video */ 11927 if (getCgsGC(xw, currentWin, gcVTcursNormal)) { 11928 setGC(gcVTcursNormal); 11929 } else { 11930 if (flags & BOLDATTR(screen)) { 11931 setGC(gcBold); 11932 } else { 11933 setGC(gcNorm); 11934 } 11935 } 11936 EXCHANGE(fg_pix, bg_pix, tmp); 11937#if OPT_HIGHLIGHT_COLOR 11938 if (screen->hilite_reverse) { 11939 if (use_selbg && !use_selfg) 11940 fg_pix = bg_pix; 11941 if (use_selfg && !use_selbg) 11942 bg_pix = fg_pix; 11943 if (use_selbg) 11944 bg_pix = selbg_pix; 11945 if (use_selfg) 11946 fg_pix = selfg_pix; 11947 } 11948#endif 11949 } else { /* normal video */ 11950 if (getCgsGC(xw, currentWin, gcVTcursReverse)) { 11951 setGC(gcVTcursReverse); 11952 } else { 11953 if (flags & BOLDATTR(screen)) { 11954 setGC(gcBoldReverse); 11955 } else { 11956 setGC(gcNormReverse); 11957 } 11958 } 11959 } 11960 11961#define CUR_XX T_COLOR(screen, TEXT_CURSOR) 11962#define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 11963#define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 11964 11965#define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground)) 11966#define FIX_328 (CUR_XX == bg_pix) 11967#define FIX_330 (FIX_328 && reversed && in_selection) 11968 11969 if (FIX_330 || FIX_311) { 11970 setCgsBack(xw, currentWin, currentCgs, fg_pix); 11971 } 11972 setCgsFore(xw, currentWin, currentCgs, bg_pix); 11973 } else { /* not selected */ 11974 if (reversed) { /* text is reverse video */ 11975 EXCHANGE(fg_pix, bg_pix, tmp); 11976 setGC(gcNormReverse); 11977 } else { /* normal video */ 11978 setGC(gcNorm); 11979 } 11980#if OPT_HIGHLIGHT_COLOR 11981 if (screen->hilite_reverse) { 11982 if (in_selection && !reversed) { 11983 /* EMPTY */ 11984 /* really INVERSE ... */ 11985 ; 11986 } else if (in_selection || reversed) { 11987 if (use_selbg) { 11988 if (use_selfg) { 11989 bg_pix = fg_pix; 11990 } else { 11991 fg_pix = bg_pix; 11992 bg_pix = selbg_pix; 11993 } 11994 } 11995 if (use_selfg) { 11996 fg_pix = selfg_pix; 11997 } 11998 } 11999 } else { 12000 if (in_selection) { 12001 if (use_selbg) { 12002 bg_pix = selbg_pix; 12003 } 12004 if (use_selfg) { 12005 fg_pix = selfg_pix; 12006 } 12007 } 12008 } 12009#endif 12010 setCgsFore(xw, currentWin, currentCgs, fg_pix); 12011 setCgsBack(xw, currentWin, currentCgs, bg_pix); 12012 } 12013 12014 if (screen->cursor_busy == 0 12015 && (screen->cursor_state != ON || screen->cursor_GC != set_at)) { 12016 int x, y; 12017 12018 screen->cursor_GC = set_at; 12019 TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n", 12020 screen->cur_row, screen->cur_col, 12021 (filled ? "filled" : "outline"), 12022 (isCursorBlock(screen) ? "box" : 12023 isCursorUnderline(screen) ? "underline" : "bar"), 12024 set_at)); 12025 12026 currentGC = getCgsGC(xw, currentWin, currentCgs); 12027 x = LineCursorX(screen, ld, cursor_col); 12028 y = CursorY(screen, screen->cur_row); 12029 12030 if (!isCursorBlock(screen)) { 12031 /* 12032 * Overriding the combination of filled, reversed, in_selection is 12033 * too complicated since the underline or bar and the text-cell use 12034 * different rules. Just redraw the text-cell, and draw the 12035 * underline or bar on top of it. 12036 */ 12037 HideCursor(xw); 12038 12039 /* 12040 * Our current-GC is likely to have been modified in HideCursor(). 12041 * Set up a new request. 12042 */ 12043 if (filled) { 12044 if (FIX_330 || FIX_311) { 12045 setCgsBack(xw, currentWin, currentCgs, fg_pix); 12046 } 12047 setCgsFore(xw, currentWin, currentCgs, bg_pix); 12048 } else { 12049 setCgsFore(xw, currentWin, currentCgs, fg_pix); 12050 setCgsBack(xw, currentWin, currentCgs, bg_pix); 12051 } 12052 } 12053 12054 /* 12055 * Update the outline-gc, to keep the cursor color distinct from the 12056 * background color. 12057 */ 12058 set_cursor_outline_gc(xw, 12059 filled, 12060 fg_pix, 12061 bg_pix, 12062 T_COLOR(screen, TEXT_CURSOR)); 12063 12064 outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline); 12065 if (outlineGC == 0) 12066 outlineGC = currentGC; 12067 12068 if (isCursorUnderline(screen)) { 12069 12070 /* 12071 * Finally, draw the underline. 12072 */ 12073 screen->box->x = (short) x; 12074 screen->box->y = (short) (y + FontHeight(screen) - 2); 12075 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12076 screen->box, NBOX, CoordModePrevious); 12077 } else if (isCursorBar(screen)) { 12078 12079 /* 12080 * Or draw the bar. 12081 */ 12082 screen->box->x = (short) x; 12083 screen->box->y = (short) y; 12084 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12085 screen->box, NBOX, CoordModePrevious); 12086 } else { 12087#if OPT_WIDE_ATTRS 12088 int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0); 12089 int italics_off = ((xw->flags & ATR_ITALIC) != 0); 12090 int fix_italics = (italics_on != italics_off); 12091 int which_font = ((xw->flags & BOLD) ? fBold : fNorm); 12092 MyGetFont getter = italics_on ? getItalicFont : getNormalFont; 12093 12094 if_OPT_WIDE_CHARS(screen, { 12095 if (isWide((int) base)) { 12096 which_font = ((xw->flags & BOLD) ? fWBold : fWide); 12097 } 12098 }); 12099 12100 if (fix_italics && UseItalicFont(screen)) { 12101 xtermLoadItalics(xw); 12102 setCgsFont(xw, currentWin, currentCgs, 12103 getter(screen, which_font)); 12104 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 12105 ? getItalicFont 12106 : getNormalFont); 12107 } 12108 currentGC = getCgsGC(xw, currentWin, currentCgs); 12109#endif /* OPT_WIDE_ATTRS */ 12110 12111 /* *INDENT-EQLS* */ 12112 params.xw = xw; 12113 params.attr_flags = (flags & DRAWX_MASK); 12114 params.draw_flags = 0; 12115 params.this_chrset = LineCharSet(screen, ld); 12116 params.real_chrset = CSET_SWL; 12117 params.on_wide = 0; 12118 12119 drawXtermText(¶ms, 12120 currentGC, x, y, 12121 &base, 1); 12122 12123#if OPT_WIDE_CHARS 12124 if_OPT_WIDE_CHARS(screen, { 12125 size_t off; 12126 12127 /* *INDENT-EQLS* */ 12128 params.draw_flags = NOBACKGROUND; 12129 params.on_wide = isWide((int) base); 12130 12131 for_each_combData(off, ld) { 12132 if (!(ld->combData[off][my_col])) 12133 break; 12134 drawXtermText(¶ms, 12135 currentGC, x, y, 12136 ld->combData[off] + my_col, 1); 12137 } 12138 }); 12139#endif 12140 12141 if (!filled) { 12142 screen->box->x = (short) x; 12143 screen->box->y = (short) y; 12144 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12145 screen->box, NBOX, CoordModePrevious); 12146 } 12147#if OPT_WIDE_ATTRS 12148 if (fix_italics && UseItalicFont(screen)) { 12149 setCgsFont(xw, currentWin, currentCgs, 12150 getter(screen, which_font)); 12151 } 12152#endif 12153 } 12154 } 12155 screen->cursor_state = ON; 12156 12157 return; 12158} 12159 12160/* 12161 * hide cursor at previous cursor position in screen. 12162 */ 12163void 12164HideCursor(XtermWidget xw) 12165{ 12166 TScreen *screen = TScreenOf(xw); 12167 XTermDraw params; 12168 GC currentGC; 12169 int x, y; 12170 IChar base; 12171 unsigned flags; 12172 CellColor fg_bg = initCColor; 12173 Bool in_selection; 12174#if OPT_WIDE_CHARS 12175 int my_col = 0; 12176#endif 12177 int cursor_col; 12178 CLineData *ld = 0; 12179#if OPT_WIDE_ATTRS 12180 int which_Cgs = gcMAX; 12181 unsigned attr_flags; 12182 int which_font = fNorm; 12183 MyGetFont getter = getNormalFont; 12184#endif 12185 12186 if (screen->cursor_state == OFF) 12187 return; 12188 if (INX2ROW(screen, screen->cursorp.row) > screen->max_row) 12189 return; 12190 12191 cursor_col = screen->cursorp.col; 12192 12193#ifndef NO_ACTIVE_ICON 12194 if (IsIcon(screen)) { 12195 screen->cursor_state = OFF; 12196 return; 12197 } 12198#endif /* NO_ACTIVE_ICON */ 12199 12200 ld = getLineData(screen, screen->cursorp.row); 12201 12202 base = ld->charData[cursor_col]; 12203 flags = ld->attribs[cursor_col]; 12204 12205 if_OPT_WIDE_CHARS(screen, { 12206 if (base == HIDDEN_CHAR && cursor_col > 0) { 12207 /* if cursor points to non-initial part of wide character, 12208 * back it up 12209 */ 12210 --cursor_col; 12211 base = ld->charData[cursor_col]; 12212 } 12213 my_col = cursor_col; 12214 if (base == 0) 12215 base = ' '; 12216 if (isWide((int) base)) 12217 my_col += 1; 12218 }); 12219 12220 if (base == 0) { 12221 base = ' '; 12222 } 12223#ifdef EXP_BOGUS_FG 12224 /* 12225 * If the cursor happens to be on blanks, and we have not set both 12226 * foreground and background color, do not treat it as a colored cell. 12227 */ 12228#if OPT_ISO_COLORS 12229 if (base == ' ') { 12230 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 12231 TRACE(("HideCursor - do not treat as a colored cell\n")); 12232 flags &= ~(FG_COLOR | BG_COLOR); 12233 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 12234 TRACE(("HideCursor - should we treat as a colored cell?\n")); 12235 if (!(xw->flags & FG_COLOR)) 12236 if (CheckBogusForeground(screen, "HideCursor")) 12237 flags &= ~(FG_COLOR | BG_COLOR); 12238 } 12239 } 12240#endif 12241#endif 12242 12243 /* 12244 * Compare the current cell to the last set of colors used for the 12245 * cursor and update the GC's if needed. 12246 */ 12247 if_OPT_ISO_COLORS(screen, { 12248 fg_bg = ld->color[cursor_col]; 12249 }); 12250 12251 if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col)) 12252 in_selection = False; 12253 else 12254 in_selection = True; 12255 12256#if OPT_WIDE_ATTRS 12257 attr_flags = ld->attribs[cursor_col]; 12258 if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) { 12259 which_font = ((attr_flags & BOLD) ? fBold : fNorm); 12260 if ((attr_flags & ATR_ITALIC) && UseItalicFont(screen)) 12261 getter = getItalicFont; 12262 12263 if_OPT_WIDE_CHARS(screen, { 12264 if (isWide((int) base)) { 12265 which_font = ((attr_flags & BOLD) ? fWBold : fWide); 12266 } 12267 }); 12268 12269 which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font); 12270 if (which_Cgs != gcMAX) { 12271 setCgsFont(xw, WhichVWin(screen), 12272 (CgsEnum) which_Cgs, 12273 getter(screen, which_font)); 12274 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 12275 ? getItalicFont 12276 : getNormalFont); 12277 } 12278 } 12279#endif 12280 12281 currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection); 12282 12283 TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n", 12284 screen->cursorp.row, screen->cursorp.col)); 12285 12286 x = LineCursorX(screen, ld, cursor_col); 12287 y = CursorY(screen, screen->cursorp.row); 12288 12289 /* *INDENT-EQLS* */ 12290 params.xw = xw; 12291 params.attr_flags = (flags & DRAWX_MASK); 12292 params.draw_flags = 0; 12293 params.this_chrset = LineCharSet(screen, ld); 12294 params.real_chrset = CSET_SWL; 12295 params.on_wide = 0; 12296 12297 drawXtermText(¶ms, 12298 currentGC, x, y, 12299 &base, 1); 12300 12301#if OPT_WIDE_CHARS 12302 if_OPT_WIDE_CHARS(screen, { 12303 size_t off; 12304 12305 /* *INDENT-EQLS* */ 12306 params.draw_flags = NOBACKGROUND; 12307 params.on_wide = isWide((int) base); 12308 12309 for_each_combData(off, ld) { 12310 if (!(ld->combData[off][my_col])) 12311 break; 12312 drawXtermText(¶ms, 12313 currentGC, x, y, 12314 ld->combData[off] + my_col, 1); 12315 } 12316 }); 12317#endif 12318 screen->cursor_state = OFF; 12319 12320#if OPT_WIDE_ATTRS 12321 if (which_Cgs != gcMAX) { 12322 setCgsFont(xw, WhichVWin(screen), 12323 (CgsEnum) which_Cgs, 12324 getter(screen, which_font)); 12325 } 12326#endif 12327 resetXtermGC(xw, flags, in_selection); 12328 12329 refresh_displayed_graphics(xw, 12330 screen->cursorp.col, 12331 screen->cursorp.row, 12332 1, 1); 12333 12334 return; 12335} 12336 12337#if OPT_BLINK_CURS || OPT_BLINK_TEXT 12338static void 12339StartBlinking(XtermWidget xw) 12340{ 12341 TScreen *screen = TScreenOf(xw); 12342 12343 if (screen->blink_timer == 0) { 12344 unsigned long interval = (unsigned long) ((screen->cursor_state == ON) 12345 ? screen->blink_on 12346 : screen->blink_off); 12347 if (interval == 0) /* wow! */ 12348 interval = 1; /* let's humor him anyway */ 12349 screen->blink_timer = XtAppAddTimeOut(app_con, 12350 interval, 12351 HandleBlinking, 12352 xw); 12353 } 12354} 12355 12356static void 12357StopBlinking(XtermWidget xw) 12358{ 12359 TScreen *screen = TScreenOf(xw); 12360 12361 if (screen->blink_timer) { 12362 XtRemoveTimeOut(screen->blink_timer); 12363 screen->blink_timer = 0; 12364 reallyStopBlinking(xw); 12365 } else { 12366 screen->blink_timer = 0; 12367 } 12368} 12369 12370#if OPT_BLINK_TEXT 12371Bool 12372LineHasBlinking(TScreen *screen, CLineData *ld) 12373{ 12374 Bool result = False; 12375 if (ld != 0) { 12376 int col; 12377 12378 for (col = 0; col < MaxCols(screen); ++col) { 12379 if (ld->attribs[col] & BLINK) { 12380 result = True; 12381 break; 12382 } 12383 } 12384 } 12385 return result; 12386} 12387#endif 12388 12389/* 12390 * Blink the cursor by alternately showing/hiding cursor. We leave the timer 12391 * running all the time (even though that's a little inefficient) to make the 12392 * logic simple. 12393 */ 12394static void 12395HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED) 12396{ 12397 XtermWidget xw = (XtermWidget) closure; 12398 TScreen *screen = TScreenOf(xw); 12399 Bool resume = False; 12400 12401 screen->blink_timer = 0; 12402 screen->blink_state = !screen->blink_state; 12403 12404#if OPT_BLINK_CURS 12405 if (DoStartBlinking(screen)) { 12406 if (screen->cursor_state == ON) { 12407 if (screen->select || screen->always_highlight) { 12408 HideCursor(xw); 12409 if (screen->cursor_state == OFF) 12410 screen->cursor_state = BLINKED_OFF; 12411 } 12412 } else if (screen->cursor_state == BLINKED_OFF) { 12413 screen->cursor_state = OFF; 12414 ShowCursor(xw); 12415 if (screen->cursor_state == OFF) 12416 screen->cursor_state = BLINKED_OFF; 12417 } 12418 resume = True; 12419 } 12420#endif 12421 12422#if OPT_BLINK_TEXT 12423 /* 12424 * Inspect the lines on the current screen to see if any have the BLINK flag 12425 * associated with them. Prune off any that have had the corresponding 12426 * cells reset. If any are left, repaint those lines with ScrnRefresh(). 12427 */ 12428 if (!(screen->blink_as_bold)) { 12429 int row; 12430 int first_row = screen->max_row; 12431 int last_row = -1; 12432 12433 for (row = screen->max_row; row >= 0; row--) { 12434 LineData *ld = getLineData(screen, ROW2INX(screen, row)); 12435 12436 if (ld != 0 && LineTstBlinked(ld)) { 12437 if (LineHasBlinking(screen, ld)) { 12438 resume = True; 12439 if (row > last_row) 12440 last_row = row; 12441 if (row < first_row) 12442 first_row = row; 12443 } else { 12444 LineClrBlinked(ld); 12445 } 12446 } 12447 } 12448 /* 12449 * FIXME: this could be a little more efficient, e.g,. by limiting the 12450 * columns which are updated. 12451 */ 12452 if (first_row <= last_row) { 12453 ScrnRefresh(xw, 12454 first_row, 12455 0, 12456 last_row + 1 - first_row, 12457 MaxCols(screen), 12458 True); 12459 } 12460 } 12461#endif 12462 12463 /* 12464 * If either the cursor or text is blinking, restart the timer. 12465 */ 12466 if (resume) 12467 StartBlinking(xw); 12468} 12469#endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */ 12470 12471void 12472RestartBlinking(XtermWidget xw) 12473{ 12474#if OPT_BLINK_CURS || OPT_BLINK_TEXT 12475 TScreen *screen = TScreenOf(xw); 12476 12477 if (screen->blink_timer == 0) { 12478 Bool resume = False; 12479 12480#if OPT_BLINK_CURS 12481 if (DoStartBlinking(screen)) { 12482 resume = True; 12483 } 12484#endif 12485#if OPT_BLINK_TEXT 12486 if (!resume) { 12487 int row; 12488 12489 for (row = screen->max_row; row >= 0; row--) { 12490 CLineData *ld = getLineData(screen, ROW2INX(screen, row)); 12491 12492 if (ld != 0 && LineTstBlinked(ld)) { 12493 if (LineHasBlinking(screen, ld)) { 12494 resume = True; 12495 break; 12496 } 12497 } 12498 } 12499 } 12500#endif 12501 if (resume) 12502 StartBlinking(xw); 12503 } 12504#else 12505 (void) xw; 12506#endif 12507} 12508 12509/* 12510 * Implement soft or hard (full) reset of the VTxxx emulation. There are a 12511 * couple of differences from real DEC VTxxx terminals (to avoid breaking 12512 * applications which have come to rely on xterm doing this): 12513 * 12514 * + autowrap mode should be reset (instead it's reset to the resource 12515 * default). 12516 * + the popup menu offers a choice of resetting the savedLines, or not. 12517 * (but the control sequence does this anyway). 12518 */ 12519static void 12520ReallyReset(XtermWidget xw, Bool full, Bool saved) 12521{ 12522 TScreen *screen = TScreenOf(xw); 12523 IFlags saveflags = xw->flags; 12524 12525 TRACE(("ReallyReset %s, %s\n", 12526 full ? "hard" : "soft", 12527 saved ? "clear savedLines" : "keep savedLines")); 12528 12529 if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) { 12530 Bell(xw, XkbBI_MinorError, 0); 12531 return; 12532 } 12533 12534 if (saved) { 12535 screen->savedlines = 0; 12536 ScrollBarDrawThumb(xw, 0); 12537 } 12538 12539 /* make cursor visible */ 12540 screen->cursor_set = ON; 12541 InitCursorShape(screen, screen); 12542#if OPT_BLINK_CURS 12543 screen->cursor_blink = screen->cursor_blink_i; 12544 screen->cursor_blink_esc = 0; 12545 TRACE(("cursor_shape:%d blinks:%d\n", 12546 screen->cursor_shape, 12547 screen->cursor_blink)); 12548#endif 12549 12550 /* reset scrolling region */ 12551 resetMargins(xw); 12552 12553 bitclr(&xw->flags, ORIGIN); 12554 12555 if_OPT_ISO_COLORS(screen, { 12556 static char empty[1]; 12557 reset_SGR_Colors(xw); 12558 if (ResetAnsiColorRequest(xw, empty, 0)) 12559 xtermRepaint(xw); 12560 }); 12561 12562 /* Reset character-sets to initial state */ 12563 resetCharsets(screen); 12564 12565#if OPT_MOD_FKEYS 12566 /* Reset modifier-resources to initial state */ 12567 xw->keyboard.modify_now = xw->keyboard.modify_1st; 12568#endif 12569#if OPT_DEC_RECTOPS 12570 screen->checksum_ext = screen->checksum_ext0; 12571#endif 12572 12573 /* Reset DECSCA */ 12574 bitclr(&xw->flags, PROTECTED); 12575 screen->protected_mode = OFF_PROTECT; 12576 12577 if (full) { /* RIS */ 12578 if (screen->bellOnReset) 12579 Bell(xw, XkbBI_TerminalBell, 0); 12580 12581 reset_displayed_graphics(screen); 12582 12583 /* reset the mouse mode */ 12584 screen->send_mouse_pos = MOUSE_OFF; 12585 screen->send_focus_pos = OFF; 12586 screen->extend_coords = 0; 12587 screen->waitingForTrackInfo = False; 12588 screen->eventMode = NORMAL; 12589 12590 xtermShowPointer(xw, True); 12591 12592 TabReset(xw->tabs); 12593 xw->keyboard.flags = MODE_SRM; 12594 12595 guard_keyboard_type = False; 12596 screen->old_fkeys = screen->old_fkeys0; 12597 decode_keyboard_type(xw, &resource); 12598 update_keyboard_type(); 12599 12600#if OPT_INITIAL_ERASE 12601 if (xw->keyboard.reset_DECBKM == 1) 12602 xw->keyboard.flags |= MODE_DECBKM; 12603 else if (xw->keyboard.reset_DECBKM == 2) 12604#endif 12605 if (TScreenOf(xw)->backarrow_key) 12606 xw->keyboard.flags |= MODE_DECBKM; 12607 TRACE(("full reset DECBKM %s\n", 12608 BtoS(xw->keyboard.flags & MODE_DECBKM))); 12609 12610#if OPT_SCROLL_LOCK 12611 xtermClearLEDs(screen); 12612#endif 12613 screen->title_modes = screen->title_modes0; 12614 screen->pointer_mode = screen->pointer_mode0; 12615#if OPT_SIXEL_GRAPHICS 12616 if (TScreenOf(xw)->sixel_scrolling) 12617 xw->keyboard.flags |= MODE_DECSDM; 12618 TRACE(("full reset DECSDM to %s (resource default is %s)\n", 12619 BtoS(xw->keyboard.flags & MODE_DECSDM), 12620 BtoS(TScreenOf(xw)->sixel_scrolling))); 12621#endif 12622 12623#if OPT_GRAPHICS 12624 screen->privatecolorregisters = TScreenOf(xw)->privatecolorregisters; 12625 TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n", 12626 BtoS(screen->privatecolorregisters), 12627 BtoS(TScreenOf(xw)->privatecolorregisters))); 12628#endif 12629 12630#if OPT_SIXEL_GRAPHICS 12631 screen->sixel_scrolls_right = TScreenOf(xw)->sixel_scrolls_right; 12632 TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n", 12633 BtoS(screen->sixel_scrolls_right), 12634 BtoS(TScreenOf(xw)->sixel_scrolls_right))); 12635#endif 12636 12637 update_appcursor(); 12638 update_appkeypad(); 12639 update_decbkm(); 12640 update_decsdm(); 12641 show_8bit_control(False); 12642 reset_decudk(xw); 12643 12644 FromAlternate(xw); 12645 ClearScreen(xw); 12646 screen->cursor_state = OFF; 12647 12648 if (xw->flags & REVERSE_VIDEO) 12649 ReverseVideo(xw); 12650 ResetItalics(xw); 12651 xw->flags = xw->initflags; 12652 12653 update_reversevideo(); 12654 update_autowrap(); 12655 update_reversewrap(); 12656 update_autolinefeed(); 12657 12658 screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL)); 12659 update_jumpscroll(); 12660 12661#if OPT_DEC_RECTOPS 12662 screen->cur_decsace = 0; 12663#endif 12664#if OPT_PASTE64 || OPT_READLINE 12665 screen->paste_brackets = OFF; 12666#endif 12667#if OPT_READLINE 12668 screen->click1_moves = OFF; 12669 screen->paste_moves = OFF; 12670 screen->dclick3_deletes = OFF; 12671 screen->paste_quotes = OFF; 12672 screen->paste_literal_nl = OFF; 12673#endif /* OPT_READLINE */ 12674 12675 if (screen->c132 && (saveflags & IN132COLUMNS)) { 12676 TRACE(("Making resize-request to restore 80-columns %dx%d\n", 12677 MaxRows(screen), MaxCols(screen))); 12678 RequestResize(xw, MaxRows(screen), 80, True); 12679 repairSizeHints(); 12680 XSync(screen->display, False); /* synchronize */ 12681 if (xtermAppPending()) 12682 xevents(xw); 12683 } 12684 12685 CursorSet(screen, 0, 0, xw->flags); 12686 CursorSave(xw); 12687 } else { /* DECSTR */ 12688 /* 12689 * There's a tiny difference, to accommodate usage of xterm. 12690 * We reset autowrap to the resource values rather than turning 12691 * it off. 12692 */ 12693 UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM)); 12694 bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP); 12695 bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE); 12696 ResetItalics(xw); 12697 if_OPT_ISO_COLORS(screen, { 12698 reset_SGR_Colors(xw); 12699 }); 12700 update_appcursor(); 12701 update_autowrap(); 12702 update_reversewrap(); 12703 12704 CursorSave(xw); 12705 screen->sc[screen->whichBuf].row = 12706 screen->sc[screen->whichBuf].col = 0; 12707 } 12708} 12709 12710void 12711VTReset(XtermWidget xw, Bool full, Bool saved) 12712{ 12713 ReallyReset(xw, full, saved); 12714 12715 FreeAndNull(myState.string_area); 12716 FreeAndNull(myState.print_area); 12717 12718 longjmp(vtjmpbuf, 1); /* force ground state in parser */ 12719} 12720 12721typedef enum { 12722 ccLO, 12723 ccDASH, 12724 ccHI, 12725 ccCOLON, 12726 ccID, 12727 ccCOMMA 12728} CCLASS; 12729 12730/* 12731 * set_character_class - takes a string of the form 12732 * 12733 * low[-high][:id][,low[-high][:id][...]] 12734 * 12735 * and sets the indicated ranges to the indicated values. 12736 */ 12737static int 12738set_character_class(char *s) 12739{ 12740#define FMT "%s in range string \"%s\" (position %d)\n" 12741 12742 TRACE(("set_character_class(%s) " TRACE_L "\n", NonNull(s))); 12743 if (IsEmpty(s)) { 12744 TRACE((TRACE_R " ERR set_character_class\n")); 12745 return -1; 12746 } else { 12747 CCLASS state = ccLO; 12748 int arg[3]; 12749 int i; 12750 int len = (int) strlen(s); 12751 12752 arg[0] = 12753 arg[1] = 12754 arg[2] = -1; 12755 12756 for (i = 0; i < len; ++i) { 12757 int ch = CharOf(s[i]); 12758 char *t = 0; 12759 long value = 0; 12760 12761 if (isspace(ch)) 12762 continue; 12763 12764 switch (state) { 12765 case ccLO: 12766 case ccHI: 12767 case ccID: 12768 if (!isdigit(ch)) { 12769 xtermWarning(FMT, "missing number", s, i); 12770 TRACE((TRACE_R " ERR set_character_class\n")); 12771 return (-1); 12772 } 12773 value = strtol(s + i, &t, 0); 12774 i = (int) (t - s - 1); 12775 break; 12776 case ccDASH: 12777 case ccCOLON: 12778 case ccCOMMA: 12779 break; 12780 } 12781 12782 switch (state) { 12783 case ccLO: 12784 arg[0] = 12785 arg[1] = (int) value; 12786 arg[2] = -1; 12787 state = ccDASH; 12788 break; 12789 12790 case ccDASH: 12791 if (ch == '-') { 12792 state = ccHI; 12793 } else { 12794 goto parse_class; 12795 } 12796 break; 12797 12798 case ccHI: 12799 arg[1] = (int) value; 12800 state = ccCOLON; 12801 break; 12802 12803 parse_class: 12804 case ccCOLON: 12805 if (ch == ':') { 12806 state = ccID; 12807 } else if (ch == ',') { 12808 goto apply_class; 12809 } else { 12810 xtermWarning(FMT, "unexpected character", s, i); 12811 TRACE((TRACE_R " ERR set_character_class\n")); 12812 return (-1); 12813 } 12814 break; 12815 12816 case ccID: 12817 arg[2] = (int) value; 12818 state = ccCOMMA; 12819 break; 12820 12821 apply_class: 12822 case ccCOMMA: 12823 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 12824 xtermWarning(FMT, "bad range", s, i); 12825 TRACE((TRACE_R " ERR set_character_class\n")); 12826 return -1; 12827 } 12828 state = ccLO; 12829 break; 12830 } 12831 } 12832 if (state >= ccDASH) { 12833 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 12834 xtermWarning(FMT, "bad range", s, i); 12835 TRACE((TRACE_R " ERR set_character_class\n")); 12836 return -1; 12837 } 12838 } 12839 } 12840 12841 TRACE((TRACE_R " OK set_character_class\n")); 12842 return (0); 12843#undef FMT 12844} 12845 12846void 12847getKeymapResources(Widget w, 12848 const char *mapName, 12849 const char *mapClass, 12850 const char *type, 12851 void *result, 12852 size_t size) 12853{ 12854 XtResource key_resources[1]; 12855 key_resources[0].resource_name = XtNtranslations; 12856 key_resources[0].resource_class = XtCTranslations; 12857 key_resources[0].resource_type = (char *) type; 12858 key_resources[0].resource_size = (Cardinal) size; 12859 key_resources[0].resource_offset = 0; 12860 key_resources[0].default_type = key_resources[0].resource_type; 12861 key_resources[0].default_addr = 0; 12862 XtGetSubresources(w, (XtPointer) result, mapName, mapClass, 12863 key_resources, (Cardinal) 1, NULL, (Cardinal) 0); 12864} 12865 12866/* ARGSUSED */ 12867static void 12868HandleKeymapChange(Widget w, 12869 XEvent *event GCC_UNUSED, 12870 String *params, 12871 Cardinal *param_count) 12872{ 12873 static XtTranslations keymap, original; 12874 12875 TRACE(("HandleKeymapChange(%#lx, %s)\n", 12876 (unsigned long) w, 12877 (*param_count 12878 ? params[0] 12879 : "missing"))); 12880 12881 if (*param_count != 1) 12882 return; 12883 12884 if (original == NULL) { 12885 TRACE(("...saving original keymap-translations\n")); 12886 original = w->core.tm.translations; 12887 } 12888 12889 if (strcmp(params[0], "None") == 0) { 12890 TRACE(("...restoring original keymap-translations\n")); 12891 XtOverrideTranslations(w, original); 12892 } else { 12893 char mapName[1000]; 12894 char mapClass[1000]; 12895 char *pmapName; 12896 char *pmapClass; 12897 size_t len; 12898 12899 len = strlen(params[0]) + 7; 12900 12901 pmapName = (char *) MyStackAlloc(len, mapName); 12902 pmapClass = (char *) MyStackAlloc(len, mapClass); 12903 if (pmapName == NULL 12904 || pmapClass == NULL) { 12905 SysError(ERROR_KMMALLOC1); 12906 } else { 12907 12908 (void) sprintf(pmapName, "%sKeymap", params[0]); 12909 (void) strcpy(pmapClass, pmapName); 12910 if (islower(CharOf(pmapClass[0]))) 12911 pmapClass[0] = x_toupper(pmapClass[0]); 12912 getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable, 12913 &keymap, sizeof(keymap)); 12914 if (keymap != NULL) { 12915 TRACE(("...applying keymap \"%s\"\n", pmapName)); 12916 XtOverrideTranslations(w, keymap); 12917 } else { 12918 TRACE(("...found no match for keymap \"%s\"\n", pmapName)); 12919 } 12920 12921 MyStackFree(pmapName, mapName); 12922 MyStackFree(pmapClass, mapClass); 12923 } 12924 } 12925} 12926 12927/* ARGSUSED */ 12928static void 12929HandleBell(Widget w GCC_UNUSED, 12930 XEvent *event GCC_UNUSED, 12931 String *params, /* [0] = volume */ 12932 Cardinal *param_count) /* 0 or 1 */ 12933{ 12934 int percent = (*param_count) ? atoi(params[0]) : 0; 12935 12936 Bell(term, XkbBI_TerminalBell, percent); 12937} 12938 12939/* ARGSUSED */ 12940static void 12941HandleVisualBell(Widget w GCC_UNUSED, 12942 XEvent *event GCC_UNUSED, 12943 String *params GCC_UNUSED, 12944 Cardinal *param_count GCC_UNUSED) 12945{ 12946 VisualBell(); 12947} 12948 12949/* ARGSUSED */ 12950static void 12951HandleIgnore(Widget w, 12952 XEvent *event, 12953 String *params GCC_UNUSED, 12954 Cardinal *param_count GCC_UNUSED) 12955{ 12956 XtermWidget xw; 12957 12958 TRACE(("Handle ignore for %p %s\n", 12959 (void *) w, visibleEventType(event->type))); 12960 if ((xw = getXtermWidget(w)) != 0) { 12961 /* do nothing, but check for funny escape sequences */ 12962 switch (event->type) { 12963 case ButtonPress: 12964 case ButtonRelease: 12965 case MotionNotify: 12966 (void) SendMousePosition(xw, event); 12967 break; 12968 } 12969 } 12970} 12971 12972/* ARGSUSED */ 12973static void 12974DoSetSelectedFont(Widget w, 12975 XtPointer client_data GCC_UNUSED, 12976 Atom *selection GCC_UNUSED, 12977 Atom *type, 12978 XtPointer value, 12979 unsigned long *length, 12980 int *format) 12981{ 12982 XtermWidget xw = getXtermWidget(w); 12983 12984 if (xw == 0) { 12985 xtermWarning("unexpected widget in DoSetSelectedFont\n"); 12986 } else if (*type != XA_STRING || *format != 8) { 12987 Bell(xw, XkbBI_MinorError, 0); 12988 } else { 12989 Boolean failed = False; 12990 int oldFont = TScreenOf(xw)->menu_font_number; 12991 char *save = TScreenOf(xw)->SelectFontName(); 12992 char *val; 12993 char *test; 12994 unsigned len = (unsigned) *length; 12995 unsigned tst; 12996 12997 /* 12998 * Some versions of X deliver null-terminated selections, some do not. 12999 */ 13000 for (tst = 0; tst < len; ++tst) { 13001 if (((char *) value)[tst] == '\0') { 13002 len = tst; 13003 break; 13004 } 13005 } 13006 13007 if (len > 0 && (val = TypeMallocN(char, len + 1)) != 0) { 13008 char *used; 13009 13010 memcpy(val, value, (size_t) len); 13011 val[len] = '\0'; 13012 used = x_strtrim(val); 13013 TRACE(("DoSetSelectedFont(%s)\n", used)); 13014 /* Do some sanity checking to avoid sending a long selection 13015 back to the server in an OpenFont that is unlikely to succeed. 13016 XLFD allows up to 255 characters and no control characters; 13017 we are a little more liberal here. */ 13018 if (len < 1000 13019 && used != 0 13020 && !strchr(used, '\n') 13021 && (test = x_strdup(used)) != 0) { 13022 TScreenOf(xw)->SelectFontName() = test; 13023 if (!xtermLoadFont(xw, 13024 xtermFontName(used), 13025 True, 13026 fontMenu_fontsel)) { 13027 failed = True; 13028 free(test); 13029 TScreenOf(xw)->SelectFontName() = save; 13030 } 13031 } else { 13032 failed = True; 13033 } 13034 if (failed) { 13035 (void) xtermLoadFont(xw, 13036 xtermFontName(TScreenOf(xw)->MenuFontName(oldFont)), 13037 True, 13038 oldFont); 13039 Bell(xw, XkbBI_MinorError, 0); 13040 } 13041 free(used); 13042 free(val); 13043 } 13044 } 13045} 13046 13047void 13048FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe) 13049{ 13050 TScreen *screen = TScreenOf(xw); 13051 static AtomPtr *atoms; 13052 static unsigned int atomCount = 0; 13053 AtomPtr *pAtom; 13054 unsigned a; 13055 Atom target; 13056 13057 if (!atom_name) 13058 atom_name = ((screen->mappedSelect && atomCount) 13059 ? screen->mappedSelect[0] 13060 : "PRIMARY"); 13061 TRACE(("FindFontSelection(%s)\n", atom_name)); 13062 13063 for (pAtom = atoms, a = atomCount; a; a--, pAtom++) { 13064 if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) { 13065 TRACE(("...found atom %d:%s\n", a + 1, atom_name)); 13066 break; 13067 } 13068 } 13069 if (!a) { 13070 atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1); 13071 *(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name); 13072 ++atomCount; 13073 TRACE(("...added atom %d:%s\n", atomCount, atom_name)); 13074 } 13075 13076 target = XmuInternAtom(XtDisplay(xw), *pAtom); 13077 if (justprobe) { 13078 screen->SelectFontName() = 13079 XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : 0; 13080 TRACE(("...selected fontname '%s'\n", 13081 NonNull(screen->SelectFontName()))); 13082 } else { 13083 XtGetSelectionValue((Widget) xw, target, XA_STRING, 13084 DoSetSelectedFont, NULL, 13085 XtLastTimestampProcessed(XtDisplay(xw))); 13086 } 13087 return; 13088} 13089 13090Bool 13091set_cursor_gcs(XtermWidget xw) 13092{ 13093 TScreen *screen = TScreenOf(xw); 13094 VTwin *win = WhichVWin(screen); 13095 13096 Pixel cc = T_COLOR(screen, TEXT_CURSOR); 13097 Pixel fg = T_COLOR(screen, TEXT_FG); 13098 Pixel bg = T_COLOR(screen, TEXT_BG); 13099 Bool changed = False; 13100 13101 /* 13102 * Let's see, there are three things that have "color": 13103 * 13104 * background 13105 * text 13106 * cursorblock 13107 * 13108 * And, there are four situations when drawing a cursor, if we decide 13109 * that we like have a solid block of cursor color with the letter 13110 * that it is highlighting shown in the background color to make it 13111 * stand out: 13112 * 13113 * selected window, normal video - background on cursor 13114 * selected window, reverse video - foreground on cursor 13115 * unselected window, normal video - foreground on background 13116 * unselected window, reverse video - background on foreground 13117 * 13118 * Since the last two are really just normalGC and reverseGC, we only 13119 * need two new GC's. Under monochrome, we get the same effect as 13120 * above by setting cursor color to foreground. 13121 */ 13122 13123 TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg)); 13124 if (win != 0 && (cc != bg)) { 13125 Pixel xx = ((fg == cc) ? bg : cc); 13126 13127 /* set the fonts to the current one */ 13128 setCgsFont(xw, win, gcVTcursNormal, 0); 13129 setCgsFont(xw, win, gcVTcursFilled, 0); 13130 setCgsFont(xw, win, gcVTcursReverse, 0); 13131 setCgsFont(xw, win, gcVTcursOutline, 0); 13132 13133 /* we have a colored cursor */ 13134 setCgsFore(xw, win, gcVTcursNormal, fg); 13135 setCgsBack(xw, win, gcVTcursNormal, xx); 13136 13137 setCgsFore(xw, win, gcVTcursFilled, xx); 13138 setCgsBack(xw, win, gcVTcursFilled, fg); 13139 13140 if (screen->always_highlight) { 13141 /* both GC's use the same color */ 13142 setCgsFore(xw, win, gcVTcursReverse, bg); 13143 setCgsBack(xw, win, gcVTcursReverse, cc); 13144 } else { 13145 setCgsFore(xw, win, gcVTcursReverse, bg); 13146 setCgsBack(xw, win, gcVTcursReverse, cc); 13147 } 13148 set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc); 13149 changed = True; 13150 FreeMarkGCs(xw); 13151 } 13152 13153 if (changed) { 13154 TRACE(("...set_cursor_gcs - done\n")); 13155 } 13156 return changed; 13157} 13158 13159/* 13160 * Build up the default translations string, allowing the user to suppress 13161 * some of the features. 13162 */ 13163void 13164VTInitTranslations(void) 13165{ 13166 /* *INDENT-OFF* */ 13167 static struct { 13168 Boolean wanted; 13169 const char *name; 13170 const char *value; 13171 } table[] = { 13172#define DATA(name,value) { False, name, value } 13173 DATA("select", 13174"\ 13175 Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\ 13176 Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\ 13177" 13178 ), 13179#if OPT_MAXIMIZE 13180 DATA("fullscreen", 13181"\ 13182 Alt <Key>Return:fullscreen() \n\ 13183" 13184 ), 13185#endif 13186#if OPT_SCROLL_LOCK 13187 DATA("scroll-lock", 13188"\ 13189 <KeyRelease> Scroll_Lock:scroll-lock() \n\ 13190" 13191 ), 13192#endif 13193#if OPT_SHIFT_FONTS 13194 DATA("shift-fonts", 13195"\ 13196 Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\ 13197 Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\ 13198 Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\ 13199" 13200 ), 13201#endif 13202 DATA("paging", 13203"\ 13204 Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\ 13205 Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\ 13206" 13207 ), 13208 /* This must be the last set mentioning "KeyPress" */ 13209 DATA("keypress", 13210"\ 13211 ~Meta <KeyPress>:insert-seven-bit() \n\ 13212 Meta <KeyPress>:insert-eight-bit() \n\ 13213" 13214 ), 13215 DATA("popup-menu", 13216"\ 13217 !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13218 !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13219 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\ 13220 ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13221 !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13222 !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13223 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\ 13224 ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13225 !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13226 !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13227 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\ 13228 ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13229" 13230 ), 13231 /* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */ 13232 DATA("reset", 13233"\ 13234 Meta <Btn2Down>:clear-saved-lines() \n\ 13235" 13236 ), 13237 DATA("select", 13238"\ 13239 ~Meta <Btn1Down>:select-start() \n\ 13240 ~Meta <Btn1Motion>:select-extend() \n\ 13241 ~Ctrl ~Meta <Btn2Down>:ignore() \n\ 13242 ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\ 13243 ~Ctrl ~Meta <Btn3Down>:start-extend() \n\ 13244 ~Meta <Btn3Motion>:select-extend() \n\ 13245 <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\ 13246" 13247 ), 13248 DATA("wheel-mouse", 13249"\ 13250 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13251 Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13252 Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13253 @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13254 <Btn4Down>:scroll-back(5,line,m) \n\ 13255 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13256 Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13257 Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13258 @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13259 <Btn5Down>:scroll-forw(5,line,m) \n\ 13260" 13261 ), 13262 DATA("pointer", 13263"\ 13264 <BtnMotion>:pointer-motion() \n\ 13265 <BtnDown>:pointer-button() \n\ 13266 <BtnUp>:pointer-button() \n\ 13267" 13268 ), 13269 DATA("default", 13270"\ 13271 <BtnUp>:ignore() \n\ 13272" 13273 ) 13274 }; 13275#undef DATA 13276 /* *INDENT-ON* */ 13277 13278 char *result = 0; 13279 13280 int pass; 13281 Cardinal item; 13282 13283 TRACE(("VTInitTranslations\n")); 13284 for (item = 0; item < XtNumber(table); ++item) { 13285 table[item].wanted = True; 13286 } 13287#if OPT_MAXIMIZE 13288 /* 13289 * As a special case, allow for disabling the alt-enter translation if 13290 * the resource settings prevent fullscreen from being used. We would 13291 * do the same for scroll-lock and shift-fonts if they were application 13292 * resources too, rather than in the widget. 13293 */ 13294 if (resource.fullscreen == esNever) { 13295 for (item = 0; item < XtNumber(table); ++item) { 13296 if (!strcmp(table[item].name, "fullscreen")) { 13297 table[item].wanted = False; 13298 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 13299 } 13300 } 13301 } 13302#endif 13303 if (!IsEmpty(resource.omitTranslation)) { 13304 char *value; 13305 const char *source = resource.omitTranslation; 13306 13307 while (*source != '\0' && (value = ParseList(&source)) != 0) { 13308 size_t len = strlen(value); 13309 13310 TRACE(("parsed:%s\n", value)); 13311 for (item = 0; item < XtNumber(table); ++item) { 13312 if (strlen(table[item].name) >= len 13313 && x_strncasecmp(table[item].name, 13314 value, 13315 (unsigned) len) == 0) { 13316 table[item].wanted = False; 13317 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 13318 /* continue: "select", for instance is two chunks */ 13319 } 13320 } 13321 free(value); 13322 } 13323 } 13324 13325 for (pass = 0; pass < 2; ++pass) { 13326 size_t needed = 0; 13327 for (item = 0; item < XtNumber(table); ++item) { 13328 if (table[item].wanted) { 13329 if (pass) { 13330 strcat(result, table[item].value); 13331 } else { 13332 needed += strlen(table[item].value) + 1; 13333 } 13334 } 13335 } 13336 if (!pass) { 13337 result = XtMalloc((Cardinal) needed); 13338 *result = '\0'; 13339 } 13340 } 13341 13342 TRACE(("result:\n%s\n", result)); 13343 13344 defaultTranslations = result; 13345 free((void *) xtermClassRec.core_class.tm_table); 13346 xtermClassRec.core_class.tm_table = result; 13347} 13348 13349#ifdef NO_LEAKS 13350void 13351noleaks_charproc(void) 13352{ 13353 free(v_buffer); 13354} 13355#endif 13356