charproc.c revision 4419d26b
1/* $XTermId: charproc.c,v 1.1888 2022/02/22 09:00:26 Vladimir.A.Pavlov Exp $ */ 2 3/* 4 * Copyright 1999-2021,2022 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_EXEC_XTERM 343 { "spawn-new-terminal", HandleSpawnTerminal }, 344#endif 345#if OPT_GRAPHICS 346 { "set-private-colors", HandleSetPrivateColorRegisters }, 347#endif 348#if OPT_HP_FUNC_KEYS 349 { "set-hp-function-keys", HandleHpFunctionKeys }, 350#endif 351#if OPT_LOAD_VTFONTS 352 { "load-vt-fonts", HandleLoadVTFonts }, 353#endif 354#if OPT_MAXIMIZE 355 { "deiconify", HandleDeIconify }, 356 { "fullscreen", HandleFullscreen }, 357 { "iconify", HandleIconify }, 358 { "maximize", HandleMaximize }, 359 { "restore", HandleRestoreSize }, 360#endif 361#if OPT_NUM_LOCK 362 { "alt-sends-escape", HandleAltEsc }, 363 { "meta-sends-escape", HandleMetaEsc }, 364 { "set-num-lock", HandleNumLock }, 365#endif 366#ifdef OPT_PRINT_ON_EXIT 367 { "print-immediate", HandlePrintImmediate }, 368 { "print-on-error", HandlePrintOnError }, 369#endif 370#if OPT_READLINE 371 { "readline-button", ReadLineButton }, 372#endif 373#if OPT_RENDERFONT 374 { "set-render-font", HandleRenderFont }, 375#endif 376#if OPT_SCO_FUNC_KEYS 377 { "set-sco-function-keys", HandleScoFunctionKeys }, 378#endif 379#if OPT_SCREEN_DUMPS 380 { "dump-html", HandleDumpHtml }, 381 { "dump-svg", HandleDumpSvg }, 382#endif 383#if OPT_SCROLL_LOCK 384 { "scroll-lock", HandleScrollLock }, 385#endif 386#if OPT_SELECTION_OPS 387 { "exec-formatted", HandleExecFormatted }, 388 { "exec-selectable", HandleExecSelectable }, 389 { "insert-formatted", HandleInsertFormatted }, 390 { "insert-selectable", HandleInsertSelectable }, 391#endif 392#if OPT_SHIFT_FONTS 393 { "larger-vt-font", HandleLargerFont }, 394 { "smaller-vt-font", HandleSmallerFont }, 395#endif 396#if OPT_SIXEL_GRAPHICS 397 { "set-sixel-scrolling", HandleSixelScrolling }, 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 Sres(XtNcdXtraScroll, XtCCdXtraScroll, misc.cdXtraScroll_s, DEF_CD_XTRA_SCROLL), 452 Bres(XtNcolorInnerBorder, XtCColorInnerBorder, misc.color_inner_border, False), 453 Bres(XtNcurses, XtCCurses, screen.curses, False), 454 Bres(XtNcutNewline, XtCCutNewline, screen.cutNewline, True), 455 Bres(XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, 456 screen.cutToBeginningOfLine, True), 457 Bres(XtNdeleteIsDEL, XtCDeleteIsDEL, screen.delete_is_del, DEFDELETE_DEL), 458 Bres(XtNdynamicColors, XtCDynamicColors, misc.dynamicColors, True), 459 Bres(XtNeightBitControl, XtCEightBitControl, screen.control_eight_bits, False), 460 Bres(XtNeightBitInput, XtCEightBitInput, screen.input_eight_bits, True), 461 Bres(XtNeightBitOutput, XtCEightBitOutput, screen.output_eight_bits, True), 462 Bres(XtNeraseSavedLines, XtCEraseSavedLines, screen.eraseSavedLines0, True), 463 Bres(XtNhighlightSelection, XtCHighlightSelection, 464 screen.highlight_selection, False), 465 Bres(XtNshowWrapMarks, XtCShowWrapMarks, screen.show_wrap_marks, False), 466 Bres(XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, screen.hp_ll_bc, False), 467 Bres(XtNi18nSelections, XtCI18nSelections, screen.i18nSelections, True), 468 Bres(XtNfastScroll, XtCFastScroll, screen.fastscroll, False), 469 Bres(XtNjumpScroll, XtCJumpScroll, screen.jumpscroll, True), 470 Bres(XtNkeepClipboard, XtCKeepClipboard, screen.keepClipboard, False), 471 Bres(XtNkeepSelection, XtCKeepSelection, screen.keepSelection, True), 472 Bres(XtNloginShell, XtCLoginShell, misc.login_shell, False), 473 Bres(XtNmarginBell, XtCMarginBell, screen.marginbell, False), 474 Bres(XtNmetaSendsEscape, XtCMetaSendsEscape, screen.meta_sends_esc, DEF_META_SENDS_ESC), 475 Bres(XtNmultiScroll, XtCMultiScroll, screen.multiscroll, False), 476 Bres(XtNoldXtermFKeys, XtCOldXtermFKeys, screen.old_fkeys, False), 477 Bres(XtNpopOnBell, XtCPopOnBell, screen.poponbell, False), 478 Bres(XtNprinterAutoClose, XtCPrinterAutoClose, SPS.printer_autoclose, False), 479 Bres(XtNprinterExtent, XtCPrinterExtent, SPS.printer_extent, False), 480 Bres(XtNprinterFormFeed, XtCPrinterFormFeed, SPS.printer_formfeed, False), 481 Bres(XtNprinterNewLine, XtCPrinterNewLine, SPS.printer_newline, True), 482 Bres(XtNquietGrab, XtCQuietGrab, screen.quiet_grab, False), 483 Bres(XtNresizeByPixel, XtCResizeByPixel, misc.resizeByPixel, False), 484 Bres(XtNreverseVideo, XtCReverseVideo, misc.re_verse, False), 485 Bres(XtNreverseWrap, XtCReverseWrap, misc.reverseWrap, False), 486 Bres(XtNscrollBar, XtCScrollBar, misc.scrollbar, False), 487 Bres(XtNscrollKey, XtCScrollCond, screen.scrollkey, False), 488 Bres(XtNscrollTtyOutput, XtCScrollCond, screen.scrollttyoutput, True), 489 Bres(XtNselectToClipboard, XtCSelectToClipboard, 490 screen.selectToClipboard, False), 491 Bres(XtNsignalInhibit, XtCSignalInhibit, misc.signalInhibit, False), 492 Bres(XtNtiteInhibit, XtCTiteInhibit, misc.titeInhibit, False), 493 Sres(XtNtiXtraScroll, XtCTiXtraScroll, misc.tiXtraScroll_s, DEF_TI_XTRA_SCROLL), 494 Bres(XtNtrimSelection, XtCTrimSelection, screen.trim_selection, False), 495 Bres(XtNunderLine, XtCUnderLine, screen.underline, True), 496 Bres(XtNvisualBell, XtCVisualBell, screen.visualbell, False), 497 Bres(XtNvisualBellLine, XtCVisualBellLine, screen.flash_line, False), 498 499 Dres(XtNscaleHeight, XtCScaleHeight, screen.scale_height, "1.0"), 500 501 Ires(XtNbellSuppressTime, XtCBellSuppressTime, screen.bellSuppressTime, BELLSUPPRESSMSEC), 502 Ires(XtNfontWarnings, XtCFontWarnings, misc.fontWarnings, fwResource), 503 Ires(XtNinternalBorder, XtCBorderWidth, screen.border, DEFBORDER), 504 Ires(XtNlimitResize, XtCLimitResize, misc.limit_resize, 1), 505 Ires(XtNlimitResponse, XtCLimitResponse, screen.unparse_max, DEF_LIMIT_RESPONSE), 506 Ires(XtNmultiClickTime, XtCMultiClickTime, screen.multiClickTime, MULTICLICKTIME), 507 Ires(XtNnMarginBell, XtCColumn, screen.nmarginbell, N_MARGINBELL), 508 Ires(XtNpointerMode, XtCPointerMode, screen.pointer_mode, DEF_POINTER_MODE), 509 Ires(XtNprinterControlMode, XtCPrinterControlMode, 510 SPS.printer_controlmode, 0), 511 Ires(XtNtitleModes, XtCTitleModes, screen.title_modes, DEF_TITLE_MODES), 512 Ires(XtNnextEventDelay, XtCNextEventDelay, screen.nextEventDelay, 1), 513 Ires(XtNvisualBellDelay, XtCVisualBellDelay, screen.visualBellDelay, 100), 514 Ires(XtNsaveLines, XtCSaveLines, screen.savelines, DEF_SAVE_LINES), 515 Ires(XtNscrollBarBorder, XtCScrollBarBorder, screen.scrollBarBorder, 1), 516 Ires(XtNscrollLines, XtCScrollLines, screen.scrolllines, DEF_SCROLL_LINES), 517 518 Sres(XtNinitialFont, XtCInitialFont, screen.initial_font, NULL), 519 Sres(XtNfont1, XtCFont1, screen.MenuFontName(fontMenu_font1), NULL), 520 Sres(XtNfont2, XtCFont2, screen.MenuFontName(fontMenu_font2), NULL), 521 Sres(XtNfont3, XtCFont3, screen.MenuFontName(fontMenu_font3), NULL), 522 Sres(XtNfont4, XtCFont4, screen.MenuFontName(fontMenu_font4), NULL), 523 Sres(XtNfont5, XtCFont5, screen.MenuFontName(fontMenu_font5), NULL), 524 Sres(XtNfont6, XtCFont6, screen.MenuFontName(fontMenu_font6), NULL), 525 Sres(XtNfont7, XtCFont7, screen.MenuFontName(fontMenu_font7), NULL), 526 527 Sres(XtNanswerbackString, XtCAnswerbackString, screen.answer_back, ""), 528 Sres(XtNboldFont, XtCBoldFont, misc.default_font.f_b, DEFBOLDFONT), 529 Sres(XtNcharClass, XtCCharClass, screen.charClass, NULL), 530 Sres(XtNdecTerminalID, XtCDecTerminalID, screen.term_id, DFT_DECID), 531 Sres(XtNdefaultString, XtCDefaultString, screen.default_string, "#"), 532 Sres(XtNdisallowedColorOps, XtCDisallowedColorOps, 533 screen.disallowedColorOps, DEF_DISALLOWED_COLOR), 534 Sres(XtNdisallowedFontOps, XtCDisallowedFontOps, 535 screen.disallowedFontOps, DEF_DISALLOWED_FONT), 536 Sres(XtNdisallowedMouseOps, XtCDisallowedMouseOps, 537 screen.disallowedMouseOps, DEF_DISALLOWED_MOUSE), 538 Sres(XtNdisallowedPasteControls, XtCDisallowedPasteControls, 539 screen.disallowedPasteControls, DEF_DISALLOWED_PASTE_CONTROLS), 540 Sres(XtNdisallowedTcapOps, XtCDisallowedTcapOps, 541 screen.disallowedTcapOps, DEF_DISALLOWED_TCAP), 542 Sres(XtNdisallowedWindowOps, XtCDisallowedWindowOps, 543 screen.disallowedWinOps, DEF_DISALLOWED_WINDOW), 544 Sres(XtNeightBitMeta, XtCEightBitMeta, screen.eight_bit_meta_s, DEF_8BIT_META), 545 Sres(XtNeightBitSelectTypes, XtCEightBitSelectTypes, 546 screen.eightbit_select_types, NULL), 547 Sres(XtNfont, XtCFont, misc.default_font.f_n, DEFFONT), 548 Sres(XtNgeometry, XtCGeometry, misc.geo_metry, NULL), 549 Sres(XtNkeyboardDialect, XtCKeyboardDialect, screen.keyboard_dialect, DFT_KBD_DIALECT), 550 Sres(XtNprinterCommand, XtCPrinterCommand, SPS.printer_command, ""), 551 Sres(XtNtekGeometry, XtCGeometry, misc.T_geometry, NULL), 552 Sres(XtNpointerFont, XtCPointerFont, screen.cursor_font_name, NULL), 553 554 Tres(XtNcursorColor, XtCCursorColor, TEXT_CURSOR, XtDefaultForeground), 555 Tres(XtNforeground, XtCForeground, TEXT_FG, XtDefaultForeground), 556 Tres(XtNpointerColor, XtCPointerColor, MOUSE_FG, XtDefaultForeground), 557 Tres(XtNbackground, XtCBackground, TEXT_BG, XtDefaultBackground), 558 Tres(XtNpointerColorBackground, XtCBackground, MOUSE_BG, XtDefaultBackground), 559 560 {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity), 561 XtOffsetOf(XtermWidgetRec, misc.resizeGravity), 562 XtRImmediate, (XtPointer) SouthWestGravity}, 563 564 Sres(XtNpointerShape, XtCCursor, screen.pointer_shape, "xterm"), 565 566#ifdef ALLOWLOGGING 567 Bres(XtNlogInhibit, XtCLogInhibit, misc.logInhibit, False), 568 Bres(XtNlogging, XtCLogging, misc.log_on, False), 569 Sres(XtNlogFile, XtCLogfile, screen.logfile, NULL), 570#endif 571 572#ifndef NO_ACTIVE_ICON 573 Sres("activeIcon", "ActiveIcon", misc.active_icon_s, "default"), 574 Ires("iconBorderWidth", XtCBorderWidth, misc.icon_border_width, 2), 575 Sres("iconFont", "IconFont", screen.icon_fontname, "nil2"), 576 Cres("iconBorderColor", XtCBorderColor, misc.icon_border_pixel, XtDefaultBackground), 577#endif /* NO_ACTIVE_ICON */ 578 579#if OPT_BLINK_CURS 580 Bres(XtNcursorBlinkXOR, XtCCursorBlinkXOR, screen.cursor_blink_xor, True), 581 Sres(XtNcursorBlink, XtCCursorBlink, screen.cursor_blink_s, "false"), 582#endif 583 Bres(XtNcursorUnderLine, XtCCursorUnderLine, screen.cursor_underline, False), 584 585#if OPT_BLINK_TEXT 586 Bres(XtNshowBlinkAsBold, XtCCursorBlink, screen.blink_as_bold, DEFBLINKASBOLD), 587#endif 588 589#if OPT_BLINK_CURS || OPT_BLINK_TEXT 590 Ires(XtNcursorOnTime, XtCCursorOnTime, screen.blink_on, 600), 591 Ires(XtNcursorOffTime, XtCCursorOffTime, screen.blink_off, 300), 592#endif 593 594#if OPT_BOX_CHARS 595 Bres(XtNforceBoxChars, XtCForceBoxChars, screen.force_box_chars, False), 596 Bres(XtNforcePackedFont, XtCForcePackedFont, screen.force_packed, True), 597 Bres(XtNshowMissingGlyphs, XtCShowMissingGlyphs, screen.force_all_chars, False), 598 Bres(XtNassumeAllChars, XtCAssumeAllChars, screen.assume_all_chars, True), 599#endif 600 601#if OPT_BROKEN_OSC 602 Bres(XtNbrokenLinuxOSC, XtCBrokenLinuxOSC, screen.brokenLinuxOSC, True), 603#endif 604 605#if OPT_BROKEN_ST 606 Bres(XtNbrokenStringTerm, XtCBrokenStringTerm, screen.brokenStringTerm, False), 607#endif 608 609#if OPT_C1_PRINT 610 Bres(XtNallowC1Printable, XtCAllowC1Printable, screen.c1_printable, False), 611#endif 612 613#if OPT_CLIP_BOLD 614 Bres(XtNuseClipping, XtCUseClipping, screen.use_clipping, True), 615 Bres(XtNuseBorderClipping, XtCUseBorderClipping, 616 screen.use_border_clipping, False), 617#endif 618 619#if OPT_DEC_CHRSET 620 Bres(XtNfontDoublesize, XtCFontDoublesize, screen.font_doublesize, True), 621 Ires(XtNcacheDoublesize, XtCCacheDoublesize, screen.cache_doublesize, NUM_CHRSET), 622#endif 623 624#if OPT_DEC_RECTOPS 625 Ires(XtNchecksumExtension, XtCChecksumExtension, screen.checksum_ext0, csDEC), 626#endif 627 628#if OPT_HIGHLIGHT_COLOR 629 Tres(XtNhighlightColor, XtCHighlightColor, HIGHLIGHT_BG, XtDefaultForeground), 630 Tres(XtNhighlightTextColor, XtCHighlightTextColor, HIGHLIGHT_FG, XtDefaultBackground), 631 Bres(XtNhighlightReverse, XtCHighlightReverse, screen.hilite_reverse, True), 632 Bres(XtNhighlightColorMode, XtCHighlightColorMode, screen.hilite_color, Maybe), 633#endif /* OPT_HIGHLIGHT_COLOR */ 634 635#if OPT_INPUT_METHOD 636 Bres(XtNopenIm, XtCOpenIm, misc.open_im, True), 637 Sres(XtNinputMethod, XtCInputMethod, misc.input_method, NULL), 638 Sres(XtNpreeditType, XtCPreeditType, misc.preedit_type, 639 "OverTheSpot,Root"), 640 Ires(XtNretryInputMethod, XtCRetryInputMethod, misc.retry_im, 3), 641#endif 642 643#if OPT_ISO_COLORS 644 Bres(XtNboldColors, XtCColorMode, screen.boldColors, True), 645 Ires(XtNveryBoldColors, XtCVeryBoldColors, screen.veryBoldColors, 0), 646 Bres(XtNcolorMode, XtCColorMode, screen.colorMode, DFT_COLORMODE), 647 648 Bres(XtNcolorAttrMode, XtCColorAttrMode, screen.colorAttrMode, False), 649 Bres(XtNcolorBDMode, XtCColorAttrMode, screen.colorBDMode, False), 650 Bres(XtNcolorBLMode, XtCColorAttrMode, screen.colorBLMode, False), 651 Bres(XtNcolorRVMode, XtCColorAttrMode, screen.colorRVMode, False), 652 Bres(XtNcolorULMode, XtCColorAttrMode, screen.colorULMode, False), 653 Bres(XtNitalicULMode, XtCColorAttrMode, screen.italicULMode, False), 654#if OPT_WIDE_ATTRS 655 Bres(XtNcolorITMode, XtCColorAttrMode, screen.colorITMode, False), 656#endif 657#if OPT_DIRECT_COLOR 658 Bres(XtNdirectColor, XtCDirectColor, screen.direct_color, True), 659#endif 660 661 COLOR_RES("0", screen.Acolors[COLOR_0], DFT_COLOR("black")), 662 COLOR_RES("1", screen.Acolors[COLOR_1], DFT_COLOR("red3")), 663 COLOR_RES("2", screen.Acolors[COLOR_2], DFT_COLOR("green3")), 664 COLOR_RES("3", screen.Acolors[COLOR_3], DFT_COLOR("yellow3")), 665 COLOR_RES("4", screen.Acolors[COLOR_4], DFT_COLOR(DEF_COLOR4)), 666 COLOR_RES("5", screen.Acolors[COLOR_5], DFT_COLOR("magenta3")), 667 COLOR_RES("6", screen.Acolors[COLOR_6], DFT_COLOR("cyan3")), 668 COLOR_RES("7", screen.Acolors[COLOR_7], DFT_COLOR("gray90")), 669 COLOR_RES("8", screen.Acolors[COLOR_8], DFT_COLOR("gray50")), 670 COLOR_RES("9", screen.Acolors[COLOR_9], DFT_COLOR("red")), 671 COLOR_RES("10", screen.Acolors[COLOR_10], DFT_COLOR("green")), 672 COLOR_RES("11", screen.Acolors[COLOR_11], DFT_COLOR("yellow")), 673 COLOR_RES("12", screen.Acolors[COLOR_12], DFT_COLOR(DEF_COLOR12)), 674 COLOR_RES("13", screen.Acolors[COLOR_13], DFT_COLOR("magenta")), 675 COLOR_RES("14", screen.Acolors[COLOR_14], DFT_COLOR("cyan")), 676 COLOR_RES("15", screen.Acolors[COLOR_15], DFT_COLOR("white")), 677 COLOR_RES("BD", screen.Acolors[COLOR_BD], DFT_COLOR(XtDefaultForeground)), 678 COLOR_RES("BL", screen.Acolors[COLOR_BL], DFT_COLOR(XtDefaultForeground)), 679 COLOR_RES("UL", screen.Acolors[COLOR_UL], DFT_COLOR(XtDefaultForeground)), 680 COLOR_RES("RV", screen.Acolors[COLOR_RV], DFT_COLOR(XtDefaultForeground)), 681 682#if OPT_WIDE_ATTRS 683 COLOR_RES("IT", screen.Acolors[COLOR_IT], DFT_COLOR(XtDefaultForeground)), 684#endif 685 686#endif /* OPT_ISO_COLORS */ 687 688 CLICK_RES("2", screen.onClick[1], "word"), 689 CLICK_RES("3", screen.onClick[2], "line"), 690 CLICK_RES("4", screen.onClick[3], 0), 691 CLICK_RES("5", screen.onClick[4], 0), 692 693 Sres(XtNshiftEscape, XtCShiftEscape, keyboard.shift_escape_s, "false"), 694 695#if OPT_MOD_FKEYS 696 Ires(XtNmodifyKeyboard, XtCModifyKeyboard, 697 keyboard.modify_1st.allow_keys, 0), 698 Ires(XtNmodifyCursorKeys, XtCModifyCursorKeys, 699 keyboard.modify_1st.cursor_keys, 2), 700 Ires(XtNmodifyFunctionKeys, XtCModifyFunctionKeys, 701 keyboard.modify_1st.function_keys, 2), 702 Ires(XtNmodifyKeypadKeys, XtCModifyKeypadKeys, 703 keyboard.modify_1st.keypad_keys, 0), 704 Ires(XtNmodifyOtherKeys, XtCModifyOtherKeys, 705 keyboard.modify_1st.other_keys, 0), 706 Ires(XtNmodifyStringKeys, XtCModifyStringKeys, 707 keyboard.modify_1st.string_keys, 0), 708 Ires(XtNformatOtherKeys, XtCFormatOtherKeys, 709 keyboard.format_keys, 0), 710#endif 711 712#if OPT_NUM_LOCK 713 Bres(XtNalwaysUseMods, XtCAlwaysUseMods, misc.alwaysUseMods, False), 714 Bres(XtNnumLock, XtCNumLock, misc.real_NumLock, True), 715#endif 716 717#if OPT_PRINT_COLORS 718 Ires(XtNprintAttributes, XtCPrintAttributes, SPS.print_attributes, 1), 719#endif 720 721#if OPT_REGIS_GRAPHICS 722 Sres(XtNregisDefaultFont, XtCRegisDefaultFont, 723 screen.graphics_regis_default_font, ""), 724 Sres(XtNregisScreenSize, XtCRegisScreenSize, 725 screen.graphics_regis_screensize, "auto"), 726#endif 727 728#if OPT_GRAPHICS 729 Sres(XtNdecGraphicsID, XtCDecGraphicsID, screen.graph_termid, DFT_DECID), 730 Sres(XtNmaxGraphicSize, XtCMaxGraphicSize, screen.graphics_max_size, 731 "1000x1000"), 732#endif 733 734#if OPT_SHIFT_FONTS 735 Bres(XtNshiftFonts, XtCShiftFonts, misc.shift_fonts, True), 736#endif 737 738#if OPT_SIXEL_GRAPHICS 739 Bres(XtNsixelScrolling, XtCSixelScrolling, screen.sixel_scrolling, False), 740 Bres(XtNsixelScrollsRight, XtCSixelScrollsRight, 741 screen.sixel_scrolls_right, False), 742#endif 743 744#if OPT_GRAPHICS 745 Ires(XtNnumColorRegisters, XtCNumColorRegisters, 746 screen.numcolorregisters, 0), 747 Bres(XtNprivateColorRegisters, XtCPrivateColorRegisters, 748 screen.privatecolorregisters, True), 749#endif 750 751#if OPT_STATUS_LINE 752 Sres(XtNindicatorFormat, XtCIndicatorFormat, screen.status_fmt, DEF_SL_FORMAT), 753#endif 754 755#if OPT_SUNPC_KBD 756 Ires(XtNctrlFKeys, XtCCtrlFKeys, misc.ctrl_fkeys, 10), 757#endif 758 759#if OPT_TEK4014 760 Bres(XtNtekInhibit, XtCTekInhibit, misc.tekInhibit, False), 761 Bres(XtNtekSmall, XtCTekSmall, misc.tekSmall, False), 762 Bres(XtNtekStartup, XtCTekStartup, misc.TekEmu, False), 763#endif 764 765#if OPT_TOOLBAR 766 Wres(XtNmenuBar, XtCMenuBar, VT100_TB_INFO(menu_bar), 0), 767 Ires(XtNmenuHeight, XtCMenuHeight, VT100_TB_INFO(menu_height), 25), 768#endif 769 770#if OPT_WIDE_CHARS 771 Bres(XtNcjkWidth, XtCCjkWidth, misc.cjk_width, False), 772 Bres(XtNmkWidth, XtCMkWidth, misc.mk_width, False), 773 Bres(XtNprecompose, XtCPrecompose, screen.normalized_c, True), 774 Bres(XtNutf8Latin1, XtCUtf8Latin1, screen.utf8_latin1, False), 775 Bres(XtNutf8Weblike, XtCUtf8Weblike, screen.utf8_weblike, False), 776 Bres(XtNvt100Graphics, XtCVT100Graphics, screen.vt100_graphics, True), 777 Bres(XtNwideChars, XtCWideChars, screen.wide_chars, False), 778 Ires(XtNcombiningChars, XtCCombiningChars, screen.max_combining, 2), 779 Ires(XtNmkSamplePass, XtCMkSamplePass, misc.mk_samplepass, 655), 780 Ires(XtNmkSampleSize, XtCMkSampleSize, misc.mk_samplesize, 65536), 781 Sres(XtNutf8, XtCUtf8, screen.utf8_mode_s, "default"), 782 Sres(XtNutf8Fonts, XtCUtf8Fonts, screen.utf8_fonts_s, "default"), 783 Sres(XtNutf8Title, XtCUtf8Title, screen.utf8_title_s, "default"), 784 Sres(XtNwideBoldFont, XtCWideBoldFont, misc.default_font.f_wb, DEFWIDEBOLDFONT), 785 Sres(XtNwideFont, XtCWideFont, misc.default_font.f_w, DEFWIDEFONT), 786 Sres(XtNutf8SelectTypes, XtCUtf8SelectTypes, screen.utf8_select_types, NULL), 787#endif 788 789#if OPT_LUIT_PROG 790 Sres(XtNlocale, XtCLocale, misc.locale_str, "medium"), 791 Sres(XtNlocaleFilter, XtCLocaleFilter, misc.localefilter, DEFLOCALEFILTER), 792#endif 793 794#if OPT_INPUT_METHOD 795 Sres(XtNximFont, XtCXimFont, misc.f_x, DEFXIMFONT), 796#endif 797 798#if OPT_SCROLL_LOCK 799 Bres(XtNallowScrollLock, XtCAllowScrollLock, screen.allowScrollLock0, False), 800 Bres(XtNautoScrollLock, XtCAutoScrollLock, screen.autoScrollLock, False), 801#endif 802 803 /* these are used only for testing ncurses, not in the manual page */ 804#if OPT_XMC_GLITCH 805 Bres(XtNxmcInline, XtCXmcInline, screen.xmc_inline, False), 806 Bres(XtNxmcMoveSGR, XtCXmcMoveSGR, screen.move_sgr_ok, True), 807 Ires(XtNxmcAttributes, XtCXmcAttributes, screen.xmc_attributes, 1), 808 Ires(XtNxmcGlitch, XtCXmcGlitch, screen.xmc_glitch, 0), 809#endif 810 811#ifdef SCROLLBAR_RIGHT 812 Bres(XtNrightScrollBar, XtCRightScrollBar, misc.useRight, False), 813#endif 814 815#if OPT_RENDERFONT 816 Bres(XtNforceXftHeight, XtCForceXftHeight, screen.force_xft_height, False), 817#define RES_FACESIZE(n) Dres(XtNfaceSize #n, XtCFaceSize #n, misc.face_size[n], "0.0") 818 RES_FACESIZE(1), 819 RES_FACESIZE(2), 820 RES_FACESIZE(3), 821 RES_FACESIZE(4), 822 RES_FACESIZE(5), 823 RES_FACESIZE(6), 824 RES_FACESIZE(7), 825 Dres(XtNfaceSize, XtCFaceSize, misc.face_size[0], DEFFACESIZE), 826 Sres(XtNfaceName, XtCFaceName, misc.default_xft.f_n, DEFFACENAME), 827 Sres(XtNrenderFont, XtCRenderFont, misc.render_font_s, "default"), 828 Ires(XtNlimitFontsets, XtCLimitFontsets, misc.limit_fontsets, DEF_XFT_CACHE), 829#if OPT_RENDERWIDE 830 Sres(XtNfaceNameDoublesize, XtCFaceNameDoublesize, misc.default_xft.f_w, DEFFACENAME), 831#endif 832#endif 833}; 834 835static Boolean VTSetValues(Widget cur, Widget request, Widget new_arg, 836 ArgList args, Cardinal *num_args); 837static void VTClassInit(void); 838static void VTDestroy(Widget w); 839static void VTExpose(Widget w, XEvent *event, Region region); 840static void VTInitialize(Widget wrequest, Widget new_arg, ArgList args, 841 Cardinal *num_args); 842static void VTRealize(Widget w, XtValueMask * valuemask, 843 XSetWindowAttributes * values); 844static void VTResize(Widget w); 845 846#if OPT_INPUT_METHOD 847static void VTInitI18N(XtermWidget); 848#endif 849 850#ifdef VMS 851globaldef { 852 "xtermclassrec" 853} noshare 854 855#else 856static 857#endif /* VMS */ 858WidgetClassRec xtermClassRec = 859{ 860 { 861 /* core_class fields */ 862 (WidgetClass) & widgetClassRec, /* superclass */ 863 "VT100", /* class_name */ 864 sizeof(XtermWidgetRec), /* widget_size */ 865 VTClassInit, /* class_initialize */ 866 NULL, /* class_part_initialize */ 867 False, /* class_inited */ 868 VTInitialize, /* initialize */ 869 NULL, /* initialize_hook */ 870 VTRealize, /* realize */ 871 actionsList, /* actions */ 872 XtNumber(actionsList), /* num_actions */ 873 xterm_resources, /* resources */ 874 XtNumber(xterm_resources), /* num_resources */ 875 NULLQUARK, /* xrm_class */ 876 True, /* compress_motion */ 877 False, /* compress_exposure */ 878 True, /* compress_enterleave */ 879 False, /* visible_interest */ 880 VTDestroy, /* destroy */ 881 VTResize, /* resize */ 882 VTExpose, /* expose */ 883 VTSetValues, /* set_values */ 884 NULL, /* set_values_hook */ 885 XtInheritSetValuesAlmost, /* set_values_almost */ 886 NULL, /* get_values_hook */ 887 NULL, /* accept_focus */ 888 XtVersion, /* version */ 889 NULL, /* callback_offsets */ 890 0, /* tm_table */ 891 XtInheritQueryGeometry, /* query_geometry */ 892 XtInheritDisplayAccelerator, /* display_accelerator */ 893 NULL /* extension */ 894 } 895}; 896 897#ifdef VMS 898globaldef { 899 "xtermwidgetclass" 900} 901noshare 902#endif /* VMS */ 903WidgetClass xtermWidgetClass = (WidgetClass) & xtermClassRec; 904 905/* 906 * Add input-actions for widgets that are overlooked (scrollbar and toolbar): 907 * 908 * a) Sometimes the scrollbar passes through translations, sometimes it 909 * doesn't. We add the KeyPress translations here, just to be sure. 910 * b) In the normal (non-toolbar) configuration, the xterm widget covers 911 * almost all of the window. With a toolbar, there's a relatively 912 * large area that the user would expect to enter keystrokes since the 913 * program can get the focus. 914 */ 915void 916xtermAddInput(Widget w) 917{ 918 /* *INDENT-OFF* */ 919 XtActionsRec input_actions[] = { 920 { "insert", HandleKeyPressed }, /* alias */ 921 { "insert-eight-bit", HandleEightBitKeyPressed }, 922 { "insert-seven-bit", HandleKeyPressed }, 923 { "pointer-motion", HandlePointerMotion }, 924 { "pointer-button", HandlePointerButton }, 925 { "secure", HandleSecure }, 926 { "string", HandleStringEvent }, 927 { "scroll-back", HandleScrollBack }, 928 { "scroll-forw", HandleScrollForward }, 929 { "scroll-to", HandleScrollTo }, 930 { "select-cursor-end", HandleKeyboardSelectEnd }, 931 { "select-cursor-extend", HandleKeyboardSelectExtend }, 932 { "select-cursor-start", HandleKeyboardSelectStart }, 933 { "insert-selection", HandleInsertSelection }, 934 { "select-start", HandleSelectStart }, 935 { "select-extend", HandleSelectExtend }, 936 { "start-extend", HandleStartExtend }, 937 { "select-end", HandleSelectEnd }, 938 { "clear-saved-lines", HandleClearSavedLines }, 939 { "popup-menu", HandlePopupMenu }, 940 { "bell", HandleBell }, 941 { "ignore", HandleIgnore }, 942#if OPT_DABBREV 943 { "dabbrev-expand", HandleDabbrevExpand }, 944#endif 945#if OPT_MAXIMIZE 946 { "fullscreen", HandleFullscreen }, 947#endif 948#if OPT_SCROLL_LOCK 949 { "scroll-lock", HandleScrollLock }, 950#endif 951#if OPT_SHIFT_FONTS 952 { "larger-vt-font", HandleLargerFont }, 953 { "smaller-vt-font", HandleSmallerFont }, 954#endif 955 }; 956 /* *INDENT-ON* */ 957 958 TRACE_TRANS("BEFORE", w); 959 XtAppAddActions(app_con, input_actions, XtNumber(input_actions)); 960 XtAugmentTranslations(w, XtParseTranslationTable(defaultTranslations)); 961 TRACE_TRANS("AFTER:", w); 962 963#if OPT_EXTRA_PASTE 964 if (term && term->keyboard.extra_translations) 965 XtOverrideTranslations((Widget) term, XtParseTranslationTable(term->keyboard.extra_translations)); 966#endif 967} 968 969#if OPT_ISO_COLORS 970#ifdef EXP_BOGUS_FG 971static Bool 972CheckBogusForeground(TScreen *screen, const char *tag) 973{ 974 int row = -1, col = -1, pass; 975 Bool isClear = True; 976 977 (void) tag; 978 for (pass = 0; pass < 2; ++pass) { 979 row = screen->cur_row; 980 for (; isClear && (row <= screen->max_row); ++row) { 981 CLineData *ld = getLineData(screen, row); 982 983 if (ld != 0) { 984 IAttr *attribs = ld->attribs; 985 986 col = (row == screen->cur_row) ? screen->cur_col : 0; 987 for (; isClear && (col <= screen->max_col); ++col) { 988 unsigned flags = attribs[col]; 989 if (pass) { 990 flags &= ~FG_COLOR; 991 attribs[col] = (IAttr) flags; 992 } else if ((flags & BG_COLOR)) { 993 isClear = False; 994 } else if ((flags & FG_COLOR)) { 995 unsigned ch = ld->charData[col]; 996 isClear = ((ch == ' ') || (ch == 0)); 997 } else { 998 isClear = False; 999 } 1000 } 1001 } 1002 } 1003 } 1004 TRACE(("%s checked %d,%d to %d,%d %s pass %d\n", 1005 tag, screen->cur_row, screen->cur_col, 1006 row, col, 1007 isClear && pass ? "cleared" : "unchanged", 1008 pass)); 1009 1010 return isClear; 1011} 1012#endif 1013 1014/* 1015 * The terminal's foreground and background colors are set via two mechanisms: 1016 * text (cur_foreground, cur_background values that are passed down to 1017 * XDrawImageString and XDrawString) 1018 * area (X11 graphics context used in XClearArea and XFillRectangle) 1019 */ 1020void 1021SGR_Foreground(XtermWidget xw, int color) 1022{ 1023 TScreen *screen = TScreenOf(xw); 1024 Pixel fg; 1025 1026 if (color >= 0) { 1027 UIntSet(xw->flags, FG_COLOR); 1028 } else { 1029 UIntClr(xw->flags, FG_COLOR); 1030 } 1031 fg = getXtermFG(xw, xw->flags, color); 1032 xw->cur_foreground = color; 1033 1034 setCgsFore(xw, WhichVWin(screen), gcNorm, fg); 1035 setCgsBack(xw, WhichVWin(screen), gcNormReverse, fg); 1036 1037 setCgsFore(xw, WhichVWin(screen), gcBold, fg); 1038 setCgsBack(xw, WhichVWin(screen), gcBoldReverse, fg); 1039 1040#ifdef EXP_BOGUS_FG 1041 /* 1042 * If we've just turned off the foreground color, check for blank cells 1043 * which have no background color, but do have foreground color. This 1044 * could happen due to setting the foreground color just before scrolling. 1045 * 1046 * Those cells look uncolored, but will confuse ShowCursor(), which looks 1047 * for the colors in the current cell, and will see the foreground color. 1048 * In that case, remove the foreground color from the blank cells. 1049 */ 1050 if (color < 0) { 1051 CheckBogusForeground(screen, "SGR_Foreground"); 1052 } 1053#endif 1054} 1055 1056void 1057SGR_Background(XtermWidget xw, int color) 1058{ 1059 TScreen *screen = TScreenOf(xw); 1060 Pixel bg; 1061 1062 /* 1063 * An indexing operation may have set screen->scroll_amt, which would 1064 * normally result in calling FlushScroll() in WriteText(). However, 1065 * if we're changing the background color now, then the new value 1066 * should not apply to the pending blank lines. 1067 */ 1068 if (screen->scroll_amt && (color != xw->cur_background)) 1069 FlushScroll(xw); 1070 1071 if (color >= 0) { 1072 UIntSet(xw->flags, BG_COLOR); 1073 } else { 1074 UIntClr(xw->flags, BG_COLOR); 1075 } 1076 bg = getXtermBG(xw, xw->flags, color); 1077 xw->cur_background = color; 1078 1079 setCgsBack(xw, WhichVWin(screen), gcNorm, bg); 1080 setCgsFore(xw, WhichVWin(screen), gcNormReverse, bg); 1081 1082 setCgsBack(xw, WhichVWin(screen), gcBold, bg); 1083 setCgsFore(xw, WhichVWin(screen), gcBoldReverse, bg); 1084} 1085 1086/* Invoked after updating bold/underline flags, computes the extended color 1087 * index to use for foreground. (See also 'extract_fg()'). 1088 */ 1089static void 1090setExtendedFG(XtermWidget xw) 1091{ 1092 int fg = xw->sgr_foreground; 1093 1094 if (TScreenOf(xw)->colorAttrMode 1095 || (fg < 0)) { 1096 fg = MapToColorMode(fg, TScreenOf(xw), xw->flags); 1097 } 1098 1099 /* This implements the IBM PC-style convention of 8-colors, with one 1100 * bit for bold, thus mapping the 0-7 codes to 8-15. It won't make 1101 * much sense for 16-color applications, but we keep it to retain 1102 * compatibility with ANSI-color applications. 1103 */ 1104#if OPT_PC_COLORS /* XXXJTL should be settable at runtime (resource or OSC?) */ 1105 if (TScreenOf(xw)->boldColors 1106 && (!xw->sgr_38_xcolors) 1107 && (fg >= 0) 1108 && (fg < 8) 1109 && (xw->flags & BOLD)) 1110 fg |= 8; 1111#endif 1112 1113 SGR_Foreground(xw, fg); 1114} 1115 1116/* Invoked after updating inverse flag, computes the extended color 1117 * index to use for background. (See also 'extract_bg()'). 1118 */ 1119static void 1120setExtendedBG(XtermWidget xw) 1121{ 1122 int bg = xw->sgr_background; 1123 1124 if (TScreenOf(xw)->colorAttrMode 1125 || (bg < 0)) { 1126 if (TScreenOf(xw)->colorRVMode && (xw->flags & INVERSE)) 1127 bg = COLOR_RV; 1128 } 1129 1130 SGR_Background(xw, bg); 1131} 1132 1133void 1134setExtendedColors(XtermWidget xw) 1135{ 1136 setExtendedFG(xw); 1137 setExtendedBG(xw); 1138} 1139 1140static void 1141reset_SGR_Foreground(XtermWidget xw) 1142{ 1143 xw->sgr_foreground = -1; 1144 xw->sgr_38_xcolors = False; 1145 clrDirectFG(xw->flags); 1146 setExtendedFG(xw); 1147} 1148 1149static void 1150reset_SGR_Background(XtermWidget xw) 1151{ 1152 xw->sgr_background = -1; 1153 clrDirectBG(xw->flags); 1154 setExtendedBG(xw); 1155} 1156 1157static void 1158reset_SGR_Colors(XtermWidget xw) 1159{ 1160 reset_SGR_Foreground(xw); 1161 reset_SGR_Background(xw); 1162} 1163#endif /* OPT_ISO_COLORS */ 1164 1165#if OPT_WIDE_ATTRS 1166/* 1167 * Call this before changing the state of ATR_ITALIC, to update the GC fonts. 1168 */ 1169static void 1170setItalicFont(XtermWidget xw, Bool enable) 1171{ 1172 if (enable) { 1173 if ((xw->flags & ATR_ITALIC) == 0) { 1174 xtermLoadItalics(xw); 1175 TRACE(("setItalicFont: enabling Italics\n")); 1176 xtermUpdateFontGCs(xw, getItalicFont); 1177 } 1178 } else if ((xw->flags & ATR_ITALIC) != 0) { 1179 TRACE(("setItalicFont: disabling Italics\n")); 1180 xtermUpdateFontGCs(xw, getNormalFont); 1181 } 1182} 1183 1184static void 1185ResetItalics(XtermWidget xw) 1186{ 1187 setItalicFont(xw, False); 1188 UIntClr(xw->flags, ATR_ITALIC); 1189} 1190 1191#else 1192#define ResetItalics(xw) /* nothing */ 1193#endif 1194 1195static void 1196initCharset(TScreen *screen, int which, DECNRCM_codes code) 1197{ 1198 screen->gsets[which] = code; 1199} 1200 1201void 1202saveCharsets(TScreen *screen, DECNRCM_codes * target) 1203{ 1204 int g; 1205 for (g = 0; g < NUM_GSETS; ++g) { 1206 target[g] = screen->gsets[g]; 1207 } 1208} 1209 1210void 1211restoreCharsets(TScreen *screen, DECNRCM_codes * source) 1212{ 1213 int g; 1214 for (g = 0; g < NUM_GSETS; ++g) { 1215 screen->gsets[g] = source[g]; 1216 } 1217} 1218 1219void 1220resetCharsets(TScreen *screen) 1221{ 1222 TRACE(("resetCharsets\n")); 1223 1224 initCharset(screen, 0, nrc_ASCII); 1225 initCharset(screen, 1, nrc_ASCII); 1226 initCharset(screen, 2, nrc_ASCII); 1227 initCharset(screen, 3, nrc_ASCII); 1228 1229 screen->curgl = 0; /* G0 => GL. */ 1230 screen->curgr = 2; /* G2 => GR. */ 1231 screen->curss = 0; /* No single shift. */ 1232 1233#if OPT_VT52_MODE 1234 if (screen->vtXX_level == 0) 1235 initCharset(screen, 1, nrc_DEC_Spec_Graphic); /* Graphics */ 1236#endif 1237} 1238 1239static void 1240modified_DECNRCM(XtermWidget xw) 1241{ 1242#if OPT_WIDE_CHARS 1243 TScreen *screen = TScreenOf(xw); 1244 if (screen->wide_chars && (screen->utf8_mode || screen->utf8_nrc_mode)) { 1245 int enabled = ((xw->flags & NATIONAL) != 0); 1246 int modefix; 1247 EXCHANGE(screen->utf8_nrc_mode, screen->utf8_mode, modefix); 1248 switchPtyData(screen, !enabled); 1249 TRACE(("UTF8 mode temporarily %s\n", enabled ? "ON" : "OFF")); 1250 } 1251#else 1252 (void) xw; 1253#endif 1254} 1255 1256/* 1257 * VT300 and up support three ANSI conformance levels, defined according to 1258 * the dpANSI X3.134.1 standard. DEC's manuals equate levels 1 and 2, and 1259 * are unclear. This code is written based on the manuals. 1260 */ 1261static void 1262set_ansi_conformance(TScreen *screen, int level) 1263{ 1264 TRACE(("set_ansi_conformance(%d) dec_level %d:%d, ansi_level %d\n", 1265 level, 1266 screen->vtXX_level * 100, 1267 screen->terminal_id, 1268 screen->ansi_level)); 1269 if (screen->vtXX_level >= 3) { 1270 switch (screen->ansi_level = level) { 1271 case 1: 1272 /* FALLTHRU */ 1273 case 2: 1274 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */ 1275 initCharset(screen, 1, nrc_ASCII); /* G1 is ISO Latin-1 */ 1276 screen->curgl = 0; 1277 screen->curgr = 1; 1278 break; 1279 case 3: 1280 initCharset(screen, 0, nrc_ASCII); /* G0 is ASCII */ 1281 screen->curgl = 0; 1282 break; 1283 } 1284 } 1285} 1286 1287/* 1288 * Set scrolling margins. VTxxx terminals require that the top/bottom are 1289 * different, so we have at least two lines in the scrolling region. 1290 */ 1291static void 1292set_tb_margins(TScreen *screen, int top, int bottom) 1293{ 1294 TRACE(("set_tb_margins %d..%d, prior %d..%d\n", 1295 top, bottom, 1296 screen->top_marg, 1297 screen->bot_marg)); 1298 if (bottom > top) { 1299 screen->top_marg = top; 1300 screen->bot_marg = bottom; 1301 } 1302 if (screen->top_marg > screen->max_row) 1303 screen->top_marg = screen->max_row; 1304 if (screen->bot_marg > screen->max_row) 1305 screen->bot_marg = screen->max_row; 1306} 1307 1308static void 1309set_lr_margins(TScreen *screen, int left, int right) 1310{ 1311 TRACE(("set_lr_margins %d..%d, prior %d..%d\n", 1312 left, right, 1313 screen->lft_marg, 1314 screen->rgt_marg)); 1315 if (right > left) { 1316 screen->lft_marg = left; 1317 screen->rgt_marg = right; 1318 } 1319 if (screen->lft_marg > screen->max_col) 1320 screen->lft_marg = screen->max_col; 1321 if (screen->rgt_marg > screen->max_col) 1322 screen->rgt_marg = screen->max_col; 1323} 1324 1325#define reset_tb_margins(screen) set_tb_margins(screen, 0, screen->max_row) 1326#define reset_lr_margins(screen) set_lr_margins(screen, 0, screen->max_col) 1327 1328void 1329resetMargins(XtermWidget xw) 1330{ 1331 TScreen *screen = TScreenOf(xw); 1332 1333 reset_tb_margins(screen); 1334 reset_lr_margins(screen); 1335} 1336 1337static void 1338resetMarginMode(XtermWidget xw) 1339{ 1340 UIntClr(xw->flags, LEFT_RIGHT); 1341 resetMargins(xw); 1342} 1343 1344static void 1345resetRendition(XtermWidget xw) 1346{ 1347 TScreen *screen = TScreenOf(xw); 1348 (void) screen; 1349 ResetItalics(xw); 1350 UIntClr(xw->flags, 1351 (SGR_MASK | SGR_MASK2 | INVISIBLE)); 1352} 1353 1354void 1355set_max_col(TScreen *screen, int cols) 1356{ 1357 TRACE(("set_max_col %d, prior %d\n", cols, screen->max_col)); 1358 if (cols < 0) 1359 cols = 0; 1360 screen->max_col = cols; 1361} 1362 1363void 1364set_max_row(TScreen *screen, int rows) 1365{ 1366 TRACE(("set_max_row %d, prior %d\n", rows, screen->max_row)); 1367 if (rows < 0) 1368 rows = 0; 1369 screen->max_row = rows; 1370} 1371 1372#if OPT_MOD_FKEYS 1373static void 1374set_mod_fkeys(XtermWidget xw, int which, int what, Bool enabled) 1375{ 1376#define SET_MOD_FKEYS(field) \ 1377 xw->keyboard.modify_now.field = ((what == DEFAULT) && enabled) \ 1378 ? xw->keyboard.modify_1st.field \ 1379 : what; \ 1380 TRACE(("set modify_now.%s to %d\n", #field, \ 1381 xw->keyboard.modify_now.field)); 1382 1383 switch (which) { 1384 case 0: 1385 SET_MOD_FKEYS(allow_keys); 1386 break; 1387 case 1: 1388 SET_MOD_FKEYS(cursor_keys); 1389 break; 1390 case 2: 1391 SET_MOD_FKEYS(function_keys); 1392 break; 1393 case 3: 1394 SET_MOD_FKEYS(keypad_keys); 1395 break; 1396 case 4: 1397 SET_MOD_FKEYS(other_keys); 1398 break; 1399 case 5: 1400 SET_MOD_FKEYS(string_keys); 1401 break; 1402 } 1403} 1404#endif /* OPT_MOD_FKEYS */ 1405 1406#if OPT_TRACE 1407#define DATA(name) { name, #name } 1408static const struct { 1409 Const PARSE_T *table; 1410 const char *name; 1411} all_tables[] = { 1412 1413 DATA(ansi_table) 1414 ,DATA(cigtable) 1415 ,DATA(csi2_table) 1416 ,DATA(csi_ex_table) 1417 ,DATA(csi_quo_table) 1418 ,DATA(csi_table) 1419 ,DATA(dec2_table) 1420 ,DATA(dec3_table) 1421 ,DATA(dec_table) 1422 ,DATA(eigtable) 1423 ,DATA(esc_sp_table) 1424 ,DATA(esc_table) 1425 ,DATA(scrtable) 1426 ,DATA(scs96table) 1427 ,DATA(scstable) 1428 ,DATA(sos_table) 1429#if OPT_BLINK_CURS 1430 ,DATA(csi_sp_table) 1431#endif 1432#if OPT_DEC_LOCATOR 1433 ,DATA(csi_tick_table) 1434#endif 1435#if OPT_DEC_RECTOPS 1436 ,DATA(csi_dollar_table) 1437 ,DATA(csi_star_table) 1438 ,DATA(csi_dec_dollar_table) 1439#endif 1440#if OPT_WIDE_CHARS 1441 ,DATA(esc_pct_table) 1442 ,DATA(scs_amp_table) 1443 ,DATA(scs_pct_table) 1444 ,DATA(scs_2qt_table) 1445#endif 1446#if OPT_VT52_MODE 1447 ,DATA(vt52_table) 1448 ,DATA(vt52_esc_table) 1449 ,DATA(vt52_ignore_table) 1450#endif 1451#if OPT_XTERM_SGR 1452 ,DATA(csi_hash_table) 1453#endif 1454#undef DATA 1455}; 1456 1457#define WHICH_TABLE(name) if (table == name) result = #name 1458static const char * 1459which_table(Const PARSE_T * table) 1460{ 1461 const char *result = "?"; 1462 Cardinal n; 1463 for (n = 0; n < XtNumber(all_tables); ++n) { 1464 if (table == all_tables[n].table) { 1465 result = all_tables[n].name; 1466 break; 1467 } 1468 } 1469 1470 return result; 1471} 1472 1473static void 1474check_tables(void) 1475{ 1476 Cardinal n; 1477 int ch; 1478 int total_codes = 0; 1479 int total_ground = 0; 1480 int total_ignored = 0; 1481 1482 TRACE(("** check_tables\n")); 1483 for (n = 0; n < XtNumber(all_tables); ++n) { 1484 Const PARSE_T *table = all_tables[n].table; 1485 TRACE(("*** %s\n", all_tables[n].name)); 1486 /* 1487 * Most of the tables should use the same codes in 0..31, 128..159 1488 * as the "ansi" table. 1489 */ 1490 if (strncmp(all_tables[n].name, "ansi", 4) && 1491 strncmp(all_tables[n].name, "sos_", 4) && 1492 strncmp(all_tables[n].name, "vt52", 4)) { 1493 for (ch = 0; ch < 32; ++ch) { 1494 int c1 = ch + 128; 1495 PARSE_T st_l = table[ch]; 1496 PARSE_T st_r = table[c1]; 1497 if (st_l != ansi_table[ch]) { 1498 TRACE((" %3d: %d vs %d\n", ch, st_l, ansi_table[ch])); 1499 } 1500 if (st_r != ansi_table[c1]) { 1501 TRACE((" %3d: %d vs %d\n", c1, st_r, ansi_table[c1])); 1502 } 1503 } 1504 } 1505 /* 1506 * All of the tables should have their GL/GR parts encoded the same. 1507 */ 1508 for (ch = 32; ch < 127; ++ch) { 1509 PARSE_T st_l = table[ch]; 1510 PARSE_T st_r = table[ch + 128]; 1511 if (st_l != st_r) { 1512 if (st_r == CASE_IGNORE && 1513 !strncmp(all_tables[n].name, "vt52", 4)) { 1514 ; 1515 } else { 1516 TRACE((" %3d: %d vs %d\n", ch, st_l, st_r)); 1517 } 1518 } 1519 } 1520 /* 1521 * Just for amusement, show how sparse the encoding tables are. 1522 */ 1523 for (ch = 0; ch < 256; ++ch) { 1524 ++total_codes; 1525 switch (table[ch]) { 1526 case CASE_GROUND_STATE: 1527 total_ground++; 1528 break; 1529 case CASE_ESC_IGNORE: 1530 /* FALLTHRU */ 1531 case CASE_IGNORE: 1532 /* FALLTHRU */ 1533 case CASE_VT52_IGNORE: 1534 total_ignored++; 1535 break; 1536 } 1537 } 1538 } 1539 TRACE(("VTPrsTbl:\n")); 1540 TRACE(("%d total codes\n", total_codes)); 1541 TRACE(("%d total ignored\n", total_ignored)); 1542 TRACE(("%d total reset/ground\n", total_ground)); 1543} 1544 1545static void 1546check_bitmasks(void) 1547{ 1548#define dMSK 0x100 1549#define DATA(mode,name) { mode, name, #name } 1550#define DMSK(what) (dMSK | (what)) 1551#define DGRP(offs) (1 << ((offs) - 1)) 1552 static struct { 1553 int mode; 1554 int code; 1555 Const char *name; 1556 } table[] = { 1557 DATA(DGRP(1), INVERSE), 1558 DATA(DGRP(1), UNDERLINE), 1559 DATA(DGRP(1), BOLD), 1560 DATA(DGRP(1), BLINK), 1561 DATA(DMSK(DGRP(1)), SGR_MASK), 1562 DATA(DGRP(2), BG_COLOR), 1563 DATA(DGRP(2), FG_COLOR), 1564 DATA(DGRP(2), PROTECTED), 1565 DATA(DGRP(4), CHARDRAWN), 1566#if OPT_WIDE_ATTRS 1567 DATA(DGRP(2), ATR_FAINT), 1568 DATA(DGRP(2), ATR_ITALIC), 1569 DATA(DGRP(2), ATR_STRIKEOUT), 1570 DATA(DGRP(2), ATR_DBL_UNDER), 1571 DATA(DGRP(2), ATR_DIRECT_FG), 1572 DATA(DGRP(2), ATR_DIRECT_BG), 1573#endif 1574 DATA(DMSK(DGRP(2)), SGR_MASK2), 1575 DATA(DGRP(3), WRAPAROUND), 1576 DATA(DGRP(3), REVERSEWRAP), 1577 DATA(DGRP(3), REVERSE_VIDEO), 1578 DATA(DGRP(3), LINEFEED), 1579 DATA(DGRP(3), ORIGIN), 1580 DATA(DGRP(3), INSERT), 1581 DATA(DGRP(3), SMOOTHSCROLL), 1582 DATA(DGRP(3), IN132COLUMNS), 1583 DATA(DGRP(3), INVISIBLE), 1584 DATA(DMSK(DGRP(3)), ATTRIBUTES), 1585 DATA(DGRP(5), NATIONAL), 1586 DATA(DGRP(5), LEFT_RIGHT), 1587 DATA(DGRP(5), NOCLEAR_COLM), 1588 DATA(DGRP(4), NOBACKGROUND), 1589 DATA(DGRP(4), NOTRANSLATION), 1590 DATA(DGRP(4), DOUBLEWFONT), 1591 DATA(DGRP(4), DOUBLEHFONT), 1592 DATA(DGRP(4), CHARBYCHAR), 1593 DATA(DGRP(4), NORESOLUTION), 1594 DATA(DMSK(DGRP(1) | DGRP(2) | DGRP(4)), DRAWX_MASK), 1595 DATA(-1, EOF) 1596 }; 1597#undef DATA 1598 int j, k; 1599 TRACE(("** check_bitmasks:\n")); 1600 for (j = 0; table[j].mode >= 0; ++j) { 1601 TRACE(("%4X %8X %s\n", table[j].mode, table[j].code, table[j].name)); 1602 if (table[j].mode & dMSK) { 1603 int mask = dMSK; 1604 for (k = 0; table[k].mode >= 0; ++k) { 1605 if (j == k) 1606 continue; 1607 if (table[k].mode & dMSK) 1608 continue; 1609 if ((table[j].mode & table[k].mode) != 0) 1610 mask |= table[k].mode; 1611 } 1612 if (mask != table[j].mode) { 1613 TRACE(("...expected %08X\n", mask)); 1614 } 1615 } else { 1616 for (k = 0; table[k].mode >= 0; ++k) { 1617 if (j == k) 1618 continue; 1619 if (table[k].mode & dMSK) 1620 continue; 1621 if ((table[j].code & table[k].code) != 0) { 1622 TRACE(("...same bits %s\n", table[k].name)); 1623 } 1624 } 1625 } 1626 } 1627} 1628#endif 1629 1630static int 1631init_params(void) 1632{ 1633 while (parms.count-- > 0) { 1634 parms.is_sub[parms.count] = 0; 1635 parms.params[parms.count] = 0; 1636 } 1637 parms.count = 0; 1638 parms.has_subparams = 0; 1639 return 0; 1640} 1641 1642#if OPT_TRACE > 0 1643static void 1644dump_params(void) 1645{ 1646 int n; 1647 int arg; 1648 TRACE(("params %d (%d)\n", nparam, parms.has_subparams)); 1649 for (arg = 1, n = 0; n < nparam; ++n) { 1650 TRACE(("%3d.%d %d\n", arg, parms.is_sub[n], parms.params[n])); 1651 if (!parms.is_sub[n]) 1652 ++arg; 1653 } 1654} 1655#define DumpParams() dump_params() 1656#else 1657#define DumpParams() /* nothing */ 1658#endif 1659 1660 /* allocate larger buffer if needed/possible */ 1661#define SafeAlloc(type, area, used, size) \ 1662 type *new_string = area; \ 1663 size_t new_length = size; \ 1664 if (new_length == 0) { \ 1665 new_length = 1024; \ 1666 new_string = TypeMallocN(type, new_length); \ 1667 } else if (used+1 >= new_length) { \ 1668 new_length = size * 2; \ 1669 new_string = TypeMallocN(type, new_length); \ 1670 if (new_string != 0 \ 1671 && area != 0 \ 1672 && used != 0) { \ 1673 memcpy(new_string, area, used * sizeof(type)); \ 1674 } \ 1675 } 1676#define SafeFree(area, size) \ 1677 if (area != new_string) { \ 1678 free(area); \ 1679 area = new_string; \ 1680 } \ 1681 size = new_length 1682 1683#define WriteNow() { \ 1684 unsigned single = 0; \ 1685 \ 1686 if (screen->curss) { \ 1687 dotext(xw, \ 1688 screen->gsets[(int) (screen->curss)], \ 1689 sp->print_area, \ 1690 (Cardinal) 1); \ 1691 screen->curss = 0; \ 1692 single++; \ 1693 } \ 1694 if (sp->print_used > single) { \ 1695 dotext(xw, \ 1696 screen->gsets[(int) (screen->curgl)], \ 1697 sp->print_area + single, \ 1698 (Cardinal) (sp->print_used - single)); \ 1699 } \ 1700 sp->print_used = 0; \ 1701 } \ 1702 1703#define PARSE_SRM 1 1704 1705struct ParseState { 1706 unsigned check_recur; 1707#if OPT_VT52_MODE 1708 Bool vt52_cup; 1709#endif 1710 Const PARSE_T *groundtable; 1711 Const PARSE_T *parsestate; 1712 int scstype; 1713 int scssize; 1714 Bool private_function; /* distinguish private-mode from standard */ 1715 int string_mode; /* nonzero iff we're processing a string */ 1716 int lastchar; /* positive iff we had a graphic character */ 1717 int nextstate; 1718#if OPT_WIDE_CHARS 1719 int last_was_wide; 1720#endif 1721 /* Buffer for processing printable text */ 1722 IChar *print_area; 1723 size_t print_size; 1724 size_t print_used; 1725 /* Buffer for processing strings (e.g., OSC ... ST) */ 1726 Char *string_area; 1727 size_t string_size; 1728 size_t string_used; 1729 /* Buffer for deferring input */ 1730 Char *defer_area; 1731 size_t defer_size; 1732 size_t defer_used; 1733}; 1734 1735static struct ParseState myState; 1736 1737static void 1738init_groundtable(TScreen *screen, struct ParseState *sp) 1739{ 1740 (void) screen; 1741 1742#if OPT_VT52_MODE 1743 if (!(screen->vtXX_level)) { 1744 sp->groundtable = vt52_table; 1745 } else if (screen->terminal_id >= 100) 1746#endif 1747 { 1748 sp->groundtable = ansi_table; 1749 } 1750} 1751 1752static void 1753select_charset(struct ParseState *sp, int type, int size) 1754{ 1755 TRACE(("select_charset G%d size %d -> G%d size %d\n", 1756 sp->scstype, sp->scssize, 1757 type, size)); 1758 1759 sp->scstype = type; 1760 sp->scssize = size; 1761 if (size == 94) { 1762 sp->parsestate = scstable; 1763 } else { 1764 sp->parsestate = scs96table; 1765 } 1766} 1767/* *INDENT-OFF* */ 1768static const struct { 1769 DECNRCM_codes result; 1770 int prefix; 1771 int suffix; 1772 int min_level; 1773 int max_level; 1774 int need_nrc; 1775} scs_table[] = { 1776 { nrc_ASCII, 0, 'B', 1, 9, 0 }, 1777 { nrc_British, 0, 'A', 1, 9, 0 }, 1778 { nrc_DEC_Spec_Graphic, 0, '0', 1, 9, 0 }, 1779 { nrc_DEC_Alt_Chars, 0, '1', 1, 1, 0 }, 1780 { nrc_DEC_Alt_Graphics, 0, '2', 1, 1, 0 }, 1781 /* VT2xx */ 1782 { nrc_DEC_Supp, 0, '<', 2, 9, 0 }, 1783 { nrc_Dutch, 0, '4', 2, 9, 1 }, 1784 { nrc_Finnish, 0, '5', 2, 9, 1 }, 1785 { nrc_Finnish2, 0, 'C', 2, 9, 1 }, 1786 { nrc_French, 0, 'R', 2, 9, 1 }, 1787 { nrc_French2, 0, 'f', 2, 9, 1 }, 1788 { nrc_French_Canadian, 0, 'Q', 2, 9, 1 }, 1789 { nrc_German, 0, 'K', 2, 9, 1 }, 1790 { nrc_Italian, 0, 'Y', 2, 9, 1 }, 1791 { nrc_Norwegian_Danish2, 0, 'E', 2, 9, 1 }, 1792 { nrc_Norwegian_Danish3, 0, '6', 2, 9, 1 }, 1793 { nrc_Spanish, 0, 'Z', 2, 9, 1 }, 1794 { nrc_Swedish, 0, '7', 2, 9, 1 }, 1795 { nrc_Swedish2, 0, 'H', 2, 9, 1 }, 1796 { nrc_Swiss, 0, '=', 2, 9, 1 }, 1797 /* VT3xx */ 1798 { nrc_British_Latin_1, 0, 'A', 3, 9, 1 }, 1799 { nrc_DEC_Supp_Graphic, '%', '5', 3, 9, 0 }, 1800 { nrc_DEC_Technical, 0, '>', 3, 9, 0 }, 1801 { nrc_French_Canadian2, 0, '9', 3, 9, 1 }, 1802 { nrc_Norwegian_Danish, 0, '`', 3, 9, 1 }, 1803 { nrc_Portugese, '%', '6', 3, 9, 1 }, 1804 { nrc_ISO_Latin_1_Supp, 0, 'A', 3, 9, 0 }, 1805 /* VT5xx */ 1806 { nrc_Greek, '"', '>', 5, 9, 1 }, 1807 { nrc_Hebrew, '%', '=', 5, 9, 1 }, 1808 { nrc_Turkish, '%', '2', 5, 9, 1 }, 1809 { nrc_DEC_Cyrillic, '&', '4', 5, 9, 0 }, 1810 { nrc_DEC_Greek_Supp, '"', '?', 5, 9, 0 }, 1811 { nrc_DEC_Hebrew_Supp, '"', '4', 5, 9, 0 }, 1812 { nrc_DEC_Turkish_Supp, '%', '0', 5, 9, 0 }, 1813 { nrc_ISO_Greek_Supp, 0, 'F', 5, 9, 0 }, 1814 { nrc_ISO_Hebrew_Supp, 0, 'H', 5, 9, 0 }, 1815 { nrc_ISO_Latin_2_Supp, 0, 'B', 5, 9, 0 }, 1816 { nrc_ISO_Latin_5_Supp, 0, 'M', 5, 9, 0 }, 1817 { nrc_ISO_Latin_Cyrillic,0, 'L', 5, 9, 0 }, 1818 /* VT5xx (not implemented) */ 1819#if 0 1820 { nrc_Russian, '&', '5', 5, 9, 1 }, 1821 { nrc_SCS_NRCS, '%', '3', 5, 9, 0 }, 1822#endif 1823}; 1824/* *INDENT-ON* */ 1825 1826#if OPT_DEC_RECTOPS 1827static char * 1828encode_scs(DECNRCM_codes value) 1829{ 1830 static char buffer[3]; 1831 Cardinal n; 1832 char *result = buffer; 1833 for (n = 0; n < XtNumber(scs_table); ++n) { 1834 if (scs_table[n].result == value) { 1835 if (scs_table[n].prefix) 1836 *result++ = (char) scs_table[n].prefix; 1837 if (scs_table[n].suffix) 1838 *result++ = (char) scs_table[n].suffix; 1839 break; 1840 } 1841 } 1842 *result = '\0'; 1843 return buffer; 1844} 1845#endif 1846 1847void 1848xtermDecodeSCS(XtermWidget xw, int which, int sgroup, int prefix, int suffix) 1849{ 1850 TScreen *screen = TScreenOf(xw); 1851 Cardinal n; 1852 DECNRCM_codes result = nrc_Unknown; 1853 1854 suffix &= 0x7f; 1855 for (n = 0; n < XtNumber(scs_table); ++n) { 1856 if (prefix == scs_table[n].prefix 1857 && suffix == scs_table[n].suffix 1858 && sgroup == scs_table[n].min_level 1859 && screen->vtXX_level >= scs_table[n].min_level 1860 && screen->vtXX_level <= scs_table[n].max_level 1861 && (scs_table[n].need_nrc == 0 || (xw->flags & NATIONAL) != 0)) { 1862 result = scs_table[n].result; 1863 break; 1864 } 1865 } 1866 if (result != nrc_Unknown) { 1867 initCharset(screen, which, result); 1868 TRACE(("setting G%d to table #%d %s", 1869 which, n, visibleScsCode((int) result))); 1870 } else { 1871 TRACE(("...unknown GSET")); 1872 initCharset(screen, which, nrc_ASCII); 1873 } 1874#if OPT_TRACE 1875 TRACE((" (")); 1876 if (prefix) 1877 TRACE(("prefix='%c', ", prefix)); 1878 TRACE(("suffix='%c', sgroup=%d", suffix, sgroup)); 1879 TRACE((")\n")); 1880#endif 1881} 1882 1883/* 1884 * Given a parameter number, and subparameter (starting in each case from zero) 1885 * return the corresponding index into the parameter array. If the combination 1886 * is not found, return -1. 1887 */ 1888static int 1889subparam_index(int p, int s) 1890{ 1891 int result = -1; 1892 int j, p2, s2; 1893 1894 for (j = p2 = 0; j < nparam; ++j, ++p2) { 1895 if (parms.is_sub[j]) { 1896 s2 = 0; 1897 1898 do { 1899 if ((p == p2) && (s == s2)) { 1900 result = j; 1901 break; 1902 } 1903 ++s2; 1904 } while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])); 1905 1906 if (result >= 0) 1907 break; 1908 1909 --j; /* undo the last "while" */ 1910 } else if (p == p2) { 1911 if (s == 0) { 1912 result = j; 1913 } 1914 break; 1915 } 1916 } 1917 TRACE2(("...subparam_index %d.%d = %d\n", p + 1, s + 1, result)); 1918 return result; 1919} 1920 1921/* 1922 * Check if the given item in the parameter array has subparameters. 1923 * If so, return the number of subparameters to use as a loop limit, etc. 1924 */ 1925static int 1926param_has_subparams(int item) 1927{ 1928 int result = 0; 1929 if (parms.has_subparams) { 1930 int n = subparam_index(item, 0); 1931 if (n >= 0 && parms.is_sub[n]) { 1932 while (++n < nparam && parms.is_sub[n - 1] < parms.is_sub[n]) { 1933 result++; 1934 } 1935 } 1936 } 1937 TRACE(("...param_has_subparams(%d) ->%d\n", item, result)); 1938 return result; 1939} 1940 1941#if OPT_DIRECT_COLOR || OPT_256_COLORS || OPT_88_COLORS || OPT_ISO_COLORS 1942/* 1943 * Given an index into the parameter array, return the corresponding parameter 1944 * number (starting from zero). 1945 */ 1946static int 1947param_number(int item) 1948{ 1949 int result = -1; 1950 int j, p; 1951 1952 for (j = p = 0; j < nparam; ++j, ++p) { 1953 if (p >= item) { 1954 result = j; 1955 break; 1956 } 1957 if (parms.is_sub[j]) { 1958 while ((++j < nparam) && (parms.is_sub[j - 1] < parms.is_sub[j])) { 1959 /* EMPTY */ 1960 } 1961 --j; 1962 } 1963 } 1964 1965 TRACE2(("...param_number(%d) = %d\n", item, result)); 1966 return result; 1967} 1968 1969static int 1970get_subparam(int p, int s) 1971{ 1972 int item = subparam_index(p, s); 1973 int result = (item >= 0) ? parms.params[item] : DEFAULT; 1974 TRACE(("...get_subparam[%d] = %d\n", item, result)); 1975 return result; 1976} 1977 1978/* 1979 * Some background - 1980 * 1981 * Todd Larason provided the initial changes to support 256-colors in July 1999. 1982 * I pointed out that the description of SGR 38/48 in ECMA-48 was vague, and 1983 * was unsure if there would be some standard using those codes. His response 1984 * was that this was documented (it turns out, in equally vague terms) in ITU 1985 * T.416 1986 * 1987 * Discussing this with Todd Larason in mid-1999, my point was that given the 1988 * high cost of obtaining ITU T.416 (ISO-8613-6), the standard was not going 1989 * to be effective (more than $100 then, more than $200 in 2012) 1990 * 1991 * We overlooked the detail about ":" as a subparameter delimiter (documented 1992 * in 5.4.2 in ECMA-48). Some discussion in KDE in mid-2006 led Lars Doelle 1993 * to discuss the issue with me. Lars' initial concern dealt with the fact 1994 * that a sequence such as 1995 * CSI 38 ; 5 ; 1 m 1996 * violated the principle that SGR parameters could be used in any order. 1997 * Further discussion (see KDE #107487) resolved that the standard expected 1998 * that the sequence would look like 1999 * CSI 38 ; 5 : 1 m 2000 * which still violates that principle, since the "5:1" parameter has to 2001 * follow the "38" to be useful. 2002 * 2003 * This function accepts either format (per request by Paul Leonerd Evans). 2004 * It also accepts 2005 * CSI 38 : 5 : 1 m 2006 * according to Lars' original assumption. While implementing that, I added 2007 * support for Konsole's interpretation of "CSI 38 : 2" as a 24-bit RGB value. 2008 * ISO-8613-6 documents that as "direct color". 2009 * 2010 * At the time in 2012, no one noticed (or commented) regarding ISO-8613-6's 2011 * quirk in the description of direct color: it mentions a color space 2012 * identifier parameter which should follow the "2" (as parameter 1). In the 2013 * same section, ISO-8613-6 mentions a parameter 6 which can be ignored, as 2014 * well as parameters 7 and 8. Like parameter 1, parameters 7 and 8 are not 2015 * defined clearly in the standard, and a close reading indicates they are 2016 * optional, saying they "may be used". This implementation ignores parameters 2017 * 6 (and above), and provides for the color space identifier by checking the 2018 * number of parameters: 2019 * 3 after "2" (no color space identifier) 2020 * 4 or more after "2" (color space identifier) 2021 * 2022 * By the way - all of the parameters are decimal integers, and missing 2023 * parameters represent a default value. ISO-8613-6 is clear about that. 2024 * 2025 * Aside from ISO-8613-3, there is no standard use of ":" as a delimiter. 2026 * ECMA-48 says only: 2027 * 2028 * 5.4.2 Parameter string format 2029 * 2030 * A parameter string which does not start with a bit combination in the 2031 * range 03/12 to 03/15 shall have the following format: 2032 * 2033 * a) A parameter string consists of one or more parameter 2034 * sub-strings, each of which represents a number in decimal 2035 * notation. 2036 * 2037 * b) Each parameter sub-string consists of one or more bit 2038 * combinations from 03/00 to 03/10; the bit combinations from 2039 * 03/00 to 03/09 represent the digits ZERO to NINE; bit 2040 * combination 03/10 may be used as a separator in a parameter 2041 * sub-string, for example, to separate the fractional part of a 2042 * decimal number from the integer part of that number. 2043 * 2044 * That is, there is no mention in ECMA-48 of the possibility that a parameter 2045 * string might be a list of parameters, as done in ISO-8613-3 (nor does 2046 * ECMA-48 provide an example where the ":" separator might be used). Because 2047 * of this, xterm treats other cases than those needed for ISO-8613-3 as an 2048 * error, and stops interpreting the sequence. 2049 */ 2050#define extended_colors_limit(n) ((n) == 5 ? 1 : ((n) == 2 ? 3 : 0)) 2051static Boolean 2052parse_extended_colors(XtermWidget xw, int *colorp, int *itemp, Boolean *extended) 2053{ 2054 Boolean result = False; 2055 int item = *itemp; 2056 int next = item; 2057 int base = param_number(item); 2058 int code = -1; 2059 int values[3]; /* maximum number of subparameters */ 2060 int need = 0; /* number of subparameters needed */ 2061 int have; 2062 int n; 2063 2064 /* 2065 * On entry, 'item' points to the 38/48 code in the parameter array. 2066 * If that has subparameters, we will expect all of the values to 2067 * be subparameters of that item. 2068 */ 2069 if ((have = param_has_subparams(item)) != 0) { 2070 /* accept CSI 38 : 5 : 1 m */ 2071 /* accept CSI 38 : 2 : 1 : 2 : 3 m */ 2072 code = get_subparam(base, 1); 2073 need = extended_colors_limit(code); 2074 next = item + have; 2075 for (n = 0; n < need && n < 3; ++n) { 2076 values[n] = get_subparam(base, 2 + n + (have > 4)); 2077 } 2078 } else if (++item < nparam) { 2079 ++base; 2080 if ((have = param_has_subparams(item)) != 0) { 2081 /* accept CSI 38 ; 5 : 1 m */ 2082 /* accept CSI 38 ; 2 : 1 : 2 : 3 m */ 2083 code = get_subparam(base, 0); 2084 need = extended_colors_limit(code); 2085 next = base + have; 2086 for (n = 0; n < need && n < 3; ++n) { 2087 values[n] = get_subparam(base, 1 + n + (have > 3)); 2088 } 2089 } else { 2090 /* accept CSI 38 ; 5 ; 1 m */ 2091 /* accept CSI 38 ; 2 ; 1 ; 2 ; 3 m */ 2092 code = GetParam(item); 2093 need = extended_colors_limit(code); 2094 next = item + need; 2095 for (n = 0; n < need && n < 3; ++n) { 2096 values[n] = GetParam(item + 1 + n); 2097 } 2098 } 2099 } 2100 item = next; 2101 2102 *extended = False; 2103 switch (code) { 2104 case 2: 2105 /* direct color in rgb space */ 2106 if ((values[0] >= 0 && values[0] < 256) && 2107 (values[1] >= 0 && values[1] < 256) && 2108 (values[2] >= 0 && values[2] < 256)) { 2109#if OPT_DIRECT_COLOR 2110 if (TScreenOf(xw)->direct_color && xw->has_rgb) { 2111 *colorp = getDirectColor(xw, values[0], values[1], values[2]); 2112 result = True; 2113 *extended = True; 2114 } else 2115#endif 2116 { 2117 *colorp = xtermClosestColor(xw, values[0], values[1], values[2]); 2118 result = okIndexedColor(*colorp); 2119 } 2120 } else { 2121 *colorp = -1; 2122 } 2123 break; 2124 case 5: 2125 /* indexed color */ 2126 *colorp = values[0]; 2127 result = okIndexedColor(*colorp); 2128 break; 2129 default: 2130 *colorp = -1; 2131 break; 2132 } 2133 2134 TRACE(("...resulting color %d/%d %s\n", 2135 *colorp, NUM_ANSI_COLORS, 2136 result ? "OK" : "ERR")); 2137 2138 *itemp = item; 2139 return result; 2140} 2141#endif /* ...extended_colors */ 2142 2143static int 2144optional_param(int which) 2145{ 2146 return (nparam > which) ? GetParam(which) : DEFAULT; 2147} 2148 2149static int 2150zero_if_default(int which) 2151{ 2152 int result = (nparam > which) ? GetParam(which) : 0; 2153 if (result <= 0) 2154 result = 0; 2155 return result; 2156} 2157 2158static int 2159one_if_default(int which) 2160{ 2161 int result = (nparam > which) ? GetParam(which) : 0; 2162 if (result <= 0) 2163 result = 1; 2164 return result; 2165} 2166 2167/* 2168 * Color palette changes using the OSC controls require a repaint of the 2169 * screen - but not immediately. Do the repaint as soon as we detect a 2170 * state which will not lead to another color palette change. 2171 */ 2172static void 2173repaintWhenPaletteChanged(XtermWidget xw, struct ParseState *sp) 2174{ 2175 Boolean ignore = False; 2176 2177 switch (sp->nextstate) { 2178 case CASE_ESC: 2179 ignore = ((sp->parsestate == ansi_table) || 2180 (sp->parsestate == sos_table)); 2181#if USE_DOUBLE_BUFFER 2182 if (resource.buffered && TScreenOf(xw)->needSwap) { 2183 ignore = False; 2184 } 2185#endif 2186 break; 2187 case CASE_OSC: 2188 ignore = ((sp->parsestate == ansi_table) || 2189 (sp->parsestate == esc_table)); 2190 break; 2191 case CASE_IGNORE: 2192 ignore = (sp->parsestate == sos_table); 2193 break; 2194 case CASE_ST: 2195 ignore = ((sp->parsestate == esc_table) || 2196 (sp->parsestate == sos_table)); 2197 break; 2198 case CASE_ESC_DIGIT: 2199 ignore = (sp->parsestate == csi_table); 2200 break; 2201 case CASE_ESC_SEMI: 2202 ignore = (sp->parsestate == csi2_table); 2203 break; 2204 } 2205 2206 if (!ignore) { 2207 TRACE(("repaintWhenPaletteChanged\n")); 2208 xw->work.palette_changed = False; 2209 xtermRepaint(xw); 2210 xtermFlushDbe(xw); 2211 } 2212} 2213 2214#if OPT_C1_PRINT || OPT_WIDE_CHARS 2215#define ParseSOS(screen) ((screen)->c1_printable == 0) 2216#else 2217#define ParseSOS(screen) 0 2218#endif 2219 2220#define ResetState(sp) InitParams(), (sp)->parsestate = (sp)->groundtable 2221 2222static void 2223illegal_parse(XtermWidget xw, unsigned c, struct ParseState *sp) 2224{ 2225 ResetState(sp); 2226 sp->nextstate = sp->parsestate[E2A(c)]; 2227 Bell(xw, XkbBI_MinorError, 0); 2228} 2229 2230static void 2231init_parser(XtermWidget xw, struct ParseState *sp) 2232{ 2233 TScreen *screen = TScreenOf(xw); 2234 2235 free(sp->defer_area); 2236 free(sp->print_area); 2237 free(sp->string_area); 2238 memset(sp, 0, sizeof(*sp)); 2239 sp->scssize = 94; /* number of printable/nonspace ASCII */ 2240 sp->lastchar = -1; /* not a legal IChar */ 2241 sp->nextstate = -1; /* not a legal state */ 2242 2243 init_groundtable(screen, sp); 2244 ResetState(sp); 2245} 2246 2247static void 2248init_reply(unsigned type) 2249{ 2250 memset(&reply, 0, sizeof(reply)); 2251 reply.a_type = (Char) type; 2252} 2253 2254static void 2255deferparsing(unsigned c, struct ParseState *sp) 2256{ 2257 SafeAlloc(Char, sp->defer_area, sp->defer_used, sp->defer_size); 2258 if (new_string == 0) { 2259 xtermWarning("Cannot allocate %lu bytes for deferred parsing of %u\n", 2260 (unsigned long) new_length, c); 2261 return; 2262 } 2263 SafeFree(sp->defer_area, sp->defer_size); 2264 sp->defer_area[(sp->defer_used)++] = CharOf(c); 2265} 2266 2267#if OPT_STATUS_LINE 2268typedef enum { 2269 SLnone = 0, /* no status-line timer needed */ 2270 SLclock = 1, /* status-line updates once/second */ 2271 SLcoords = 2, /* status-line shows cursor-position */ 2272 SLwritten = 3 /* status-line may need asynchonous repainting */ 2273} SL_MODE; 2274 2275#define SL_BUFSIZ 80 2276 2277#if OPT_TRACE 2278static const char * 2279visibleStatusType(int code) 2280{ 2281 const char *result = "?"; 2282 switch (code) { 2283 case 0: 2284 result = "none"; 2285 break; 2286 case 1: 2287 result = "indicator"; 2288 break; 2289 case 2: 2290 result = "writable"; 2291 break; 2292 } 2293 return result; 2294} 2295 2296static void 2297trace_status_line(XtermWidget xw, int lineno, const char *tag) 2298{ 2299 TScreen *screen = TScreenOf(xw); 2300 2301 TRACE(("@%d, %s (%s, %s)%s%s @ (%d,%d) vs %d\n", 2302 lineno, 2303 tag, 2304 screen->status_active ? "active" : "inactive", 2305 visibleStatusType(screen->status_type), 2306 ((screen->status_type != screen->status_shown) 2307 ? " vs " 2308 : ""), 2309 ((screen->status_type != screen->status_shown) 2310 ? visibleStatusType(screen->status_shown) 2311 : ""), 2312 screen->cur_row, 2313 screen->cur_col, 2314 LastRowNumber(screen))); 2315} 2316 2317#define TRACE_SL(tag) trace_status_line(xw, __LINE__, tag) 2318#else 2319#define TRACE_SL(tag) /* nothing */ 2320#endif 2321 2322static SL_MODE 2323find_SL_MODE(XtermWidget xw) 2324{ 2325 TScreen *screen = TScreenOf(xw); 2326 SL_MODE result = SLnone; 2327 const char *parse; 2328 2329 for (parse = screen->status_fmt; *parse != '\0'; ++parse) { 2330 const char *found = parse; 2331 if (*parse == '%') { 2332 if (*++parse == L_CURL) { 2333 const char *check = strchr(parse, '%'); 2334 size_t length = 0; 2335 2336 if (check != NULL && check[1] == R_CURL) { 2337 length = (size_t) (2 + check - found); 2338 } else { 2339 length = strlen(found); 2340 } 2341 2342 if (!strncmp(found, "%{unixtime%}", length)) { 2343 if (result == SLnone) 2344 result = SLclock; 2345 } else if (!strncmp(found, "%{position%}", length)) { 2346 result = SLcoords; 2347 } 2348 parse = found + length - 1; 2349 } 2350#if defined(HAVE_STRFTIME) 2351 else if (*parse != '\0') { 2352 if (result == SLnone && strchr("cEgOrsSTX+", *parse) != NULL) { 2353 result = SLclock; 2354 } 2355 } 2356#endif 2357 } 2358 } 2359 return result; 2360} 2361 2362static long 2363find_SL_Timeout(XtermWidget xw) 2364{ 2365 long result = 0; 2366 switch (find_SL_MODE(xw)) { 2367 case SLnone: 2368 case SLwritten: 2369 break; 2370 case SLclock: 2371 result = 1000; 2372 break; 2373 case SLcoords: 2374 result = 80; 2375 break; 2376 } 2377 return result; 2378} 2379 2380static void 2381StatusInit(SavedCursor * data) 2382{ 2383 memset(data, 0, sizeof(*data)); 2384 data->sgr_foreground = -1; 2385 data->sgr_background = -1; 2386} 2387 2388/* save the status-line position, restore main display */ 2389static void 2390StatusSave(XtermWidget xw) 2391{ 2392 TScreen *screen = TScreenOf(xw); 2393 2394 CursorSave2(xw, &screen->status_data[1]); 2395 CursorRestore2(xw, &screen->status_data[0]); 2396 2397 TRACE(("...StatusSave %d,%d -> %d,%d (main)\n", 2398 screen->status_data[1].row, 2399 screen->status_data[1].col, 2400 screen->cur_row, 2401 screen->cur_col)); 2402} 2403 2404/* save the main-display position, restore status-line */ 2405static void 2406StatusRestore(XtermWidget xw) 2407{ 2408 TScreen *screen = TScreenOf(xw); 2409 2410 CursorSave2(xw, &screen->status_data[0]); 2411 CursorRestore2(xw, &screen->status_data[1]); 2412 screen->cur_row = FirstRowNumber(screen); 2413 2414 TRACE(("...StatusRestore %d,%d -> %d,%d (status)\n", 2415 screen->status_data[0].row, 2416 screen->status_data[0].col, 2417 screen->cur_row, 2418 screen->cur_col)); 2419} 2420 2421static void 2422StatusPutChars(XtermWidget xw, const char *value, int length) 2423{ 2424 TScreen *screen = TScreenOf(xw); 2425 2426 if (length < 0) 2427 length = (int) strlen(value); 2428 2429 while (length > 0) { 2430 IChar buffer[SL_BUFSIZ + 1]; 2431 Cardinal n; 2432 for (n = 0; n < SL_BUFSIZ && length > 0 && *value != '\0'; ++n) { 2433 buffer[n] = CharOf(*value++); 2434 --length; 2435 } 2436 buffer[n] = 0; 2437 dotext(xw, 2438 screen->gsets[(int) (screen->curgl)], 2439 buffer, n); 2440 } 2441} 2442 2443static void 2444show_indicator_status(XtPointer closure, XtIntervalId * id GCC_UNUSED) 2445{ 2446 XtermWidget xw = (XtermWidget) closure; 2447 TScreen *screen = TScreenOf(xw); 2448 2449 time_t now; 2450 const char *parse; 2451 char buffer[SL_BUFSIZ + 1]; 2452 long interval; 2453 2454 if (screen->status_type != 1) { 2455 screen->status_timeout = False; 2456 return; 2457 } 2458 if (screen->status_active) { 2459 return; 2460 } 2461 2462 screen->status_active = True; 2463 2464 CursorSave2(xw, &screen->status_data[0]); 2465 screen->cur_row = FirstRowNumber(screen); 2466 screen->cur_col = 0; 2467 2468 xw->flags |= INVERSE; 2469 xw->flags &= (IFlags) (~WRAPAROUND); 2470 2471 now = time((time_t *) 0); 2472 2473 for (parse = screen->status_fmt; *parse != '\0'; ++parse) { 2474 const char *found = parse; 2475 if (*parse == '%') { 2476 if (*++parse == L_CURL) { 2477 const char *check = strchr(parse, '%'); 2478 size_t length = 0; 2479 2480 if (check != NULL && check[1] == R_CURL) { 2481 length = (size_t) (2 + check - found); 2482 } else { 2483 length = strlen(found); 2484 } 2485 2486 if (!strncmp(found, "%{version%}", length)) { 2487 StatusPutChars(xw, xtermVersion(), -1); 2488 } else if (!strncmp(found, "%{unixtime%}", length)) { 2489 char *t = x_strtrim(ctime(&now)); 2490 if (t != 0) { 2491 StatusPutChars(xw, t, -1); 2492 free(t); 2493 } 2494 } else if (!strncmp(found, "%{position%}", length)) { 2495 sprintf(buffer, "(%02d,%03d)", 2496 screen->status_data[0].row + 1, 2497 screen->status_data[0].col + 1); 2498 StatusPutChars(xw, buffer, -1); 2499 } else { 2500 StatusPutChars(xw, found, (int) length); 2501 } 2502 parse = found + length - 1; 2503 } 2504#if defined(HAVE_STRFTIME) 2505 else if (*parse != '\0') { 2506 char format[3]; 2507 struct tm *tm = localtime(&now); 2508 2509 format[0] = '%'; 2510 format[1] = *parse; 2511 format[2] = '\0'; 2512 if (strftime(buffer, sizeof(buffer) - 1, format, tm) != 0) { 2513 StatusPutChars(xw, buffer, -1); 2514 } else { 2515 StatusPutChars(xw, "?", 1); 2516 StatusPutChars(xw, parse - 1, 2); 2517 } 2518 } 2519#endif 2520 } else { 2521 StatusPutChars(xw, parse, 1); 2522 } 2523 } 2524 while (screen->cur_col < screen->max_col) 2525 StatusPutChars(xw, " ", 1); 2526 2527 ScrnRefresh(xw, FirstRowNumber(screen), 0, 1, screen->max_col, True); 2528 screen->status_active = False; 2529 2530 CursorRestore2(xw, &screen->status_data[0]); 2531 2532 /* if we processed a position or date/time, repeat */ 2533 interval = find_SL_Timeout(xw); 2534 if (interval > 0) { 2535 (void) XtAppAddTimeOut(app_con, 2536 (unsigned long) interval, 2537 show_indicator_status, xw); 2538 } 2539 screen->status_timeout = True; 2540} 2541 2542static void 2543clear_status_line(XtermWidget xw) 2544{ 2545 TScreen *screen = TScreenOf(xw); 2546 SavedCursor save_me; 2547 SavedCursor clearit; 2548 int save_type = screen->status_type; 2549 2550 TRACE_SL("clear_status_line"); 2551 StatusInit(&clearit); 2552 CursorSave2(xw, &save_me); 2553 CursorRestore2(xw, &clearit); 2554 2555 screen->status_type = 2; 2556 set_cur_row(screen, LastRowNumber(screen)); 2557#if 1 2558 ClearLine(xw); 2559#else 2560 if (getLineData(screen, screen->cur_row) != NULL) { 2561 int n; 2562 char buffer[SL_BUFSIZ + 1]; 2563 CLineData *ld = getLineData(screen, screen->cur_row); 2564 2565 TRACE(("...text[%d:%d]:%s\n", 2566 screen->cur_row, 2567 LastRowNumber(screen), 2568 visibleIChars(ld->charData, ld->lineSize))); 2569 2570 memset(buffer, '#', SL_BUFSIZ); 2571 for (n = 0; n < screen->max_col; n += SL_BUFSIZ) { 2572 StatusPutChars(xw, buffer, screen->max_col - n); 2573 } 2574 } 2575#endif 2576 CursorRestore2(xw, &save_me); 2577 screen->status_type = save_type; 2578 TRACE_SL("clear_status_line (done)"); 2579} 2580 2581static void 2582show_writable_status(XtermWidget xw) 2583{ 2584 TScreen *screen = TScreenOf(xw); 2585 2586 TRACE(("show_writable_status (%d:%d) max=%d\n", 2587 FirstRowNumber(screen), 2588 LastRowNumber(screen), 2589 MaxRows(screen))); 2590 screen->cur_row = FirstRowNumber(screen); 2591} 2592 2593/* 2594 * Depending the status-type, make the window grow or shrink by one row to 2595 * show or hide the status-line. Keep the rest of the window from scrolling 2596 * by overriding the resize-gravity. 2597 */ 2598static void 2599resize_status_line(XtermWidget xw) 2600{ 2601 TScreen *screen = TScreenOf(xw); 2602 XtGravity savedGravity = xw->misc.resizeGravity; 2603 2604 TRACE_SL(screen->status_type 2605 ? "...resize to show status-line" 2606 : "...resize to hide status-line"); 2607 2608 xw->misc.resizeGravity = NorthWestGravity; 2609 2610 RequestResize(xw, MaxRows(screen), MaxCols(screen), True); 2611 2612 xw->misc.resizeGravity = savedGravity; 2613} 2614 2615/* 2616 * DEC STD 070, chapter 14 "VSRM - Status Display Extension" 2617 */ 2618static void 2619update_status_line(XtermWidget xw) 2620{ 2621 TScreen *screen = TScreenOf(xw); 2622 2623 TRACE_SL("update_status_line"); 2624 2625 if (screen->status_type == 1) { 2626 if (screen->status_type != screen->status_shown) { 2627 if (screen->status_shown == 0) { 2628 resize_status_line(xw); 2629 } else { 2630 clear_status_line(xw); 2631 } 2632 screen->status_shown = screen->status_type; 2633 TRACE_SL("...updating shown"); 2634 } 2635 show_indicator_status(xw, NULL); 2636 } else if (screen->status_active) { 2637 if (screen->status_type != screen->status_shown) { 2638 Boolean do_resize = False; 2639 2640 if (screen->status_type == 0) { 2641 if (screen->status_shown >= 2) { 2642 StatusSave(xw); 2643 } 2644 do_resize = True; /* shrink... */ 2645 clear_status_line(xw); 2646 StatusInit(&screen->status_data[1]); 2647 } else if (screen->status_shown == 0) { 2648 if (screen->status_type >= 2) { 2649 StatusRestore(xw); 2650 } 2651 do_resize = True; /* grow... */ 2652 } else { 2653 clear_status_line(xw); 2654 } 2655 if (do_resize) { 2656 resize_status_line(xw); 2657 } 2658 screen->status_shown = screen->status_type; 2659 TRACE_SL("...updating shown"); 2660 } 2661 show_writable_status(xw); 2662 } else { 2663 if (screen->status_shown) { 2664 if (screen->status_type != 0 && 2665 screen->status_type != screen->status_shown) { 2666 clear_status_line(xw); 2667 } 2668 if (screen->status_shown >= 2) { 2669 StatusSave(xw); 2670 } 2671 if (screen->status_type == 0) { 2672 screen->status_timeout = False; 2673 clear_status_line(xw); 2674 StatusInit(&screen->status_data[1]); 2675 resize_status_line(xw); /* shrink... */ 2676 } 2677 screen->status_shown = screen->status_type; 2678 TRACE_SL("...updating shown"); 2679 } 2680 } 2681 TRACE_SL("update_status_line (done)"); 2682} 2683 2684/* 2685 * If the status-type is "2", we can switch the active status display back and 2686 * forth between the main-display and the status-line without clearing the 2687 * status-line (unless the status-line was not shown before). 2688 * 2689 * This has no effect if the status-line displays an indicator (type==1). 2690 */ 2691static void 2692handle_DECSASD(XtermWidget xw, int value) 2693{ 2694 TScreen *screen = TScreenOf(xw); 2695 Boolean updates = value ? True : False; 2696 2697 TRACE(("CASE_DECSASD - select active status display: %s (currently %s)\n", 2698 BtoS(value), 2699 BtoS(screen->status_active))); 2700 2701 if (screen->status_active != updates) { 2702 screen->status_active = updates; 2703 if (screen->status_type != 1) { 2704 if (updates) { 2705 TRACE(("...@%d, saving main position %d,%d\n", 2706 __LINE__, screen->cur_row, screen->cur_col)); 2707 CursorSave2(xw, &screen->status_data[0]); 2708 } 2709 update_status_line(xw); 2710 } 2711 } 2712} 2713 2714/* 2715 * If the status-line is inactive (i.e., only the main-display is used), 2716 * changing the status-type between none/writable has no immediate effect. 2717 * 2718 * But if the status-line is active, setting the status-type reinitializes the 2719 * status-line. 2720 * 2721 * Setting the status-type to indicator overrides the DECSASD active-display 2722 * mode. 2723 */ 2724static void 2725handle_DECSSDT(XtermWidget xw, int value) 2726{ 2727 TScreen *screen = TScreenOf(xw); 2728 2729 TRACE(("CASE_DECSSDT - select type of status display: %d (currently %d)\n", 2730 value, 2731 screen->status_type)); 2732 if (value <= 2) { 2733 screen->status_type = value; 2734 if (!screen->status_active) { 2735 TRACE(("...@%d, saving main position %d,%d\n", 2736 __LINE__, screen->cur_row, screen->cur_col)); 2737 CursorSave2(xw, &screen->status_data[0]); 2738 } 2739 update_status_line(xw); 2740 } 2741} 2742#endif 2743 2744#if OPT_VT52_MODE 2745static void 2746update_vt52_vt100_settings(void) 2747{ 2748 update_autowrap(); 2749 update_reversewrap(); 2750 update_autolinefeed(); 2751 update_appcursor(); 2752 update_appkeypad(); 2753 update_allow132(); 2754} 2755#endif 2756 2757static Boolean 2758doparsing(XtermWidget xw, unsigned c, struct ParseState *sp) 2759{ 2760 TScreen *screen = TScreenOf(xw); 2761 int item; 2762 int count; 2763 int value; 2764 int laststate; 2765 int thischar = -1; 2766 XTermRect myRect; 2767#if OPT_DEC_RECTOPS 2768 int thispage = 1; 2769#endif 2770 2771 if (sp->check_recur) { 2772 /* Defer parsing when parser is already running as the parser is not 2773 * safe to reenter. 2774 */ 2775 deferparsing(c, sp); 2776 return True; 2777 } 2778 sp->check_recur++; 2779 2780 do { 2781#if OPT_WIDE_CHARS 2782 int this_is_wide = 0; 2783 2784 /* 2785 * Handle zero-width combining characters. Make it faster by noting 2786 * that according to the Unicode charts, the majority of Western 2787 * character sets do not use this feature. There are some unassigned 2788 * codes at 0x242, but no zero-width characters until past 0x300. 2789 */ 2790 if (c >= 0x300 2791 && screen->wide_chars 2792 && CharWidth(screen, c) == 0 2793 && !isWideControl(c)) { 2794 int prev, test; 2795 Boolean used = True; 2796 int use_row; 2797 int use_col; 2798 2799 WriteNow(); 2800 use_row = (screen->char_was_written 2801 ? screen->last_written_row 2802 : screen->cur_row); 2803 use_col = (screen->char_was_written 2804 ? screen->last_written_col 2805 : screen->cur_col); 2806 2807 /* 2808 * Check if the latest data can be added to the base character. 2809 * If there is already a combining character stored for the cell, 2810 * we cannot, since that would change the order. 2811 */ 2812 if (screen->normalized_c 2813 && !IsCellCombined(screen, use_row, use_col)) { 2814 prev = (int) XTERM_CELL(use_row, use_col); 2815 test = do_precomposition(prev, (int) c); 2816 TRACE(("do_precomposition (U+%04X [%d], U+%04X [%d]) -> U+%04X [%d]\n", 2817 prev, CharWidth(screen, prev), 2818 (int) c, CharWidth(screen, c), 2819 test, CharWidth(screen, test))); 2820 } else { 2821 prev = -1; 2822 test = -1; 2823 } 2824 2825 /* substitute combined character with precomposed character 2826 * only if it does not change the width of the base character 2827 */ 2828 if (test != -1 2829 && CharWidth(screen, test) == CharWidth(screen, prev)) { 2830 putXtermCell(screen, use_row, use_col, test); 2831 } else if (screen->char_was_written 2832 || getXtermCell(screen, use_row, use_col) >= ' ') { 2833 addXtermCombining(screen, use_row, use_col, c); 2834 } else { 2835 /* 2836 * none of the above... we will add the combining character as 2837 * a base character. 2838 */ 2839 used = False; 2840 } 2841 2842 if (used) { 2843 if (!screen->scroll_amt) 2844 ScrnUpdate(xw, use_row, use_col, 1, 1, 1); 2845 continue; 2846 } 2847 } 2848#endif 2849 2850 /* Intercept characters for printer controller mode */ 2851 if (PrinterOf(screen).printer_controlmode == 2) { 2852 if ((c = (unsigned) xtermPrinterControl(xw, (int) c)) == 0) 2853 continue; 2854 } 2855 2856 /* 2857 * VT52 is a little ugly in the one place it has a parameterized 2858 * control sequence, since the parameter falls after the character 2859 * that denotes the type of sequence. 2860 */ 2861#if OPT_VT52_MODE 2862 if (sp->vt52_cup) { 2863 if (nparam < NPARAM - 1) { 2864 SetParam(nparam++, (int) (c & 0x7f) - 32); 2865 parms.is_sub[nparam] = 0; 2866 } 2867 if (nparam < 2) 2868 continue; 2869 sp->vt52_cup = False; 2870 CursorSet(screen, zero_if_default(0), zero_if_default(1), xw->flags); 2871 sp->parsestate = vt52_table; 2872 SetParam(0, 0); 2873 SetParam(1, 0); 2874 continue; 2875 } 2876#endif 2877 2878 laststate = sp->nextstate; 2879 if (c == ANSI_DEL 2880 && sp->parsestate == sp->groundtable 2881 && sp->scssize == 96 2882 && sp->scstype != 0) { 2883 /* 2884 * Handle special case of shifts for 96-character sets by checking 2885 * if we have a DEL. The other special case for SPACE will always 2886 * be printable. 2887 */ 2888 sp->nextstate = CASE_PRINT; 2889 } else 2890#if OPT_WIDE_CHARS 2891 if (c > 255) { 2892 /* 2893 * The parsing tables all have 256 entries. If we're supporting 2894 * wide characters, we handle them by treating them the same as 2895 * printing characters. 2896 */ 2897 if (sp->parsestate == sp->groundtable) { 2898 sp->nextstate = CASE_PRINT; 2899 } else if (sp->parsestate == sos_table) { 2900 c &= WIDEST_ICHAR; 2901 if (c > 255) { 2902 TRACE(("Found code > 255 while in SOS state: %04X\n", c)); 2903 c = BAD_ASCII; 2904 } 2905 } else { 2906 sp->nextstate = CASE_GROUND_STATE; 2907 } 2908 } else 2909#endif 2910 sp->nextstate = sp->parsestate[E2A(c)]; 2911 2912#if OPT_BROKEN_OSC 2913 /* 2914 * Linux console palette escape sequences start with an OSC, but do 2915 * not terminate correctly. Some scripts do not check before writing 2916 * them, making xterm appear to hang (it's awaiting a valid string 2917 * terminator). Just ignore these if we see them - there's no point 2918 * in emulating bad code. 2919 */ 2920 if (screen->brokenLinuxOSC 2921 && sp->parsestate == sos_table) { 2922 if (sp->string_used) { 2923 switch (sp->string_area[0]) { 2924 case 'P': 2925 if (sp->string_used <= 7) 2926 break; 2927 /* FALLTHRU */ 2928 case 'R': 2929 illegal_parse(xw, c, sp); 2930 TRACE(("Reset to ground state (brokenLinuxOSC)\n")); 2931 break; 2932 } 2933 } 2934 } 2935#endif 2936 2937#if OPT_BROKEN_ST 2938 /* 2939 * Before patch #171, carriage control embedded within an OSC string 2940 * would terminate it. Some (buggy, of course) applications rely on 2941 * this behavior. Accommodate them by allowing one to compile xterm 2942 * and emulate the old behavior. 2943 */ 2944 if (screen->brokenStringTerm 2945 && sp->parsestate == sos_table 2946 && c < 32) { 2947 switch (c) { 2948 case ANSI_EOT: /* FALLTHRU */ 2949 case ANSI_BS: /* FALLTHRU */ 2950 case ANSI_HT: /* FALLTHRU */ 2951 case ANSI_LF: /* FALLTHRU */ 2952 case ANSI_VT: /* FALLTHRU */ 2953 case ANSI_FF: /* FALLTHRU */ 2954 case ANSI_CR: /* FALLTHRU */ 2955 case ANSI_SO: /* FALLTHRU */ 2956 case ANSI_SI: /* FALLTHRU */ 2957 case ANSI_XON: /* FALLTHRU */ 2958 case ANSI_CAN: 2959 illegal_parse(xw, c, sp); 2960 TRACE(("Reset to ground state (brokenStringTerm)\n")); 2961 break; 2962 } 2963 } 2964#endif 2965 2966#if OPT_C1_PRINT 2967 /* 2968 * This is not completely foolproof, but will allow an application 2969 * with values in the C1 range to use them as printable characters, 2970 * provided that they are not intermixed with an escape sequence. 2971 */ 2972 if (screen->c1_printable 2973 && (c >= 128 && c < 256)) { 2974 sp->nextstate = (sp->parsestate == esc_table 2975 ? CASE_ESC_IGNORE 2976 : sp->parsestate[E2A(160)]); 2977 TRACE(("allowC1Printable %04X %s ->%s\n", 2978 c, which_table(sp->parsestate), 2979 visibleVTparse(sp->nextstate))); 2980 } 2981#endif 2982 2983#if OPT_WIDE_CHARS 2984 /* 2985 * If we have a C1 code and the c1_printable flag is not set, simply 2986 * ignore it when it was translated from UTF-8. That is because the 2987 * value could not have been present as-is in the UTF-8. 2988 * 2989 * To see that CASE_IGNORE is a consistent value, note that it is 2990 * always used for NUL and other uninteresting C0 controls. 2991 */ 2992#if OPT_C1_PRINT 2993 if (!screen->c1_printable) 2994#endif 2995 if (screen->wide_chars 2996 && (c >= 128 && c < 160)) { 2997 sp->nextstate = CASE_IGNORE; 2998 } 2999 3000 /* 3001 * If this character is a different width than the last one, put the 3002 * previous text into the buffer and draw it now. 3003 */ 3004 this_is_wide = isWide((int) c); 3005 if (this_is_wide != sp->last_was_wide) { 3006 WriteNow(); 3007 } 3008#endif 3009 3010 /* 3011 * Accumulate string for printable text. This may be 8/16-bit 3012 * characters. 3013 */ 3014 if (sp->nextstate == CASE_PRINT) { 3015 SafeAlloc(IChar, sp->print_area, sp->print_used, sp->print_size); 3016 if (new_string == 0) { 3017 xtermWarning("Cannot allocate %lu bytes for printable text\n", 3018 (unsigned long) new_length); 3019 continue; 3020 } 3021 SafeFree(sp->print_area, sp->print_size); 3022#if OPT_VT52_MODE 3023 /* 3024 * Strip output text to 7-bits for VT52. We should do this for 3025 * VT100 also (which is a 7-bit device), but xterm has been 3026 * doing this for so long we shouldn't change this behavior. 3027 */ 3028 if (screen->vtXX_level < 1) 3029 c &= 0x7f; 3030#endif 3031 sp->print_area[sp->print_used++] = (IChar) c; 3032 sp->lastchar = thischar = (int) c; 3033#if OPT_WIDE_CHARS 3034 sp->last_was_wide = this_is_wide; 3035#endif 3036 if (morePtyData(screen, VTbuffer)) { 3037 continue; 3038 } 3039 } 3040 3041 if (sp->nextstate == CASE_PRINT 3042 || (laststate == CASE_PRINT && sp->print_used)) { 3043 WriteNow(); 3044 } 3045 3046 /* 3047 * Accumulate string for APC, DCS, PM, OSC, SOS controls 3048 * This should always be 8-bit characters. 3049 */ 3050 if (sp->parsestate == sos_table) { 3051 SafeAlloc(Char, sp->string_area, sp->string_used, sp->string_size); 3052 if (new_string == 0) { 3053 xtermWarning("Cannot allocate %lu bytes for string mode %d\n", 3054 (unsigned long) new_length, sp->string_mode); 3055 continue; 3056 } 3057 SafeFree(sp->string_area, sp->string_size); 3058#if OPT_WIDE_CHARS 3059 /* 3060 * We cannot display codes above 255, but let's try to 3061 * accommodate the application a little by not aborting the 3062 * string. 3063 */ 3064 if ((c & WIDEST_ICHAR) > 255) { 3065 sp->nextstate = CASE_PRINT; 3066 c = BAD_ASCII; 3067 } 3068#endif 3069 sp->string_area[(sp->string_used)++] = CharOf(c); 3070 } else if (sp->parsestate != esc_table) { 3071 /* if we were accumulating, we're not any more */ 3072 sp->string_mode = 0; 3073 sp->string_used = 0; 3074 } 3075 3076 DumpParams(); 3077 TRACE(("parse %04X -> %s %s (used=%lu)\n", 3078 c, visibleVTparse(sp->nextstate), 3079 which_table(sp->parsestate), 3080 (unsigned long) sp->string_used)); 3081 3082 /* 3083 * If the parameter list has subparameters (tokens separated by ":") 3084 * reject any controls that do not accept subparameters. 3085 */ 3086 if (parms.has_subparams) { 3087 switch (sp->nextstate) { 3088 case CASE_GROUND_STATE: 3089 case CASE_CSI_IGNORE: 3090 /* FALLTHRU */ 3091 3092 case CASE_ESC_DIGIT: 3093 case CASE_ESC_SEMI: 3094 case CASE_ESC_COLON: 3095 /* these states are required to parse parameter lists */ 3096 break; 3097 3098 case CASE_SGR: 3099 TRACE(("...possible subparam usage\n")); 3100 break; 3101 3102 case CASE_CSI_DEC_DOLLAR_STATE: 3103 case CASE_CSI_DOLLAR_STATE: 3104 case CASE_CSI_HASH_STATE: 3105 case CASE_CSI_EX_STATE: 3106 case CASE_CSI_QUOTE_STATE: 3107 case CASE_CSI_SPACE_STATE: 3108 case CASE_CSI_STAR_STATE: 3109 case CASE_CSI_TICK_STATE: 3110 case CASE_DEC2_STATE: 3111 case CASE_DEC3_STATE: 3112 case CASE_DEC_STATE: 3113 /* use this branch when we do not yet have the final character */ 3114 TRACE(("...unexpected subparam usage\n")); 3115 InitParams(); 3116 sp->nextstate = CASE_CSI_IGNORE; 3117 break; 3118 3119 default: 3120 /* use this branch for cases where we have the final character 3121 * in the table that processed the parameter list. 3122 */ 3123 TRACE(("...unexpected subparam usage\n")); 3124 ResetState(sp); 3125 continue; 3126 } 3127 } 3128 3129 if (xw->work.palette_changed) { 3130 repaintWhenPaletteChanged(xw, sp); 3131 } 3132 3133 switch (sp->nextstate) { 3134 case CASE_PRINT: 3135 TRACE(("CASE_PRINT - printable characters\n")); 3136 break; 3137 3138 case CASE_GROUND_STATE: 3139 TRACE(("CASE_GROUND_STATE - exit ignore mode\n")); 3140 ResetState(sp); 3141 break; 3142 3143 case CASE_IGNORE: 3144 TRACE(("CASE_IGNORE - Ignore character %02X\n", c)); 3145 break; 3146 3147 case CASE_ENQ: 3148 TRACE(("CASE_ENQ - answerback\n")); 3149 if (((xw->keyboard.flags & MODE_SRM) == 0) 3150 ? (sp->check_recur == 0) 3151 : (sp->check_recur <= 1)) { 3152 for (count = 0; screen->answer_back[count] != 0; count++) 3153 unparseputc(xw, screen->answer_back[count]); 3154 unparse_end(xw); 3155 } 3156 break; 3157 3158 case CASE_BELL: 3159 TRACE(("CASE_BELL - bell\n")); 3160 if (sp->string_mode == ANSI_OSC) { 3161 if (sp->string_used) 3162 sp->string_area[--(sp->string_used)] = '\0'; 3163 if (sp->check_recur <= 1) 3164 do_osc(xw, sp->string_area, sp->string_used, (int) c); 3165 ResetState(sp); 3166 } else { 3167 /* bell */ 3168 Bell(xw, XkbBI_TerminalBell, 0); 3169 } 3170 break; 3171 3172 case CASE_BS: 3173 TRACE(("CASE_BS - backspace\n")); 3174 CursorBack(xw, 1); 3175 break; 3176 3177 case CASE_CR: 3178 TRACE(("CASE_CR\n")); 3179 CarriageReturn(xw); 3180 break; 3181 3182 case CASE_ESC: 3183 if_OPT_VT52_MODE(screen, { 3184 sp->parsestate = vt52_esc_table; 3185 break; 3186 }); 3187 sp->parsestate = esc_table; 3188 break; 3189 3190#if OPT_VT52_MODE 3191 case CASE_VT52_CUP: 3192 TRACE(("CASE_VT52_CUP - VT52 cursor addressing\n")); 3193 sp->vt52_cup = True; 3194 ResetState(sp); 3195 break; 3196 3197 case CASE_VT52_IGNORE: 3198 TRACE(("CASE_VT52_IGNORE - VT52 ignore-character\n")); 3199 sp->parsestate = vt52_ignore_table; 3200 break; 3201#endif 3202 3203 case CASE_VMOT: 3204 TRACE(("CASE_VMOT\n")); 3205 /* 3206 * form feed, line feed, vertical tab 3207 */ 3208 xtermAutoPrint(xw, c); 3209 xtermIndex(xw, 1); 3210 if (xw->flags & LINEFEED) 3211 CarriageReturn(xw); 3212 else 3213 do_xevents(xw); 3214 break; 3215 3216 case CASE_CBT: 3217 TRACE(("CASE_CBT\n")); 3218 /* cursor backward tabulation */ 3219 count = one_if_default(0); 3220 while ((count-- > 0) 3221 && (TabToPrevStop(xw))) ; 3222 ResetState(sp); 3223 break; 3224 3225 case CASE_CHT: 3226 TRACE(("CASE_CHT\n")); 3227 /* cursor forward tabulation */ 3228 count = one_if_default(0); 3229 while ((count-- > 0) 3230 && (TabToNextStop(xw))) ; 3231 ResetState(sp); 3232 break; 3233 3234 case CASE_TAB: 3235 /* tab */ 3236 TabToNextStop(xw); 3237 break; 3238 3239 case CASE_SI: 3240 screen->curgl = 0; 3241 if_OPT_VT52_MODE(screen, { 3242 ResetState(sp); 3243 }); 3244 break; 3245 3246 case CASE_SO: 3247 screen->curgl = 1; 3248 if_OPT_VT52_MODE(screen, { 3249 ResetState(sp); 3250 }); 3251 break; 3252 3253 case CASE_DECDHL: 3254 xterm_DECDHL(xw, c == '3'); 3255 ResetState(sp); 3256 break; 3257 3258 case CASE_DECSWL: 3259 xterm_DECSWL(xw); 3260 ResetState(sp); 3261 break; 3262 3263 case CASE_DECDWL: 3264 xterm_DECDWL(xw); 3265 ResetState(sp); 3266 break; 3267 3268 case CASE_SCR_STATE: 3269 /* enter scr state */ 3270 sp->parsestate = scrtable; 3271 break; 3272 3273 case CASE_SCS0_STATE: 3274 /* enter scs state 0 */ 3275 select_charset(sp, 0, 94); 3276 break; 3277 3278 case CASE_SCS1_STATE: 3279 /* enter scs state 1 */ 3280 select_charset(sp, 1, 94); 3281 break; 3282 3283 case CASE_SCS2_STATE: 3284 /* enter scs state 2 */ 3285 select_charset(sp, 2, 94); 3286 break; 3287 3288 case CASE_SCS3_STATE: 3289 /* enter scs state 3 */ 3290 select_charset(sp, 3, 94); 3291 break; 3292 3293 case CASE_SCS1A_STATE: 3294 /* enter scs state 1 */ 3295 select_charset(sp, 1, 96); 3296 break; 3297 3298 case CASE_SCS2A_STATE: 3299 /* enter scs state 2 */ 3300 select_charset(sp, 2, 96); 3301 break; 3302 3303 case CASE_SCS3A_STATE: 3304 /* enter scs state 3 */ 3305 select_charset(sp, 3, 96); 3306 break; 3307 3308 case CASE_ESC_IGNORE: 3309 /* unknown escape sequence */ 3310 sp->parsestate = eigtable; 3311 break; 3312 3313 case CASE_ESC_DIGIT: 3314 /* digit in csi or dec mode */ 3315 if (nparam > 0) { 3316 value = zero_if_default(nparam - 1); 3317 SetParam(nparam - 1, (10 * value) + ((int) c - '0')); 3318 if (GetParam(nparam - 1) > MAX_I_PARAM) 3319 SetParam(nparam - 1, MAX_I_PARAM); 3320 if (sp->parsestate == csi_table) 3321 sp->parsestate = csi2_table; 3322 } 3323 break; 3324 3325 case CASE_ESC_SEMI: 3326 /* semicolon in csi or dec mode */ 3327 if (nparam < NPARAM) { 3328 parms.is_sub[nparam] = 0; 3329 SetParam(nparam++, DEFAULT); 3330 } 3331 if (sp->parsestate == csi_table) 3332 sp->parsestate = csi2_table; 3333 break; 3334 3335 /* 3336 * A _few_ commands accept colon-separated subparameters. 3337 * Mark the parameter list so that we can exclude (most) bogus 3338 * commands with simple/fast checks. 3339 */ 3340 case CASE_ESC_COLON: 3341 if (nparam < NPARAM) { 3342 parms.has_subparams = 1; 3343 if (nparam == 0) { 3344 parms.is_sub[nparam] = 1; 3345 SetParam(nparam++, DEFAULT); 3346 } else if (parms.is_sub[nparam - 1] == 0) { 3347 parms.is_sub[nparam - 1] = 1; 3348 parms.is_sub[nparam] = 2; 3349 parms.params[nparam] = 0; 3350 ++nparam; 3351 } else { 3352 parms.is_sub[nparam] = 1 + parms.is_sub[nparam - 1]; 3353 parms.params[nparam] = 0; 3354 ++nparam; 3355 } 3356 } 3357 break; 3358 3359 case CASE_DEC_STATE: 3360 /* enter dec mode */ 3361 sp->parsestate = dec_table; 3362 break; 3363 3364 case CASE_DEC2_STATE: 3365 /* enter dec2 mode */ 3366 sp->parsestate = dec2_table; 3367 break; 3368 3369 case CASE_DEC3_STATE: 3370 /* enter dec3 mode */ 3371 sp->parsestate = dec3_table; 3372 break; 3373 3374 case CASE_ICH: 3375 TRACE(("CASE_ICH - insert char\n")); 3376 InsertChar(xw, (unsigned) one_if_default(0)); 3377 ResetState(sp); 3378 break; 3379 3380 case CASE_CUU: 3381 TRACE(("CASE_CUU - cursor up\n")); 3382 CursorUp(screen, one_if_default(0)); 3383 ResetState(sp); 3384 break; 3385 3386 case CASE_CUD: 3387 TRACE(("CASE_CUD - cursor down\n")); 3388 CursorDown(screen, one_if_default(0)); 3389 ResetState(sp); 3390 break; 3391 3392 case CASE_CUF: 3393 TRACE(("CASE_CUF - cursor forward\n")); 3394 CursorForward(xw, one_if_default(0)); 3395 ResetState(sp); 3396 break; 3397 3398 case CASE_CUB: 3399 TRACE(("CASE_CUB - cursor backward\n")); 3400 CursorBack(xw, one_if_default(0)); 3401 ResetState(sp); 3402 break; 3403 3404 case CASE_CUP: 3405 TRACE(("CASE_CUP - cursor position\n")); 3406 if_OPT_XMC_GLITCH(screen, { 3407 Jump_XMC(xw); 3408 }); 3409 CursorSet(screen, one_if_default(0) - 1, one_if_default(1) - 1, xw->flags); 3410 ResetState(sp); 3411 break; 3412 3413 case CASE_VPA: 3414 TRACE(("CASE_VPA - vertical position absolute\n")); 3415 CursorSet(screen, one_if_default(0) - 1, CursorCol(xw), xw->flags); 3416 ResetState(sp); 3417 break; 3418 3419 case CASE_HPA: 3420 TRACE(("CASE_HPA - horizontal position absolute\n")); 3421 CursorSet(screen, CursorRow(xw), one_if_default(0) - 1, xw->flags); 3422 ResetState(sp); 3423 break; 3424 3425 case CASE_VPR: 3426 TRACE(("CASE_VPR - vertical position relative\n")); 3427 CursorSet(screen, 3428 CursorRow(xw) + one_if_default(0), 3429 CursorCol(xw), 3430 xw->flags); 3431 ResetState(sp); 3432 break; 3433 3434 case CASE_HPR: 3435 TRACE(("CASE_HPR - horizontal position relative\n")); 3436 CursorSet(screen, 3437 CursorRow(xw), 3438 CursorCol(xw) + one_if_default(0), 3439 xw->flags); 3440 ResetState(sp); 3441 break; 3442 3443 case CASE_HP_BUGGY_LL: 3444 TRACE(("CASE_HP_BUGGY_LL\n")); 3445 /* Some HP-UX applications have the bug that they 3446 assume ESC F goes to the lower left corner of 3447 the screen, regardless of what terminfo says. */ 3448 if (screen->hp_ll_bc) 3449 CursorSet(screen, screen->max_row, 0, xw->flags); 3450 ResetState(sp); 3451 break; 3452 3453 case CASE_ED: 3454 TRACE(("CASE_ED - erase display\n")); 3455 do_cd_xtra_scroll(xw, zero_if_default(0)); 3456 do_erase_display(xw, zero_if_default(0), OFF_PROTECT); 3457 ResetState(sp); 3458 break; 3459 3460 case CASE_EL: 3461 TRACE(("CASE_EL - erase line\n")); 3462 do_erase_line(xw, zero_if_default(0), OFF_PROTECT); 3463 ResetState(sp); 3464 break; 3465 3466 case CASE_ECH: 3467 TRACE(("CASE_ECH - erase char\n")); 3468 /* ECH */ 3469 do_erase_char(xw, one_if_default(0), OFF_PROTECT); 3470 ResetState(sp); 3471 break; 3472 3473 case CASE_IL: 3474 TRACE(("CASE_IL - insert line\n")); 3475 InsertLine(xw, one_if_default(0)); 3476 ResetState(sp); 3477 break; 3478 3479 case CASE_DL: 3480 TRACE(("CASE_DL - delete line\n")); 3481 DeleteLine(xw, one_if_default(0), True); 3482 ResetState(sp); 3483 break; 3484 3485 case CASE_DCH: 3486 TRACE(("CASE_DCH - delete char\n")); 3487 DeleteChar(xw, (unsigned) one_if_default(0)); 3488 ResetState(sp); 3489 break; 3490 3491 case CASE_TRACK_MOUSE: 3492 /* 3493 * A single parameter other than zero is always scroll-down. 3494 * A zero-parameter is used to reset the mouse mode, and is 3495 * not useful for scrolling anyway. 3496 */ 3497 if (nparam > 1 || GetParam(0) == 0) { 3498 CELL start; 3499 3500 TRACE(("CASE_TRACK_MOUSE\n")); 3501 /* Track mouse as long as in window and between 3502 * specified rows 3503 */ 3504 start.row = one_if_default(2) - 1; 3505 start.col = GetParam(1) - 1; 3506 TrackMouse(xw, 3507 GetParam(0), 3508 &start, 3509 GetParam(3) - 1, GetParam(4) - 2); 3510 } else { 3511 TRACE(("CASE_SD - scroll down\n")); 3512 /* SD */ 3513 RevScroll(xw, one_if_default(0)); 3514 do_xevents(xw); 3515 } 3516 ResetState(sp); 3517 break; 3518 3519 case CASE_SD: 3520 /* 3521 * Cater to ECMA-48's typographical error... 3522 */ 3523 TRACE(("CASE_SD - scroll down\n")); 3524 RevScroll(xw, one_if_default(0)); 3525 do_xevents(xw); 3526 ResetState(sp); 3527 break; 3528 3529 case CASE_DECID: 3530 TRACE(("CASE_DECID\n")); 3531 if_OPT_VT52_MODE(screen, { 3532 unparseputc(xw, ANSI_ESC); 3533 unparseputc(xw, '/'); 3534 unparseputc(xw, 'Z'); 3535 unparse_end(xw); 3536 ResetState(sp); 3537 break; 3538 }); 3539 SetParam(0, DEFAULT); /* Default ID parameter */ 3540 /* FALLTHRU */ 3541 case CASE_DA1: 3542 TRACE(("CASE_DA1\n")); 3543 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 3544 count = 0; 3545 init_reply(ANSI_CSI); 3546 reply.a_pintro = '?'; 3547 3548 /* 3549 * The first parameter corresponds to the highest operating 3550 * level (i.e., service level) of the emulation. A DEC 3551 * terminal can be setup to respond with a different DA 3552 * response, but there's no control sequence that modifies 3553 * this. We set it via a resource. 3554 */ 3555 if (screen->terminal_id < 200) { 3556 switch (screen->terminal_id) { 3557 case 132: 3558 reply.a_param[count++] = 4; /* VT132 */ 3559#if OPT_REGIS_GRAPHICS 3560 reply.a_param[count++] = 6; /* no STP, AVO, GPO (ReGIS) */ 3561#else 3562 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */ 3563#endif 3564 break; 3565 case 131: 3566 reply.a_param[count++] = 7; /* VT131 */ 3567 break; 3568 case 125: 3569 reply.a_param[count++] = 12; /* VT125 */ 3570#if OPT_REGIS_GRAPHICS 3571 reply.a_param[count++] = 0 | 2 | 1; /* no STP, AVO, GPO (ReGIS) */ 3572#else 3573 reply.a_param[count++] = 0 | 2 | 0; /* no STP, AVO, no GPO (ReGIS) */ 3574#endif 3575 reply.a_param[count++] = 0; /* no printer */ 3576 reply.a_param[count++] = XTERM_PATCH; /* ROM version */ 3577 break; 3578 case 102: 3579 reply.a_param[count++] = 6; /* VT102 */ 3580 break; 3581 case 101: 3582 reply.a_param[count++] = 1; /* VT101 */ 3583 reply.a_param[count++] = 0; /* no options */ 3584 break; 3585 default: /* VT100 */ 3586 reply.a_param[count++] = 1; /* VT100 */ 3587 reply.a_param[count++] = 2; /* no STP, AVO, no GPO (ReGIS) */ 3588 break; 3589 } 3590 } else { 3591 reply.a_param[count++] = (ParmType) (60 3592 + screen->terminal_id 3593 / 100); 3594 reply.a_param[count++] = 1; /* 132-columns */ 3595 reply.a_param[count++] = 2; /* printer */ 3596#if OPT_REGIS_GRAPHICS 3597 if (optRegisGraphics(screen)) { 3598 reply.a_param[count++] = 3; /* ReGIS graphics */ 3599 } 3600#endif 3601#if OPT_SIXEL_GRAPHICS 3602 if (optSixelGraphics(screen)) { 3603 reply.a_param[count++] = 4; /* sixel graphics */ 3604 } 3605#endif 3606 reply.a_param[count++] = 6; /* selective-erase */ 3607#if OPT_SUNPC_KBD 3608 if (xw->keyboard.type == keyboardIsVT220) 3609#endif 3610 reply.a_param[count++] = 8; /* user-defined-keys */ 3611 reply.a_param[count++] = 9; /* national replacement charsets */ 3612 reply.a_param[count++] = 15; /* technical characters */ 3613 reply.a_param[count++] = 16; /* locator port */ 3614 if (screen->terminal_id >= 400) { 3615 reply.a_param[count++] = 17; /* terminal state interrogation */ 3616 reply.a_param[count++] = 18; /* windowing extension */ 3617 reply.a_param[count++] = 21; /* horizontal scrolling */ 3618 } 3619 if_OPT_ISO_COLORS(screen, { 3620 reply.a_param[count++] = 22; /* ANSI color, VT525 */ 3621 }); 3622 reply.a_param[count++] = 28; /* rectangular editing */ 3623#if OPT_DEC_LOCATOR 3624 reply.a_param[count++] = 29; /* ANSI text locator */ 3625#endif 3626 } 3627 reply.a_nparam = (ParmType) count; 3628 reply.a_inters = 0; 3629 reply.a_final = 'c'; 3630 unparseseq(xw, &reply); 3631 } 3632 ResetState(sp); 3633 break; 3634 3635 case CASE_DA2: 3636 TRACE(("CASE_DA2\n")); 3637 if (GetParam(0) <= 0) { /* less than means DEFAULT */ 3638 count = 0; 3639 init_reply(ANSI_CSI); 3640 reply.a_pintro = '>'; 3641 3642 if (screen->terminal_id >= 200) { 3643 switch (screen->terminal_id) { 3644 case 220: 3645 default: 3646 reply.a_param[count++] = 1; /* VT220 */ 3647 break; 3648 case 240: 3649 case 241: 3650 /* http://www.decuslib.com/DECUS/vax87a/gendyn/vt200_kind.lis */ 3651 reply.a_param[count++] = 2; /* VT240 */ 3652 break; 3653 case 320: 3654 /* http://www.vt100.net/docs/vt320-uu/appendixe.html */ 3655 reply.a_param[count++] = 24; /* VT320 */ 3656 break; 3657 case 330: 3658 reply.a_param[count++] = 18; /* VT330 */ 3659 break; 3660 case 340: 3661 reply.a_param[count++] = 19; /* VT340 */ 3662 break; 3663 case 382: 3664 reply.a_param[count++] = 32; /* VT382 */ 3665 break; 3666 case 420: 3667 reply.a_param[count++] = 41; /* VT420 */ 3668 break; 3669 case 510: 3670 /* http://www.vt100.net/docs/vt510-rm/DA2 */ 3671 reply.a_param[count++] = 61; /* VT510 */ 3672 break; 3673 case 520: 3674 reply.a_param[count++] = 64; /* VT520 */ 3675 break; 3676 case 525: 3677 reply.a_param[count++] = 65; /* VT525 */ 3678 break; 3679 } 3680 } else { 3681 reply.a_param[count++] = 0; /* VT100 (nonstandard) */ 3682 } 3683 reply.a_param[count++] = XTERM_PATCH; /* Version */ 3684 reply.a_param[count++] = 0; /* options (none) */ 3685 reply.a_nparam = (ParmType) count; 3686 reply.a_inters = 0; 3687 reply.a_final = 'c'; 3688 unparseseq(xw, &reply); 3689 } 3690 ResetState(sp); 3691 break; 3692 3693 case CASE_DECRPTUI: 3694 TRACE(("CASE_DECRPTUI\n")); 3695 if ((screen->vtXX_level >= 4) 3696 && (GetParam(0) <= 0)) { /* less than means DEFAULT */ 3697 unparseputc1(xw, ANSI_DCS); 3698 unparseputc(xw, '!'); 3699 unparseputc(xw, '|'); 3700 /* report the "terminal unit id" as 4 pairs of hexadecimal 3701 * digits -- meaningless for a terminal emulator, but some 3702 * host may care about the format. 3703 */ 3704 for (count = 0; count < 8; ++count) { 3705 unparseputc(xw, '0'); 3706 } 3707 unparseputc1(xw, ANSI_ST); 3708 unparse_end(xw); 3709 } 3710 ResetState(sp); 3711 break; 3712 3713 case CASE_TBC: 3714 TRACE(("CASE_TBC - tab clear\n")); 3715 if ((value = GetParam(0)) <= 0) /* less than means default */ 3716 TabClear(xw->tabs, screen->cur_col); 3717 else if (value == 3) 3718 TabZonk(xw->tabs); 3719 ResetState(sp); 3720 break; 3721 3722 case CASE_SET: 3723 TRACE(("CASE_SET - set mode\n")); 3724 ansi_modes(xw, bitset); 3725 ResetState(sp); 3726 break; 3727 3728 case CASE_RST: 3729 TRACE(("CASE_RST - reset mode\n")); 3730 ansi_modes(xw, bitclr); 3731 ResetState(sp); 3732 break; 3733 3734 case CASE_SGR: 3735 for (item = 0; item < nparam; ++item) { 3736 int op = GetParam(item); 3737 int skip; 3738 3739 if_OPT_XMC_GLITCH(screen, { 3740 Mark_XMC(xw, op); 3741 }); 3742 TRACE(("CASE_SGR %d\n", op)); 3743 3744 /* 3745 * Only SGR 38/48 accept subparameters, and in those cases 3746 * the values will not be seen at this point. 3747 */ 3748 if ((skip = param_has_subparams(item))) { 3749 switch (op) { 3750 case 38: 3751 /* FALLTHRU */ 3752 case 48: 3753 if_OPT_ISO_COLORS(screen, { 3754 break; 3755 }); 3756 /* FALLTHRU */ 3757 default: 3758 TRACE(("...unexpected subparameter in SGR\n")); 3759 item += skip; /* ignore this */ 3760 op = NPARAM; /* will never use this, anyway */ 3761 break; 3762 } 3763 } 3764 3765 switch (op) { 3766 case DEFAULT: 3767 /* FALLTHRU */ 3768 case 0: 3769 resetRendition(xw); 3770 if_OPT_ISO_COLORS(screen, { 3771 reset_SGR_Colors(xw); 3772 }); 3773 break; 3774 case 1: /* Bold */ 3775 UIntSet(xw->flags, BOLD); 3776 if_OPT_ISO_COLORS(screen, { 3777 setExtendedFG(xw); 3778 }); 3779 break; 3780#if OPT_WIDE_ATTRS 3781 case 2: /* faint, decreased intensity or second colour */ 3782 UIntSet(xw->flags, ATR_FAINT); 3783 if_OPT_ISO_COLORS(screen, { 3784 setExtendedFG(xw); 3785 }); 3786 break; 3787 case 3: /* italicized */ 3788 setItalicFont(xw, UseItalicFont(screen)); 3789 UIntSet(xw->flags, ATR_ITALIC); 3790 if_OPT_ISO_COLORS(screen, { 3791 setExtendedFG(xw); 3792 }); 3793 break; 3794#endif 3795 case 4: /* Underscore */ 3796 UIntSet(xw->flags, UNDERLINE); 3797 if_OPT_ISO_COLORS(screen, { 3798 setExtendedFG(xw); 3799 }); 3800 break; 3801 case 5: /* Blink (less than 150 per minute) */ 3802 /* FALLTHRU */ 3803 case 6: /* Blink (150 per minute, or more) */ 3804 UIntSet(xw->flags, BLINK); 3805 StartBlinking(xw); 3806 if_OPT_ISO_COLORS(screen, { 3807 setExtendedFG(xw); 3808 }); 3809 break; 3810 case 7: 3811 UIntSet(xw->flags, INVERSE); 3812 if_OPT_ISO_COLORS(screen, { 3813 setExtendedBG(xw); 3814 }); 3815 break; 3816 case 8: 3817 UIntSet(xw->flags, INVISIBLE); 3818 break; 3819#if OPT_WIDE_ATTRS 3820 case 9: /* crossed-out characters */ 3821 UIntSet(xw->flags, ATR_STRIKEOUT); 3822 break; 3823#endif 3824#if OPT_WIDE_ATTRS 3825 case 21: /* doubly-underlined */ 3826 UIntSet(xw->flags, ATR_DBL_UNDER); 3827 break; 3828#endif 3829 case 22: /* reset 'bold' */ 3830 UIntClr(xw->flags, BOLD); 3831#if OPT_WIDE_ATTRS 3832 UIntClr(xw->flags, ATR_FAINT); 3833#endif 3834 if_OPT_ISO_COLORS(screen, { 3835 setExtendedFG(xw); 3836 }); 3837 break; 3838#if OPT_WIDE_ATTRS 3839 case 23: /* not italicized */ 3840 ResetItalics(xw); 3841 if_OPT_ISO_COLORS(screen, { 3842 setExtendedFG(xw); 3843 }); 3844 break; 3845#endif 3846 case 24: 3847 UIntClr(xw->flags, UNDERLINE); 3848#if OPT_WIDE_ATTRS 3849 UIntClr(xw->flags, ATR_DBL_UNDER); 3850#endif 3851 if_OPT_ISO_COLORS(screen, { 3852 setExtendedFG(xw); 3853 }); 3854 break; 3855 case 25: /* reset 'blink' */ 3856 UIntClr(xw->flags, BLINK); 3857 if_OPT_ISO_COLORS(screen, { 3858 setExtendedFG(xw); 3859 }); 3860 break; 3861 case 27: 3862 UIntClr(xw->flags, INVERSE); 3863 if_OPT_ISO_COLORS(screen, { 3864 setExtendedBG(xw); 3865 }); 3866 break; 3867 case 28: 3868 UIntClr(xw->flags, INVISIBLE); 3869 break; 3870#if OPT_WIDE_ATTRS 3871 case 29: /* not crossed out */ 3872 UIntClr(xw->flags, ATR_STRIKEOUT); 3873 break; 3874#endif 3875 case 30: 3876 /* FALLTHRU */ 3877 case 31: 3878 /* FALLTHRU */ 3879 case 32: 3880 /* FALLTHRU */ 3881 case 33: 3882 /* FALLTHRU */ 3883 case 34: 3884 /* FALLTHRU */ 3885 case 35: 3886 /* FALLTHRU */ 3887 case 36: 3888 /* FALLTHRU */ 3889 case 37: 3890 if_OPT_ISO_COLORS(screen, { 3891 xw->sgr_foreground = (op - 30); 3892 xw->sgr_38_xcolors = False; 3893 clrDirectFG(xw->flags); 3894 setExtendedFG(xw); 3895 }); 3896 break; 3897 case 38: 3898 /* This is more complicated than I'd like, but it should 3899 * properly eat all the parameters for unsupported modes. 3900 */ 3901 if_OPT_ISO_COLORS(screen, { 3902 Boolean extended; 3903 if (parse_extended_colors(xw, &value, &item, 3904 &extended)) { 3905 xw->sgr_foreground = value; 3906 xw->sgr_38_xcolors = True; 3907 setDirectFG(xw->flags, extended); 3908 setExtendedFG(xw); 3909 } 3910 }); 3911 break; 3912 case 39: 3913 if_OPT_ISO_COLORS(screen, { 3914 reset_SGR_Foreground(xw); 3915 }); 3916 break; 3917 case 40: 3918 /* FALLTHRU */ 3919 case 41: 3920 /* FALLTHRU */ 3921 case 42: 3922 /* FALLTHRU */ 3923 case 43: 3924 /* FALLTHRU */ 3925 case 44: 3926 /* FALLTHRU */ 3927 case 45: 3928 /* FALLTHRU */ 3929 case 46: 3930 /* FALLTHRU */ 3931 case 47: 3932 if_OPT_ISO_COLORS(screen, { 3933 xw->sgr_background = (op - 40); 3934 clrDirectBG(xw->flags); 3935 setExtendedBG(xw); 3936 }); 3937 break; 3938 case 48: 3939 if_OPT_ISO_COLORS(screen, { 3940 Boolean extended; 3941 if (parse_extended_colors(xw, &value, &item, 3942 &extended)) { 3943 xw->sgr_background = value; 3944 setDirectBG(xw->flags, extended); 3945 setExtendedBG(xw); 3946 } 3947 }); 3948 break; 3949 case 49: 3950 if_OPT_ISO_COLORS(screen, { 3951 reset_SGR_Background(xw); 3952 }); 3953 break; 3954 case 90: 3955 /* FALLTHRU */ 3956 case 91: 3957 /* FALLTHRU */ 3958 case 92: 3959 /* FALLTHRU */ 3960 case 93: 3961 /* FALLTHRU */ 3962 case 94: 3963 /* FALLTHRU */ 3964 case 95: 3965 /* FALLTHRU */ 3966 case 96: 3967 /* FALLTHRU */ 3968 case 97: 3969 if_OPT_AIX_COLORS(screen, { 3970 xw->sgr_foreground = (op - 90 + 8); 3971 clrDirectFG(xw->flags); 3972 setExtendedFG(xw); 3973 }); 3974 break; 3975 case 100: 3976#if !OPT_AIX_COLORS 3977 if_OPT_ISO_COLORS(screen, { 3978 reset_SGR_Foreground(xw); 3979 reset_SGR_Background(xw); 3980 }); 3981 break; 3982#endif 3983 case 101: 3984 /* FALLTHRU */ 3985 case 102: 3986 /* FALLTHRU */ 3987 case 103: 3988 /* FALLTHRU */ 3989 case 104: 3990 /* FALLTHRU */ 3991 case 105: 3992 /* FALLTHRU */ 3993 case 106: 3994 /* FALLTHRU */ 3995 case 107: 3996 if_OPT_AIX_COLORS(screen, { 3997 xw->sgr_background = (op - 100 + 8); 3998 clrDirectBG(xw->flags); 3999 setExtendedBG(xw); 4000 }); 4001 break; 4002 default: 4003 /* later: skip += NPARAM; */ 4004 break; 4005 } 4006 } 4007 ResetState(sp); 4008 break; 4009 4010 /* DSR (except for the '?') is a superset of CPR */ 4011 case CASE_DSR: 4012 sp->private_function = True; 4013 4014 /* FALLTHRU */ 4015 case CASE_CPR: 4016 TRACE(("CASE_DSR - device status report\n")); 4017 count = 0; 4018 init_reply(ANSI_CSI); 4019 reply.a_pintro = CharOf(sp->private_function ? '?' : 0); 4020 reply.a_inters = 0; 4021 reply.a_final = 'n'; 4022 4023 switch (GetParam(0)) { 4024 case 5: 4025 TRACE(("...request operating status\n")); 4026 /* operating status */ 4027 reply.a_param[count++] = 0; /* (no malfunction ;-) */ 4028 break; 4029 case 6: 4030 TRACE(("...request %s\n", 4031 (sp->private_function 4032 ? "DECXCPR" 4033 : "CPR"))); 4034 /* CPR */ 4035 /* DECXCPR (with page=1) */ 4036 value = screen->cur_row; 4037 if ((xw->flags & ORIGIN) != 0) { 4038 value -= screen->top_marg; 4039 } 4040 if_STATUS_LINE(screen, { 4041 if ((value -= LastRowNumber(screen)) < 0) 4042 value = 0; 4043 }); 4044 reply.a_param[count++] = (ParmType) (value + 1); 4045 4046 value = (screen->cur_col + 1); 4047 if ((xw->flags & ORIGIN) != 0) { 4048 value -= screen->lft_marg; 4049 } 4050 reply.a_param[count++] = (ParmType) value; 4051 4052 if (sp->private_function 4053 && screen->vtXX_level >= 4) { /* VT420 */ 4054 reply.a_param[count++] = 1; 4055 } 4056 reply.a_final = 'R'; 4057 break; 4058 case 15: 4059 TRACE(("...request printer status\n")); 4060 if (sp->private_function 4061 && screen->vtXX_level >= 2) { /* VT220 */ 4062 reply.a_param[count++] = 13; /* no printer detected */ 4063 } 4064 break; 4065 case 25: 4066 TRACE(("...request UDK status\n")); 4067 if (sp->private_function 4068 && screen->vtXX_level >= 2) { /* VT220 */ 4069 reply.a_param[count++] = 20; /* UDK always unlocked */ 4070 } 4071 break; 4072 case 26: 4073 TRACE(("...request keyboard status\n")); 4074 if (sp->private_function 4075 && screen->vtXX_level >= 2) { /* VT220 */ 4076 reply.a_param[count++] = 27; 4077 reply.a_param[count++] = 1; /* North American */ 4078 if (screen->vtXX_level >= 3) { /* VT320 */ 4079 reply.a_param[count++] = 0; /* ready */ 4080 } 4081 if (screen->vtXX_level >= 4) { /* VT420 */ 4082 reply.a_param[count++] = 0; /* LK201 */ 4083 } 4084 } 4085 break; 4086 case 53: /* according to existing xterm handling */ 4087 /* FALLTHRU */ 4088 case 55: /* according to the VT330/VT340 Text Programming Manual */ 4089 TRACE(("...request locator status\n")); 4090 if (sp->private_function 4091 && screen->vtXX_level >= 3) { /* VT330 */ 4092#if OPT_DEC_LOCATOR 4093 reply.a_param[count++] = 50; /* locator ready */ 4094#else 4095 reply.a_param[count++] = 53; /* no locator */ 4096#endif 4097 } 4098 break; 4099 case 56: 4100 TRACE(("...request locator type\n")); 4101 if (sp->private_function 4102 && screen->vtXX_level >= 3) { /* VT330 */ 4103 reply.a_param[count++] = 57; 4104#if OPT_DEC_LOCATOR 4105 reply.a_param[count++] = 1; /* mouse */ 4106#else 4107 reply.a_param[count++] = 0; /* unknown */ 4108#endif 4109 } 4110 break; 4111 case 62: 4112 TRACE(("...request DECMSR - macro space\n")); 4113 if (sp->private_function 4114 && screen->vtXX_level >= 4) { /* VT420 */ 4115 reply.a_pintro = 0; 4116 reply.a_radix[count] = 16; /* no data */ 4117 reply.a_param[count++] = 0; /* no space for macros */ 4118 reply.a_inters = '*'; 4119 reply.a_final = L_CURL; 4120 } 4121 break; 4122 case 63: 4123 TRACE(("...request DECCKSR - memory checksum\n")); 4124 /* DECCKSR - Memory checksum */ 4125 if (sp->private_function 4126 && screen->vtXX_level >= 4) { /* VT420 */ 4127 init_reply(ANSI_DCS); 4128 reply.a_param[count++] = (ParmType) GetParam(1); /* PID */ 4129 reply.a_delim = "!~"; /* delimiter */ 4130 reply.a_radix[count] = 16; /* use hex */ 4131 reply.a_param[count++] = 0; /* no data */ 4132 } 4133 break; 4134 case 75: 4135 TRACE(("...request data integrity\n")); 4136 if (sp->private_function 4137 && screen->vtXX_level >= 4) { /* VT420 */ 4138 reply.a_param[count++] = 70; /* no errors */ 4139 } 4140 break; 4141 case 85: 4142 TRACE(("...request multi-session configuration\n")); 4143 if (sp->private_function 4144 && screen->vtXX_level >= 4) { /* VT420 */ 4145 reply.a_param[count++] = 83; /* not configured */ 4146 } 4147 break; 4148 default: 4149 break; 4150 } 4151 4152 if ((reply.a_nparam = (ParmType) count) != 0) 4153 unparseseq(xw, &reply); 4154 4155 ResetState(sp); 4156 sp->private_function = False; 4157 break; 4158 4159 case CASE_MC: 4160 TRACE(("CASE_MC - media control\n")); 4161 xtermMediaControl(xw, GetParam(0), False); 4162 ResetState(sp); 4163 break; 4164 4165 case CASE_DEC_MC: 4166 TRACE(("CASE_DEC_MC - DEC media control\n")); 4167 xtermMediaControl(xw, GetParam(0), True); 4168 ResetState(sp); 4169 break; 4170 4171 case CASE_HP_MEM_LOCK: 4172 /* FALLTHRU */ 4173 case CASE_HP_MEM_UNLOCK: 4174 TRACE(("%s\n", ((sp->parsestate[c] == CASE_HP_MEM_LOCK) 4175 ? "CASE_HP_MEM_LOCK" 4176 : "CASE_HP_MEM_UNLOCK"))); 4177 if (screen->scroll_amt) 4178 FlushScroll(xw); 4179 if (sp->parsestate[c] == CASE_HP_MEM_LOCK) 4180 set_tb_margins(screen, screen->cur_row, screen->bot_marg); 4181 else 4182 set_tb_margins(screen, 0, screen->bot_marg); 4183 ResetState(sp); 4184 break; 4185 4186 case CASE_DECSTBM: 4187 TRACE(("CASE_DECSTBM - set scrolling region\n")); 4188 { 4189 int top; 4190 int bot; 4191 top = one_if_default(0); 4192 if (nparam < 2 || (bot = GetParam(1)) == DEFAULT 4193 || bot > MaxRows(screen) 4194 || bot == 0) 4195 bot = MaxRows(screen); 4196 if (bot > top) { 4197 if (screen->scroll_amt) 4198 FlushScroll(xw); 4199 set_tb_margins(screen, top - 1, bot - 1); 4200 CursorSet(screen, 0, 0, xw->flags); 4201 } 4202 ResetState(sp); 4203 } 4204 break; 4205 4206 case CASE_DECREQTPARM: 4207 TRACE(("CASE_DECREQTPARM\n")); 4208 if (screen->terminal_id < 200) { /* VT102 */ 4209 value = zero_if_default(0); 4210 if (value == 0 || value == 1) { 4211 init_reply(ANSI_CSI); 4212 reply.a_pintro = 0; 4213 reply.a_nparam = 7; 4214 reply.a_param[0] = (ParmType) (value + 2); 4215 reply.a_param[1] = 1; /* no parity */ 4216 reply.a_param[2] = 1; /* eight bits */ 4217 reply.a_param[3] = 128; /* transmit 38.4k baud */ 4218 reply.a_param[4] = 128; /* receive 38.4k baud */ 4219 reply.a_param[5] = 1; /* clock multiplier ? */ 4220 reply.a_param[6] = 0; /* STP flags ? */ 4221 reply.a_inters = 0; 4222 reply.a_final = 'x'; 4223 unparseseq(xw, &reply); 4224 } 4225 } 4226 ResetState(sp); 4227 break; 4228 4229 case CASE_DECSET: 4230 /* DECSET */ 4231#if OPT_VT52_MODE 4232 if (screen->vtXX_level != 0) 4233#endif 4234 dpmodes(xw, bitset); 4235 ResetState(sp); 4236#if OPT_TEK4014 4237 if (TEK4014_ACTIVE(xw)) { 4238 TRACE(("Tek4014 is now active...\n")); 4239 if (sp->check_recur) 4240 sp->check_recur--; 4241 return False; 4242 } 4243#endif 4244 break; 4245 4246 case CASE_DECRST: 4247 /* DECRST */ 4248 dpmodes(xw, bitclr); 4249 init_groundtable(screen, sp); 4250 ResetState(sp); 4251 break; 4252 4253 case CASE_DECALN: 4254 TRACE(("CASE_DECALN - alignment test\n")); 4255 if (screen->cursor_state) 4256 HideCursor(xw); 4257 /* 4258 * DEC STD 070 (see pages D-19 to D-20) does not mention left/right 4259 * margins. The section is dated March 1985, not updated for the 4260 * VT420 (introduced in 1990). 4261 */ 4262 UIntClr(xw->flags, ORIGIN); 4263 screen->do_wrap = False; 4264 resetRendition(xw); 4265 resetMargins(xw); 4266 xterm_ResetDouble(xw); 4267 CursorSet(screen, 0, 0, xw->flags); 4268 xtermParseRect(xw, 0, 0, &myRect); 4269 ScrnFillRectangle(xw, &myRect, 'E', 0, False); 4270 ResetState(sp); 4271 break; 4272 4273 case CASE_GSETS5: 4274 if (screen->vtXX_level >= 5) { 4275 TRACE(("CASE_GSETS5(%d) = '%c'\n", sp->scstype, c)); 4276 xtermDecodeSCS(xw, sp->scstype, 5, 0, (int) c); 4277 } 4278 ResetState(sp); 4279 break; 4280 4281 case CASE_GSETS3: 4282 if (screen->vtXX_level >= 3) { 4283 TRACE(("CASE_GSETS3(%d) = '%c'\n", sp->scstype, c)); 4284 xtermDecodeSCS(xw, sp->scstype, 3, 0, (int) c); 4285 } 4286 ResetState(sp); 4287 break; 4288 4289 case CASE_GSETS: 4290 if (strchr("012AB", (int) c) != 0) { 4291 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c)); 4292 xtermDecodeSCS(xw, sp->scstype, 1, 0, (int) c); 4293 } else if (screen->vtXX_level >= 2) { 4294 TRACE(("CASE_GSETS(%d) = '%c'\n", sp->scstype, c)); 4295 xtermDecodeSCS(xw, sp->scstype, 2, 0, (int) c); 4296 } 4297 ResetState(sp); 4298 break; 4299 4300 case CASE_ANSI_SC: 4301 if (IsLeftRightMode(xw)) { 4302 int left; 4303 int right; 4304 4305 TRACE(("CASE_DECSLRM - set left and right margin\n")); 4306 left = one_if_default(0); 4307 if (nparam < 2 || (right = GetParam(1)) == DEFAULT 4308 || right > MaxCols(screen) 4309 || right == 0) 4310 right = MaxCols(screen); 4311 if (right > left) { 4312 set_lr_margins(screen, left - 1, right - 1); 4313 CursorSet(screen, 0, 0, xw->flags); 4314 } 4315 } else { 4316 TRACE(("CASE_ANSI_SC - save cursor\n")); 4317 CursorSave(xw); 4318 } 4319 ResetState(sp); 4320 break; 4321 4322 case CASE_DECSC: 4323 TRACE(("CASE_DECSC - save cursor\n")); 4324 CursorSave(xw); 4325 ResetState(sp); 4326 break; 4327 4328 case CASE_ANSI_RC: 4329 /* FALLTHRU */ 4330 case CASE_DECRC: 4331 TRACE(("CASE_%sRC - restore cursor\n", 4332 (sp->nextstate == CASE_DECRC) ? "DEC" : "ANSI_")); 4333 CursorRestore(xw); 4334 if_OPT_ISO_COLORS(screen, { 4335 setExtendedFG(xw); 4336 }); 4337 ResetState(sp); 4338 break; 4339 4340 case CASE_DECKPAM: 4341 TRACE(("CASE_DECKPAM\n")); 4342 xw->keyboard.flags |= MODE_DECKPAM; 4343 update_appkeypad(); 4344 ResetState(sp); 4345 break; 4346 4347 case CASE_DECKPNM: 4348 TRACE(("CASE_DECKPNM\n")); 4349 UIntClr(xw->keyboard.flags, MODE_DECKPAM); 4350 update_appkeypad(); 4351 ResetState(sp); 4352 break; 4353 4354 case CASE_CSI_QUOTE_STATE: 4355 sp->parsestate = csi_quo_table; 4356 break; 4357 4358#if OPT_BLINK_CURS 4359 case CASE_CSI_SPACE_STATE: 4360 sp->parsestate = csi_sp_table; 4361 break; 4362 4363 case CASE_DECSCUSR: 4364 TRACE(("CASE_DECSCUSR\n")); 4365 { 4366 Boolean change = True; 4367 int blinks = screen->cursor_blink_esc; 4368 4369 HideCursor(xw); 4370 4371 switch (GetParam(0)) { 4372 case DEFAULT: 4373 /* FALLTHRU */ 4374 case DEFAULT_STYLE: 4375 /* FALLTHRU */ 4376 case BLINK_BLOCK: 4377 blinks = True; 4378 screen->cursor_shape = CURSOR_BLOCK; 4379 break; 4380 case STEADY_BLOCK: 4381 blinks = False; 4382 screen->cursor_shape = CURSOR_BLOCK; 4383 break; 4384 case BLINK_UNDERLINE: 4385 blinks = True; 4386 screen->cursor_shape = CURSOR_UNDERLINE; 4387 break; 4388 case STEADY_UNDERLINE: 4389 blinks = False; 4390 screen->cursor_shape = CURSOR_UNDERLINE; 4391 break; 4392 case BLINK_BAR: 4393 blinks = True; 4394 screen->cursor_shape = CURSOR_BAR; 4395 break; 4396 case STEADY_BAR: 4397 blinks = False; 4398 screen->cursor_shape = CURSOR_BAR; 4399 break; 4400 default: 4401 change = False; 4402 break; 4403 } 4404 TRACE(("cursor_shape:%d blinks:%s\n", 4405 screen->cursor_shape, BtoS(blinks))); 4406 if (change) { 4407 xtermSetCursorBox(screen); 4408 if (SettableCursorBlink(screen)) { 4409 screen->cursor_blink_esc = blinks; 4410 UpdateCursorBlink(xw); 4411 } 4412 } 4413 } 4414 ResetState(sp); 4415 break; 4416#endif 4417 4418#if OPT_SCROLL_LOCK 4419 case CASE_DECLL: 4420 TRACE(("CASE_DECLL\n")); 4421 if (nparam > 0) { 4422 for (count = 0; count < nparam; ++count) { 4423 int op = zero_if_default(count); 4424 switch (op) { 4425 case 0: 4426 case DEFAULT: 4427 xtermClearLEDs(screen); 4428 break; 4429 case 1: 4430 /* FALLTHRU */ 4431 case 2: 4432 /* FALLTHRU */ 4433 case 3: 4434 xtermShowLED(screen, 4435 (Cardinal) op, 4436 True); 4437 break; 4438 case 21: 4439 /* FALLTHRU */ 4440 case 22: 4441 /* FALLTHRU */ 4442 case 23: 4443 xtermShowLED(screen, 4444 (Cardinal) (op - 20), 4445 True); 4446 break; 4447 } 4448 } 4449 } else { 4450 xtermClearLEDs(screen); 4451 } 4452 ResetState(sp); 4453 break; 4454#endif 4455 4456#if OPT_VT52_MODE 4457 case CASE_VT52_FINISH: 4458 TRACE(("CASE_VT52_FINISH terminal_id %d, vtXX_level %d\n", 4459 screen->terminal_id, 4460 screen->vtXX_level)); 4461 if (screen->terminal_id >= 100 4462 && screen->vtXX_level == 0) { 4463 sp->groundtable = 4464 sp->parsestate = ansi_table; 4465 /* 4466 * On restore, the terminal does not recognize DECRQSS for 4467 * DECSCL (per vttest). 4468 */ 4469 screen->vtXX_level = 1; 4470 xw->flags = screen->vt52_save_flags; 4471 screen->curgl = screen->vt52_save_curgl; 4472 screen->curgr = screen->vt52_save_curgr; 4473 screen->curss = screen->vt52_save_curss; 4474 restoreCharsets(screen, screen->vt52_save_gsets); 4475 update_vt52_vt100_settings(); 4476 } 4477 break; 4478#endif 4479 4480 case CASE_ANSI_LEVEL_1: 4481 TRACE(("CASE_ANSI_LEVEL_1\n")); 4482 set_ansi_conformance(screen, 1); 4483 ResetState(sp); 4484 break; 4485 4486 case CASE_ANSI_LEVEL_2: 4487 TRACE(("CASE_ANSI_LEVEL_2\n")); 4488 set_ansi_conformance(screen, 2); 4489 ResetState(sp); 4490 break; 4491 4492 case CASE_ANSI_LEVEL_3: 4493 TRACE(("CASE_ANSI_LEVEL_3\n")); 4494 set_ansi_conformance(screen, 3); 4495 ResetState(sp); 4496 break; 4497 4498 case CASE_DECSCL: 4499 TRACE(("CASE_DECSCL(%d,%d)\n", GetParam(0), GetParam(1))); 4500 /* 4501 * This changes the emulation level, and is not recognized by 4502 * VT100s. However, a VT220 or above can be set to conformance 4503 * level 1 to act like a VT100. 4504 */ 4505 if (screen->terminal_id >= 200) { 4506 /* 4507 * Disallow unrecognized parameters, as well as attempts to set 4508 * the operating level higher than the given terminal-id. 4509 */ 4510 if (GetParam(0) >= 61 4511 && GetParam(0) <= 60 + (screen->terminal_id / 100)) { 4512 int new_vtXX_level = GetParam(0) - 60; 4513 int case_value = zero_if_default(1); 4514 /* 4515 * Note: 4516 * 4517 * The VT300, VT420, VT520 manuals claim that DECSCL does a 4518 * hard reset (RIS). 4519 * 4520 * Both the VT220 manual and DEC STD 070 (which documents 4521 * levels 1-4 in detail) state that it is a soft reset. 4522 * 4523 * Perhaps both sets of manuals are right (unlikely). 4524 * Kermit says it's soft. 4525 */ 4526 ReallyReset(xw, False, False); 4527 init_parser(xw, sp); 4528 screen->vtXX_level = new_vtXX_level; 4529 if (new_vtXX_level > 1) { 4530 switch (case_value) { 4531 case 1: 4532 show_8bit_control(False); 4533 break; 4534 case 0: 4535 case 2: 4536 show_8bit_control(True); 4537 break; 4538 } 4539 } 4540 } 4541 } 4542 ResetState(sp); 4543 break; 4544 4545 case CASE_DECSCA: 4546 TRACE(("CASE_DECSCA\n")); 4547 screen->protected_mode = DEC_PROTECT; 4548 if (GetParam(0) <= 0 || GetParam(0) == 2) { 4549 UIntClr(xw->flags, PROTECTED); 4550 TRACE(("...clear PROTECTED\n")); 4551 } else if (GetParam(0) == 1) { 4552 xw->flags |= PROTECTED; 4553 TRACE(("...set PROTECTED\n")); 4554 } 4555 ResetState(sp); 4556 break; 4557 4558 case CASE_DECSED: 4559 TRACE(("CASE_DECSED\n")); 4560 do_erase_display(xw, zero_if_default(0), DEC_PROTECT); 4561 ResetState(sp); 4562 break; 4563 4564 case CASE_DECSEL: 4565 TRACE(("CASE_DECSEL\n")); 4566 do_erase_line(xw, zero_if_default(0), DEC_PROTECT); 4567 ResetState(sp); 4568 break; 4569 4570 case CASE_GRAPHICS_ATTRIBUTES: 4571#if OPT_GRAPHICS 4572 TRACE(("CASE_GRAPHICS_ATTRIBUTES\n")); 4573 { 4574 /* request: item, action, value */ 4575 /* reply: item, status, value */ 4576 if (nparam != 3) { 4577 TRACE(("DATA_ERROR: malformed CASE_GRAPHICS_ATTRIBUTES request with %d parameters\n", nparam)); 4578 } else { 4579 int status = 3; /* assume failure */ 4580 int result = 0; 4581 int result2 = 0; 4582 4583 TRACE(("CASE_GRAPHICS_ATTRIBUTES request: %d, %d, %d\n", 4584 GetParam(0), GetParam(1), GetParam(2))); 4585 switch (GetParam(0)) { 4586 case 1: /* color register count */ 4587 switch (GetParam(1)) { 4588 case 1: /* read */ 4589 status = 0; /* success */ 4590 result = (int) get_color_register_count(screen); 4591 break; 4592 case 2: /* reset */ 4593 screen->numcolorregisters = 0; 4594 status = 0; /* success */ 4595 result = (int) get_color_register_count(screen); 4596 break; 4597 case 3: /* set */ 4598 if (GetParam(2) > 1 && 4599 (unsigned) GetParam(2) <= MAX_COLOR_REGISTERS) { 4600 screen->numcolorregisters = GetParam(2); 4601 status = 0; /* success */ 4602 result = (int) get_color_register_count(screen); 4603 } 4604 break; 4605 case 4: /* read maximum */ 4606 status = 0; /* success */ 4607 result = MAX_COLOR_REGISTERS; 4608 break; 4609 default: 4610 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES color register count request with unknown action parameter: %d\n", 4611 GetParam(1))); 4612 status = 2; /* error in Pa */ 4613 break; 4614 } 4615 if (status == 0 && !(optSixelGraphics(screen) 4616 || optRegisGraphics(screen))) 4617 status = 3; 4618 break; 4619# if OPT_SIXEL_GRAPHICS 4620 case 2: /* graphics geometry */ 4621 switch (GetParam(1)) { 4622 case 1: /* read */ 4623 TRACE(("Get sixel graphics geometry\n")); 4624 status = 0; /* success */ 4625 result = Min(Width(screen), (int) screen->graphics_max_wide); 4626 result2 = Min(Height(screen), (int) screen->graphics_max_high); 4627 break; 4628 case 2: /* reset */ 4629 /* FALLTHRU */ 4630 case 3: /* set */ 4631 break; 4632 case 4: /* read maximum */ 4633 status = 0; /* success */ 4634 result = screen->graphics_max_wide; 4635 result2 = screen->graphics_max_high; 4636 break; 4637 default: 4638 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES graphics geometry request with unknown action parameter: %d\n", 4639 GetParam(1))); 4640 status = 2; /* error in Pa */ 4641 break; 4642 } 4643 if (status == 0 && !optSixelGraphics(screen)) 4644 status = 3; 4645 break; 4646#endif 4647# if OPT_REGIS_GRAPHICS 4648 case 3: /* ReGIS geometry */ 4649 switch (GetParam(1)) { 4650 case 1: /* read */ 4651 status = 0; /* success */ 4652 result = screen->graphics_regis_def_wide; 4653 result2 = screen->graphics_regis_def_high; 4654 break; 4655 case 2: /* reset */ 4656 /* FALLTHRU */ 4657 case 3: /* set */ 4658 /* FALLTHRU */ 4659 case 4: /* read maximum */ 4660 /* not implemented */ 4661 break; 4662 default: 4663 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES ReGIS geometry request with unknown action parameter: %d\n", 4664 GetParam(1))); 4665 status = 2; /* error in Pa */ 4666 break; 4667 } 4668 if (status == 0 && !optRegisGraphics(screen)) 4669 status = 3; 4670 break; 4671#endif 4672 default: 4673 TRACE(("DATA_ERROR: CASE_GRAPHICS_ATTRIBUTES request with unknown item parameter: %d\n", 4674 GetParam(0))); 4675 status = 1; 4676 break; 4677 } 4678 4679 init_reply(ANSI_CSI); 4680 reply.a_pintro = '?'; 4681 count = 0; 4682 reply.a_param[count++] = (ParmType) GetParam(0); 4683 reply.a_param[count++] = (ParmType) status; 4684 if (status == 0) { 4685 reply.a_param[count++] = (ParmType) result; 4686 if (GetParam(0) >= 2) 4687 reply.a_param[count++] = (ParmType) result2; 4688 } 4689 reply.a_nparam = (ParmType) count; 4690 reply.a_inters = 0; 4691 reply.a_final = 'S'; 4692 unparseseq(xw, &reply); 4693 } 4694 } 4695#endif 4696 ResetState(sp); 4697 break; 4698 4699 case CASE_ST: 4700 TRACE(("CASE_ST: End of String (%lu bytes) (mode=%d)\n", 4701 (unsigned long) sp->string_used, 4702 sp->string_mode)); 4703 ResetState(sp); 4704 if (!sp->string_used) 4705 break; 4706 sp->string_area[--(sp->string_used)] = '\0'; 4707 if (sp->check_recur <= 1) 4708 switch (sp->string_mode) { 4709 case ANSI_APC: 4710 /* ignored */ 4711 break; 4712 case ANSI_DCS: 4713 do_dcs(xw, sp->string_area, sp->string_used); 4714 break; 4715 case ANSI_OSC: 4716 do_osc(xw, sp->string_area, sp->string_used, ANSI_ST); 4717 break; 4718 case ANSI_PM: 4719 /* ignored */ 4720 break; 4721 case ANSI_SOS: 4722 /* ignored */ 4723 break; 4724 default: 4725 TRACE(("unknown mode\n")); 4726 break; 4727 } 4728 break; 4729 4730 case CASE_SOS: 4731 TRACE(("CASE_SOS: Start of String\n")); 4732 if (ParseSOS(screen)) { 4733 sp->string_mode = ANSI_SOS; 4734 sp->parsestate = sos_table; 4735 } else { 4736 illegal_parse(xw, c, sp); 4737 } 4738 break; 4739 4740 case CASE_PM: 4741 TRACE(("CASE_PM: Privacy Message\n")); 4742 if (ParseSOS(screen)) { 4743 sp->string_mode = ANSI_PM; 4744 sp->parsestate = sos_table; 4745 } else { 4746 illegal_parse(xw, c, sp); 4747 } 4748 break; 4749 4750 case CASE_DCS: 4751 TRACE(("CASE_DCS: Device Control String\n")); 4752 sp->string_mode = ANSI_DCS; 4753 sp->parsestate = sos_table; 4754 break; 4755 4756 case CASE_APC: 4757 TRACE(("CASE_APC: Application Program Command\n")); 4758 if (ParseSOS(screen)) { 4759 sp->string_mode = ANSI_APC; 4760 sp->parsestate = sos_table; 4761 } else { 4762 illegal_parse(xw, c, sp); 4763 } 4764 break; 4765 4766 case CASE_SPA: 4767 TRACE(("CASE_SPA - start protected area\n")); 4768 screen->protected_mode = ISO_PROTECT; 4769 xw->flags |= PROTECTED; 4770 ResetState(sp); 4771 break; 4772 4773 case CASE_EPA: 4774 TRACE(("CASE_EPA - end protected area\n")); 4775 UIntClr(xw->flags, PROTECTED); 4776 ResetState(sp); 4777 break; 4778 4779 case CASE_SU: 4780 TRACE(("CASE_SU - scroll up\n")); 4781 xtermScroll(xw, one_if_default(0)); 4782 ResetState(sp); 4783 break; 4784 4785 case CASE_SL: /* ISO 6429, non-DEC */ 4786 TRACE(("CASE_SL - scroll left\n")); 4787 xtermScrollLR(xw, one_if_default(0), True); 4788 ResetState(sp); 4789 break; 4790 4791 case CASE_SR: /* ISO 6429, non-DEC */ 4792 TRACE(("CASE_SR - scroll right\n")); 4793 xtermScrollLR(xw, one_if_default(0), False); 4794 ResetState(sp); 4795 break; 4796 4797 case CASE_DECDC: 4798 TRACE(("CASE_DC - delete column\n")); 4799 if (screen->vtXX_level >= 4) { 4800 xtermColScroll(xw, one_if_default(0), True, screen->cur_col); 4801 } 4802 ResetState(sp); 4803 break; 4804 4805 case CASE_DECIC: 4806 TRACE(("CASE_IC - insert column\n")); 4807 if (screen->vtXX_level >= 4) { 4808 xtermColScroll(xw, one_if_default(0), False, screen->cur_col); 4809 } 4810 ResetState(sp); 4811 break; 4812 4813 case CASE_DECBI: 4814 TRACE(("CASE_BI - back index\n")); 4815 if (screen->vtXX_level >= 4) { 4816 xtermColIndex(xw, True); 4817 } 4818 ResetState(sp); 4819 break; 4820 4821 case CASE_DECFI: 4822 TRACE(("CASE_FI - forward index\n")); 4823 if (screen->vtXX_level >= 4) { 4824 xtermColIndex(xw, False); 4825 } 4826 ResetState(sp); 4827 break; 4828 4829 case CASE_IND: 4830 TRACE(("CASE_IND - index\n")); 4831 xtermIndex(xw, 1); 4832 do_xevents(xw); 4833 ResetState(sp); 4834 break; 4835 4836 case CASE_CPL: 4837 TRACE(("CASE_CPL - cursor prev line\n")); 4838 CursorPrevLine(xw, one_if_default(0)); 4839 ResetState(sp); 4840 break; 4841 4842 case CASE_CNL: 4843 TRACE(("CASE_CNL - cursor next line\n")); 4844 CursorNextLine(xw, one_if_default(0)); 4845 ResetState(sp); 4846 break; 4847 4848 case CASE_NEL: 4849 TRACE(("CASE_NEL\n")); 4850 xtermIndex(xw, 1); 4851 CarriageReturn(xw); 4852 ResetState(sp); 4853 break; 4854 4855 case CASE_HTS: 4856 TRACE(("CASE_HTS - horizontal tab set\n")); 4857 TabSet(xw->tabs, screen->cur_col); 4858 ResetState(sp); 4859 break; 4860 4861 case CASE_REPORT_VERSION: 4862 TRACE(("CASE_REPORT_VERSION - report terminal version\n")); 4863 if (GetParam(0) <= 0) { 4864 unparseputc1(xw, ANSI_DCS); 4865 unparseputc(xw, '>'); 4866 unparseputc(xw, '|'); 4867 unparseputs(xw, xtermVersion()); 4868 unparseputc1(xw, ANSI_ST); 4869 unparse_end(xw); 4870 } 4871 ResetState(sp); 4872 break; 4873 4874 case CASE_RI: 4875 TRACE(("CASE_RI - reverse index\n")); 4876 RevIndex(xw, 1); 4877 ResetState(sp); 4878 break; 4879 4880 case CASE_SS2: 4881 TRACE(("CASE_SS2\n")); 4882 screen->curss = 2; 4883 ResetState(sp); 4884 break; 4885 4886 case CASE_SS3: 4887 TRACE(("CASE_SS3\n")); 4888 screen->curss = 3; 4889 ResetState(sp); 4890 break; 4891 4892 case CASE_CSI_STATE: 4893 /* enter csi state */ 4894 InitParams(); 4895 SetParam(nparam++, DEFAULT); 4896 sp->parsestate = csi_table; 4897 break; 4898 4899 case CASE_ESC_SP_STATE: 4900 /* esc space */ 4901 sp->parsestate = esc_sp_table; 4902 break; 4903 4904 case CASE_CSI_EX_STATE: 4905 /* csi exclamation */ 4906 sp->parsestate = csi_ex_table; 4907 break; 4908 4909 case CASE_CSI_TICK_STATE: 4910 /* csi tick (') */ 4911 sp->parsestate = csi_tick_table; 4912 break; 4913 4914#if OPT_DEC_LOCATOR 4915 case CASE_DECEFR: 4916 TRACE(("CASE_DECEFR - Enable Filter Rectangle\n")); 4917 if (okSendMousePos(xw) == DEC_LOCATOR) { 4918 MotionOff(screen, xw); 4919 if ((screen->loc_filter_top = GetParam(0)) < 1) 4920 screen->loc_filter_top = LOC_FILTER_POS; 4921 if (nparam < 2 4922 || (screen->loc_filter_left = GetParam(1)) < 1) 4923 screen->loc_filter_left = LOC_FILTER_POS; 4924 if (nparam < 3 4925 || (screen->loc_filter_bottom = GetParam(2)) < 1) 4926 screen->loc_filter_bottom = LOC_FILTER_POS; 4927 if (nparam < 4 4928 || (screen->loc_filter_right = GetParam(3)) < 1) 4929 screen->loc_filter_right = LOC_FILTER_POS; 4930 InitLocatorFilter(xw); 4931 } 4932 ResetState(sp); 4933 break; 4934 4935 case CASE_DECELR: 4936 MotionOff(screen, xw); 4937 if (GetParam(0) <= 0 || GetParam(0) > 2) { 4938 screen->send_mouse_pos = MOUSE_OFF; 4939 TRACE(("DECELR - Disable Locator Reports\n")); 4940 } else { 4941 TRACE(("DECELR - Enable Locator Reports\n")); 4942 screen->send_mouse_pos = DEC_LOCATOR; 4943 xtermShowPointer(xw, True); 4944 if (GetParam(0) == 2) { 4945 screen->locator_reset = True; 4946 } else { 4947 screen->locator_reset = False; 4948 } 4949 if (nparam < 2 || GetParam(1) != 1) { 4950 screen->locator_pixels = False; 4951 } else { 4952 screen->locator_pixels = True; 4953 } 4954 screen->loc_filter = False; 4955 } 4956 ResetState(sp); 4957 break; 4958 4959 case CASE_DECSLE: 4960 TRACE(("DECSLE - Select Locator Events\n")); 4961 for (count = 0; count < nparam; ++count) { 4962 switch (zero_if_default(count)) { 4963 case 0: 4964 MotionOff(screen, xw); 4965 screen->loc_filter = False; 4966 screen->locator_events = 0; 4967 break; 4968 case 1: 4969 screen->locator_events |= LOC_BTNS_DN; 4970 break; 4971 case 2: 4972 UIntClr(screen->locator_events, LOC_BTNS_DN); 4973 break; 4974 case 3: 4975 screen->locator_events |= LOC_BTNS_UP; 4976 break; 4977 case 4: 4978 UIntClr(screen->locator_events, LOC_BTNS_UP); 4979 break; 4980 } 4981 } 4982 ResetState(sp); 4983 break; 4984 4985 case CASE_DECRQLP: 4986 TRACE(("DECRQLP - Request Locator Position\n")); 4987 if (GetParam(0) < 2) { 4988 /* Issue DECLRP Locator Position Report */ 4989 GetLocatorPosition(xw); 4990 } 4991 ResetState(sp); 4992 break; 4993#endif /* OPT_DEC_LOCATOR */ 4994 4995#if OPT_DEC_RECTOPS 4996 case CASE_CSI_DOLLAR_STATE: 4997 TRACE(("CASE_CSI_DOLLAR_STATE\n")); 4998 /* csi dollar ($) */ 4999 if (screen->vtXX_level >= 3) 5000 sp->parsestate = csi_dollar_table; 5001 else 5002 sp->parsestate = eigtable; 5003 break; 5004 5005 case CASE_CSI_STAR_STATE: 5006 TRACE(("CASE_CSI_STAR_STATE\n")); 5007 /* csi star (*) */ 5008 if (screen->vtXX_level >= 4) 5009 sp->parsestate = csi_star_table; 5010 else 5011 sp->parsestate = eigtable; 5012 break; 5013 5014 case CASE_DECRQCRA: 5015 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewGetChecksum)) { 5016 int checksum; 5017 int pid; 5018 5019 TRACE(("CASE_DECRQCRA - Request checksum of rectangular area\n")); 5020 xtermCheckRect(xw, ParamPair(0), &checksum); 5021 init_reply(ANSI_DCS); 5022 count = 0; 5023 checksum &= 0xffff; 5024 pid = GetParam(0); 5025 reply.a_param[count++] = (ParmType) pid; 5026 reply.a_delim = "!~"; /* delimiter */ 5027 reply.a_radix[count] = 16; 5028 reply.a_param[count++] = (ParmType) checksum; 5029 reply.a_nparam = (ParmType) count; 5030 TRACE(("...checksum(%d) = %04X\n", pid, checksum)); 5031 unparseseq(xw, &reply); 5032 } 5033 ResetState(sp); 5034 break; 5035 5036 case CASE_DECCRA: 5037 if (screen->vtXX_level >= 4) { 5038 TRACE(("CASE_DECCRA - Copy rectangular area\n")); 5039 xtermParseRect(xw, ParamPair(0), &myRect); 5040 ScrnCopyRectangle(xw, &myRect, ParamPair(5)); 5041 } 5042 ResetState(sp); 5043 break; 5044 5045 case CASE_DECERA: 5046 if (screen->vtXX_level >= 4) { 5047 TRACE(("CASE_DECERA - Erase rectangular area\n")); 5048 xtermParseRect(xw, ParamPair(0), &myRect); 5049 ScrnFillRectangle(xw, &myRect, ' ', xw->flags, True); 5050 } 5051 ResetState(sp); 5052 break; 5053 5054 case CASE_DECFRA: 5055 if (screen->vtXX_level >= 4) { 5056 value = zero_if_default(0); 5057 5058 TRACE(("CASE_DECFRA - Fill rectangular area\n")); 5059 if (nparam > 0 && CharWidth(screen, value) > 0) { 5060 xtermParseRect(xw, ParamPair(1), &myRect); 5061 ScrnFillRectangle(xw, &myRect, value, xw->flags, True); 5062 } 5063 } 5064 ResetState(sp); 5065 break; 5066 5067 case CASE_DECSERA: 5068 if (screen->vtXX_level >= 4) { 5069 TRACE(("CASE_DECSERA - Selective erase rectangular area\n")); 5070 xtermParseRect(xw, ParamPair(0), &myRect); 5071 ScrnWipeRectangle(xw, &myRect); 5072 } 5073 ResetState(sp); 5074 break; 5075 5076 case CASE_DECSACE: 5077 TRACE(("CASE_DECSACE - Select attribute change extent\n")); 5078 screen->cur_decsace = zero_if_default(0); 5079 ResetState(sp); 5080 break; 5081 5082 case CASE_DECCARA: 5083 if (screen->vtXX_level >= 4) { 5084 TRACE(("CASE_DECCARA - Change attributes in rectangular area\n")); 5085 xtermParseRect(xw, ParamPair(0), &myRect); 5086 ScrnMarkRectangle(xw, &myRect, False, ParamPair(4)); 5087 } 5088 ResetState(sp); 5089 break; 5090 5091 case CASE_DECRARA: 5092 if (screen->vtXX_level >= 4) { 5093 TRACE(("CASE_DECRARA - Reverse attributes in rectangular area\n")); 5094 xtermParseRect(xw, ParamPair(0), &myRect); 5095 ScrnMarkRectangle(xw, &myRect, True, ParamPair(4)); 5096 } 5097 ResetState(sp); 5098 break; 5099 5100 case CASE_DECSCPP: 5101 if (screen->vtXX_level >= 3) { 5102 TRACE(("CASE_DECSCPP\n")); 5103 /* default and 0 are "80", with "132" as the other legal choice */ 5104 switch (zero_if_default(0)) { 5105 case 0: 5106 case 80: 5107 value = 80; 5108 break; 5109 case 132: 5110 value = 132; 5111 break; 5112 default: 5113 value = -1; 5114 break; 5115 } 5116 if (value > 0) { 5117 if (screen->cur_col + 1 > value) 5118 CursorSet(screen, screen->cur_row, value - 1, xw->flags); 5119 UIntClr(xw->flags, IN132COLUMNS); 5120 if (value == 132) 5121 UIntSet(xw->flags, IN132COLUMNS); 5122 RequestResize(xw, -1, value, True); 5123 } 5124 } 5125 ResetState(sp); 5126 break; 5127 5128 case CASE_DECSNLS: 5129 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetWinLines)) { 5130 TRACE(("CASE_DECSNLS\n")); 5131 value = zero_if_default(0); 5132 if (value >= 1 && value <= 255) { 5133 RequestResize(xw, value, -1, True); 5134 } 5135 } 5136 ResetState(sp); 5137 break; 5138 5139 case CASE_DECRQPSR: 5140#define reply_char(n,c) do { reply.a_radix[(n)] = 1; reply.a_param[(n)++] = (ParmType)(c); } while (0) 5141#define reply_bit(n,c) ((n) ? (c) : 0) 5142 if (screen->vtXX_level >= 3) { 5143 TRACE(("CASE_DECRQPSR\n")); 5144 switch (GetParam(0)) { 5145 case 1: 5146 TRACE(("...DECCIR\n")); 5147 init_reply(ANSI_DCS); 5148 count = 0; 5149 reply_char(count, '1'); 5150 reply_char(count, '$'); 5151 reply_char(count, 'u'); 5152 reply.a_param[count++] = (ParmType) (screen->cur_row + 1); 5153 reply.a_param[count++] = (ParmType) (screen->cur_col + 1); 5154 reply.a_param[count++] = (ParmType) thispage; 5155 reply_char(count, ';'); 5156 reply_char(count, (0x40 5157 | reply_bit(xw->flags & INVERSE, 8) 5158 | reply_bit(xw->flags & BLINK, 4) 5159 | reply_bit(xw->flags & UNDERLINE, 2) 5160 | reply_bit(xw->flags & BOLD, 1) 5161 )); 5162 reply_char(count, ';'); 5163 reply_char(count, 0x40 | 5164 reply_bit(screen->protected_mode & 5165 DEC_PROTECT, 1) 5166 ); 5167 reply_char(count, ';'); 5168 reply_char(count, (0x40 5169 | reply_bit(screen->do_wrap, 8) 5170 | reply_bit((screen->curss == 3), 4) 5171 | reply_bit((screen->curss == 2), 2) 5172 | reply_bit(xw->flags & ORIGIN, 1) 5173 )); 5174 reply_char(count, ';'); 5175 reply.a_param[count++] = screen->curgl; 5176 reply.a_param[count++] = screen->curgr; 5177 reply_char(count, ';'); 5178 reply_char(count, 0x4f); /* assert all 96's */ 5179 reply_char(count, ';'); 5180 for (item = 0; item < NUM_GSETS; ++item) { 5181 char *temp = encode_scs(screen->gsets[item]); 5182 while (*temp != '\0') { 5183 reply_char(count, *temp++); 5184 } 5185 } 5186 reply.a_nparam = (ParmType) count; 5187 unparseseq(xw, &reply); 5188 break; 5189 case 2: 5190 TRACE(("...DECTABSR\n")); 5191 init_reply(ANSI_DCS); 5192 reply.a_delim = "/"; 5193 count = 0; 5194 reply_char(count, '2'); 5195 reply_char(count, '$'); 5196 reply_char(count, 'u'); 5197 for (item = 0; item < MAX_TABS; ++item) { 5198 if (count + 1 >= NPARAM) 5199 break; 5200 if (TabIsSet(xw->tabs, item)) { 5201 reply.a_param[count++] = (ParmType) (item + 1); 5202 } 5203 if (item > screen->max_col) 5204 break; 5205 } 5206 reply.a_nparam = (ParmType) count; 5207 unparseseq(xw, &reply); 5208 break; 5209 } 5210 } 5211 ResetState(sp); 5212 break; 5213 5214 case CASE_RQM: 5215 TRACE(("CASE_RQM\n")); 5216 do_ansi_rqm(xw, ParamPair(0)); 5217 ResetState(sp); 5218 break; 5219 5220 case CASE_DECRQM: 5221 TRACE(("CASE_DECRQM\n")); 5222 do_dec_rqm(xw, ParamPair(0)); 5223 ResetState(sp); 5224 break; 5225 5226 case CASE_CSI_DEC_DOLLAR_STATE: 5227 TRACE(("CASE_CSI_DEC_DOLLAR_STATE\n")); 5228 /* csi ? dollar ($) */ 5229 sp->parsestate = csi_dec_dollar_table; 5230 break; 5231#else 5232 case CASE_CSI_DOLLAR_STATE: 5233 /* csi dollar ($) */ 5234 sp->parsestate = eigtable; 5235 break; 5236 5237 case CASE_CSI_STAR_STATE: 5238 /* csi dollar (*) */ 5239 sp->parsestate = eigtable; 5240 break; 5241 5242 case CASE_CSI_DEC_DOLLAR_STATE: 5243 /* csi ? dollar ($) */ 5244 sp->parsestate = eigtable; 5245 break; 5246#endif /* OPT_DEC_RECTOPS */ 5247 5248 case CASE_DECSASD: 5249#if OPT_STATUS_LINE 5250 if (screen->vtXX_level >= 2) { 5251 handle_DECSASD(xw, zero_if_default(0)); 5252 } 5253#endif 5254 ResetState(sp); 5255 break; 5256 5257 case CASE_DECSSDT: 5258#if OPT_STATUS_LINE 5259 if (screen->vtXX_level >= 2) { 5260 handle_DECSSDT(xw, zero_if_default(0)); 5261 } 5262#endif 5263 ResetState(sp); 5264 break; 5265 5266#if OPT_XTERM_SGR 5267 case CASE_CSI_HASH_STATE: 5268 TRACE(("CASE_CSI_HASH_STATE\n")); 5269 /* csi hash (#) */ 5270 sp->parsestate = csi_hash_table; 5271 break; 5272 5273 case CASE_XTERM_CHECKSUM: 5274#if OPT_DEC_RECTOPS 5275 if (screen->vtXX_level >= 4 && AllowWindowOps(xw, ewSetChecksum)) { 5276 TRACE(("CASE_XTERM_CHECKSUM\n")); 5277 screen->checksum_ext = zero_if_default(0); 5278 } 5279#endif 5280 ResetState(sp); 5281 break; 5282 5283 case CASE_XTERM_PUSH_SGR: 5284 TRACE(("CASE_XTERM_PUSH_SGR\n")); 5285 value = 0; 5286 if (nparam == 0 || (nparam == 1 && GetParam(0) == DEFAULT)) { 5287 value = DEFAULT; 5288 } else if (nparam > 0) { 5289 for (count = 0; count < nparam; ++count) { 5290 item = zero_if_default(count); 5291 /* deprecated - for compatibility */ 5292#if OPT_ISO_COLORS 5293 if (item == psFG_COLOR_obs) { 5294 item = psFG_COLOR; 5295 } else if (item == psBG_COLOR_obs) { 5296 item = psBG_COLOR; 5297 } 5298#endif 5299 if (item > 0 && item < MAX_PUSH_SGR) { 5300 value |= (1 << (item - 1)); 5301 } 5302 } 5303 } 5304 xtermPushSGR(xw, value); 5305 ResetState(sp); 5306 break; 5307 5308 case CASE_XTERM_REPORT_SGR: 5309 TRACE(("CASE_XTERM_REPORT_SGR\n")); 5310 xtermParseRect(xw, ParamPair(0), &myRect); 5311 xtermReportSGR(xw, &myRect); 5312 ResetState(sp); 5313 break; 5314 5315 case CASE_XTERM_POP_SGR: 5316 TRACE(("CASE_XTERM_POP_SGR\n")); 5317 xtermPopSGR(xw); 5318 ResetState(sp); 5319 break; 5320 5321 case CASE_XTERM_PUSH_COLORS: 5322 TRACE(("CASE_XTERM_PUSH_COLORS\n")); 5323 if (nparam == 0) { 5324 xtermPushColors(xw, DEFAULT); 5325 } else { 5326 for (count = 0; count < nparam; ++count) { 5327 xtermPushColors(xw, GetParam(count)); 5328 } 5329 } 5330 ResetState(sp); 5331 break; 5332 5333 case CASE_XTERM_POP_COLORS: 5334 TRACE(("CASE_XTERM_POP_COLORS\n")); 5335 if (nparam == 0) { 5336 xtermPopColors(xw, DEFAULT); 5337 } else { 5338 for (count = 0; count < nparam; ++count) { 5339 xtermPopColors(xw, GetParam(count)); 5340 } 5341 } 5342 ResetState(sp); 5343 break; 5344 5345 case CASE_XTERM_REPORT_COLORS: 5346 TRACE(("CASE_XTERM_REPORT_COLORS\n")); 5347 xtermReportColors(xw); 5348 ResetState(sp); 5349 break; 5350#endif 5351 5352 case CASE_S7C1T: 5353 TRACE(("CASE_S7C1T\n")); 5354 if (screen->vtXX_level >= 2) { 5355 show_8bit_control(False); 5356 ResetState(sp); 5357 } 5358 break; 5359 5360 case CASE_S8C1T: 5361 TRACE(("CASE_S8C1T\n")); 5362 if (screen->vtXX_level >= 2) { 5363 show_8bit_control(True); 5364 ResetState(sp); 5365 } 5366 break; 5367 5368 case CASE_OSC: 5369 TRACE(("CASE_OSC: Operating System Command\n")); 5370 sp->parsestate = sos_table; 5371 sp->string_mode = ANSI_OSC; 5372 break; 5373 5374 case CASE_RIS: 5375 TRACE(("CASE_RIS\n")); 5376 VTReset(xw, True, True); 5377 /* NOTREACHED */ 5378 5379 case CASE_DECSTR: 5380 TRACE(("CASE_DECSTR\n")); 5381 VTReset(xw, False, False); 5382 /* NOTREACHED */ 5383 5384 case CASE_REP: 5385 TRACE(("CASE_REP\n")); 5386 if (CharWidth(screen, sp->lastchar) > 0) { 5387 IChar repeated[2]; 5388 count = one_if_default(0); 5389 repeated[0] = (IChar) sp->lastchar; 5390 while (count-- > 0) { 5391 dotext(xw, 5392 screen->gsets[(int) (screen->curgl)], 5393 repeated, 1); 5394 } 5395 } 5396 ResetState(sp); 5397 break; 5398 5399 case CASE_LS2: 5400 TRACE(("CASE_LS2\n")); 5401 screen->curgl = 2; 5402 ResetState(sp); 5403 break; 5404 5405 case CASE_LS3: 5406 TRACE(("CASE_LS3\n")); 5407 screen->curgl = 3; 5408 ResetState(sp); 5409 break; 5410 5411 case CASE_LS3R: 5412 TRACE(("CASE_LS3R\n")); 5413 screen->curgr = 3; 5414 ResetState(sp); 5415 break; 5416 5417 case CASE_LS2R: 5418 TRACE(("CASE_LS2R\n")); 5419 screen->curgr = 2; 5420 ResetState(sp); 5421 break; 5422 5423 case CASE_LS1R: 5424 TRACE(("CASE_LS1R\n")); 5425 screen->curgr = 1; 5426 ResetState(sp); 5427 break; 5428 5429 case CASE_XTERM_SAVE: 5430 savemodes(xw); 5431 ResetState(sp); 5432 break; 5433 5434 case CASE_XTERM_RESTORE: 5435 restoremodes(xw); 5436 ResetState(sp); 5437 break; 5438 5439 case CASE_XTERM_WINOPS: 5440 TRACE(("CASE_XTERM_WINOPS\n")); 5441 window_ops(xw); 5442 ResetState(sp); 5443 break; 5444#if OPT_WIDE_CHARS 5445 case CASE_ESC_PERCENT: 5446 TRACE(("CASE_ESC_PERCENT\n")); 5447 sp->parsestate = esc_pct_table; 5448 break; 5449 5450 case CASE_UTF8: 5451 /* If we did not set UTF-8 mode from resource or the 5452 * command-line, allow it to be enabled/disabled by 5453 * control sequence. 5454 */ 5455 TRACE(("CASE_UTF8 wide:%d, utf8:%d, req:%s\n", 5456 screen->wide_chars, 5457 screen->utf8_mode, 5458 BtoS(c == 'G'))); 5459 if ((!screen->wide_chars) && (c == 'G')) { 5460 WriteNow(); 5461 ChangeToWide(xw); 5462 } 5463 if (screen->wide_chars 5464 && !screen->utf8_always) { 5465 switchPtyData(screen, c == 'G'); 5466 TRACE(("UTF8 mode %s\n", 5467 BtoS(screen->utf8_mode))); 5468 } else { 5469 TRACE(("UTF8 mode NOT turned %s (%s)\n", 5470 BtoS(c == 'G'), 5471 (screen->utf8_mode == uAlways) 5472 ? "UTF-8 mode set from command-line" 5473 : "wideChars resource was not set")); 5474 } 5475 ResetState(sp); 5476 break; 5477 5478 case CASE_SCS_DQUOTE: 5479 TRACE(("CASE_SCS_DQUOTE\n")); 5480 sp->parsestate = scs_2qt_table; 5481 break; 5482 5483 case CASE_GSETS_DQUOTE: 5484 if (screen->vtXX_level >= 5) { 5485 TRACE(("CASE_GSETS_DQUOTE(%d) = '%c'\n", sp->scstype, c)); 5486 xtermDecodeSCS(xw, sp->scstype, 5, '"', (int) c); 5487 } 5488 ResetState(sp); 5489 break; 5490 5491 case CASE_SCS_AMPRSND: 5492 TRACE(("CASE_SCS_AMPRSND\n")); 5493 sp->parsestate = scs_amp_table; 5494 break; 5495 5496 case CASE_GSETS_AMPRSND: 5497 if (screen->vtXX_level >= 5) { 5498 TRACE(("CASE_GSETS_AMPRSND(%d) = '%c'\n", sp->scstype, c)); 5499 xtermDecodeSCS(xw, sp->scstype, 5, '&', (int) c); 5500 } 5501 ResetState(sp); 5502 break; 5503 5504 case CASE_SCS_PERCENT: 5505 TRACE(("CASE_SCS_PERCENT\n")); 5506 sp->parsestate = scs_pct_table; 5507 break; 5508 5509 case CASE_GSETS_PERCENT: 5510 if (screen->vtXX_level >= 3) { 5511 TRACE(("CASE_GSETS_PERCENT(%d) = '%c'\n", sp->scstype, c)); 5512 switch (c) { 5513 case '0': /* DEC Turkish */ 5514 case '2': /* Turkish */ 5515 case '=': /* Hebrew */ 5516 value = 5; 5517 break; 5518 case '5': /* DEC Supplemental Graphics */ 5519 case '6': /* Portuguese */ 5520 default: 5521 value = 3; 5522 break; 5523 } 5524 xtermDecodeSCS(xw, sp->scstype, value, '%', (int) c); 5525 } 5526 ResetState(sp); 5527 break; 5528#endif 5529 case CASE_XTERM_SHIFT_ESCAPE: 5530 TRACE(("CASE_XTERM_SHIFT_ESCAPE\n")); 5531 value = ((nparam == 0) 5532 ? 0 5533 : one_if_default(0)); 5534 if (value >= 0 && value <= 1) 5535 xw->keyboard.shift_escape = value; 5536 ResetState(sp); 5537 break; 5538 5539#if OPT_MOD_FKEYS 5540 case CASE_SET_MOD_FKEYS: 5541 TRACE(("CASE_SET_MOD_FKEYS\n")); 5542 if (nparam >= 1) { 5543 set_mod_fkeys(xw, 5544 GetParam(0), 5545 ((nparam > 1) 5546 ? GetParam(1) 5547 : DEFAULT), 5548 True); 5549 } else { 5550 for (value = 1; value <= 5; ++value) 5551 set_mod_fkeys(xw, value, DEFAULT, True); 5552 } 5553 ResetState(sp); 5554 break; 5555 5556 case CASE_SET_MOD_FKEYS0: 5557 TRACE(("CASE_SET_MOD_FKEYS0\n")); 5558 if (nparam >= 1 && GetParam(0) != DEFAULT) { 5559 set_mod_fkeys(xw, GetParam(0), -1, False); 5560 } else { 5561 xw->keyboard.modify_now.function_keys = -1; 5562 } 5563 ResetState(sp); 5564 break; 5565#endif 5566 case CASE_HIDE_POINTER: 5567 TRACE(("CASE_HIDE_POINTER\n")); 5568 if (nparam >= 1 && GetParam(0) != DEFAULT) { 5569 screen->pointer_mode = GetParam(0); 5570 } else { 5571 screen->pointer_mode = DEF_POINTER_MODE; 5572 } 5573 ResetState(sp); 5574 break; 5575 5576 case CASE_XTERM_SM_TITLE: 5577 TRACE(("CASE_XTERM_SM_TITLE\n")); 5578 if (nparam >= 1) { 5579 int n; 5580 for (n = 0; n < nparam; ++n) { 5581 if (GetParam(n) != DEFAULT) 5582 screen->title_modes |= (1 << GetParam(n)); 5583 } 5584 } else { 5585 screen->title_modes = DEF_TITLE_MODES; 5586 } 5587 TRACE(("...title_modes %#x\n", screen->title_modes)); 5588 ResetState(sp); 5589 break; 5590 5591 case CASE_XTERM_RM_TITLE: 5592 TRACE(("CASE_XTERM_RM_TITLE\n")); 5593 if (nparam >= 1) { 5594 int n; 5595 for (n = 0; n < nparam; ++n) { 5596 if (GetParam(n) != DEFAULT) 5597 screen->title_modes &= ~(1 << GetParam(n)); 5598 } 5599 } else { 5600 screen->title_modes = DEF_TITLE_MODES; 5601 } 5602 TRACE(("...title_modes %#x\n", screen->title_modes)); 5603 ResetState(sp); 5604 break; 5605 5606 case CASE_CSI_IGNORE: 5607 sp->parsestate = cigtable; 5608 break; 5609 5610 case CASE_DECSWBV: 5611 TRACE(("CASE_DECSWBV\n")); 5612 switch (zero_if_default(0)) { 5613 case 2: 5614 /* FALLTHRU */ 5615 case 3: 5616 /* FALLTHRU */ 5617 case 4: 5618 screen->warningVolume = bvLow; 5619 break; 5620 case 5: 5621 /* FALLTHRU */ 5622 case 6: 5623 /* FALLTHRU */ 5624 case 7: 5625 /* FALLTHRU */ 5626 case 8: 5627 screen->warningVolume = bvHigh; 5628 break; 5629 default: 5630 screen->warningVolume = bvOff; 5631 break; 5632 } 5633 TRACE(("...warningVolume %d\n", screen->warningVolume)); 5634 ResetState(sp); 5635 break; 5636 5637 case CASE_DECSMBV: 5638 TRACE(("CASE_DECSMBV\n")); 5639 switch (zero_if_default(0)) { 5640 case 2: 5641 /* FALLTHRU */ 5642 case 3: 5643 /* FALLTHRU */ 5644 case 4: 5645 screen->marginVolume = bvLow; 5646 break; 5647 case 0: 5648 /* FALLTHRU */ 5649 case 5: 5650 /* FALLTHRU */ 5651 case 6: 5652 /* FALLTHRU */ 5653 case 7: 5654 /* FALLTHRU */ 5655 case 8: 5656 screen->marginVolume = bvHigh; 5657 break; 5658 default: 5659 screen->marginVolume = bvOff; 5660 break; 5661 } 5662 TRACE(("...marginVolume %d\n", screen->marginVolume)); 5663 ResetState(sp); 5664 break; 5665 } 5666 if (sp->parsestate == sp->groundtable) 5667 sp->lastchar = thischar; 5668 } while (0); 5669 5670#if OPT_WIDE_CHARS 5671 screen->utf8_inparse = (Boolean) ((screen->utf8_mode != uFalse) 5672 && (sp->parsestate != sos_table)); 5673#endif 5674 5675 if (sp->check_recur) 5676 sp->check_recur--; 5677 return True; 5678} 5679 5680static void 5681VTparse(XtermWidget xw) 5682{ 5683 Boolean keep_running; 5684 5685 /* We longjmp back to this point in VTReset() */ 5686 (void) setjmp(vtjmpbuf); 5687 init_parser(xw, &myState); 5688 5689 do { 5690 keep_running = doparsing(xw, doinput(xw), &myState); 5691 if (myState.check_recur == 0 && myState.defer_used != 0) { 5692 while (myState.defer_used) { 5693 Char *deferred = myState.defer_area; 5694 size_t len = myState.defer_used; 5695 size_t i; 5696 myState.defer_area = NULL; 5697 myState.defer_size = 0; 5698 myState.defer_used = 0; 5699 for (i = 0; i < len; i++) { 5700 (void) doparsing(xw, deferred[i], &myState); 5701 } 5702 free(deferred); 5703 } 5704 } else { 5705 free(myState.defer_area); 5706 } 5707 myState.defer_area = NULL; 5708 myState.defer_size = 0; 5709 myState.defer_used = 0; 5710 } while (keep_running); 5711} 5712 5713static Char *v_buffer; /* pointer to physical buffer */ 5714static Char *v_bufstr = NULL; /* beginning of area to write */ 5715static Char *v_bufptr; /* end of area to write */ 5716static Char *v_bufend; /* end of physical buffer */ 5717 5718/* Write data to the pty as typed by the user, pasted with the mouse, 5719 or generated by us in response to a query ESC sequence. */ 5720 5721void 5722v_write(int f, const Char *data, unsigned len) 5723{ 5724 TRACE2(("v_write(%d:%s)\n", len, visibleChars(data, len))); 5725 if (v_bufstr == NULL) { 5726 if (len > 0) { 5727 v_buffer = (Char *) XtMalloc((Cardinal) len); 5728 v_bufstr = v_buffer; 5729 v_bufptr = v_buffer; 5730 v_bufend = v_buffer + len; 5731 } 5732 if (v_bufstr == NULL) { 5733 return; 5734 } 5735 } 5736 if_DEBUG({ 5737 fprintf(stderr, "v_write called with %u bytes (%ld left over)", 5738 len, (long) (v_bufptr - v_bufstr)); 5739 if (len > 1 && len < 10) 5740 fprintf(stderr, " \"%.*s\"", len, (const char *) data); 5741 fprintf(stderr, "\n"); 5742 }); 5743 5744#ifdef VMS 5745 if ((1 << f) != pty_mask) { 5746 tt_write((const char *) data, len); 5747 return; 5748 } 5749#else /* VMS */ 5750 if (!FD_ISSET(f, &pty_mask)) { 5751 IGNORE_RC(write(f, (const char *) data, (size_t) len)); 5752 return; 5753 } 5754#endif /* VMS */ 5755 5756 /* 5757 * Append to the block we already have. 5758 * Always doing this simplifies the code, and 5759 * isn't too bad, either. If this is a short 5760 * block, it isn't too expensive, and if this is 5761 * a long block, we won't be able to write it all 5762 * anyway. 5763 */ 5764 5765 if (len > 0) { 5766#if OPT_DABBREV 5767 TScreenOf(term)->dabbrev_working = False; /* break dabbrev sequence */ 5768#endif 5769 if (v_bufend < v_bufptr + len) { /* we've run out of room */ 5770 if (v_bufstr != v_buffer) { 5771 /* there is unused space, move everything down */ 5772 /* possibly overlapping memmove here */ 5773 if_DEBUG({ 5774 fprintf(stderr, "moving data down %ld\n", 5775 (long) (v_bufstr - v_buffer)); 5776 }); 5777 memmove(v_buffer, v_bufstr, (size_t) (v_bufptr - v_bufstr)); 5778 v_bufptr -= v_bufstr - v_buffer; 5779 v_bufstr = v_buffer; 5780 } 5781 if (v_bufend < v_bufptr + len) { 5782 /* still won't fit: get more space */ 5783 /* Don't use XtRealloc because an error is not fatal. */ 5784 unsigned size = (unsigned) (v_bufptr - v_buffer); 5785 v_buffer = TypeRealloc(Char, size + len, v_buffer); 5786 if (v_buffer) { 5787 if_DEBUG({ 5788 fprintf(stderr, "expanded buffer to %u\n", 5789 size + len); 5790 }); 5791 v_bufstr = v_buffer; 5792 v_bufptr = v_buffer + size; 5793 v_bufend = v_bufptr + len; 5794 } else { 5795 /* no memory: ignore entire write request */ 5796 xtermWarning("cannot allocate buffer space\n"); 5797 v_buffer = v_bufstr; /* restore clobbered pointer */ 5798 } 5799 } 5800 } 5801 if (v_bufend >= v_bufptr + len) { 5802 /* new stuff will fit */ 5803 memmove(v_bufptr, data, (size_t) len); 5804 v_bufptr += len; 5805 } 5806 } 5807 5808 /* 5809 * Write out as much of the buffer as we can. 5810 * Be careful not to overflow the pty's input silo. 5811 * We are conservative here and only write 5812 * a small amount at a time. 5813 * 5814 * If we can't push all the data into the pty yet, we expect write 5815 * to return a non-negative number less than the length requested 5816 * (if some data written) or -1 and set errno to EAGAIN, 5817 * EWOULDBLOCK, or EINTR (if no data written). 5818 * 5819 * (Not all systems do this, sigh, so the code is actually 5820 * a little more forgiving.) 5821 */ 5822 5823#define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */ 5824 5825 if (v_bufptr > v_bufstr) { 5826 int riten; 5827 5828#ifdef VMS 5829 riten = tt_write(v_bufstr, 5830 ((v_bufptr - v_bufstr <= VMS_TERM_BUFFER_SIZE) 5831 ? v_bufptr - v_bufstr 5832 : VMS_TERM_BUFFER_SIZE)); 5833 if (riten == 0) 5834 return (riten); 5835#else /* VMS */ 5836 riten = (int) write(f, v_bufstr, 5837 (size_t) ((v_bufptr - v_bufstr <= MAX_PTY_WRITE) 5838 ? v_bufptr - v_bufstr 5839 : MAX_PTY_WRITE)); 5840 if (riten < 0) 5841#endif /* VMS */ 5842 { 5843 if_DEBUG({ 5844 perror("write"); 5845 }); 5846 riten = 0; 5847 } 5848 if_DEBUG({ 5849 fprintf(stderr, "write called with %ld, wrote %d\n", 5850 ((long) ((v_bufptr - v_bufstr) <= MAX_PTY_WRITE) 5851 ? (long) (v_bufptr - v_bufstr) 5852 : MAX_PTY_WRITE), 5853 riten); 5854 }); 5855 v_bufstr += riten; 5856 if (v_bufstr >= v_bufptr) /* we wrote it all */ 5857 v_bufstr = v_bufptr = v_buffer; 5858 } 5859 5860 /* 5861 * If we have lots of unused memory allocated, return it 5862 */ 5863 if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */ 5864 /* save pointers across realloc */ 5865 int start = (int) (v_bufstr - v_buffer); 5866 int size = (int) (v_bufptr - v_buffer); 5867 unsigned allocsize = (unsigned) (size ? size : 1); 5868 5869 v_buffer = TypeRealloc(Char, allocsize, v_buffer); 5870 if (v_buffer) { 5871 v_bufstr = v_buffer + start; 5872 v_bufptr = v_buffer + size; 5873 v_bufend = v_buffer + allocsize; 5874 if_DEBUG({ 5875 fprintf(stderr, "shrunk buffer to %u\n", allocsize); 5876 }); 5877 } else { 5878 /* should we print a warning if couldn't return memory? */ 5879 v_buffer = v_bufstr - start; /* restore clobbered pointer */ 5880 } 5881 } 5882} 5883 5884static void 5885updateCursor(XtermWidget xw) 5886{ 5887 TScreen *screen = TScreenOf(xw); 5888 5889 if (screen->cursor_set != screen->cursor_state) { 5890 if (screen->cursor_set) 5891 ShowCursor(xw); 5892 else 5893 HideCursor(xw); 5894 } 5895} 5896 5897#if OPT_BLINK_CURS || OPT_BLINK_TEXT 5898static void 5899reallyStopBlinking(XtermWidget xw) 5900{ 5901 TScreen *screen = TScreenOf(xw); 5902 5903 if (screen->cursor_state == BLINKED_OFF) { 5904 /* force cursor to display if it is enabled */ 5905 screen->cursor_state = !screen->cursor_set; 5906 updateCursor(xw); 5907 xevents(xw); 5908 } 5909} 5910#endif 5911 5912static void 5913update_the_screen(XtermWidget xw) 5914{ 5915 TScreen *screen = TScreenOf(xw); 5916 Boolean moved; 5917 5918 if (screen->scroll_amt) 5919 FlushScroll(xw); 5920 moved = CursorMoved(screen); 5921 if (screen->cursor_set && moved) { 5922 if (screen->cursor_state) 5923 HideCursor(xw); 5924 ShowCursor(xw); 5925#if OPT_INPUT_METHOD 5926 PreeditPosition(xw); 5927#endif 5928 } else { 5929#if OPT_INPUT_METHOD 5930 if (moved) 5931 PreeditPosition(xw); 5932#endif 5933 updateCursor(xw); 5934 } 5935} 5936 5937#ifdef VMS 5938#define ptymask() (v_bufptr > v_bufstr ? pty_mask : 0) 5939 5940static void 5941in_put(XtermWidget xw) 5942{ 5943 static PtySelect select_mask; 5944 static PtySelect write_mask; 5945 int update = VTbuffer->update; 5946 int size; 5947 5948 int status; 5949 Dimension replyWidth, replyHeight; 5950 XtGeometryResult stat; 5951 5952 TScreen *screen = TScreenOf(xw); 5953 char *cp; 5954 int i; 5955 5956 select_mask = pty_mask; /* force initial read */ 5957 for (;;) { 5958 5959 /* if the terminal changed size, resize the widget */ 5960 if (tt_changed) { 5961 tt_changed = False; 5962 5963 stat = REQ_RESIZE((Widget) xw, 5964 ((Dimension) FontWidth(screen) 5965 * (tt_width) 5966 + 2 * screen->border 5967 + screen->fullVwin.sb_info.width), 5968 ((Dimension) FontHeight(screen) 5969 * (tt_length) 5970 + 2 * screen->border), 5971 &replyWidth, &replyHeight); 5972 5973 if (stat == XtGeometryYes || stat == XtGeometryDone) { 5974 xw->core.width = replyWidth; 5975 xw->core.height = replyHeight; 5976 5977 ScreenResize(xw, replyWidth, replyHeight, &xw->flags); 5978 } 5979 repairSizeHints(); 5980 } 5981 5982 if (screen->eventMode == NORMAL 5983 && readPtyData(xw, &select_mask, VTbuffer)) { 5984 if (screen->scrollWidget 5985 && screen->scrollttyoutput 5986 && screen->topline < 0) 5987 /* Scroll to bottom */ 5988 WindowScroll(xw, 0, False); 5989 break; 5990 } 5991 update_the_screen(xw); 5992 5993 if (QLength(screen->display)) { 5994 select_mask = X_mask; 5995 } else { 5996 write_mask = ptymask(); 5997 XFlush(screen->display); 5998 select_mask = Select_mask; 5999 if (screen->eventMode != NORMAL) 6000 select_mask = X_mask; 6001 } 6002 if (write_mask & ptymask()) { 6003 v_write(screen->respond, 0, 0); /* flush buffer */ 6004 } 6005 6006 if (select_mask & X_mask) { 6007 xevents(xw); 6008 if (VTbuffer->update != update) 6009 break; 6010 } 6011 } 6012} 6013#else /* VMS */ 6014 6015static void 6016init_timeval(struct timeval *target, long usecs) 6017{ 6018 target->tv_sec = 0; 6019 target->tv_usec = usecs; 6020 while (target->tv_usec > 1000000) { 6021 target->tv_usec -= 1000000; 6022 target->tv_sec++; 6023 } 6024} 6025 6026static Boolean 6027better_timeout(struct timeval *check, struct timeval *against) 6028{ 6029 Boolean result = False; 6030 if (against->tv_sec == 0 && against->tv_usec == 0) { 6031 result = True; 6032 } else if (check->tv_sec == against->tv_sec) { 6033 if (check->tv_usec < against->tv_usec) { 6034 result = True; 6035 } 6036 } else if (check->tv_sec < against->tv_sec) { 6037 result = True; 6038 } 6039 return result; 6040} 6041 6042#if OPT_BLINK_CURS 6043static long 6044smaller_timeout(long value) 6045{ 6046 /* 1000 for msec/usec, 8 for "much" smaller */ 6047 value *= (1000 / 8); 6048 if (value < 1) 6049 value = 1; 6050 return value; 6051} 6052#endif 6053 6054static void 6055in_put(XtermWidget xw) 6056{ 6057 static PtySelect select_mask; 6058 static PtySelect write_mask; 6059 6060 TScreen *screen = TScreenOf(xw); 6061 int i; 6062 int update = VTbuffer->update; 6063#if USE_DOUBLE_BUFFER 6064 int should_wait = 1; 6065#endif 6066 struct timeval my_timeout; 6067 6068 for (;;) { 6069 int size; 6070 int time_select; 6071 6072 if (screen->eventMode == NORMAL 6073 && (size = readPtyData(xw, &select_mask, VTbuffer)) != 0) { 6074 if (screen->scrollWidget 6075 && screen->scrollttyoutput 6076 && screen->topline < 0) 6077 WindowScroll(xw, 0, False); /* Scroll to bottom */ 6078 /* stop speed reading at some point to look for X stuff */ 6079 TRACE(("VTbuffer uses %ld/%d\n", 6080 (long) (VTbuffer->last - VTbuffer->buffer), 6081 BUF_SIZE)); 6082 if ((VTbuffer->last - VTbuffer->buffer) > BUF_SIZE) { 6083 FD_CLR(screen->respond, &select_mask); 6084 break; 6085 } 6086#if USE_DOUBLE_BUFFER 6087 if (resource.buffered && should_wait) { 6088 /* wait for potential extra data (avoids some flickering) */ 6089 usleep((unsigned) DbeMsecs(xw)); 6090 should_wait = 0; 6091 } 6092#endif 6093#if defined(HAVE_SCHED_YIELD) 6094 /* 6095 * If we've read a full (small/fragment) buffer, let the operating 6096 * system have a turn, and we'll resume reading until we've either 6097 * read only a fragment of the buffer, or we've filled the large 6098 * buffer (see above). Doing this helps keep up with large bursts 6099 * of output. 6100 */ 6101 if (size == FRG_SIZE) { 6102 init_timeval(&my_timeout, 0); 6103 i = Select(max_plus1, &select_mask, &write_mask, 0, &my_timeout); 6104 if (i > 0 && FD_ISSET(screen->respond, &select_mask)) { 6105 sched_yield(); 6106 } else 6107 break; 6108 } else { 6109 break; 6110 } 6111#else 6112 (void) size; /* unused in this branch */ 6113 break; 6114#endif 6115 } 6116 update_the_screen(xw); 6117 6118 XFlush(screen->display); /* always flush writes before waiting */ 6119 6120 /* Update the masks and, unless X events are already in the queue, 6121 wait for I/O to be possible. */ 6122 XFD_COPYSET(&Select_mask, &select_mask); 6123 /* in selection mode xterm does not read pty */ 6124 if (screen->eventMode != NORMAL) 6125 FD_CLR(screen->respond, &select_mask); 6126 6127 if (v_bufptr > v_bufstr) { 6128 XFD_COPYSET(&pty_mask, &write_mask); 6129 } else 6130 FD_ZERO(&write_mask); 6131 init_timeval(&my_timeout, 0); 6132 time_select = 0; 6133 6134 /* 6135 * if there's either an XEvent or an XtTimeout pending, just take 6136 * a quick peek, i.e. timeout from the select() immediately. If 6137 * there's nothing pending, let select() block a little while, but 6138 * for a shorter interval than the arrow-style scrollbar timeout. 6139 * The blocking is optional, because it tends to increase the load 6140 * on the host. 6141 */ 6142 if (xtermAppPending()) { 6143 time_select = 1; 6144 } else { 6145#define ImproveTimeout(usecs) \ 6146 struct timeval try_timeout; \ 6147 init_timeval(&try_timeout, usecs); \ 6148 if (better_timeout(&try_timeout, &my_timeout)) { \ 6149 my_timeout = try_timeout; \ 6150 } 6151#if OPT_STATUS_LINE 6152 if ((screen->status_type == 1) && screen->status_timeout) { 6153 ImproveTimeout(find_SL_Timeout(xw) * 1000); 6154 time_select = 1; 6155 } 6156#endif 6157 if (screen->awaitInput) { 6158 ImproveTimeout(50000); 6159 time_select = 1; 6160 } 6161#if OPT_BLINK_CURS 6162 if ((screen->blink_timer != 0 && 6163 ((screen->select & FOCUS) || screen->always_highlight)) || 6164 (screen->cursor_state == BLINKED_OFF)) { 6165 /* 6166 * Compute the timeout for the blinking cursor to be much 6167 * smaller than the "on" or "off" interval. 6168 */ 6169 long tick = smaller_timeout((screen->blink_on < screen->blink_off) 6170 ? screen->blink_on 6171 : screen->blink_off); 6172 ImproveTimeout(tick); 6173 time_select = 1; 6174 } 6175#endif 6176 } 6177#if OPT_SESSION_MGT 6178 if (resource.sessionMgt && (ice_fd >= 0)) { 6179 FD_SET(ice_fd, &select_mask); 6180 } 6181#endif 6182 if (need_cleanup) 6183 NormalExit(); 6184 xtermFlushDbe(xw); 6185 i = Select(max_plus1, &select_mask, &write_mask, 0, 6186 (time_select ? &my_timeout : 0)); 6187 if (i < 0) { 6188 if (errno != EINTR) 6189 SysError(ERROR_SELECT); 6190 continue; 6191 } 6192 6193 /* if there is room to write more data to the pty, go write more */ 6194 if (FD_ISSET(screen->respond, &write_mask)) { 6195 v_write(screen->respond, (Char *) 0, 0); /* flush buffer */ 6196 } 6197 6198 /* if there are X events already in our queue, it 6199 counts as being readable */ 6200 if (xtermAppPending() || 6201 FD_ISSET(ConnectionNumber(screen->display), &select_mask)) { 6202 xevents(xw); 6203 if (VTbuffer->update != update) /* HandleInterpret */ 6204 break; 6205 } 6206 6207 } 6208} 6209#endif /* VMS */ 6210 6211static IChar 6212doinput(XtermWidget xw) 6213{ 6214 TScreen *screen = TScreenOf(xw); 6215 6216 while (!morePtyData(screen, VTbuffer)) 6217 in_put(xw); 6218 return nextPtyData(screen, VTbuffer); 6219} 6220 6221#if OPT_INPUT_METHOD 6222/* 6223 * For OverTheSpot, client has to inform the position for XIM preedit. 6224 */ 6225static void 6226PreeditPosition(XtermWidget xw) 6227{ 6228 TInput *input = lookupTInput(xw, (Widget) xw); 6229 TScreen *screen = TScreenOf(xw); 6230 CLineData *ld; 6231 XPoint spot; 6232 XVaNestedList list; 6233 6234 if (input && input->xic 6235 && (ld = getLineData(screen, screen->cur_row)) != 0) { 6236 spot.x = (short) LineCursorX(screen, ld, screen->cur_col); 6237 spot.y = (short) (CursorY(screen, screen->cur_row) + xw->work.xim_fs_ascent); 6238 list = XVaCreateNestedList(0, 6239 XNSpotLocation, &spot, 6240 XNForeground, T_COLOR(screen, TEXT_FG), 6241 XNBackground, T_COLOR(screen, TEXT_BG), 6242 (void *) 0); 6243 XSetICValues(input->xic, XNPreeditAttributes, list, (void *) 0); 6244 XFree(list); 6245 } 6246} 6247#endif 6248 6249static void 6250WrapLine(XtermWidget xw) 6251{ 6252 TScreen *screen = TScreenOf(xw); 6253 LineData *ld = getLineData(screen, screen->cur_row); 6254 6255 if (ld != 0) { 6256 /* mark that we had to wrap this line */ 6257 LineSetFlag(ld, LINEWRAPPED); 6258 ShowWrapMarks(xw, screen->cur_row, ld); 6259 xtermAutoPrint(xw, '\n'); 6260 xtermIndex(xw, 1); 6261 set_cur_col(screen, ScrnLeftMargin(xw)); 6262 } 6263} 6264 6265/* 6266 * Process a string of characters according to the character set indicated by 6267 * charset. Worry about end of line conditions (wraparound if selected). 6268 * 6269 * It is possible to use CUP, etc., to move outside margins. In that case, the 6270 * right-margin is ineffective until the text (may) wrap and get within the 6271 * margins. 6272 */ 6273void 6274dotext(XtermWidget xw, 6275 DECNRCM_codes charset, 6276 IChar *buf, /* start of characters to process */ 6277 Cardinal len) /* end */ 6278{ 6279 TScreen *screen = TScreenOf(xw); 6280#if OPT_WIDE_CHARS 6281 Cardinal chars_chomped = 1; 6282 int next_col = screen->cur_col; 6283#else 6284 int next_col, this_col; /* must be signed */ 6285#endif 6286 Cardinal offset; 6287 int rmargin = ScrnRightMargin(xw); 6288 6289#if OPT_WIDE_CHARS 6290 if (screen->vt100_graphics) 6291#endif 6292 if (!(len = (Cardinal) xtermCharSetOut(xw, buf, buf + len, charset))) 6293 return; 6294 6295 if_OPT_XMC_GLITCH(screen, { 6296 Cardinal n; 6297 if (charset != '?') { 6298 for (n = 0; n < len; n++) { 6299 if (buf[n] == XMC_GLITCH) 6300 buf[n] = XMC_GLITCH + 1; 6301 } 6302 } 6303 }); 6304 6305#if OPT_WIDE_CHARS 6306 for (offset = 0; 6307 offset < len && (chars_chomped > 0 || screen->do_wrap); 6308 offset += chars_chomped) { 6309#if OPT_DEC_CHRSET 6310 CLineData *ld = getLineData(screen, screen->cur_row); 6311 int real_rmargin = (CSET_DOUBLE(GetLineDblCS(ld)) 6312 ? (rmargin / 2) 6313 : rmargin); 6314#else 6315 int real_rmargin = rmargin; 6316#endif 6317 int last_col = LineMaxCol(screen, ld); 6318 int width_here = 0; 6319 int last_chomp = 0; 6320 Boolean force_wrap; 6321 6322 chars_chomped = 0; 6323 do { 6324 int right = ((screen->cur_col > real_rmargin) 6325 ? last_col 6326 : real_rmargin); 6327 int width_available = right + 1 - screen->cur_col; 6328 Boolean need_wrap = False; 6329 Boolean did_wrap = False; 6330 6331 force_wrap = False; 6332 6333 if (screen->do_wrap) { 6334 screen->do_wrap = False; 6335 if ((xw->flags & WRAPAROUND)) { 6336 WrapLine(xw); 6337 right = ((screen->cur_col > real_rmargin) 6338 ? last_col 6339 : real_rmargin); 6340 width_available = right + 1 - screen->cur_col; 6341 next_col = screen->cur_col; 6342 did_wrap = True; 6343 } 6344 } 6345 6346 /* 6347 * This can happen with left/right margins... 6348 */ 6349 if (width_available <= 0) { 6350 break; 6351 } 6352 6353 /* 6354 * Regarding the soft-hyphen aberration, see 6355 * http://archives.miloush.net/michkap/archive/2006/09/02/736881.html 6356 */ 6357 while (width_here <= width_available 6358 && chars_chomped < (len - offset)) { 6359 Cardinal n = chars_chomped + offset; 6360 if (!screen->utf8_mode 6361 || (screen->vt100_graphics && charset == '0')) { 6362 last_chomp = 1; 6363 } else if (screen->c1_printable && 6364 buf[n] >= 0x80 && 6365 buf[n] <= 0xa0) { 6366 last_chomp = 1; 6367 } else { 6368 last_chomp = CharWidth(screen, buf[n]); 6369 if (last_chomp <= 0) { 6370 IChar ch = buf[n]; 6371 Bool eat_it = !screen->utf8_mode && (ch > 127); 6372 if (ch == 0xad) { 6373 /* 6374 * Only display soft-hyphen if it happens to be at 6375 * the right-margin. While that means that only 6376 * the displayed character could be selected for 6377 * pasting, a well-behaved application would never 6378 * send this, anyway... 6379 */ 6380 if (width_here < width_available - 1) { 6381 eat_it = True; 6382 } else { 6383 last_chomp = 1; 6384 eat_it = False; 6385 } 6386 TRACE(("...will%s display soft-hyphen\n", 6387 eat_it ? " not" : "")); 6388 } 6389 /* 6390 * Supposedly we dealt with combining characters and 6391 * control characters in doparse(). Anything left over 6392 * is junk that we will not attempt to display. 6393 */ 6394 if (eat_it) { 6395 TRACE(("...will not display U+%04X\n", ch)); 6396 --len; 6397 while (n < len) { 6398 buf[n] = buf[n + 1]; 6399 ++n; 6400 } 6401 last_chomp = 0; 6402 chars_chomped--; 6403 } 6404 } 6405 } 6406 width_here += last_chomp; 6407 chars_chomped++; 6408 } 6409 6410 if (width_here > width_available) { 6411 if (last_chomp > right + 1) { 6412 break; /* give up - it is too big */ 6413 } else if (chars_chomped-- == 0) { 6414 /* This can happen with left/right margins... */ 6415 break; 6416 } 6417 width_here -= last_chomp; 6418 if (chars_chomped > 0) { 6419 if (!(xw->flags & WRAPAROUND)) { 6420 buf[chars_chomped + offset - 1] = buf[len - 1]; 6421 } else { 6422 need_wrap = True; 6423 } 6424 } 6425 } else if (width_here == width_available) { 6426 need_wrap = True; 6427 } else if (chars_chomped != (len - offset)) { 6428 need_wrap = True; 6429 } 6430 6431 if (chars_chomped != 0 && next_col <= last_col) { 6432 WriteText(xw, buf + offset, chars_chomped); 6433 } else if (!did_wrap 6434 && len > 0 6435 && (xw->flags & WRAPAROUND) 6436 && screen->cur_col > ScrnLeftMargin(xw)) { 6437 force_wrap = True; 6438 need_wrap = True; 6439 } 6440 next_col += width_here; 6441 screen->do_wrap = need_wrap; 6442 } while (force_wrap); 6443 } 6444 6445 /* 6446 * Remember that we wrote something to the screen, for use as a base of 6447 * combining characters. The logic above may have called cursor-forward 6448 * or carriage-return operations which resets this flag, so we set it at 6449 * the very end. 6450 */ 6451 screen->char_was_written = True; 6452#else /* ! OPT_WIDE_CHARS */ 6453 6454 for (offset = 0; offset < len; offset += (Cardinal) this_col) { 6455#if OPT_DEC_CHRSET 6456 CLineData *ld = getLineData(screen, screen->cur_row); 6457#endif 6458 int right = ((screen->cur_col > rmargin) 6459 ? screen->max_col 6460 : rmargin); 6461 6462 int last_col = LineMaxCol(screen, ld); 6463 if (last_col > right) 6464 last_col = right; 6465 this_col = last_col - screen->cur_col + 1; 6466 if (screen->do_wrap) { 6467 screen->do_wrap = False; 6468 if ((xw->flags & WRAPAROUND)) { 6469 WrapLine(xw); 6470 } 6471 this_col = 1; 6472 } 6473 if (offset + (Cardinal) this_col > len) { 6474 this_col = (int) (len - offset); 6475 } 6476 next_col = screen->cur_col + this_col; 6477 6478 WriteText(xw, buf + offset, (unsigned) this_col); 6479 6480 /* 6481 * The call to WriteText updates screen->cur_col. 6482 * If screen->cur_col is less than next_col, we must have 6483 * hit the right margin - so set the do_wrap flag. 6484 */ 6485 screen->do_wrap = (Boolean) (screen->cur_col < next_col); 6486 } 6487 6488#endif /* OPT_WIDE_CHARS */ 6489} 6490 6491#if OPT_WIDE_CHARS 6492unsigned 6493visual_width(const IChar *str, Cardinal len) 6494{ 6495 /* returns the visual width of a string (doublewide characters count 6496 as 2, normalwide characters count as 1) */ 6497 unsigned my_len = 0; 6498 while (len) { 6499 int ch = (int) *str++; 6500 if (isWide(ch)) 6501 my_len += 2; 6502 else 6503 my_len++; 6504 len--; 6505 } 6506 return my_len; 6507} 6508#endif 6509 6510#if HANDLE_STRUCT_NOTIFY 6511/* Flag icon name with "***" on window output when iconified. 6512 */ 6513static void 6514HandleStructNotify(Widget w GCC_UNUSED, 6515 XtPointer closure GCC_UNUSED, 6516 XEvent *event, 6517 Boolean *cont GCC_UNUSED) 6518{ 6519 XtermWidget xw = term; 6520 TScreen *screen = TScreenOf(xw); 6521 6522 (void) screen; 6523 TRACE_EVENT("HandleStructNotify", event, NULL, 0); 6524 switch (event->type) { 6525 case MapNotify: 6526 resetZIconBeep(xw); 6527 mapstate = !IsUnmapped; 6528 break; 6529 case UnmapNotify: 6530 mapstate = IsUnmapped; 6531 break; 6532 case MappingNotify: 6533 XRefreshKeyboardMapping(&(event->xmapping)); 6534 VTInitModifiers(xw); 6535 break; 6536 case ConfigureNotify: 6537 if (event->xconfigure.window == XtWindow(toplevel)) { 6538#if !OPT_TOOLBAR 6539 int height = event->xconfigure.height; 6540 int width = event->xconfigure.width; 6541#endif 6542 6543#if USE_DOUBLE_BUFFER 6544 discardRenderDraw(screen); 6545#endif /* USE_DOUBLE_BUFFER */ 6546#if OPT_TOOLBAR 6547 /* 6548 * The notification is for the top-level widget, but we care about 6549 * vt100 (ignore the tek4014 window). 6550 */ 6551 if (screen->Vshow) { 6552 VTwin *Vwin = WhichVWin(screen); 6553 TbInfo *info = &(Vwin->tb_info); 6554 TbInfo save = *info; 6555 6556 if (info->menu_bar) { 6557 XtVaGetValues(info->menu_bar, 6558 XtNheight, &info->menu_height, 6559 XtNborderWidth, &info->menu_border, 6560 (XtPointer) 0); 6561 6562 if (save.menu_height != info->menu_height 6563 || save.menu_border != info->menu_border) { 6564 6565 TRACE(("...menu_height %d\n", info->menu_height)); 6566 TRACE(("...menu_border %d\n", info->menu_border)); 6567 TRACE(("...had height %d, border %d\n", 6568 save.menu_height, 6569 save.menu_border)); 6570 6571 /* 6572 * Window manager still may be using the old values. 6573 * Try to fool it. 6574 */ 6575 REQ_RESIZE((Widget) xw, 6576 screen->fullVwin.fullwidth, 6577 (Dimension) (info->menu_height 6578 - save.menu_height 6579 + screen->fullVwin.fullheight), 6580 NULL, NULL); 6581 repairSizeHints(); 6582 } 6583 } 6584 } 6585#else 6586 if (!xw->work.doing_resize 6587#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 6588 && !(resource.buffered && UsingRenderFont(xw)) /* buggyXft */ 6589#endif 6590 && (height != xw->hints.height 6591 || width != xw->hints.width)) { 6592 /* 6593 * This is a special case: other calls to RequestResize that 6594 * could set the screensize arbitrarily are via escape 6595 * sequences, and we've limited resizing. But a configure 6596 * notify is from the window manager, presumably under control 6597 * of the interactive user (ignoring abuse of wmctrl). Ignore 6598 * the limit for this case. 6599 */ 6600 int saved_limit = xw->misc.limit_resize; 6601 xw->misc.limit_resize = 0; 6602 RequestResize(xw, height, width, False); 6603 xw->misc.limit_resize = saved_limit; 6604 } 6605#endif /* OPT_TOOLBAR */ 6606 } 6607 break; 6608 } 6609} 6610#endif /* HANDLE_STRUCT_NOTIFY */ 6611 6612#if OPT_BLINK_CURS 6613static int 6614DoStartBlinking(TScreen *screen) 6615{ 6616 int actual = ((screen->cursor_blink == cbTrue || 6617 screen->cursor_blink == cbAlways) 6618 ? 1 6619 : 0); 6620 int wanted = screen->cursor_blink_esc ? 1 : 0; 6621 int result; 6622 if (screen->cursor_blink_xor) { 6623 result = actual ^ wanted; 6624 } else { 6625 result = actual | wanted; 6626 } 6627 return result; 6628} 6629 6630static void 6631SetCursorBlink(XtermWidget xw, BlinkOps enable) 6632{ 6633 TScreen *screen = TScreenOf(xw); 6634 6635 if (SettableCursorBlink(screen)) { 6636 screen->cursor_blink = enable; 6637 } 6638 if (DoStartBlinking(screen)) { 6639 StartBlinking(xw); 6640 } else { 6641 /* EMPTY */ 6642#if OPT_BLINK_TEXT 6643 reallyStopBlinking(xw); 6644#else 6645 StopBlinking(xw); 6646#endif 6647 } 6648 update_cursorblink(); 6649} 6650 6651void 6652ToggleCursorBlink(XtermWidget xw) 6653{ 6654 TScreen *screen = TScreenOf(xw); 6655 6656 if (screen->cursor_blink == cbTrue) { 6657 SetCursorBlink(xw, cbFalse); 6658 } else if (screen->cursor_blink == cbFalse) { 6659 SetCursorBlink(xw, cbTrue); 6660 } 6661} 6662#endif 6663 6664/* 6665 * process ANSI modes set, reset 6666 */ 6667static void 6668ansi_modes(XtermWidget xw, BitFunc func) 6669{ 6670 int i; 6671 6672 for (i = 0; i < nparam; ++i) { 6673 switch (GetParam(i)) { 6674 case 2: /* KAM (if set, keyboard locked */ 6675 (*func) (&xw->keyboard.flags, MODE_KAM); 6676 break; 6677 6678 case 4: /* IRM */ 6679 (*func) (&xw->flags, INSERT); 6680 break; 6681 6682 case 12: /* SRM (if set, local echo */ 6683 (*func) (&xw->keyboard.flags, MODE_SRM); 6684 break; 6685 6686 case 20: /* LNM */ 6687 (*func) (&xw->flags, LINEFEED); 6688 update_autolinefeed(); 6689 break; 6690 } 6691 } 6692} 6693 6694#define IsSM() (func == bitset) 6695 6696#define set_bool_mode(flag) \ 6697 flag = (Boolean) IsSM() 6698 6699static void 6700really_set_mousemode(XtermWidget xw, 6701 Bool enabled, 6702 XtermMouseModes mode) 6703{ 6704 TScreenOf(xw)->send_mouse_pos = enabled ? mode : MOUSE_OFF; 6705 if (okSendMousePos(xw) != MOUSE_OFF) 6706 xtermShowPointer(xw, True); 6707} 6708 6709#define set_mousemode(mode) really_set_mousemode(xw, IsSM(), mode) 6710 6711#if OPT_PASTE64 || OPT_READLINE 6712#define set_mouseflag(f) \ 6713 (IsSM() \ 6714 ? SCREEN_FLAG_set(screen, f) \ 6715 : SCREEN_FLAG_unset(screen, f)) 6716#endif 6717 6718/* 6719 * DEC 070, pp 5-29 to 5-30 (DECLRMM). 6720 * DEC 070, pp 5-71 to 5-72 (DECCOLM). 6721 * 6722 * The descriptions for DECLRMM and DECCOLM agree that setting DECLRMM resets 6723 * double-sized mode to single-size, and that if DECLRMM is being set, then 6724 * double-sized mode is disabled. Resetting DECLRMM has no effect on the 6725 * double-sized mode. The description of DECCOLM has an apparent error in its 6726 * pseudo-code (because it is inconsistent with the description of DECLRMM), 6727 * indicating that left_right_margins_mode is changed to SETABLE no matter 6728 * which way DECCOLM is set. 6729 */ 6730static void 6731set_column_mode(XtermWidget xw) 6732{ 6733 TScreen *screen = TScreenOf(xw); 6734 6735 /* switch 80/132 columns clears the screen and sets to single-width */ 6736 xterm_ResetDouble(xw); 6737 resetMargins(xw); 6738 CursorSet(screen, 0, 0, xw->flags); 6739} 6740 6741/* 6742 * DEC 070, pp 5-29 to 5-30. 6743 */ 6744static void 6745set_left_right_margin_mode(XtermWidget xw) 6746{ 6747 TScreen *screen = TScreenOf(xw); 6748 6749 if (screen->vtXX_level >= 4) { 6750 if (IsLeftRightMode(xw)) { 6751 xterm_ResetDouble(xw); 6752 } else { 6753 reset_lr_margins(screen); 6754 } 6755 } 6756} 6757 6758/* 6759 * process DEC private modes set, reset 6760 */ 6761static void 6762dpmodes(XtermWidget xw, BitFunc func) 6763{ 6764 TScreen *screen = TScreenOf(xw); 6765 int i, j; 6766 unsigned myflags; 6767 6768 TRACE(("changing %d DEC private modes\n", nparam)); 6769 if_STATUS_LINE(screen, { 6770 return; 6771 }); 6772 for (i = 0; i < nparam; ++i) { 6773 int code = GetParam(i); 6774 6775 TRACE(("%s %d\n", IsSM()? "DECSET" : "DECRST", code)); 6776 switch ((DECSET_codes) code) { 6777 case srm_DECCKM: 6778 (*func) (&xw->keyboard.flags, MODE_DECCKM); 6779 update_appcursor(); 6780 break; 6781 case srm_DECANM: /* ANSI/VT52 mode */ 6782 if (IsSM()) { /* ANSI (VT100) */ 6783 /* 6784 * Setting DECANM should have no effect, since this function 6785 * cannot be reached from vt52 mode. 6786 */ 6787 /* EMPTY */ ; 6788 } 6789#if OPT_VT52_MODE 6790 else if (screen->terminal_id >= 100) { /* VT52 */ 6791 TRACE(("DECANM terminal_id %d, vtXX_level %d\n", 6792 screen->terminal_id, 6793 screen->vtXX_level)); 6794 /* 6795 * According to DEC STD 070 section A.5.5, the various VT100 6796 * modes have undefined behavior when entering/exiting VT52 6797 * mode. xterm saves/restores/initializes the most commonly 6798 * used settings, but a real VT100 or VT520 may differ. 6799 * 6800 * For instance, DEC's documentation goes on to comment that 6801 * while the VT52 uses hardware tabs (8 columns), the emulation 6802 * (e.g., a VT420) does not alter those tab settings when 6803 * switching modes. 6804 */ 6805 screen->vtXX_level = 0; 6806 screen->vt52_save_flags = xw->flags; 6807 xw->flags = 0; 6808 screen->vt52_save_curgl = screen->curgl; 6809 screen->vt52_save_curgr = screen->curgr; 6810 screen->vt52_save_curss = screen->curss; 6811 saveCharsets(screen, screen->vt52_save_gsets); 6812 resetCharsets(screen); 6813 InitParams(); /* ignore the remaining params, if any */ 6814 update_vt52_vt100_settings(); 6815 RequestResize(xw, -1, 80, True); 6816 } 6817#endif 6818 break; 6819 case srm_DECCOLM: 6820 if (screen->c132) { 6821 Boolean willResize = ((j = IsSM() 6822 ? 132 6823 : 80) 6824 != ((xw->flags & IN132COLUMNS) 6825 ? 132 6826 : 80) 6827 || j != MaxCols(screen)); 6828 if (!(xw->flags & NOCLEAR_COLM)) 6829 ClearScreen(xw); 6830 if (willResize) 6831 RequestResize(xw, -1, j, True); 6832 (*func) (&xw->flags, IN132COLUMNS); 6833 set_column_mode(xw); 6834 } 6835 break; 6836 case srm_DECSCLM: /* (slow scroll) */ 6837 if (IsSM()) { 6838 screen->jumpscroll = 0; 6839 if (screen->scroll_amt) 6840 FlushScroll(xw); 6841 } else 6842 screen->jumpscroll = 1; 6843 (*func) (&xw->flags, SMOOTHSCROLL); 6844 update_jumpscroll(); 6845 break; 6846 case srm_DECSCNM: 6847 myflags = xw->flags; 6848 (*func) (&xw->flags, REVERSE_VIDEO); 6849 if ((xw->flags ^ myflags) & REVERSE_VIDEO) 6850 ReverseVideo(xw); 6851 /* update_reversevideo done in RevVid */ 6852 break; 6853 6854 case srm_DECOM: 6855 (*func) (&xw->flags, ORIGIN); 6856 CursorSet(screen, 0, 0, xw->flags); 6857 break; 6858 6859 case srm_DECAWM: 6860 (*func) (&xw->flags, WRAPAROUND); 6861 update_autowrap(); 6862 break; 6863 case srm_DECARM: 6864 /* ignore autorepeat 6865 * XAutoRepeatOn() and XAutoRepeatOff() can do this, but only 6866 * for the whole display - not limited to a given window. 6867 */ 6868 break; 6869 case srm_X10_MOUSE: /* MIT bogus sequence */ 6870 MotionOff(screen, xw); 6871 set_mousemode(X10_MOUSE); 6872 break; 6873#if OPT_TOOLBAR 6874 case srm_RXVT_TOOLBAR: 6875 ShowToolbar(IsSM()); 6876 break; 6877#endif 6878#if OPT_BLINK_CURS 6879 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 6880 if (SettableCursorBlink(screen)) { 6881 set_bool_mode(screen->cursor_blink_esc); 6882 UpdateCursorBlink(xw); 6883 } 6884 break; 6885 case srm_CURSOR_BLINK_OPS: 6886 /* intentionally ignored (this is user-preference) */ 6887 break; 6888 case srm_XOR_CURSOR_BLINKS: 6889 /* intentionally ignored (this is user-preference) */ 6890 break; 6891#endif 6892 case srm_DECPFF: /* print form feed */ 6893 set_bool_mode(PrinterOf(screen).printer_formfeed); 6894 break; 6895 case srm_DECPEX: /* print extent */ 6896 set_bool_mode(PrinterOf(screen).printer_extent); 6897 break; 6898 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 6899 set_bool_mode(screen->cursor_set); 6900 break; 6901 case srm_RXVT_SCROLLBAR: 6902 if (screen->fullVwin.sb_info.width != (IsSM()? ON : OFF)) 6903 ToggleScrollBar(xw); 6904 break; 6905#if OPT_SHIFT_FONTS 6906 case srm_RXVT_FONTSIZE: 6907 set_bool_mode(xw->misc.shift_fonts); 6908 break; 6909#endif 6910#if OPT_TEK4014 6911 case srm_DECTEK: 6912 if (IsSM() && !(screen->inhibit & I_TEK)) { 6913 FlushLog(xw); 6914 TEK4014_ACTIVE(xw) = True; 6915 TRACE(("Tek4014 is now active...\n")); 6916 update_vttekmode(); 6917 } 6918 break; 6919#endif 6920 case srm_132COLS: /* 132 column mode */ 6921 set_bool_mode(screen->c132); 6922 update_allow132(); 6923 break; 6924 case srm_CURSES_HACK: 6925 set_bool_mode(screen->curses); 6926 update_cursesemul(); 6927 break; 6928 case srm_DECNRCM: /* national charset (VT220) */ 6929 if (screen->vtXX_level >= 2) { 6930 if ((*func) (&xw->flags, NATIONAL)) { 6931 modified_DECNRCM(xw); 6932 } 6933 } 6934 break; 6935#if OPT_PRINT_GRAPHICS 6936 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 6937 set_bool_mode(screen->graphics_expanded_print_mode); 6938 break; 6939#endif 6940 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 6941 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_mode)) { 6942 set_bool_mode(screen->marginbell); 6943 if (!screen->marginbell) 6944 screen->bellArmed = -1; 6945 update_marginbell(); 6946 } 6947 break; 6948 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 6949 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_color_syntax)) { 6950 (*func) (&xw->flags, REVERSEWRAP); 6951 update_reversewrap(); 6952 } 6953 break; 6954#ifdef ALLOWLOGGING 6955 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 6956 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_print_background_mode)) { 6957#ifdef ALLOWLOGFILEONOFF 6958 /* 6959 * if this feature is enabled, logging may be 6960 * enabled and disabled via escape sequences. 6961 */ 6962 if (IsSM()) 6963 StartLog(xw); 6964 else 6965 CloseLog(xw); 6966#else 6967 Bell(xw, XkbBI_Info, 0); 6968 Bell(xw, XkbBI_Info, 0); 6969#endif /* ALLOWLOGFILEONOFF */ 6970 } 6971 break; 6972#elif OPT_PRINT_GRAPHICS 6973 case srm_DECGPBM: /* Graphics Print Background Mode */ 6974 set_bool_mode(screen->graphics_print_background_mode); 6975 break; 6976#endif /* ALLOWLOGGING */ 6977 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 6978 if (!xw->misc.titeInhibit) { 6979 if (IsSM()) { 6980 CursorSave(xw); 6981 ToAlternate(xw, True); 6982 ClearScreen(xw); 6983 } else { 6984 FromAlternate(xw); 6985 CursorRestore(xw); 6986 } 6987 } else if (IsSM()) { 6988 do_ti_xtra_scroll(xw); 6989 } 6990 break; 6991 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 6992 if (!xw->misc.titeInhibit) { 6993 if (IsSM()) { 6994 ToAlternate(xw, False); 6995 } else { 6996 if (screen->whichBuf) 6997 ClearScreen(xw); 6998 FromAlternate(xw); 6999 } 7000 } else if (IsSM()) { 7001 do_ti_xtra_scroll(xw); 7002 } 7003 break; 7004 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7005 if_PRINT_GRAPHICS2(set_bool_mode(screen->graphics_rotated_print_mode)) { 7006 if (!xw->misc.titeInhibit) { 7007 if (IsSM()) { 7008 ToAlternate(xw, False); 7009 } else { 7010 FromAlternate(xw); 7011 } 7012 } else if (IsSM()) { 7013 do_ti_xtra_scroll(xw); 7014 } 7015 } 7016 break; 7017 case srm_DECNKM: 7018 (*func) (&xw->keyboard.flags, MODE_DECKPAM); 7019 update_appkeypad(); 7020 break; 7021 case srm_DECBKM: 7022 /* back-arrow mapped to backspace or delete(D) */ 7023 (*func) (&xw->keyboard.flags, MODE_DECBKM); 7024 TRACE(("DECSET DECBKM %s\n", 7025 BtoS(xw->keyboard.flags & MODE_DECBKM))); 7026 update_decbkm(); 7027 break; 7028 case srm_DECLRMM: 7029 if (screen->vtXX_level >= 4) { /* VT420 */ 7030 (*func) (&xw->flags, LEFT_RIGHT); 7031 set_left_right_margin_mode(xw); 7032 } 7033 break; 7034#if OPT_SIXEL_GRAPHICS 7035 case srm_DECSDM: /* sixel scrolling */ 7036 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 7037 (*func) (&xw->keyboard.flags, MODE_DECSDM); 7038 TRACE(("DECSET/DECRST DECSDM %s (resource default is %d)\n", 7039 BtoS(xw->keyboard.flags & MODE_DECSDM), 7040 TScreenOf(xw)->sixel_scrolling)); 7041 update_decsdm(); 7042 } 7043 break; 7044#endif 7045 case srm_DECNCSM: 7046 if (screen->vtXX_level >= 5) { /* VT510 */ 7047 (*func) (&xw->flags, NOCLEAR_COLM); 7048 } 7049 break; 7050 case srm_VT200_MOUSE: /* xterm bogus sequence */ 7051 MotionOff(screen, xw); 7052 set_mousemode(VT200_MOUSE); 7053 break; 7054 case srm_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */ 7055 MotionOff(screen, xw); 7056 set_mousemode(VT200_HIGHLIGHT_MOUSE); 7057 break; 7058 case srm_BTN_EVENT_MOUSE: 7059 MotionOff(screen, xw); 7060 set_mousemode(BTN_EVENT_MOUSE); 7061 break; 7062 case srm_ANY_EVENT_MOUSE: 7063 set_mousemode(ANY_EVENT_MOUSE); 7064 if (screen->send_mouse_pos == MOUSE_OFF) { 7065 MotionOff(screen, xw); 7066 } else { 7067 MotionOn(screen, xw); 7068 } 7069 break; 7070#if OPT_FOCUS_EVENT 7071 case srm_FOCUS_EVENT_MOUSE: 7072 set_bool_mode(screen->send_focus_pos); 7073 break; 7074#endif 7075 case srm_EXT_MODE_MOUSE: 7076 /* FALLTHRU */ 7077 case srm_SGR_EXT_MODE_MOUSE: 7078 /* FALLTHRU */ 7079 case srm_URXVT_EXT_MODE_MOUSE: 7080 /* FALLTHRU */ 7081 case srm_PIXEL_POSITION_MOUSE: 7082 /* 7083 * Rather than choose an arbitrary precedence among the coordinate 7084 * modes, they are mutually exclusive. For consistency, a reset is 7085 * only effective against the matching mode. 7086 */ 7087 if (IsSM()) { 7088 screen->extend_coords = code; 7089 } else if (screen->extend_coords == code) { 7090 screen->extend_coords = 0; 7091 } 7092 break; 7093 case srm_ALTERNATE_SCROLL: 7094 set_bool_mode(screen->alternateScroll); 7095 break; 7096 case srm_RXVT_SCROLL_TTY_OUTPUT: 7097 set_bool_mode(screen->scrollttyoutput); 7098 update_scrollttyoutput(); 7099 break; 7100 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7101 set_bool_mode(screen->scrollkey); 7102 update_scrollkey(); 7103 break; 7104 case srm_EIGHT_BIT_META: 7105 if (screen->eight_bit_meta != ebNever) { 7106 set_bool_mode(screen->eight_bit_meta); 7107 } 7108 break; 7109#if OPT_NUM_LOCK 7110 case srm_REAL_NUMLOCK: 7111 set_bool_mode(xw->misc.real_NumLock); 7112 update_num_lock(); 7113 break; 7114 case srm_META_SENDS_ESC: 7115 set_bool_mode(screen->meta_sends_esc); 7116 update_meta_esc(); 7117 break; 7118#endif 7119 case srm_DELETE_IS_DEL: 7120 set_bool_mode(screen->delete_is_del); 7121 update_delete_del(); 7122 break; 7123#if OPT_NUM_LOCK 7124 case srm_ALT_SENDS_ESC: 7125 set_bool_mode(screen->alt_sends_esc); 7126 update_alt_esc(); 7127 break; 7128#endif 7129 case srm_KEEP_SELECTION: 7130 set_bool_mode(screen->keepSelection); 7131 update_keepSelection(); 7132 break; 7133 case srm_SELECT_TO_CLIPBOARD: 7134 set_bool_mode(screen->selectToClipboard); 7135 update_selectToClipboard(); 7136 break; 7137 case srm_BELL_IS_URGENT: 7138 set_bool_mode(screen->bellIsUrgent); 7139 update_bellIsUrgent(); 7140 break; 7141 case srm_POP_ON_BELL: 7142 set_bool_mode(screen->poponbell); 7143 update_poponbell(); 7144 break; 7145 case srm_KEEP_CLIPBOARD: 7146 set_bool_mode(screen->keepClipboard); 7147 update_keepClipboard(); 7148 break; 7149 case srm_ALLOW_ALTBUF: 7150 if (IsSM()) { 7151 xw->misc.titeInhibit = False; 7152 } else if (!xw->misc.titeInhibit) { 7153 xw->misc.titeInhibit = True; 7154 FromAlternate(xw); 7155 } 7156 update_titeInhibit(); 7157 break; 7158 case srm_SAVE_CURSOR: 7159 if (!xw->misc.titeInhibit) { 7160 if (IsSM()) 7161 CursorSave(xw); 7162 else 7163 CursorRestore(xw); 7164 } 7165 break; 7166#if OPT_TCAP_FKEYS 7167 case srm_TCAP_FKEYS: 7168 set_keyboard_type(xw, keyboardIsTermcap, IsSM()); 7169 break; 7170#endif 7171#if OPT_SUN_FUNC_KEYS 7172 case srm_SUN_FKEYS: 7173 set_keyboard_type(xw, keyboardIsSun, IsSM()); 7174 break; 7175#endif 7176#if OPT_HP_FUNC_KEYS 7177 case srm_HP_FKEYS: 7178 set_keyboard_type(xw, keyboardIsHP, IsSM()); 7179 break; 7180#endif 7181#if OPT_SCO_FUNC_KEYS 7182 case srm_SCO_FKEYS: 7183 set_keyboard_type(xw, keyboardIsSCO, IsSM()); 7184 break; 7185#endif 7186 case srm_LEGACY_FKEYS: 7187 set_keyboard_type(xw, keyboardIsLegacy, IsSM()); 7188 break; 7189#if OPT_SUNPC_KBD 7190 case srm_VT220_FKEYS: 7191 set_keyboard_type(xw, keyboardIsVT220, IsSM()); 7192 break; 7193#endif 7194#if OPT_PASTE64 || OPT_READLINE 7195 case srm_PASTE_IN_BRACKET: 7196 set_mouseflag(paste_brackets); 7197 break; 7198#endif 7199#if OPT_READLINE 7200 case srm_BUTTON1_MOVE_POINT: 7201 set_mouseflag(click1_moves); 7202 break; 7203 case srm_BUTTON2_MOVE_POINT: 7204 set_mouseflag(paste_moves); 7205 break; 7206 case srm_DBUTTON3_DELETE: 7207 set_mouseflag(dclick3_deletes); 7208 break; 7209 case srm_PASTE_QUOTE: 7210 set_mouseflag(paste_quotes); 7211 break; 7212 case srm_PASTE_LITERAL_NL: 7213 set_mouseflag(paste_literal_nl); 7214 break; 7215#endif /* OPT_READLINE */ 7216#if OPT_GRAPHICS 7217 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 7218 TRACE(("DECSET/DECRST PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n", 7219 BtoS(screen->privatecolorregisters), 7220 BtoS(TScreenOf(xw)->privatecolorregisters))); 7221 set_bool_mode(screen->privatecolorregisters); 7222 update_privatecolorregisters(); 7223 break; 7224#endif 7225#if OPT_SIXEL_GRAPHICS 7226 case srm_SIXEL_SCROLLS_RIGHT: /* sixel scrolling moves cursor to right */ 7227 if (optSixelGraphics(screen)) { /* FIXME: VT24x did not scroll sixel graphics */ 7228 set_bool_mode(screen->sixel_scrolls_right); 7229 TRACE(("DECSET/DECRST SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n", 7230 BtoS(screen->sixel_scrolls_right), 7231 BtoS(TScreenOf(xw)->sixel_scrolls_right))); 7232 } 7233 break; 7234#endif 7235 default: 7236 TRACE(("DATA_ERROR: unknown private code %d\n", code)); 7237 break; 7238 } 7239 } 7240} 7241 7242/* 7243 * process xterm private modes save 7244 */ 7245static void 7246savemodes(XtermWidget xw) 7247{ 7248 TScreen *screen = TScreenOf(xw); 7249 int i; 7250 7251 if_STATUS_LINE(screen, { 7252 return; 7253 }); 7254 for (i = 0; i < nparam; i++) { 7255 int code = GetParam(i); 7256 7257 TRACE(("savemodes %d\n", code)); 7258 switch ((DECSET_codes) code) { 7259 case srm_DECCKM: 7260 DoSM(DP_DECCKM, xw->keyboard.flags & MODE_DECCKM); 7261 break; 7262 case srm_DECANM: /* ANSI/VT52 mode */ 7263 /* no effect */ 7264 break; 7265 case srm_DECCOLM: 7266 if (screen->c132) 7267 DoSM(DP_DECCOLM, xw->flags & IN132COLUMNS); 7268 break; 7269 case srm_DECSCLM: /* (slow scroll) */ 7270 DoSM(DP_DECSCLM, xw->flags & SMOOTHSCROLL); 7271 break; 7272 case srm_DECSCNM: 7273 DoSM(DP_DECSCNM, xw->flags & REVERSE_VIDEO); 7274 break; 7275 case srm_DECOM: 7276 DoSM(DP_DECOM, xw->flags & ORIGIN); 7277 break; 7278 case srm_DECAWM: 7279 DoSM(DP_DECAWM, xw->flags & WRAPAROUND); 7280 break; 7281 case srm_DECARM: 7282 /* ignore autorepeat */ 7283 break; 7284 case srm_X10_MOUSE: /* mouse bogus sequence */ 7285 DoSM(DP_X_X10MSE, screen->send_mouse_pos); 7286 break; 7287#if OPT_TOOLBAR 7288 case srm_RXVT_TOOLBAR: 7289 DoSM(DP_TOOLBAR, resource.toolBar); 7290 break; 7291#endif 7292#if OPT_BLINK_CURS 7293 case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ 7294 if (SettableCursorBlink(screen)) { 7295 DoSM(DP_CRS_BLINK, screen->cursor_blink_esc); 7296 } 7297 break; 7298 case srm_CURSOR_BLINK_OPS: 7299 /* intentionally ignored (this is user-preference) */ 7300 break; 7301 case srm_XOR_CURSOR_BLINKS: 7302 /* intentionally ignored (this is user-preference) */ 7303 break; 7304#endif 7305 case srm_DECPFF: /* print form feed */ 7306 DoSM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 7307 break; 7308 case srm_DECPEX: /* print extent */ 7309 DoSM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 7310 break; 7311 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 7312 DoSM(DP_CRS_VISIBLE, screen->cursor_set); 7313 break; 7314 case srm_RXVT_SCROLLBAR: 7315 DoSM(DP_RXVT_SCROLLBAR, (screen->fullVwin.sb_info.width != 0)); 7316 break; 7317#if OPT_SHIFT_FONTS 7318 case srm_RXVT_FONTSIZE: 7319 DoSM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 7320 break; 7321#endif 7322#if OPT_TEK4014 7323 case srm_DECTEK: 7324 DoSM(DP_DECTEK, TEK4014_ACTIVE(xw)); 7325 break; 7326#endif 7327 case srm_132COLS: /* 132 column mode */ 7328 DoSM(DP_X_DECCOLM, screen->c132); 7329 break; 7330 case srm_CURSES_HACK: /* curses hack */ 7331 DoSM(DP_X_MORE, screen->curses); 7332 break; 7333 case srm_DECNRCM: /* national charset (VT220) */ 7334 if (screen->vtXX_level >= 2) { 7335 DoSM(DP_DECNRCM, xw->flags & NATIONAL); 7336 } 7337 break; 7338#if OPT_PRINT_GRAPHICS 7339 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 7340 DoSM(DP_DECGEPM, screen->graphics_expanded_print_mode); 7341 break; 7342#endif 7343 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 7344 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCM, screen->graphics_print_color_mode)) { 7345 DoSM(DP_X_MARGIN, screen->marginbell); 7346 } 7347 break; 7348 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 7349 if_PRINT_GRAPHICS2(DoSM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 7350 DoSM(DP_X_REVWRAP, xw->flags & REVERSEWRAP); 7351 } 7352 break; 7353#ifdef ALLOWLOGGING 7354 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 7355 if_PRINT_GRAPHICS2(DoSM(DP_DECGPBM, screen->graphics_print_background_mode)) { 7356#ifdef ALLOWLOGFILEONOFF 7357 DoSM(DP_X_LOGGING, screen->logging); 7358#endif /* ALLOWLOGFILEONOFF */ 7359 } 7360 break; 7361#elif OPT_PRINT_GRAPHICS 7362 case srm_DECGPBM: /* Graphics Print Background Mode */ 7363 DoSM(DP_DECGPBM, screen->graphics_print_background_mode); 7364 break; 7365#endif /* ALLOWLOGGING */ 7366 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 7367 /* FALLTHRU */ 7368 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 7369 DoSM(DP_X_ALTBUF, screen->whichBuf); 7370 break; 7371 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7372 if_PRINT_GRAPHICS2(DoSM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 7373 DoSM(DP_X_ALTBUF, screen->whichBuf); 7374 } 7375 break; 7376 case srm_DECNKM: 7377 DoSM(DP_DECKPAM, xw->keyboard.flags & MODE_DECKPAM); 7378 break; 7379 case srm_DECBKM: /* backarrow mapping */ 7380 DoSM(DP_DECBKM, xw->keyboard.flags & MODE_DECBKM); 7381 break; 7382 case srm_DECLRMM: /* left-right */ 7383 DoSM(DP_X_LRMM, LEFT_RIGHT); 7384 break; 7385#if OPT_SIXEL_GRAPHICS 7386 case srm_DECSDM: /* sixel scrolling */ 7387 DoSM(DP_DECSDM, xw->keyboard.flags & MODE_DECSDM); 7388 update_decsdm(); 7389 break; 7390#endif 7391 case srm_DECNCSM: /* noclear */ 7392 DoSM(DP_X_NCSM, NOCLEAR_COLM); 7393 break; 7394 case srm_VT200_MOUSE: /* mouse bogus sequence */ 7395 /* FALLTHRU */ 7396 case srm_VT200_HIGHLIGHT_MOUSE: 7397 /* FALLTHRU */ 7398 case srm_BTN_EVENT_MOUSE: 7399 /* FALLTHRU */ 7400 case srm_ANY_EVENT_MOUSE: 7401 DoSM(DP_X_MOUSE, screen->send_mouse_pos); 7402 break; 7403#if OPT_FOCUS_EVENT 7404 case srm_FOCUS_EVENT_MOUSE: 7405 DoSM(DP_X_FOCUS, screen->send_focus_pos); 7406 break; 7407#endif 7408 case srm_EXT_MODE_MOUSE: 7409 /* FALLTHRU */ 7410 case srm_SGR_EXT_MODE_MOUSE: 7411 /* FALLTHRU */ 7412 case srm_URXVT_EXT_MODE_MOUSE: 7413 /* FALLTHRU */ 7414 case srm_PIXEL_POSITION_MOUSE: 7415 DoSM(DP_X_EXT_MOUSE, screen->extend_coords); 7416 break; 7417 case srm_ALTERNATE_SCROLL: 7418 DoSM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 7419 break; 7420 case srm_RXVT_SCROLL_TTY_OUTPUT: 7421 DoSM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 7422 break; 7423 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7424 DoSM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 7425 break; 7426 case srm_EIGHT_BIT_META: 7427 DoSM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 7428 break; 7429#if OPT_NUM_LOCK 7430 case srm_REAL_NUMLOCK: 7431 DoSM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 7432 break; 7433 case srm_META_SENDS_ESC: 7434 DoSM(DP_META_SENDS_ESC, screen->meta_sends_esc); 7435 break; 7436#endif 7437 case srm_DELETE_IS_DEL: 7438 DoSM(DP_DELETE_IS_DEL, screen->delete_is_del); 7439 break; 7440#if OPT_NUM_LOCK 7441 case srm_ALT_SENDS_ESC: 7442 DoSM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 7443 break; 7444#endif 7445 case srm_KEEP_SELECTION: 7446 DoSM(DP_KEEP_SELECTION, screen->keepSelection); 7447 break; 7448 case srm_SELECT_TO_CLIPBOARD: 7449 DoSM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 7450 break; 7451 case srm_BELL_IS_URGENT: 7452 DoSM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 7453 break; 7454 case srm_POP_ON_BELL: 7455 DoSM(DP_POP_ON_BELL, screen->poponbell); 7456 break; 7457 case srm_KEEP_CLIPBOARD: 7458 DoSM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 7459 break; 7460#if OPT_TCAP_FKEYS 7461 case srm_TCAP_FKEYS: 7462 /* FALLTHRU */ 7463#endif 7464#if OPT_SUN_FUNC_KEYS 7465 case srm_SUN_FKEYS: 7466 /* FALLTHRU */ 7467#endif 7468#if OPT_HP_FUNC_KEYS 7469 case srm_HP_FKEYS: 7470 /* FALLTHRU */ 7471#endif 7472#if OPT_SCO_FUNC_KEYS 7473 case srm_SCO_FKEYS: 7474 /* FALLTHRU */ 7475#endif 7476#if OPT_SUNPC_KBD 7477 case srm_VT220_FKEYS: 7478 /* FALLTHRU */ 7479#endif 7480 case srm_LEGACY_FKEYS: 7481 DoSM(DP_KEYBOARD_TYPE, xw->keyboard.type); 7482 break; 7483 case srm_ALLOW_ALTBUF: 7484 DoSM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 7485 break; 7486 case srm_SAVE_CURSOR: 7487 if (!xw->misc.titeInhibit) { 7488 CursorSave(xw); 7489 } 7490 break; 7491#if OPT_PASTE64 || OPT_READLINE 7492 case srm_PASTE_IN_BRACKET: 7493 SCREEN_FLAG_save(screen, paste_brackets); 7494 break; 7495#endif 7496#if OPT_READLINE 7497 case srm_BUTTON1_MOVE_POINT: 7498 SCREEN_FLAG_save(screen, click1_moves); 7499 break; 7500 case srm_BUTTON2_MOVE_POINT: 7501 SCREEN_FLAG_save(screen, paste_moves); 7502 break; 7503 case srm_DBUTTON3_DELETE: 7504 SCREEN_FLAG_save(screen, dclick3_deletes); 7505 break; 7506 case srm_PASTE_QUOTE: 7507 SCREEN_FLAG_save(screen, paste_quotes); 7508 break; 7509 case srm_PASTE_LITERAL_NL: 7510 SCREEN_FLAG_save(screen, paste_literal_nl); 7511 break; 7512#endif /* OPT_READLINE */ 7513#if OPT_GRAPHICS 7514 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 7515 TRACE(("save PRIVATE_COLOR_REGISTERS %s\n", 7516 BtoS(screen->privatecolorregisters))); 7517 DoSM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 7518 update_privatecolorregisters(); 7519 break; 7520#endif 7521#if OPT_SIXEL_GRAPHICS 7522 case srm_SIXEL_SCROLLS_RIGHT: 7523 TRACE(("save SIXEL_SCROLLS_RIGHT %s\n", 7524 BtoS(screen->sixel_scrolls_right))); 7525 DoSM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 7526 break; 7527#endif 7528 } 7529 } 7530} 7531 7532/* 7533 * process xterm private modes restore 7534 */ 7535static void 7536restoremodes(XtermWidget xw) 7537{ 7538 TScreen *screen = TScreenOf(xw); 7539 int i, j; 7540 7541 if_STATUS_LINE(screen, { 7542 return; 7543 }); 7544 for (i = 0; i < nparam; i++) { 7545 int code = GetParam(i); 7546 7547 TRACE(("restoremodes %d\n", code)); 7548 switch ((DECSET_codes) code) { 7549 case srm_DECCKM: 7550 bitcpy(&xw->keyboard.flags, 7551 screen->save_modes[DP_DECCKM], MODE_DECCKM); 7552 update_appcursor(); 7553 break; 7554 case srm_DECANM: /* ANSI/VT52 mode */ 7555 /* no effect */ 7556 break; 7557 case srm_DECCOLM: 7558 if (screen->c132) { 7559 if (!(xw->flags & NOCLEAR_COLM)) 7560 ClearScreen(xw); 7561 CursorSet(screen, 0, 0, xw->flags); 7562 if ((j = (screen->save_modes[DP_DECCOLM] & IN132COLUMNS) 7563 ? 132 : 80) != ((xw->flags & IN132COLUMNS) 7564 ? 132 : 80) || j != MaxCols(screen)) 7565 RequestResize(xw, -1, j, True); 7566 bitcpy(&xw->flags, 7567 screen->save_modes[DP_DECCOLM], 7568 IN132COLUMNS); 7569 } 7570 break; 7571 case srm_DECSCLM: /* (slow scroll) */ 7572 if (screen->save_modes[DP_DECSCLM] & SMOOTHSCROLL) { 7573 screen->jumpscroll = 0; 7574 if (screen->scroll_amt) 7575 FlushScroll(xw); 7576 } else 7577 screen->jumpscroll = 1; 7578 bitcpy(&xw->flags, screen->save_modes[DP_DECSCLM], SMOOTHSCROLL); 7579 update_jumpscroll(); 7580 break; 7581 case srm_DECSCNM: 7582 if ((screen->save_modes[DP_DECSCNM] ^ xw->flags) & REVERSE_VIDEO) { 7583 bitcpy(&xw->flags, screen->save_modes[DP_DECSCNM], REVERSE_VIDEO); 7584 ReverseVideo(xw); 7585 /* update_reversevideo done in RevVid */ 7586 } 7587 break; 7588 case srm_DECOM: 7589 bitcpy(&xw->flags, screen->save_modes[DP_DECOM], ORIGIN); 7590 CursorSet(screen, 0, 0, xw->flags); 7591 break; 7592 7593 case srm_DECAWM: 7594 bitcpy(&xw->flags, screen->save_modes[DP_DECAWM], WRAPAROUND); 7595 update_autowrap(); 7596 break; 7597 case srm_DECARM: 7598 /* ignore autorepeat */ 7599 break; 7600 case srm_X10_MOUSE: /* MIT bogus sequence */ 7601 DoRM0(DP_X_X10MSE, screen->send_mouse_pos); 7602 really_set_mousemode(xw, 7603 screen->send_mouse_pos != MOUSE_OFF, 7604 (XtermMouseModes) screen->send_mouse_pos); 7605 break; 7606#if OPT_TOOLBAR 7607 case srm_RXVT_TOOLBAR: 7608 DoRM(DP_TOOLBAR, resource.toolBar); 7609 ShowToolbar(resource.toolBar); 7610 break; 7611#endif 7612#if OPT_BLINK_CURS 7613 case srm_ATT610_BLINK: /* Start/stop blinking cursor */ 7614 if (SettableCursorBlink(screen)) { 7615 DoRM(DP_CRS_BLINK, screen->cursor_blink_esc); 7616 UpdateCursorBlink(xw); 7617 } 7618 break; 7619 case srm_CURSOR_BLINK_OPS: 7620 /* intentionally ignored (this is user-preference) */ 7621 break; 7622 case srm_XOR_CURSOR_BLINKS: 7623 /* intentionally ignored (this is user-preference) */ 7624 break; 7625#endif 7626 case srm_DECPFF: /* print form feed */ 7627 DoRM(DP_PRN_FORMFEED, PrinterOf(screen).printer_formfeed); 7628 break; 7629 case srm_DECPEX: /* print extent */ 7630 DoRM(DP_PRN_EXTENT, PrinterOf(screen).printer_extent); 7631 break; 7632 case srm_DECTCEM: /* Show/hide cursor (VT200) */ 7633 DoRM(DP_CRS_VISIBLE, screen->cursor_set); 7634 updateCursor(xw); 7635 break; 7636 case srm_RXVT_SCROLLBAR: 7637 if ((screen->fullVwin.sb_info.width != 0) != 7638 screen->save_modes[DP_RXVT_SCROLLBAR]) { 7639 ToggleScrollBar(xw); 7640 } 7641 break; 7642#if OPT_SHIFT_FONTS 7643 case srm_RXVT_FONTSIZE: 7644 DoRM(DP_RXVT_FONTSIZE, xw->misc.shift_fonts); 7645 break; 7646#endif 7647#if OPT_TEK4014 7648 case srm_DECTEK: 7649 if (!(screen->inhibit & I_TEK) && 7650 (TEK4014_ACTIVE(xw) != (Boolean) screen->save_modes[DP_DECTEK])) { 7651 FlushLog(xw); 7652 TEK4014_ACTIVE(xw) = (Boolean) screen->save_modes[DP_DECTEK]; 7653 update_vttekmode(); 7654 } 7655 break; 7656#endif 7657 case srm_132COLS: /* 132 column mode */ 7658 DoRM(DP_X_DECCOLM, screen->c132); 7659 update_allow132(); 7660 break; 7661 case srm_CURSES_HACK: /* curses hack */ 7662 DoRM(DP_X_MORE, screen->curses); 7663 update_cursesemul(); 7664 break; 7665 case srm_DECNRCM: /* national charset (VT220) */ 7666 if (screen->vtXX_level >= 2) { 7667 if (bitcpy(&xw->flags, screen->save_modes[DP_DECNRCM], NATIONAL)) 7668 modified_DECNRCM(xw); 7669 } 7670 break; 7671#if OPT_PRINT_GRAPHICS 7672 case srm_DECGEPM: /* Graphics Expanded Print Mode */ 7673 DoRM(DP_DECGEPM, screen->graphics_expanded_print_mode); 7674 break; 7675#endif 7676 case srm_MARGIN_BELL: /* margin bell (xterm) also DECGPCM (Graphics Print Color Mode) */ 7677 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCM, screen->graphics_print_color_mode)) { 7678 if ((DoRM(DP_X_MARGIN, screen->marginbell)) == 0) 7679 screen->bellArmed = -1; 7680 update_marginbell(); 7681 } 7682 break; 7683 case srm_REVERSEWRAP: /* reverse wraparound (xterm) also DECGPCS (Graphics Print Color Syntax) */ 7684 if_PRINT_GRAPHICS2(DoRM(DP_DECGPCS, screen->graphics_print_color_syntax)) { 7685 bitcpy(&xw->flags, screen->save_modes[DP_X_REVWRAP], REVERSEWRAP); 7686 update_reversewrap(); 7687 } 7688 break; 7689#ifdef ALLOWLOGGING 7690 case srm_ALLOWLOGGING: /* logging (xterm) also DECGPBM (Graphics Print Background Mode) */ 7691 if_PRINT_GRAPHICS2(DoRM(DP_DECGPBM, screen->graphics_print_background_mode)) { 7692#ifdef ALLOWLOGFILEONOFF 7693 if (screen->save_modes[DP_X_LOGGING]) 7694 StartLog(xw); 7695 else 7696 CloseLog(xw); 7697#endif /* ALLOWLOGFILEONOFF */ 7698 /* update_logging done by StartLog and CloseLog */ 7699 } 7700 break; 7701#elif OPT_PRINT_GRAPHICS 7702 case srm_DECGPBM: /* Graphics Print Background Mode */ 7703 DoRM(DP_DECGPBM, screen->graphics_print_background_mode); 7704 break; 7705#endif /* ALLOWLOGGING */ 7706 case srm_OPT_ALTBUF_CURSOR: /* optional alternate buffer and clear (xterm) */ 7707 /* FALLTHRU */ 7708 case srm_OPT_ALTBUF: /* optional alternate buffer and clear (xterm) */ 7709 if (!xw->misc.titeInhibit) { 7710 if (screen->save_modes[DP_X_ALTBUF]) 7711 ToAlternate(xw, False); 7712 else 7713 FromAlternate(xw); 7714 /* update_altscreen done by ToAlt and FromAlt */ 7715 } else if (screen->save_modes[DP_X_ALTBUF]) { 7716 do_ti_xtra_scroll(xw); 7717 } 7718 break; 7719 case srm_ALTBUF: /* alternate buffer (xterm) also DECGRPM (Graphics Rotated Print Mode) */ 7720 if_PRINT_GRAPHICS2(DoRM(DP_DECGRPM, screen->graphics_rotated_print_mode)) { 7721 if (!xw->misc.titeInhibit) { 7722 if (screen->save_modes[DP_X_ALTBUF]) 7723 ToAlternate(xw, False); 7724 else 7725 FromAlternate(xw); 7726 /* update_altscreen done by ToAlt and FromAlt */ 7727 } else if (screen->save_modes[DP_X_ALTBUF]) { 7728 do_ti_xtra_scroll(xw); 7729 } 7730 } 7731 break; 7732 case srm_DECNKM: 7733 bitcpy(&xw->flags, screen->save_modes[DP_DECKPAM], MODE_DECKPAM); 7734 update_appkeypad(); 7735 break; 7736 case srm_DECBKM: /* backarrow mapping */ 7737 bitcpy(&xw->flags, screen->save_modes[DP_DECBKM], MODE_DECBKM); 7738 update_decbkm(); 7739 break; 7740 case srm_DECLRMM: /* left-right */ 7741 bitcpy(&xw->flags, screen->save_modes[DP_X_LRMM], LEFT_RIGHT); 7742 if (IsLeftRightMode(xw)) { 7743 xterm_ResetDouble(xw); 7744 } else { 7745 reset_lr_margins(screen); 7746 } 7747 break; 7748#if OPT_SIXEL_GRAPHICS 7749 case srm_DECSDM: /* sixel scrolling */ 7750 bitcpy(&xw->keyboard.flags, screen->save_modes[DP_DECSDM], MODE_DECSDM); 7751 update_decsdm(); 7752 break; 7753#endif 7754 case srm_DECNCSM: /* noclear */ 7755 bitcpy(&xw->flags, screen->save_modes[DP_X_NCSM], NOCLEAR_COLM); 7756 break; 7757 case srm_VT200_MOUSE: /* mouse bogus sequence */ 7758 /* FALLTHRU */ 7759 case srm_VT200_HIGHLIGHT_MOUSE: 7760 /* FALLTHRU */ 7761 case srm_BTN_EVENT_MOUSE: 7762 /* FALLTHRU */ 7763 case srm_ANY_EVENT_MOUSE: 7764 DoRM0(DP_X_MOUSE, screen->send_mouse_pos); 7765 really_set_mousemode(xw, 7766 screen->send_mouse_pos != MOUSE_OFF, 7767 (XtermMouseModes) screen->send_mouse_pos); 7768 break; 7769#if OPT_FOCUS_EVENT 7770 case srm_FOCUS_EVENT_MOUSE: 7771 DoRM(DP_X_FOCUS, screen->send_focus_pos); 7772 break; 7773#endif 7774 case srm_EXT_MODE_MOUSE: 7775 /* FALLTHRU */ 7776 case srm_SGR_EXT_MODE_MOUSE: 7777 /* FALLTHRU */ 7778 case srm_URXVT_EXT_MODE_MOUSE: 7779 /* FALLTHRU */ 7780 case srm_PIXEL_POSITION_MOUSE: 7781 DoRM(DP_X_EXT_MOUSE, screen->extend_coords); 7782 break; 7783 case srm_ALLOW_ALTBUF: 7784 DoRM(DP_ALLOW_ALTBUF, xw->misc.titeInhibit); 7785 if (xw->misc.titeInhibit) 7786 FromAlternate(xw); 7787 update_titeInhibit(); 7788 break; 7789 case srm_SAVE_CURSOR: 7790 if (!xw->misc.titeInhibit) { 7791 CursorRestore(xw); 7792 } 7793 break; 7794 case srm_ALTERNATE_SCROLL: 7795 DoRM(DP_ALTERNATE_SCROLL, screen->alternateScroll); 7796 break; 7797 case srm_RXVT_SCROLL_TTY_OUTPUT: 7798 DoRM(DP_RXVT_SCROLL_TTY_OUTPUT, screen->scrollttyoutput); 7799 update_scrollttyoutput(); 7800 break; 7801 case srm_RXVT_SCROLL_TTY_KEYPRESS: 7802 DoRM(DP_RXVT_SCROLL_TTY_KEYPRESS, screen->scrollkey); 7803 update_scrollkey(); 7804 break; 7805 case srm_EIGHT_BIT_META: 7806 DoRM(DP_EIGHT_BIT_META, screen->eight_bit_meta); 7807 break; 7808#if OPT_NUM_LOCK 7809 case srm_REAL_NUMLOCK: 7810 DoRM(DP_REAL_NUMLOCK, xw->misc.real_NumLock); 7811 update_num_lock(); 7812 break; 7813 case srm_META_SENDS_ESC: 7814 DoRM(DP_META_SENDS_ESC, screen->meta_sends_esc); 7815 update_meta_esc(); 7816 break; 7817#endif 7818 case srm_DELETE_IS_DEL: 7819 DoRM(DP_DELETE_IS_DEL, screen->delete_is_del); 7820 update_delete_del(); 7821 break; 7822#if OPT_NUM_LOCK 7823 case srm_ALT_SENDS_ESC: 7824 DoRM(DP_ALT_SENDS_ESC, screen->alt_sends_esc); 7825 update_alt_esc(); 7826 break; 7827#endif 7828 case srm_KEEP_SELECTION: 7829 DoRM(DP_KEEP_SELECTION, screen->keepSelection); 7830 update_keepSelection(); 7831 break; 7832 case srm_SELECT_TO_CLIPBOARD: 7833 DoRM(DP_SELECT_TO_CLIPBOARD, screen->selectToClipboard); 7834 update_selectToClipboard(); 7835 break; 7836 case srm_BELL_IS_URGENT: 7837 DoRM(DP_BELL_IS_URGENT, screen->bellIsUrgent); 7838 update_bellIsUrgent(); 7839 break; 7840 case srm_POP_ON_BELL: 7841 DoRM(DP_POP_ON_BELL, screen->poponbell); 7842 update_poponbell(); 7843 break; 7844 case srm_KEEP_CLIPBOARD: 7845 DoRM(DP_KEEP_CLIPBOARD, screen->keepClipboard); 7846 update_keepClipboard(); 7847 break; 7848#if OPT_TCAP_FKEYS 7849 case srm_TCAP_FKEYS: 7850 /* FALLTHRU */ 7851#endif 7852#if OPT_SUN_FUNC_KEYS 7853 case srm_SUN_FKEYS: 7854 /* FALLTHRU */ 7855#endif 7856#if OPT_HP_FUNC_KEYS 7857 case srm_HP_FKEYS: 7858 /* FALLTHRU */ 7859#endif 7860#if OPT_SCO_FUNC_KEYS 7861 case srm_SCO_FKEYS: 7862 /* FALLTHRU */ 7863#endif 7864#if OPT_SUNPC_KBD 7865 case srm_VT220_FKEYS: 7866 /* FALLTHRU */ 7867#endif 7868 case srm_LEGACY_FKEYS: 7869 xw->keyboard.type = (xtermKeyboardType) screen->save_modes[DP_KEYBOARD_TYPE]; 7870 break; 7871#if OPT_PASTE64 || OPT_READLINE 7872 case srm_PASTE_IN_BRACKET: 7873 SCREEN_FLAG_restore(screen, paste_brackets); 7874 break; 7875#endif 7876#if OPT_READLINE 7877 case srm_BUTTON1_MOVE_POINT: 7878 SCREEN_FLAG_restore(screen, click1_moves); 7879 break; 7880 case srm_BUTTON2_MOVE_POINT: 7881 SCREEN_FLAG_restore(screen, paste_moves); 7882 break; 7883 case srm_DBUTTON3_DELETE: 7884 SCREEN_FLAG_restore(screen, dclick3_deletes); 7885 break; 7886 case srm_PASTE_QUOTE: 7887 SCREEN_FLAG_restore(screen, paste_quotes); 7888 break; 7889 case srm_PASTE_LITERAL_NL: 7890 SCREEN_FLAG_restore(screen, paste_literal_nl); 7891 break; 7892#endif /* OPT_READLINE */ 7893#if OPT_GRAPHICS 7894 case srm_PRIVATE_COLOR_REGISTERS: /* private color registers for each graphic */ 7895 TRACE(("restore PRIVATE_COLOR_REGISTERS before: %s\n", 7896 BtoS(screen->privatecolorregisters))); 7897 DoRM(DP_X_PRIVATE_COLOR_REGISTERS, screen->privatecolorregisters); 7898 TRACE(("restore PRIVATE_COLOR_REGISTERS after: %s\n", 7899 BtoS(screen->privatecolorregisters))); 7900 update_privatecolorregisters(); 7901 break; 7902#endif 7903#if OPT_SIXEL_GRAPHICS 7904 case srm_SIXEL_SCROLLS_RIGHT: 7905 TRACE(("restore SIXEL_SCROLLS_RIGHT before: %s\n", 7906 BtoS(screen->sixel_scrolls_right))); 7907 DoRM(DP_SIXEL_SCROLLS_RIGHT, screen->sixel_scrolls_right); 7908 TRACE(("restore SIXEL_SCROLLS_RIGHT after: %s\n", 7909 BtoS(screen->sixel_scrolls_right))); 7910 break; 7911#endif 7912 } 7913 } 7914} 7915 7916/* 7917 * Convert an XTextProperty to a string. 7918 * 7919 * This frees the data owned by the XTextProperty, and returns in its place the 7920 * string, which must be freed by the caller. 7921 */ 7922static char * 7923property_to_string(XtermWidget xw, XTextProperty * text) 7924{ 7925 TScreen *screen = TScreenOf(xw); 7926 Display *dpy = screen->display; 7927 char *result = 0; 7928 char **list = NULL; 7929 int length = 0; 7930 int rc; 7931 7932 TRACE(("property_to_string value %p, encoding %s, format %d, nitems %ld\n", 7933 text->value, 7934 TraceAtomName(dpy, text->encoding), 7935 text->format, 7936 text->nitems)); 7937 7938#if OPT_WIDE_CHARS 7939 /* 7940 * We will use the XmbTextPropertyToTextList call to extract UTF-8 data. 7941 * The xtermUtf8ToTextList() call is used to convert UTF-8 explicitly to 7942 * ISO-8859-1. 7943 */ 7944 rc = -1; 7945 if ((text->format != 8) 7946 || IsTitleMode(xw, tmGetUtf8) 7947 || (text->encoding == XA_UTF8_STRING(dpy) && 7948 !(screen->wide_chars || screen->c1_printable) && 7949 (rc = xtermUtf8ToTextList(xw, text, &list, &length)) < 0) 7950 || (rc < 0)) 7951#endif 7952 if ((rc = XmbTextPropertyToTextList(dpy, text, &list, &length)) < 0) 7953 rc = XTextPropertyToStringList(text, &list, &length); 7954 7955 if (rc >= 0) { 7956 int n, c, pass; 7957 size_t need; 7958 7959 for (pass = 0; pass < 2; ++pass) { 7960 for (n = 0, need = 0; n < length; n++) { 7961 char *s = list[n]; 7962 while ((c = *s++) != '\0') { 7963 if (pass) 7964 result[need] = (char) c; 7965 ++need; 7966 } 7967 } 7968 if (pass) 7969 result[need] = '\0'; 7970 else 7971 result = malloc(need + 1); 7972 if (result == 0) 7973 break; 7974 } 7975 XFreeStringList(list); 7976 } 7977 if (text->value != 0) 7978 XFree(text->value); 7979 7980 return result; 7981} 7982 7983static char * 7984get_icon_label(XtermWidget xw) 7985{ 7986 XTextProperty text; 7987 char *result = 0; 7988 7989 if (XGetWMIconName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 7990 result = property_to_string(xw, &text); 7991 } 7992 return result; 7993} 7994 7995static char * 7996get_window_label(XtermWidget xw) 7997{ 7998 XTextProperty text; 7999 char *result = 0; 8000 8001 if (XGetWMName(TScreenOf(xw)->display, VShellWindow(xw), &text)) { 8002 result = property_to_string(xw, &text); 8003 } 8004 return result; 8005} 8006 8007/* 8008 * Report window label (icon or title) in dtterm protocol 8009 * ESC ] code label ESC backslash 8010 */ 8011static void 8012report_win_label(XtermWidget xw, 8013 int code, 8014 char *text) 8015{ 8016 unparseputc(xw, ANSI_ESC); 8017 unparseputc(xw, ']'); 8018 unparseputc(xw, code); 8019 8020 if (text != 0) { 8021 int copy = IsTitleMode(xw, tmGetBase16); 8022 if (copy) { 8023 TRACE(("Encoding hex:%s\n", text)); 8024 text = x_encode_hex(text); 8025 } 8026 unparseputs(xw, text); 8027 if (copy) 8028 free(text); 8029 } 8030 8031 unparseputc(xw, ANSI_ESC); 8032 unparseputc(xw, '\\'); /* should be ST */ 8033 unparse_end(xw); 8034} 8035 8036/* 8037 * Window operations (from CDE dtterm description, as well as extensions). 8038 * See also "allowWindowOps" resource. 8039 */ 8040static void 8041window_ops(XtermWidget xw) 8042{ 8043 TScreen *screen = TScreenOf(xw); 8044 XWindowChanges values; 8045 XWindowAttributes win_attrs; 8046#if OPT_MAXIMIZE 8047 unsigned root_width; 8048 unsigned root_height; 8049#endif 8050 int code = zero_if_default(0); 8051 char *label; 8052 8053 TRACE(("window_ops %d\n", code)); 8054 switch (code) { 8055 case ewRestoreWin: /* Restore (de-iconify) window */ 8056 if (AllowWindowOps(xw, ewRestoreWin)) { 8057 xtermDeiconify(xw); 8058 } 8059 break; 8060 8061 case ewMinimizeWin: /* Minimize (iconify) window */ 8062 if (AllowWindowOps(xw, ewMinimizeWin)) { 8063 xtermIconify(xw); 8064 } 8065 break; 8066 8067 case ewSetWinPosition: /* Move the window to the given position */ 8068 if (AllowWindowOps(xw, ewSetWinPosition)) { 8069 unsigned value_mask; 8070 8071 values.x = (Position) zero_if_default(1); 8072 values.y = (Position) zero_if_default(2); 8073 TRACE(("...move window to %d,%d\n", values.x, values.y)); 8074 value_mask = (CWX | CWY); 8075 XReconfigureWMWindow(screen->display, 8076 VShellWindow(xw), 8077 DefaultScreen(screen->display), 8078 value_mask, 8079 &values); 8080 } 8081 break; 8082 8083 case ewSetWinSizePixels: /* Resize the window to given size in pixels */ 8084 if (AllowWindowOps(xw, ewSetWinSizePixels)) { 8085 RequestResize(xw, optional_param(1), optional_param(2), False); 8086 } 8087 break; 8088 8089 case ewRaiseWin: /* Raise the window to the front of the stack */ 8090 if (AllowWindowOps(xw, ewRaiseWin)) { 8091 TRACE(("...raise window\n")); 8092 XRaiseWindow(screen->display, VShellWindow(xw)); 8093 } 8094 break; 8095 8096 case ewLowerWin: /* Lower the window to the bottom of the stack */ 8097 if (AllowWindowOps(xw, ewLowerWin)) { 8098 TRACE(("...lower window\n")); 8099 XLowerWindow(screen->display, VShellWindow(xw)); 8100 } 8101 break; 8102 8103 case ewRefreshWin: /* Refresh the window */ 8104 if (AllowWindowOps(xw, ewRefreshWin)) { 8105 TRACE(("...redraw window\n")); 8106 Redraw(); 8107 } 8108 break; 8109 8110 case ewSetWinSizeChars: /* Resize the text-area, in characters */ 8111 if (AllowWindowOps(xw, ewSetWinSizeChars)) { 8112 RequestResize(xw, optional_param(1), optional_param(2), True); 8113 } 8114 break; 8115 8116#if OPT_MAXIMIZE 8117 case ewMaximizeWin: /* Maximize or restore */ 8118 if (AllowWindowOps(xw, ewMaximizeWin)) { 8119 RequestMaximize(xw, zero_if_default(1)); 8120 } 8121 break; 8122 case ewFullscreenWin: /* Fullscreen or restore */ 8123 if (AllowWindowOps(xw, ewFullscreenWin)) { 8124 switch (zero_if_default(1)) { 8125 default: 8126 RequestMaximize(xw, 0); 8127 break; 8128 case 1: 8129 RequestMaximize(xw, 1); 8130 break; 8131 case 2: 8132 RequestMaximize(xw, !(screen->restore_data)); 8133 break; 8134 } 8135 } 8136 break; 8137#endif 8138 8139 case ewGetWinState: /* Report the window's state */ 8140 if (AllowWindowOps(xw, ewGetWinState)) { 8141 TRACE(("...get window attributes\n")); 8142 init_reply(ANSI_CSI); 8143 reply.a_pintro = 0; 8144 reply.a_nparam = 1; 8145 reply.a_param[0] = (ParmType) (xtermIsIconified(xw) ? 2 : 1); 8146 reply.a_inters = 0; 8147 reply.a_final = 't'; 8148 unparseseq(xw, &reply); 8149 } 8150 break; 8151 8152 case ewGetWinPosition: /* Report the window's position */ 8153 if (AllowWindowOps(xw, ewGetWinPosition)) { 8154 Window win; 8155 Window result_win; 8156 int result_y, result_x; 8157 8158 TRACE(("...get window position\n")); 8159 init_reply(ANSI_CSI); 8160 reply.a_pintro = 0; 8161 reply.a_nparam = 3; 8162 reply.a_param[0] = 3; 8163 switch (zero_if_default(1)) { 8164 case 2: /* report the text-window's position */ 8165 result_y = 0; 8166 result_x = 0; 8167 { 8168 Widget mw; 8169 for (mw = (Widget) xw; mw != 0; mw = XtParent(mw)) { 8170 result_x += mw->core.x; 8171 result_y += mw->core.y; 8172 if (mw == SHELL_OF(xw)) 8173 break; 8174 } 8175 } 8176 result_x += OriginX(screen); 8177 result_y += OriginY(screen); 8178 break; 8179 default: 8180 win = WMFrameWindow(xw); 8181 xtermGetWinAttrs(screen->display, 8182 win, 8183 &win_attrs); 8184 XTranslateCoordinates(screen->display, 8185 VShellWindow(xw), 8186 win_attrs.root, 8187 -win_attrs.border_width, 8188 -win_attrs.border_width, 8189 &result_x, &result_y, &result_win); 8190 TRACE(("translated position %d,%d vs %d,%d\n", 8191 result_y, result_x, 8192 win_attrs.y, win_attrs.x)); 8193 if (!discount_frame_extents(xw, &result_y, &result_x)) { 8194 TRACE(("...cancelled translation\n")); 8195 result_y = win_attrs.y; 8196 result_x = win_attrs.x; 8197 } 8198 break; 8199 } 8200 reply.a_param[1] = (ParmType) result_x; 8201 reply.a_param[2] = (ParmType) result_y; 8202 reply.a_inters = 0; 8203 reply.a_final = 't'; 8204 unparseseq(xw, &reply); 8205 } 8206 break; 8207 8208 case ewGetWinSizePixels: /* Report the window's size in pixels */ 8209 if (AllowWindowOps(xw, ewGetWinSizePixels)) { 8210 ParmType high = (ParmType) Height(screen); 8211 ParmType wide = (ParmType) Width(screen); 8212 8213 TRACE(("...get window size in pixels\n")); 8214 init_reply(ANSI_CSI); 8215 reply.a_pintro = 0; 8216 reply.a_nparam = 3; 8217 reply.a_param[0] = 4; 8218 switch (zero_if_default(1)) { 8219 case 2: /* report the shell-window's size */ 8220 xtermGetWinAttrs(screen->display, 8221 WMFrameWindow(xw), 8222 &win_attrs); 8223 high = (ParmType) win_attrs.height; 8224 wide = (ParmType) win_attrs.width; 8225 /* FALLTHRU */ 8226 default: 8227 reply.a_param[1] = high; 8228 reply.a_param[2] = wide; 8229 break; 8230 } 8231 reply.a_inters = 0; 8232 reply.a_final = 't'; 8233 unparseseq(xw, &reply); 8234 } 8235 break; 8236 8237#if OPT_MAXIMIZE 8238 case ewGetScreenSizePixels: /* Report the screen's size, in Pixels */ 8239 if (AllowWindowOps(xw, ewGetScreenSizePixels)) { 8240 TRACE(("...get screen size in pixels\n")); 8241 (void) QueryMaximize(xw, &root_width, &root_height); 8242 init_reply(ANSI_CSI); 8243 reply.a_pintro = 0; 8244 reply.a_nparam = 3; 8245 reply.a_param[0] = 5; 8246 reply.a_param[1] = (ParmType) root_height; 8247 reply.a_param[2] = (ParmType) root_width; 8248 reply.a_inters = 0; 8249 reply.a_final = 't'; 8250 unparseseq(xw, &reply); 8251 } 8252 break; 8253 case ewGetCharSizePixels: /* Report the font's size, in pixel */ 8254 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 8255 TRACE(("...get font size in pixels\n")); 8256 TRACE(("...using font size %dx%d\n", 8257 FontHeight(screen), 8258 FontWidth(screen))); 8259 init_reply(ANSI_CSI); 8260 reply.a_pintro = 0; 8261 reply.a_nparam = 3; 8262 reply.a_param[0] = 6; 8263 reply.a_param[1] = (ParmType) FontHeight(screen); 8264 reply.a_param[2] = (ParmType) FontWidth(screen); 8265 reply.a_inters = 0; 8266 reply.a_final = 't'; 8267 unparseseq(xw, &reply); 8268 } 8269 break; 8270#endif 8271 8272 case ewGetWinSizeChars: /* Report the text's size in characters */ 8273 if (AllowWindowOps(xw, ewGetWinSizeChars)) { 8274 TRACE(("...get window size in characters\n")); 8275 init_reply(ANSI_CSI); 8276 reply.a_pintro = 0; 8277 reply.a_nparam = 3; 8278 reply.a_param[0] = 8; 8279 reply.a_param[1] = (ParmType) MaxRows(screen); 8280 reply.a_param[2] = (ParmType) MaxCols(screen); 8281 reply.a_inters = 0; 8282 reply.a_final = 't'; 8283 unparseseq(xw, &reply); 8284 } 8285 break; 8286 8287#if OPT_MAXIMIZE 8288 case ewGetScreenSizeChars: /* Report the screen's size, in characters */ 8289 if (AllowWindowOps(xw, ewGetScreenSizeChars)) { 8290 TRACE(("...get screen size in characters\n")); 8291 TRACE(("...using font size %dx%d\n", 8292 FontHeight(screen), 8293 FontWidth(screen))); 8294 (void) QueryMaximize(xw, &root_width, &root_height); 8295 init_reply(ANSI_CSI); 8296 reply.a_pintro = 0; 8297 reply.a_nparam = 3; 8298 reply.a_param[0] = 9; 8299 reply.a_param[1] = (ParmType) (root_height 8300 / (unsigned) FontHeight(screen)); 8301 reply.a_param[2] = (ParmType) (root_width 8302 / (unsigned) FontWidth(screen)); 8303 reply.a_inters = 0; 8304 reply.a_final = 't'; 8305 unparseseq(xw, &reply); 8306 } 8307 break; 8308#endif 8309 8310 case ewGetIconTitle: /* Report the icon's label */ 8311 if (AllowWindowOps(xw, ewGetIconTitle)) { 8312 TRACE(("...get icon's label\n")); 8313 report_win_label(xw, 'L', label = get_icon_label(xw)); 8314 free(label); 8315 } 8316 break; 8317 8318 case ewGetWinTitle: /* Report the window's title */ 8319 if (AllowWindowOps(xw, ewGetWinTitle)) { 8320 TRACE(("...get window's label\n")); 8321 report_win_label(xw, 'l', label = get_window_label(xw)); 8322 free(label); 8323 } 8324 break; 8325 8326 case ewPushTitle: /* save the window's title(s) on stack */ 8327 if (AllowWindowOps(xw, ewPushTitle)) { 8328 SaveTitle *last = screen->save_title; 8329 SaveTitle *item = TypeCalloc(SaveTitle); 8330 8331 TRACE(("...push title onto stack\n")); 8332 if (item != 0) { 8333 switch (zero_if_default(1)) { 8334 case 0: 8335 item->iconName = get_icon_label(xw); 8336 item->windowName = get_window_label(xw); 8337 break; 8338 case 1: 8339 item->iconName = get_icon_label(xw); 8340 break; 8341 case 2: 8342 item->windowName = get_window_label(xw); 8343 break; 8344 } 8345 item->next = last; 8346 if (item->iconName == 0) { 8347 item->iconName = ((last == 0) 8348 ? get_icon_label(xw) 8349 : x_strdup(last->iconName)); 8350 } 8351 if (item->windowName == 0) { 8352 item->windowName = ((last == 0) 8353 ? get_window_label(xw) 8354 : x_strdup(last->windowName)); 8355 } 8356 screen->save_title = item; 8357 } 8358 } 8359 break; 8360 8361 case ewPopTitle: /* restore the window's title(s) from stack */ 8362 if (AllowWindowOps(xw, ewPopTitle)) { 8363 SaveTitle *item = screen->save_title; 8364 8365 TRACE(("...pop title off stack\n")); 8366 if (item != 0) { 8367 switch (zero_if_default(1)) { 8368 case 0: 8369 ChangeIconName(xw, item->iconName); 8370 ChangeTitle(xw, item->windowName); 8371 break; 8372 case 1: 8373 ChangeIconName(xw, item->iconName); 8374 break; 8375 case 2: 8376 ChangeTitle(xw, item->windowName); 8377 break; 8378 } 8379 screen->save_title = item->next; 8380 free(item->iconName); 8381 free(item->windowName); 8382 free(item); 8383 } 8384 } 8385 break; 8386 8387 default: /* DECSLPP (24, 25, 36, 48, 72, 144) */ 8388 if (AllowWindowOps(xw, ewSetWinLines)) { 8389 if (code >= 24) 8390 RequestResize(xw, code, -1, True); 8391 } 8392 break; 8393 } 8394} 8395 8396/* 8397 * set a bit in a word given a pointer to the word and a mask. 8398 */ 8399static int 8400bitset(unsigned *p, unsigned mask) 8401{ 8402 unsigned before = *p; 8403 *p |= mask; 8404 return (before != *p); 8405} 8406 8407/* 8408 * clear a bit in a word given a pointer to the word and a mask. 8409 */ 8410static int 8411bitclr(unsigned *p, unsigned mask) 8412{ 8413 unsigned before = *p; 8414 *p &= ~mask; 8415 return (before != *p); 8416} 8417 8418/* 8419 * Copy bits from one word to another, given a mask 8420 */ 8421static int 8422bitcpy(unsigned *p, unsigned q, unsigned mask) 8423{ 8424 unsigned before = *p; 8425 bitclr(p, mask); 8426 bitset(p, q & mask); 8427 return (before != *p); 8428} 8429 8430void 8431unparseputc1(XtermWidget xw, int c) 8432{ 8433 if (c >= 0x80 && c <= 0x9F) { 8434 if (!TScreenOf(xw)->control_eight_bits) { 8435 unparseputc(xw, A2E(ANSI_ESC)); 8436 c = A2E(c - 0x40); 8437 } 8438 } 8439 unparseputc(xw, c); 8440} 8441 8442void 8443unparseseq(XtermWidget xw, ANSI *ap) 8444{ 8445 int c; 8446 8447 assert(ap->a_nparam < NPARAM); 8448 unparseputc1(xw, c = ap->a_type); 8449 if (c == ANSI_ESC 8450 || c == ANSI_DCS 8451 || c == ANSI_CSI 8452 || c == ANSI_OSC 8453 || c == ANSI_PM 8454 || c == ANSI_APC 8455 || c == ANSI_SS3) { 8456 int i; 8457 int inters; 8458 char temp[8]; 8459 8460 if (ap->a_pintro != 0) 8461 unparseputc(xw, ap->a_pintro); 8462 for (i = 0; i < ap->a_nparam; ++i) { 8463 if (i != 0) { 8464 if (ap->a_radix[i] == 1 || ap->a_radix[i - 1] == 1) { 8465 ; 8466 } else if (ap->a_delim) { 8467 unparseputs(xw, ap->a_delim); 8468 } else { 8469 unparseputc(xw, ';'); 8470 } 8471 } 8472 switch (ap->a_radix[i]) { 8473 case 16: 8474 sprintf(temp, "%04X", ap->a_param[i] & 0xffff); 8475 unparseputs(xw, temp); 8476 break; 8477 case 1: 8478 unparseputc(xw, ap->a_param[i]); 8479 break; 8480 default: 8481 unparseputn(xw, (unsigned) (UParm) ap->a_param[i]); 8482 break; 8483 } 8484 } 8485 if ((inters = ap->a_inters) != 0) { 8486 for (i = 3; i >= 0; --i) { 8487 c = CharOf(inters >> (8 * i)); 8488 if (c != 0) 8489 unparseputc(xw, c); 8490 } 8491 } 8492 switch (ap->a_type) { 8493 case ANSI_DCS: 8494 /* FALLTHRU */ 8495 case ANSI_OSC: 8496 /* FALLTHRU */ 8497 case ANSI_PM: 8498 /* FALLTHRU */ 8499 case ANSI_APC: 8500 unparseputc1(xw, ANSI_ST); 8501 break; 8502 default: 8503 unparseputc(xw, (char) ap->a_final); 8504 break; 8505 } 8506 } 8507 unparse_end(xw); 8508} 8509 8510void 8511unparseputn(XtermWidget xw, unsigned n) 8512{ 8513 unsigned q; 8514 8515 q = n / 10; 8516 if (q != 0) 8517 unparseputn(xw, q); 8518 unparseputc(xw, (char) ('0' + (n % 10))); 8519} 8520 8521void 8522unparseputs(XtermWidget xw, const char *s) 8523{ 8524 if (s != 0) { 8525 while (*s) 8526 unparseputc(xw, *s++); 8527 } 8528} 8529 8530void 8531unparseputc(XtermWidget xw, int c) 8532{ 8533 TScreen *screen = TScreenOf(xw); 8534 IChar *buf = screen->unparse_bfr; 8535 unsigned len; 8536 8537 if ((screen->unparse_len + 2) >= screen->unparse_max) 8538 unparse_end(xw); 8539 8540 len = screen->unparse_len; 8541 8542#if OPT_TCAP_QUERY 8543 /* 8544 * If we're returning a termcap string, it has to be translated since 8545 * a DCS must not contain any characters except for the normal 7-bit 8546 * printable ASCII (counting tab, carriage return, etc). For now, 8547 * just use hexadecimal for the whole thing. 8548 */ 8549 if (screen->tc_query_code >= 0) { 8550 char tmp[3]; 8551 sprintf(tmp, "%02X", c & 0xFF); 8552 buf[len++] = CharOf(tmp[0]); 8553 buf[len++] = CharOf(tmp[1]); 8554 } else 8555#endif 8556 if ((buf[len++] = (IChar) c) == '\r' && (xw->flags & LINEFEED)) { 8557 buf[len++] = '\n'; 8558 } 8559 8560 screen->unparse_len = len; 8561 8562 /* If send/receive mode is reset, we echo characters locally */ 8563 if ((xw->keyboard.flags & MODE_SRM) == 0) { 8564 doparsing(xw, (unsigned) c, &myState); 8565 } 8566} 8567 8568void 8569unparse_end(XtermWidget xw) 8570{ 8571 TScreen *screen = TScreenOf(xw); 8572 8573#if OPT_TCAP_QUERY 8574 /* 8575 * tcap-query works by simulating key-presses, which ordinarily would be 8576 * flushed out at the end of each key. For better efficiency, do not do 8577 * the flush unless we are about to fill the buffer used to capture the 8578 * response. 8579 */ 8580 if ((screen->tc_query_code >= 0) 8581 && (screen->unparse_len + 2 < screen->unparse_max)) { 8582 return; 8583 } 8584#endif 8585 if (screen->unparse_len) { 8586 TRACE(("unparse_end %u:%s\n", 8587 screen->unparse_len, 8588 visibleIChars(screen->unparse_bfr, screen->unparse_len))); 8589#ifdef VMS 8590 tt_write(screen->unparse_bfr, screen->unparse_len); 8591#else /* VMS */ 8592 writePtyData(screen->respond, screen->unparse_bfr, screen->unparse_len); 8593#endif /* VMS */ 8594 screen->unparse_len = 0; 8595 } 8596} 8597 8598void 8599ToggleAlternate(XtermWidget xw) 8600{ 8601 if (TScreenOf(xw)->whichBuf) 8602 FromAlternate(xw); 8603 else 8604 ToAlternate(xw, False); 8605} 8606 8607static void 8608ToAlternate(XtermWidget xw, Bool clearFirst) 8609{ 8610 TScreen *screen = TScreenOf(xw); 8611 8612 if (screen->whichBuf == 0) { 8613 TRACE(("ToAlternate\n")); 8614 if (!screen->editBuf_index[1]) { 8615 screen->editBuf_index[1] = allocScrnBuf(xw, 8616 (unsigned) MaxRows(screen), 8617 (unsigned) MaxCols(screen), 8618 &screen->editBuf_data[1]); 8619 } 8620 SwitchBufs(xw, 1, clearFirst); 8621 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 8622 update_altscreen(); 8623 } 8624} 8625 8626static void 8627FromAlternate(XtermWidget xw) 8628{ 8629 TScreen *screen = TScreenOf(xw); 8630 8631 if (screen->whichBuf != 0) { 8632 TRACE(("FromAlternate\n")); 8633 if (screen->scroll_amt) { 8634 FlushScroll(xw); 8635 } 8636 SwitchBufs(xw, 0, False); 8637 screen->visbuf = screen->editBuf_index[screen->whichBuf]; 8638 update_altscreen(); 8639 } 8640} 8641 8642static void 8643SwitchBufs(XtermWidget xw, int toBuf, Bool clearFirst) 8644{ 8645 TScreen *screen = TScreenOf(xw); 8646 int rows, top; 8647 8648 screen->whichBuf = toBuf; 8649 if (screen->cursor_state) 8650 HideCursor(xw); 8651 8652 rows = MaxRows(screen); 8653 SwitchBufPtrs(screen, toBuf); 8654 8655 if ((top = INX2ROW(screen, 0)) < rows) { 8656 if (screen->scroll_amt) { 8657 FlushScroll(xw); 8658 } 8659 xtermClear2(xw, 8660 (int) OriginX(screen), 8661 (int) top * FontHeight(screen) + screen->border, 8662 (unsigned) Width(screen), 8663 (unsigned) ((rows - top) * FontHeight(screen))); 8664 if (clearFirst) { 8665 ClearBufRows(xw, top, rows); 8666 } 8667 } 8668 ScrnUpdate(xw, 0, 0, rows, MaxCols(screen), False); 8669} 8670 8671Bool 8672CheckBufPtrs(TScreen *screen) 8673{ 8674 return (screen->visbuf != 0 8675 && screen->editBuf_index[0] != 0 8676 && screen->editBuf_index[1] != 0); 8677} 8678 8679/* 8680 * Swap buffer line pointers between alternate and regular screens. 8681 */ 8682void 8683SwitchBufPtrs(TScreen *screen, int toBuf) 8684{ 8685 if (CheckBufPtrs(screen)) { 8686 screen->visbuf = screen->editBuf_index[toBuf]; 8687 } 8688} 8689 8690void 8691VTRun(XtermWidget xw) 8692{ 8693 TScreen *screen = TScreenOf(xw); 8694 8695 TRACE(("VTRun ...\n")); 8696 8697 if (!screen->Vshow) { 8698 set_vt_visibility(True); 8699 } 8700 update_vttekmode(); 8701 update_vtshow(); 8702 update_tekshow(); 8703 set_vthide_sensitivity(); 8704 8705 ScrnAllocBuf(xw); 8706 8707 screen->cursor_state = OFF; 8708 screen->cursor_set = ON; 8709#if OPT_BLINK_CURS 8710 if (DoStartBlinking(screen)) 8711 StartBlinking(xw); 8712#endif 8713 8714#if OPT_TEK4014 8715 if (Tpushb > Tpushback) { 8716 fillPtyData(xw, VTbuffer, (char *) Tpushback, (int) (Tpushb - Tpushback)); 8717 Tpushb = Tpushback; 8718 } 8719#endif 8720 screen->is_running = True; 8721 if (screen->embed_high && screen->embed_wide) { 8722 ScreenResize(xw, screen->embed_wide, screen->embed_high, &(xw->flags)); 8723 } 8724#if OPT_MAXIMIZE 8725 else if (resource.fullscreen == esTrue || resource.fullscreen == esAlways) 8726 FullScreen(xw, True); 8727#endif 8728 if (!setjmp(VTend)) 8729 VTparse(xw); 8730 StopBlinking(xw); 8731 HideCursor(xw); 8732 screen->cursor_set = OFF; 8733 TRACE(("... VTRun\n")); 8734} 8735 8736/*ARGSUSED*/ 8737static void 8738VTExpose(Widget w GCC_UNUSED, 8739 XEvent *event, 8740 Region region GCC_UNUSED) 8741{ 8742 DEBUG_MSG("Expose\n"); 8743 if (event->type == Expose) 8744 HandleExposure(term, event); 8745} 8746 8747static void 8748VTGraphicsOrNoExpose(XEvent *event) 8749{ 8750 XtermWidget xw = term; 8751 TScreen *screen = TScreenOf(xw); 8752 if (screen->incopy <= 0) { 8753 screen->incopy = 1; 8754 if (screen->scrolls > 0) 8755 screen->scrolls--; 8756 } 8757 if (event->type == GraphicsExpose) 8758 if (HandleExposure(xw, event)) 8759 screen->cursor_state = OFF; 8760 if ((event->type == NoExpose) 8761 || ((XGraphicsExposeEvent *) event)->count == 0) { 8762 if (screen->incopy <= 0 && screen->scrolls > 0) 8763 screen->scrolls--; 8764 if (screen->scrolls) 8765 screen->incopy = -1; 8766 else 8767 screen->incopy = 0; 8768 } 8769} 8770 8771/*ARGSUSED*/ 8772static void 8773VTNonMaskableEvent(Widget w GCC_UNUSED, 8774 XtPointer closure GCC_UNUSED, 8775 XEvent *event, 8776 Boolean *cont GCC_UNUSED) 8777{ 8778 switch (event->type) { 8779 case GraphicsExpose: 8780 /* FALLTHRU */ 8781 case NoExpose: 8782 VTGraphicsOrNoExpose(event); 8783 break; 8784 } 8785} 8786 8787static void 8788VTResize(Widget w) 8789{ 8790 if (XtIsRealized(w)) { 8791 XtermWidget xw = (XtermWidget) w; 8792 ScreenResize(xw, xw->core.width, xw->core.height, &xw->flags); 8793 } 8794} 8795 8796#define okDimension(src,dst) ((src <= MAX_U_COORD) \ 8797 && ((dst = (Dimension) src) == src)) 8798 8799static void 8800RequestResize(XtermWidget xw, int rows, int cols, Bool text) 8801{ 8802 TScreen *screen = TScreenOf(xw); 8803 Dimension replyWidth, replyHeight; 8804 Dimension askedWidth, askedHeight; 8805 XtGeometryResult status; 8806 XWindowAttributes attrs; 8807#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8808 Boolean buggyXft = False; 8809 Cardinal ignore = 0; 8810#endif 8811 8812 TRACE(("RequestResize(rows=%d, cols=%d, text=%d)\n", rows, cols, text)); 8813#if OPT_STATUS_LINE 8814 if (IsStatusShown(screen) && (rows > 0)) { 8815 TRACE(("...reserve a row for status-line\n")); 8816 ++rows; 8817 } 8818#endif 8819 8820 /* check first if the row/column values fit into a Dimension */ 8821 if (cols > 0) { 8822 if ((int) (askedWidth = (Dimension) cols) < cols) { 8823 TRACE(("... cols too large for Dimension\n")); 8824 return; 8825 } 8826 } else { 8827 askedWidth = 0; 8828 } 8829 if (rows > 0) { 8830 if ((int) (askedHeight = (Dimension) rows) < rows) { 8831 TRACE(("... rows too large for Dimension\n")); 8832 return; 8833 } 8834 } else { 8835 askedHeight = 0; 8836 } 8837 8838 xw->work.doing_resize = True; 8839 8840#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8841 /* 8842 * Work around a bug seen when vttest switches from 132 columns back to 80 8843 * columns, while double-buffering is active. If Xft is active during the 8844 * resize, the screen will be blank thereafter. This workaround causes 8845 * some extra flickering, but that is preferable to a blank screen. 8846 * 8847 * Since the bitmap- and TrueType-fonts do not always have identical sizes, 8848 * do this switching early, to use the updated font-sizes in the request 8849 * for resizing the window. 8850 */ 8851#define ToggleXft() HandleRenderFont((Widget)xw, (XEvent *)0, (String *)0, &ignore) 8852 if (resource.buffered 8853 && UsingRenderFont(xw)) { 8854 ToggleXft(); 8855 buggyXft = True; 8856 } 8857#endif 8858 8859 /* 8860 * If the requested values will fit into a Dimension, and one or both are 8861 * zero, get the current corresponding screen dimension to use as a limit. 8862 */ 8863 if (askedHeight == 0 8864 || askedWidth == 0 8865 || xw->misc.limit_resize > 0) { 8866 xtermGetWinAttrs(XtDisplay(xw), 8867 RootWindowOfScreen(XtScreen(xw)), &attrs); 8868 } 8869 8870 /* 8871 * Using the current font metrics, translate the requested character 8872 * rows/columns into pixels. 8873 */ 8874 if (text) { 8875 unsigned long value; 8876 8877 if ((value = (unsigned long) rows) != 0) { 8878 if (rows < 0) 8879 value = (unsigned long) MaxRows(screen); 8880 value *= (unsigned long) FontHeight(screen); 8881 value += (unsigned long) (2 * screen->border); 8882 if (!okDimension(value, askedHeight)) 8883 goto give_up; 8884 } 8885 8886 if ((value = (unsigned long) cols) != 0) { 8887 if (cols < 0) 8888 value = (unsigned long) MaxCols(screen); 8889 value *= (unsigned long) FontWidth(screen); 8890 value += (unsigned long) ((2 * screen->border) 8891 + ScrollbarWidth(screen)); 8892 if (!okDimension(value, askedWidth)) 8893 goto give_up; 8894 } 8895 8896 } else { 8897 if (rows < 0) 8898 askedHeight = FullHeight(screen); 8899 if (cols < 0) 8900 askedWidth = FullWidth(screen); 8901 } 8902 8903 if (rows == 0) { 8904 askedHeight = (Dimension) attrs.height; 8905 } 8906 if (cols == 0) { 8907 askedWidth = (Dimension) attrs.width; 8908 } 8909 8910 if (xw->misc.limit_resize > 0) { 8911 Dimension high = (Dimension) (xw->misc.limit_resize * attrs.height); 8912 Dimension wide = (Dimension) (xw->misc.limit_resize * attrs.width); 8913 if ((int) high < attrs.height) 8914 high = (Dimension) attrs.height; 8915 if (askedHeight > high) 8916 askedHeight = high; 8917 if ((int) wide < attrs.width) 8918 wide = (Dimension) attrs.width; 8919 if (askedWidth > wide) 8920 askedWidth = wide; 8921 } 8922#ifndef nothack 8923 getXtermSizeHints(xw); 8924#endif 8925 8926 TRACE(("...requesting resize %dx%d (%dx%d)\n", 8927 askedHeight, askedWidth, 8928 askedHeight / FontHeight(screen), 8929 askedWidth / FontWidth(screen))); 8930 status = REQ_RESIZE((Widget) xw, 8931 askedWidth, askedHeight, 8932 &replyWidth, &replyHeight); 8933 8934 if (status == XtGeometryYes || 8935 status == XtGeometryDone) { 8936 ScreenResize(xw, replyWidth, replyHeight, &xw->flags); 8937 } 8938#ifndef nothack 8939 /* 8940 * XtMakeResizeRequest() has the undesirable side-effect of clearing 8941 * the window manager's hints, even on a failed request. This would 8942 * presumably be fixed if the shell did its own work. 8943 */ 8944 if (xw->hints.flags 8945 && replyHeight 8946 && replyWidth) { 8947 xw->hints.height = replyHeight; 8948 xw->hints.width = replyWidth; 8949 8950 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 8951 TRACE_HINTS(&xw->hints); 8952 XSetWMNormalHints(screen->display, VShellWindow(xw), &xw->hints); 8953 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 8954 TRACE_WM_HINTS(xw); 8955 } 8956#endif 8957 8958 XSync(screen->display, False); /* synchronize */ 8959 if (xtermAppPending()) { 8960 xevents(xw); 8961 } 8962 8963 give_up: 8964#if OPT_RENDERFONT && USE_DOUBLE_BUFFER 8965 if (buggyXft) { 8966 ToggleXft(); 8967 if (xtermAppPending()) { 8968 xevents(xw); 8969 } 8970 } 8971#endif 8972 8973 xw->work.doing_resize = False; 8974 8975 TRACE(("...RequestResize done\n")); 8976 return; 8977} 8978 8979static String xterm_trans = 8980"<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\ 8981 <MappingNotify>: KeyboardMapping()\n"; 8982 8983int 8984VTInit(XtermWidget xw) 8985{ 8986 Widget vtparent = SHELL_OF(xw); 8987 8988 TRACE(("VTInit " TRACE_L "\n")); 8989 8990 XtRealizeWidget(vtparent); 8991 XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans)); 8992 (void) XSetWMProtocols(XtDisplay(vtparent), XtWindow(vtparent), 8993 &wm_delete_window, 1); 8994 8995 if (IsEmpty(xw->keyboard.print_translations)) { 8996 TRACE_TRANS("shell", vtparent); 8997 TRACE_TRANS("vt100", (Widget) (xw)); 8998 xtermButtonInit(xw); 8999 } 9000 9001 ScrnAllocBuf(xw); 9002 9003 TRACE(("..." TRACE_R " VTInit\n")); 9004 return (1); 9005} 9006 9007static void 9008VTClassInit(void) 9009{ 9010 XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, 9011 (XtConvertArgList) NULL, (Cardinal) 0); 9012} 9013 9014/* 9015 * Override the use of XtDefaultForeground/XtDefaultBackground to make some 9016 * colors, such as cursor color, use the actual foreground/background value 9017 * if there is no explicit resource value used. 9018 */ 9019static Pixel 9020fill_Tres(XtermWidget target, XtermWidget source, int offset) 9021{ 9022 char *name; 9023 ScrnColors temp; 9024 TScreen *src = TScreenOf(source); 9025 TScreen *dst = TScreenOf(target); 9026 9027 dst->Tcolors[offset] = src->Tcolors[offset]; 9028 dst->Tcolors[offset].mode = False; 9029 9030 if ((name = x_strtrim(dst->Tcolors[offset].resource)) != 0) 9031 dst->Tcolors[offset].resource = name; 9032 9033 if (name == 0) { 9034 dst->Tcolors[offset].value = target->dft_foreground; 9035 } else if (isDefaultForeground(name)) { 9036 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 9037 ? target->dft_foreground 9038 : dst->Tcolors[TEXT_FG].value); 9039 } else if (isDefaultBackground(name)) { 9040 dst->Tcolors[offset].value = ((offset == TEXT_FG || offset == TEXT_BG) 9041 ? target->dft_background 9042 : dst->Tcolors[TEXT_BG].value); 9043 } else { 9044 memset(&temp, 0, sizeof(temp)); 9045 if (AllocateTermColor(target, &temp, offset, name, True)) { 9046 if (COLOR_DEFINED(&(temp), offset)) 9047 free(temp.names[offset]); 9048 dst->Tcolors[offset].value = temp.colors[offset]; 9049 } else if (offset == TEXT_FG || offset == TEXT_BG) { 9050 free(name); 9051 dst->Tcolors[offset].resource = 0; 9052 } 9053 } 9054 return dst->Tcolors[offset].value; 9055} 9056 9057/* 9058 * If one or both of the foreground/background colors cannot be allocated, 9059 * e.g., due to gross misconfiguration, recover by setting both to the 9060 * display's default values. 9061 */ 9062static void 9063repairColors(XtermWidget target) 9064{ 9065 TScreen *screen = TScreenOf(target); 9066 9067 if (screen->Tcolors[TEXT_FG].resource == 0 || 9068 screen->Tcolors[TEXT_BG].resource == 0) { 9069 xtermWarning("unable to allocate fg/bg colors\n"); 9070 screen->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultForeground); 9071 screen->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultBackground); 9072 if (screen->Tcolors[TEXT_FG].resource == 0 || 9073 screen->Tcolors[TEXT_BG].resource == 0) { 9074 Exit(1); 9075 } 9076 screen->Tcolors[TEXT_FG].value = target->dft_foreground; 9077 screen->Tcolors[TEXT_BG].value = target->dft_background; 9078 } 9079} 9080 9081#if OPT_WIDE_CHARS 9082static void 9083set_utf8_feature(TScreen *screen, int *feature) 9084{ 9085 if (*feature == uDefault) { 9086 switch (screen->utf8_mode) { 9087 case uFalse: 9088 /* FALLTHRU */ 9089 case uTrue: 9090 *feature = screen->utf8_mode; 9091 break; 9092 case uDefault: 9093 /* should not happen */ 9094 *feature = uTrue; 9095 break; 9096 case uAlways: 9097 /* use this to disable menu entry */ 9098 break; 9099 } 9100 } 9101} 9102 9103static void 9104VTInitialize_locale(XtermWidget xw) 9105{ 9106 TScreen *screen = TScreenOf(xw); 9107 Bool is_utf8 = xtermEnvUTF8(); 9108 9109 TRACE(("VTInitialize_locale\n")); 9110 TRACE(("... request screen.utf8_mode = %d\n", screen->utf8_mode)); 9111 TRACE(("... request screen.utf8_fonts = %d\n", screen->utf8_fonts)); 9112 TRACE(("... request screen.utf8_title = %d\n", screen->utf8_title)); 9113 9114 screen->utf8_always = (screen->utf8_mode == uAlways); 9115 if (screen->utf8_mode < 0) 9116 screen->utf8_mode = uFalse; 9117 9118 if (screen->utf8_mode > 3) 9119 screen->utf8_mode = uDefault; 9120 9121 screen->latin9_mode = 0; 9122 screen->unicode_font = 0; 9123#if OPT_LUIT_PROG 9124 xw->misc.callfilter = 0; 9125 xw->misc.use_encoding = 0; 9126 9127 TRACE(("... setup for luit:\n")); 9128 TRACE(("... request misc.locale_str = \"%s\"\n", xw->misc.locale_str)); 9129 9130 if (screen->utf8_mode == uFalse) { 9131 TRACE(("... command-line +u8 overrides\n")); 9132 } else 9133#if OPT_MINI_LUIT 9134 if (x_strcasecmp(xw->misc.locale_str, "CHECKFONT") == 0) { 9135 int fl = (int) strlen(DefaultFontN(xw)); 9136 if (fl > 11 9137 && x_strcasecmp(DefaultFontN(xw) + fl - 11, "-ISO10646-1") == 0) { 9138 screen->unicode_font = 1; 9139 /* unicode font, use True */ 9140#ifdef HAVE_LANGINFO_CODESET 9141 if (!strcmp(xtermEnvEncoding(), "ANSI_X3.4-1968") 9142 || !strcmp(xtermEnvEncoding(), "ISO-8859-1")) { 9143 if (screen->utf8_mode == uDefault) 9144 screen->utf8_mode = uFalse; 9145 } else if (!strcmp(xtermEnvEncoding(), "ISO-8859-15")) { 9146 if (screen->utf8_mode == uDefault) 9147 screen->utf8_mode = uFalse; 9148 screen->latin9_mode = 1; 9149 } else { 9150 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 9151 screen->utf8_mode = uAlways; 9152 } 9153#else 9154 xw->misc.callfilter = is_utf8 ? 0 : 1; 9155 screen->utf8_mode = uAlways; 9156#endif 9157 } else { 9158 /* other encoding, use False */ 9159 if (screen->utf8_mode == uDefault) { 9160 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9161 } 9162 } 9163 } else 9164#endif /* OPT_MINI_LUIT */ 9165 if (x_strcasecmp(xw->misc.locale_str, "TRUE") == 0 || 9166 x_strcasecmp(xw->misc.locale_str, "ON") == 0 || 9167 x_strcasecmp(xw->misc.locale_str, "YES") == 0 || 9168 x_strcasecmp(xw->misc.locale_str, "AUTO") == 0 || 9169 strcmp(xw->misc.locale_str, "1") == 0) { 9170 /* when true ... fully obeying LC_CTYPE locale */ 9171 xw->misc.callfilter = (Boolean) (is_utf8 ? 0 : 1); 9172 screen->utf8_mode = uAlways; 9173 } else if (x_strcasecmp(xw->misc.locale_str, "FALSE") == 0 || 9174 x_strcasecmp(xw->misc.locale_str, "OFF") == 0 || 9175 x_strcasecmp(xw->misc.locale_str, "NO") == 0 || 9176 strcmp(xw->misc.locale_str, "0") == 0) { 9177 /* when false ... original value of utf8_mode is effective */ 9178 if (screen->utf8_mode == uDefault) { 9179 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9180 } 9181 } else if (x_strcasecmp(xw->misc.locale_str, "MEDIUM") == 0 || 9182 x_strcasecmp(xw->misc.locale_str, "SEMIAUTO") == 0) { 9183 /* when medium ... obeying locale only for UTF-8 and Asian */ 9184 if (is_utf8) { 9185 screen->utf8_mode = uAlways; 9186 } else if ( 9187#ifdef MB_CUR_MAX 9188 MB_CUR_MAX > 1 || 9189#else 9190 !strncmp(xtermEnvLocale(), "ja", (size_t) 2) || 9191 !strncmp(xtermEnvLocale(), "ko", (size_t) 2) || 9192 !strncmp(xtermEnvLocale(), "zh", (size_t) 2) || 9193#endif 9194 !strncmp(xtermEnvLocale(), "th", (size_t) 2) || 9195 !strncmp(xtermEnvLocale(), "vi", (size_t) 2)) { 9196 xw->misc.callfilter = 1; 9197 screen->utf8_mode = uAlways; 9198 } else { 9199 screen->utf8_mode = uFalse; 9200 } 9201 } else if (x_strcasecmp(xw->misc.locale_str, "UTF-8") == 0 || 9202 x_strcasecmp(xw->misc.locale_str, "UTF8") == 0) { 9203 /* when UTF-8 ... UTF-8 mode */ 9204 screen->utf8_mode = uAlways; 9205 } else { 9206 /* other words are regarded as encoding name passed to luit */ 9207 xw->misc.callfilter = 1; 9208 screen->utf8_mode = uAlways; 9209 xw->misc.use_encoding = 1; 9210 } 9211 TRACE(("... updated misc.callfilter = %s\n", BtoS(xw->misc.callfilter))); 9212 TRACE(("... updated misc.use_encoding = %s\n", BtoS(xw->misc.use_encoding))); 9213#else 9214 if (screen->utf8_mode == uDefault) { 9215 screen->utf8_mode = is_utf8 ? uAlways : uFalse; 9216 } 9217#endif /* OPT_LUIT_PROG */ 9218 9219 set_utf8_feature(screen, &screen->utf8_fonts); 9220 set_utf8_feature(screen, &screen->utf8_title); 9221 9222 screen->utf8_inparse = (Boolean) (screen->utf8_mode != uFalse); 9223 9224 TRACE(("... updated screen.utf8_mode = %d\n", screen->utf8_mode)); 9225 TRACE(("... updated screen.utf8_fonts = %d\n", screen->utf8_fonts)); 9226 TRACE(("... updated screen.utf8_title = %d\n", screen->utf8_title)); 9227 TRACE(("...VTInitialize_locale done\n")); 9228} 9229#endif 9230 9231void 9232lookupSelectUnit(XtermWidget xw, Cardinal item, String value) 9233{ 9234 /* *INDENT-OFF* */ 9235 static const struct { 9236 const char * name; 9237 SelectUnit code; 9238 } table[] = { 9239 { "char", Select_CHAR }, 9240 { "word", Select_WORD }, 9241 { "line", Select_LINE }, 9242 { "group", Select_GROUP }, 9243 { "page", Select_PAGE }, 9244 { "all", Select_ALL }, 9245#if OPT_SELECT_REGEX 9246 { "regex", Select_REGEX }, 9247#endif 9248 }; 9249 /* *INDENT-ON* */ 9250 9251 TScreen *screen = TScreenOf(xw); 9252 String next = x_skip_nonblanks(value); 9253 Cardinal n; 9254 9255 screen->selectMap[item] = NSELECTUNITS; 9256 for (n = 0; n < XtNumber(table); ++n) { 9257 if (!x_strncasecmp(table[n].name, value, (unsigned) (next - value))) { 9258 screen->selectMap[item] = table[n].code; 9259#if OPT_SELECT_REGEX 9260 if (table[n].code == Select_REGEX) { 9261 screen->selectExpr[item] = x_strtrim(next); 9262 TRACE(("Parsed regex \"%s\"\n", screen->selectExpr[item])); 9263 } 9264#endif 9265 break; 9266 } 9267 } 9268} 9269 9270static void 9271ParseOnClicks(XtermWidget wnew, XtermWidget wreq, Cardinal item) 9272{ 9273 lookupSelectUnit(wnew, item, TScreenOf(wreq)->onClick[item]); 9274} 9275 9276/* 9277 * Parse a comma-separated list, returning a string which the caller must 9278 * free, and updating the source pointer. 9279 */ 9280static char * 9281ParseList(const char **source) 9282{ 9283 const char *base = *source; 9284 const char *next; 9285 char *value = 0; 9286 char *result; 9287 9288 /* ignore empty values */ 9289 while (*base == ',') 9290 ++base; 9291 9292 if (*base != '\0') { 9293 size_t size; 9294 9295 next = base; 9296 while (*next != '\0' && *next != ',') 9297 ++next; 9298 size = (size_t) (1 + next - base); 9299 value = malloc(size); 9300 if (value != 0) { 9301 memcpy(value, base, size); 9302 value[size - 1] = '\0'; 9303 } 9304 *source = next; 9305 } else { 9306 *source = base; 9307 } 9308 result = x_strtrim(value); 9309 free(value); 9310 return result; 9311} 9312 9313static void 9314set_flags_from_list(char *target, 9315 const char *source, 9316 const FlagList * list) 9317{ 9318 Cardinal n; 9319 9320 while (!IsEmpty(source)) { 9321 char *next = ParseList(&source); 9322 Boolean found = False; 9323 char flag = 1; 9324 9325 if (next == 0) 9326 break; 9327 if (*next == '~') { 9328 flag = 0; 9329 next++; 9330 } 9331 if (isdigit(CharOf(*next))) { 9332 char *temp; 9333 int value = (int) strtol(next, &temp, 0); 9334 if (!FullS2L(next, temp)) { 9335 xtermWarning("Expected a number: %s\n", next); 9336 } else { 9337 for (n = 0; list[n].name != 0; ++n) { 9338 if (list[n].code == value) { 9339 target[value] = flag; 9340 found = True; 9341 TRACE(("...found %s (%d)\n", list[n].name, value)); 9342 break; 9343 } 9344 } 9345 } 9346 } else { 9347 for (n = 0; list[n].name != 0; ++n) { 9348 if (!x_wildstrcmp(next, list[n].name)) { 9349 int value = list[n].code; 9350 target[value] = flag; 9351 found = True; 9352 TRACE(("...found %s (%d)\n", list[n].name, value)); 9353 } 9354 } 9355 } 9356 if (!found) { 9357 xtermWarning("Unrecognized keyword: %s\n", next); 9358 } 9359 free(next); 9360 } 9361} 9362 9363#define InitCursorShape(target, source) \ 9364 target->cursor_shape = source->cursor_underline \ 9365 ? CURSOR_UNDERLINE \ 9366 : CURSOR_BLOCK 9367 9368#if OPT_XRES_QUERY 9369static XtResource * 9370findVT100Resource(const char *name) 9371{ 9372 Cardinal n; 9373 XtResource *result = 0; 9374 9375 if (!IsEmpty(name)) { 9376 XrmQuark quarkName = XrmPermStringToQuark(name); 9377 for (n = 0; n < XtNumber(xterm_resources); ++n) { 9378 if ((int) xterm_resources[n].resource_offset >= 0 9379 && !strcmp(xterm_resources[n].resource_name, name)) { 9380 result = &xterm_resources[n]; 9381 break; 9382 } else if (xterm_resources[n].resource_name 9383 == (String) (intptr_t) quarkName) { 9384 result = &xterm_resources[n]; 9385 break; 9386 } 9387 } 9388 } 9389 return result; 9390} 9391 9392static int 9393cmp_resources(const void *a, const void *b) 9394{ 9395 return strcmp((*(const String *) a), 9396 (*(const String *) b)); 9397} 9398 9399static void 9400reportResources(XtermWidget xw) 9401{ 9402 String *list = TypeMallocN(String, XtNumber(xterm_resources)); 9403 Cardinal n; 9404 int widest = 0; 9405 9406 if (list == NULL) 9407 return; 9408 9409 for (n = 0; n < XtNumber(xterm_resources); ++n) { 9410 int width; 9411 list[n] = (((int) xterm_resources[n].resource_offset < 0) 9412 ? XrmQuarkToString((XrmQuark) (intptr_t) 9413 xterm_resources[n].resource_name) 9414 : xterm_resources[n].resource_name); 9415 width = (int) strlen(list[n]); 9416 if (widest < width) 9417 widest = width; 9418 } 9419 qsort(list, (size_t) XtNumber(xterm_resources), sizeof(String), cmp_resources); 9420 for (n = 0; n < XtNumber(xterm_resources); ++n) { 9421 char *value = vt100ResourceToString(xw, list[n]); 9422 printf("%-*s : %s\n", widest, list[n], value ? value : "(skip)"); 9423 free(value); 9424 } 9425 free(list); 9426} 9427 9428char * 9429vt100ResourceToString(XtermWidget xw, const char *name) 9430{ 9431 XtResource *data; 9432 char *result = NULL; 9433 9434 if ((data = findVT100Resource(name)) != 0) { 9435 int fake_offset = (int) data->resource_offset; 9436 void *res_addr; 9437 int real_offset; 9438 String res_type; 9439 9440 /* 9441 * X Toolkit "compiles" the resource-list into quarks and changes the 9442 * resource-offset at the same time to a negative value. 9443 */ 9444 if (fake_offset < 0) { 9445 real_offset = -(fake_offset + 1); 9446 res_type = XrmQuarkToString((XrmQuark) (intptr_t) data->resource_type); 9447 } else { 9448 real_offset = fake_offset; 9449 res_type = data->resource_type; 9450 } 9451 res_addr = (void *) ((char *) xw + real_offset); 9452 9453 if (!strcmp(res_type, XtRString)) { 9454 char *value = *(char **) res_addr; 9455 if (value != NULL) { 9456 size_t need = strlen(value); 9457 if ((result = malloc(1 + need)) != 0) 9458 strcpy(result, value); 9459 } 9460 } else if (!strcmp(res_type, XtRInt)) { 9461 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0) 9462 sprintf(result, "%d", *(int *) res_addr); 9463 } else if (!strcmp(res_type, XtRFloat)) { 9464 if ((result = malloc(1 + (size_t) (3 * data->resource_size))) != 0) 9465 sprintf(result, "%f", (double) (*(float *) res_addr)); 9466 } else if (!strcmp(res_type, XtRBoolean)) { 9467 if ((result = malloc((size_t) 6)) != 0) 9468 strcpy(result, *(Boolean *) res_addr ? "true" : "false"); 9469 } 9470 } 9471 TRACE(("vt100ResourceToString(%s) %s\n", name, NonNull(result))); 9472 return result; 9473} 9474#endif /* OPT_XRES_QUERY */ 9475 9476/* 9477 * Decode a terminal-ID or graphics-terminal-ID, using the default terminal-ID 9478 * if the value is outside a (looser) range than limitedTerminalID. This uses 9479 * a wider range, to avoid being a nuisance when using X resources with 9480 * different configurations of xterm. 9481 */ 9482static int 9483decodeTerminalID(const char *value) 9484{ 9485 const char *s; 9486 char *t; 9487 long result; 9488 9489 for (s = value; *s; s++) { 9490 if (!isalpha(CharOf(*s))) 9491 break; 9492 } 9493 result = strtol(s, &t, 10); 9494 if (t == s || *t != '\0' || result <= 0L || result > 1000L) { 9495 xtermWarning("unexpected value for terminalID: \"%s\"\n", value); 9496 result = atoi(DFT_DECID); 9497 } 9498 TRACE(("decodeTerminalID \"%s\" ->%d\n", value, (int) result)); 9499 return (int) result; 9500} 9501 9502/* 9503 * Ensures that the value returned by decodeTerminalID is either in the range 9504 * of IDs matching a known terminal, or (failing that), set to the built-in 9505 * default. The DA response relies on having the ID being set to a known 9506 * value. 9507 */ 9508static int 9509limitedTerminalID(int terminal_id) 9510{ 9511 if (terminal_id < MIN_DECID) 9512 terminal_id = MIN_DECID; 9513 else if (terminal_id > MAX_DECID) 9514 terminal_id = MAX_DECID; 9515 else 9516 terminal_id = atoi(DFT_DECID); 9517 return terminal_id; 9518} 9519 9520/* ARGSUSED */ 9521static void 9522VTInitialize(Widget wrequest, 9523 Widget new_arg, 9524 ArgList args GCC_UNUSED, 9525 Cardinal *num_args GCC_UNUSED) 9526{ 9527#define Kolor(name) TScreenOf(wnew)->name.resource 9528#define TxtFg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_FG]), Kolor(name)) 9529#define TxtBg(name) !x_strcasecmp(Kolor(Tcolors[TEXT_BG]), Kolor(name)) 9530#define DftFg(name) isDefaultForeground(Kolor(name)) 9531#define DftBg(name) isDefaultBackground(Kolor(name)) 9532 9533#define DATA_END { NULL, -1 } 9534 9535#if OPT_BLINK_CURS 9536#define DATA(name) { #name, cb##name } 9537 static const FlagList tblBlinkOps[] = 9538 { 9539 DATA(Always) 9540 ,DATA(Never) 9541 ,DATA_END 9542 }; 9543#undef DATA 9544#endif 9545 9546#define DATA(name) { #name, ec##name } 9547 static const FlagList tblColorOps[] = 9548 { 9549 DATA(SetColor) 9550 ,DATA(GetColor) 9551 ,DATA(GetAnsiColor) 9552 ,DATA_END 9553 }; 9554#undef DATA 9555 9556#define DATA(name) { #name, ef##name } 9557 static const FlagList tblFontOps[] = 9558 { 9559 DATA(SetFont) 9560 ,DATA(GetFont) 9561 ,DATA_END 9562 }; 9563#undef DATA 9564 9565#define DATA(name) { #name, em##name } 9566 static const FlagList tblMouseOps[] = 9567 { 9568 DATA(X10) 9569 ,DATA(Locator) 9570 ,DATA(VT200Click) 9571 ,DATA(VT200Hilite) 9572 ,DATA(AnyButton) 9573 ,DATA(AnyEvent) 9574 ,DATA(FocusEvent) 9575 ,DATA(Extended) 9576 ,DATA(SGR) 9577 ,DATA(URXVT) 9578 ,DATA(AlternateScroll) 9579 ,DATA_END 9580 }; 9581#undef DATA 9582 9583#define DATA(name) { #name, ep##name } 9584#define DATA2(alias,name) { #alias, ep##name } 9585 static const FlagList tblPasteControls[] = 9586 { 9587 DATA(NUL) 9588 ,DATA(SOH) 9589 ,DATA(STX) 9590 ,DATA(ETX) 9591 ,DATA(EOT) 9592 ,DATA(ENQ) 9593 ,DATA(ACK) 9594 ,DATA(BEL) 9595 ,DATA(BS) 9596 ,DATA(HT) 9597 ,DATA(LF) 9598 ,DATA(VT) 9599 ,DATA(FF) 9600 ,DATA(CR) 9601 ,DATA(SO) 9602 ,DATA(SI) 9603 ,DATA(DLE) 9604 ,DATA(DC1) 9605 ,DATA(DC2) 9606 ,DATA(DC3) 9607 ,DATA(DC4) 9608 ,DATA(NAK) 9609 ,DATA(SYN) 9610 ,DATA(ETB) 9611 ,DATA(CAN) 9612 ,DATA(EM) 9613 ,DATA(SUB) 9614 ,DATA(ESC) 9615 ,DATA(FS) 9616 ,DATA(GS) 9617 ,DATA(RS) 9618 ,DATA(US) 9619 /* aliases */ 9620 ,DATA2(NL, LF) 9621 ,DATA(C0) 9622 ,DATA(DEL) 9623 ,DATA_END 9624 }; 9625#undef DATA 9626#undef DATA2 9627 9628#define DATA(name) { #name, et##name } 9629 static const FlagList tblTcapOps[] = 9630 { 9631 DATA(SetTcap) 9632 ,DATA(GetTcap) 9633 ,DATA_END 9634 }; 9635#undef DATA 9636 9637#define DATA(name) { #name, ew##name } 9638 static const FlagList tblWindowOps[] = 9639 { 9640 DATA(RestoreWin) 9641 ,DATA(MinimizeWin) 9642 ,DATA(SetWinPosition) 9643 ,DATA(SetWinSizePixels) 9644 ,DATA(RaiseWin) 9645 ,DATA(LowerWin) 9646 ,DATA(RefreshWin) 9647 ,DATA(SetWinSizeChars) 9648#if OPT_MAXIMIZE 9649 ,DATA(MaximizeWin) 9650 ,DATA(FullscreenWin) 9651#endif 9652 ,DATA(GetWinState) 9653 ,DATA(GetWinPosition) 9654 ,DATA(GetWinSizePixels) 9655 ,DATA(GetWinSizeChars) 9656#if OPT_MAXIMIZE 9657 ,DATA(GetScreenSizeChars) 9658#endif 9659 ,DATA(GetIconTitle) 9660 ,DATA(GetWinTitle) 9661 ,DATA(PushTitle) 9662 ,DATA(PopTitle) 9663 /* this item uses all remaining numbers in the sequence */ 9664 ,DATA(SetWinLines) 9665 /* starting at this point, numbers do not apply */ 9666 ,DATA(SetXprop) 9667 ,DATA(GetSelection) 9668 ,DATA(SetSelection) 9669 ,DATA(GetChecksum) 9670 ,DATA(SetChecksum) 9671 ,DATA_END 9672 }; 9673#undef DATA 9674 9675#if OPT_RENDERFONT 9676#define DATA(name) { #name, er##name } 9677 static const FlagList tblRenderFont[] = 9678 { 9679 DATA(Default) 9680 ,DATA(DefaultOff) 9681 ,DATA_END 9682 }; 9683#undef DATA 9684#endif 9685 9686#define DATA(name) { #name, ss##name } 9687 static const FlagList tblShift2S[] = 9688 { 9689 DATA(Always) 9690 ,DATA(Never) 9691 ,DATA_END 9692 }; 9693#undef DATA 9694 9695#if OPT_WIDE_CHARS 9696#define DATA(name) { #name, u##name } 9697 static const FlagList tblUtf8Mode[] = 9698 { 9699 DATA(Always) 9700 ,DATA(Default) 9701 ,DATA_END 9702 }; 9703#undef DATA 9704#endif 9705 9706#ifndef NO_ACTIVE_ICON 9707#define DATA(name) { #name, ei##name } 9708 static const FlagList tblAIconOps[] = 9709 { 9710 DATA(Default) 9711 ,DATA_END 9712 }; 9713#undef DATA 9714#endif 9715 9716#define DATA(name) { #name, eb##name } 9717 static const FlagList tbl8BitMeta[] = 9718 { 9719 DATA(Never) 9720 ,DATA(Locale) 9721 ,DATA_END 9722 }; 9723#undef DATA 9724 9725#define DATA(name) { #name, ed##name } 9726 static const FlagList tblCdXtraScroll[] = 9727 { 9728 DATA(Trim) 9729 ,DATA_END 9730 }; 9731#undef DATA 9732 9733 XtermWidget request = (XtermWidget) wrequest; 9734 XtermWidget wnew = (XtermWidget) new_arg; 9735 Widget my_parent = SHELL_OF(wnew); 9736 int i; 9737 9738#if OPT_ISO_COLORS 9739 Bool color_ok; 9740#endif 9741 9742#if OPT_ISO_COLORS 9743 static XtResource fake_resources[] = 9744 { 9745#if OPT_256_COLORS 9746# include <256colres.h> 9747#elif OPT_88_COLORS 9748# include <88colres.h> 9749#endif 9750 }; 9751#endif 9752 9753 TScreen *screen = TScreenOf(wnew); 9754 char *saveLocale = xtermSetLocale(LC_NUMERIC, "C"); 9755#if OPT_BLINK_CURS 9756 int ebValue; 9757#endif 9758 9759#if OPT_TRACE 9760 check_bitmasks(); 9761 check_tables(); 9762#endif 9763 9764 TRACE(("VTInitialize wnew %p, %d / %d resources " TRACE_L "\n", 9765 (void *) wnew, XtNumber(xterm_resources), MAXRESOURCES)); 9766 assert(XtNumber(xterm_resources) < MAXRESOURCES); 9767 9768 /* Zero out the entire "screen" component of "wnew" widget, then do 9769 * field-by-field assignment of "screen" fields that are named in the 9770 * resource list. 9771 */ 9772 memset(screen, 0, sizeof(wnew->screen)); 9773 9774 /* DESCO Sys#67660 9775 * Zero out the entire "keyboard" component of "wnew" widget. 9776 */ 9777 memset(&wnew->keyboard, 0, sizeof(wnew->keyboard)); 9778 9779 /* 9780 * The workspace has no resources - clear it. 9781 */ 9782 memset(&wnew->work, 0, sizeof(wnew->work)); 9783 9784 /* dummy values so that we don't try to Realize the parent shell with height 9785 * or width of 0, which is illegal in X. The real size is computed in the 9786 * xtermWidget's Realize proc, but the shell's Realize proc is called first, 9787 * and must see a valid size. 9788 */ 9789 wnew->core.height = wnew->core.width = 1; 9790 9791 /* 9792 * The definition of -rv now is that it changes the definition of 9793 * XtDefaultForeground and XtDefaultBackground. So, we no longer 9794 * need to do anything special. 9795 */ 9796 screen->display = wnew->core.screen->display; 9797 9798 /* prep getVisualInfo() */ 9799 wnew->visInfo = 0; 9800 wnew->numVisuals = 0; 9801 (void) getVisualInfo(wnew); 9802 9803#if OPT_STATUS_LINE 9804 StatusInit(&screen->status_data[0]); 9805 StatusInit(&screen->status_data[1]); 9806#endif 9807 9808 /* 9809 * We use the default foreground/background colors to compare/check if a 9810 * color-resource has been set. 9811 */ 9812#define MyBlackPixel(dpy) BlackPixel(dpy,DefaultScreen(dpy)) 9813#define MyWhitePixel(dpy) WhitePixel(dpy,DefaultScreen(dpy)) 9814 9815 if (request->misc.re_verse) { 9816 wnew->dft_foreground = MyWhitePixel(screen->display); 9817 wnew->dft_background = MyBlackPixel(screen->display); 9818 } else { 9819 wnew->dft_foreground = MyBlackPixel(screen->display); 9820 wnew->dft_background = MyWhitePixel(screen->display); 9821 } 9822 9823 init_Tres(TEXT_FG); 9824 init_Tres(TEXT_BG); 9825 repairColors(wnew); 9826 9827 wnew->old_foreground = T_COLOR(screen, TEXT_FG); 9828 wnew->old_background = T_COLOR(screen, TEXT_BG); 9829 9830 TRACE(("Color resource initialization:\n")); 9831 TRACE((" Default foreground 0x%06lx\n", wnew->dft_foreground)); 9832 TRACE((" Default background 0x%06lx\n", wnew->dft_background)); 9833 TRACE((" Screen foreground 0x%06lx\n", T_COLOR(screen, TEXT_FG))); 9834 TRACE((" Screen background 0x%06lx\n", T_COLOR(screen, TEXT_BG))); 9835 TRACE((" Actual foreground 0x%06lx\n", wnew->old_foreground)); 9836 TRACE((" Actual background 0x%06lx\n", wnew->old_background)); 9837 9838 screen->mouse_button = 0; 9839 screen->mouse_row = -1; 9840 screen->mouse_col = -1; 9841 9842#if OPT_BOX_CHARS 9843 init_Bres(screen.force_box_chars); 9844 init_Bres(screen.force_packed); 9845 init_Bres(screen.force_all_chars); 9846 init_Bres(screen.assume_all_chars); 9847#endif 9848 init_Bres(screen.free_bold_box); 9849 init_Bres(screen.allowBoldFonts); 9850 9851 init_Bres(screen.c132); 9852 init_Bres(screen.curses); 9853 init_Bres(screen.hp_ll_bc); 9854#if OPT_XMC_GLITCH 9855 init_Ires(screen.xmc_glitch); 9856 init_Ires(screen.xmc_attributes); 9857 init_Bres(screen.xmc_inline); 9858 init_Bres(screen.move_sgr_ok); 9859#endif 9860#if OPT_BLINK_CURS 9861 init_Sres(screen.cursor_blink_s); 9862 ebValue = extendedBoolean(wnew->screen.cursor_blink_s, tblBlinkOps, cbLAST); 9863 wnew->screen.cursor_blink = (BlinkOps) ebValue; 9864 init_Bres(screen.cursor_blink_xor); 9865 init_Ires(screen.blink_on); 9866 init_Ires(screen.blink_off); 9867 screen->cursor_blink_i = screen->cursor_blink; 9868#endif 9869 init_Bres(screen.cursor_underline); 9870 /* resources allow for underline or block, not (yet) bar */ 9871 InitCursorShape(screen, TScreenOf(request)); 9872#if OPT_BLINK_CURS 9873 TRACE(("cursor_shape:%d blinks:%d\n", 9874 screen->cursor_shape, 9875 screen->cursor_blink)); 9876#endif 9877#if OPT_BLINK_TEXT 9878 init_Ires(screen.blink_as_bold); 9879#endif 9880 init_Ires(screen.border); 9881 init_Bres(screen.jumpscroll); 9882 init_Bres(screen.fastscroll); 9883 9884 init_Bres(screen.old_fkeys); 9885 wnew->screen.old_fkeys0 = wnew->screen.old_fkeys; 9886 wnew->keyboard.type = screen->old_fkeys 9887 ? keyboardIsLegacy 9888 : keyboardIsDefault; 9889 9890 init_Mres(screen.delete_is_del); 9891#ifdef ALLOWLOGGING 9892 init_Bres(misc.logInhibit); 9893 init_Bres(misc.log_on); 9894 init_Sres(screen.logfile); 9895#endif 9896 init_Bres(screen.bellIsUrgent); 9897 init_Bres(screen.bellOnReset); 9898 init_Bres(screen.marginbell); 9899 init_Bres(screen.multiscroll); 9900 init_Ires(screen.nmarginbell); 9901 init_Ires(screen.savelines); 9902 init_Ires(screen.scrollBarBorder); 9903 init_Ires(screen.scrolllines); 9904 init_Bres(screen.alternateScroll); 9905 init_Bres(screen.scrollttyoutput); 9906 init_Bres(screen.scrollkey); 9907 9908 init_Dres(screen.scale_height); 9909 if (screen->scale_height < MIN_SCALE_HEIGHT) 9910 screen->scale_height = MIN_SCALE_HEIGHT; 9911 if (screen->scale_height > MAX_SCALE_HEIGHT) 9912 screen->scale_height = MAX_SCALE_HEIGHT; 9913 9914 init_Bres(misc.autoWrap); 9915 init_Bres(misc.login_shell); 9916 init_Bres(misc.reverseWrap); 9917 init_Bres(misc.scrollbar); 9918 init_Sres(misc.geo_metry); 9919 init_Sres(misc.T_geometry); 9920 9921 init_Sres(screen.term_id); 9922 screen->terminal_id = decodeTerminalID(TScreenOf(request)->term_id); 9923 /* 9924 * (1) If a known terminal model, and not a graphical terminal, preserve 9925 * the terminal id. 9926 * (2) Otherwise, if ReGIS or sixel graphics are enabled, preserve the ID, 9927 * even if it is not a known terminal. 9928 * (3) Otherwise force the terminal ID to the min, max, or VT420 depending 9929 * on the input. 9930 */ 9931 switch (screen->terminal_id) { 9932 case 52: /* MIN_DECID */ 9933 case 100: 9934 case 101: 9935 case 102: 9936 case 131: 9937 case 132: 9938 case 220: 9939 case 320: 9940 case 420: /* DFT_DECID, unless overridden in configure */ 9941 case 510: 9942 case 520: 9943 case 525: /* MAX_DECID */ 9944 break; 9945 default: 9946#if OPT_REGIS_GRAPHICS 9947 if (optRegisGraphics(screen)) 9948 break; 9949#endif 9950#if OPT_SIXEL_GRAPHICS 9951 if (optSixelGraphics(screen)) 9952 break; 9953#endif 9954 screen->terminal_id = limitedTerminalID(screen->terminal_id); 9955 break; 9956 } 9957 TRACE(("term_id '%s' -> terminal_id %d\n", 9958 screen->term_id, 9959 screen->terminal_id)); 9960 9961 screen->vtXX_level = (screen->terminal_id / 100); 9962 9963 init_Ires(screen.title_modes); 9964 screen->title_modes0 = screen->title_modes; 9965 9966 init_Ires(screen.nextEventDelay); 9967 if (screen->nextEventDelay <= 0) 9968 screen->nextEventDelay = 1; 9969 9970 init_Bres(screen.visualbell); 9971 init_Bres(screen.flash_line); 9972 init_Ires(screen.visualBellDelay); 9973 init_Bres(screen.poponbell); 9974 9975 init_Bres(screen.eraseSavedLines0); 9976 screen->eraseSavedLines = screen->eraseSavedLines0; 9977 9978 init_Ires(misc.limit_resize); 9979 9980#if OPT_NUM_LOCK 9981 init_Bres(misc.real_NumLock); 9982 init_Bres(misc.alwaysUseMods); 9983#endif 9984 9985#if OPT_INPUT_METHOD 9986 init_Bres(misc.open_im); 9987 init_Ires(misc.retry_im); 9988 init_Sres(misc.f_x); 9989 init_Sres(misc.input_method); 9990 init_Sres(misc.preedit_type); 9991#endif 9992 9993#if OPT_SHIFT_FONTS 9994 init_Bres(misc.shift_fonts); 9995#endif 9996#if OPT_SUNPC_KBD 9997 init_Ires(misc.ctrl_fkeys); 9998#endif 9999#if OPT_TEK4014 10000 TEK4014_SHOWN(wnew) = False; /* not a resource... */ 10001 init_Bres(misc.tekInhibit); 10002 init_Bres(misc.tekSmall); 10003 init_Bres(misc.TekEmu); 10004#endif 10005#if OPT_TCAP_QUERY 10006 screen->tc_query_code = -1; 10007#endif 10008 wnew->misc.re_verse0 = request->misc.re_verse; 10009 init_Bres(misc.re_verse); 10010 init_Ires(screen.multiClickTime); 10011 init_Ires(screen.bellSuppressTime); 10012 init_Sres(screen.charClass); 10013 10014 init_Bres(screen.always_highlight); 10015 init_Bres(screen.brokenSelections); 10016 init_Bres(screen.cutNewline); 10017 init_Bres(screen.cutToBeginningOfLine); 10018 init_Bres(screen.highlight_selection); 10019 init_Bres(screen.show_wrap_marks); 10020 init_Bres(screen.i18nSelections); 10021 init_Bres(screen.keepClipboard); 10022 init_Bres(screen.keepSelection); 10023 init_Bres(screen.selectToClipboard); 10024 init_Bres(screen.trim_selection); 10025 10026 screen->pointer_cursor = TScreenOf(request)->pointer_cursor; 10027 init_Ires(screen.pointer_mode); 10028 wnew->screen.pointer_mode0 = wnew->screen.pointer_mode; 10029 10030 init_Sres(screen.answer_back); 10031 10032 wnew->SPS.printer_checked = False; 10033 init_Sres(SPS.printer_command); 10034 init_Bres(SPS.printer_autoclose); 10035 init_Bres(SPS.printer_extent); 10036 init_Bres(SPS.printer_formfeed); 10037 init_Bres(SPS.printer_newline); 10038 init_Ires(SPS.printer_controlmode); 10039#if OPT_PRINT_COLORS 10040 init_Ires(SPS.print_attributes); 10041#endif 10042 10043 init_Sres(screen.keyboard_dialect); 10044 10045 init_Sres(screen.cursor_font_name); 10046 init_Sres(screen.pointer_shape); 10047 10048 init_Bres(screen.input_eight_bits); 10049 init_Bres(screen.output_eight_bits); 10050 init_Bres(screen.control_eight_bits); 10051 init_Bres(screen.backarrow_key); 10052 init_Bres(screen.alt_is_not_meta); 10053 init_Bres(screen.alt_sends_esc); 10054 init_Bres(screen.meta_sends_esc); 10055 10056 init_Bres(screen.allowPasteControl0); 10057 init_Bres(screen.allowSendEvent0); 10058 init_Bres(screen.allowColorOp0); 10059 init_Bres(screen.allowFontOp0); 10060 init_Bres(screen.allowMouseOp0); 10061 init_Bres(screen.allowTcapOp0); 10062 init_Bres(screen.allowTitleOp0); 10063 init_Bres(screen.allowWindowOp0); 10064 10065#if OPT_SCROLL_LOCK 10066 init_Bres(screen.allowScrollLock0); 10067 init_Bres(screen.autoScrollLock); 10068#endif 10069 10070 init_Sres(screen.disallowedColorOps); 10071 10072 set_flags_from_list(screen->disallow_color_ops, 10073 screen->disallowedColorOps, 10074 tblColorOps); 10075 10076 init_Sres(screen.disallowedFontOps); 10077 10078 set_flags_from_list(screen->disallow_font_ops, 10079 screen->disallowedFontOps, 10080 tblFontOps); 10081 10082 init_Sres(screen.disallowedMouseOps); 10083 10084 set_flags_from_list(screen->disallow_mouse_ops, 10085 screen->disallowedMouseOps, 10086 tblMouseOps); 10087 10088 init_Sres(screen.disallowedPasteControls); 10089 10090 set_flags_from_list(screen->disallow_paste_controls, 10091 screen->disallowedPasteControls, 10092 tblPasteControls); 10093 10094 init_Sres(screen.disallowedTcapOps); 10095 10096 set_flags_from_list(screen->disallow_tcap_ops, 10097 screen->disallowedTcapOps, 10098 tblTcapOps); 10099 10100 init_Sres(screen.disallowedWinOps); 10101 10102 set_flags_from_list(screen->disallow_win_ops, 10103 screen->disallowedWinOps, 10104 tblWindowOps); 10105 10106 init_Sres(screen.default_string); 10107 init_Sres(screen.eightbit_select_types); 10108#if OPT_WIDE_CHARS 10109 init_Sres(screen.utf8_select_types); 10110#endif 10111 10112 /* make a copy so that editres cannot change the resource after startup */ 10113 screen->allowPasteControls = screen->allowPasteControl0; 10114 screen->allowSendEvents = screen->allowSendEvent0; 10115 screen->allowColorOps = screen->allowColorOp0; 10116 screen->allowFontOps = screen->allowFontOp0; 10117 screen->allowMouseOps = screen->allowMouseOp0; 10118 screen->allowTcapOps = screen->allowTcapOp0; 10119 screen->allowTitleOps = screen->allowTitleOp0; 10120 screen->allowWindowOps = screen->allowWindowOp0; 10121 10122#if OPT_SCROLL_LOCK 10123 screen->allowScrollLock = screen->allowScrollLock0; 10124#endif 10125 10126 init_Bres(screen.quiet_grab); 10127 10128#ifndef NO_ACTIVE_ICON 10129 init_Sres(screen.icon_fontname); 10130 getIconicFont(screen)->fs = xtermLoadQueryFont(wnew, 10131 screen->icon_fontname); 10132 TRACE(("iconFont '%s' %sloaded successfully\n", 10133 screen->icon_fontname, 10134 getIconicFont(screen)->fs ? "" : "NOT ")); 10135 init_Sres(misc.active_icon_s); 10136 wnew->work.active_icon = 10137 (Boolean) extendedBoolean(wnew->misc.active_icon_s, 10138 tblAIconOps, eiLAST); 10139 init_Ires(misc.icon_border_width); 10140 wnew->misc.icon_border_pixel = request->misc.icon_border_pixel; 10141#endif /* NO_ACTIVE_ICON */ 10142 10143 init_Bres(misc.signalInhibit); 10144 init_Bres(misc.titeInhibit); 10145 init_Bres(misc.color_inner_border); 10146 init_Bres(misc.dynamicColors); 10147 init_Bres(misc.resizeByPixel); 10148 10149 init_Sres(misc.cdXtraScroll_s); 10150 wnew->misc.cdXtraScroll = 10151 extendedBoolean(request->misc.cdXtraScroll_s, tblCdXtraScroll, edLast); 10152 10153 init_Sres(misc.tiXtraScroll_s); 10154 wnew->misc.tiXtraScroll = 10155 extendedBoolean(request->misc.tiXtraScroll_s, tblCdXtraScroll, edLast); 10156 10157#if OPT_DEC_CHRSET 10158 for (i = 0; i < NUM_CHRSET; i++) { 10159 screen->double_fonts[i].warn = fwResource; 10160 } 10161#endif 10162 for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) { 10163 init_Sres2(screen.MenuFontName, i); 10164 } 10165 for (i = 0; i < fMAX; i++) { 10166 screen->fnts[i].warn = fwResource; 10167#if OPT_WIDE_ATTRS 10168 screen->ifnts[i].warn = fwResource; 10169#endif 10170 } 10171#ifndef NO_ACTIVE_ICON 10172 screen->fnt_icon.warn = fwResource; 10173#endif 10174 10175 init_Ires(misc.fontWarnings); 10176 10177 initFontLists(wnew); 10178 10179#define DefaultFontNames screen->menu_font_names[fontMenu_default] 10180 10181 /* 10182 * Process Xft font resources first, since faceName may contain X11 fonts 10183 * that should override the "font" resource. 10184 */ 10185#if OPT_RENDERFONT 10186 init_Bres(screen.force_xft_height); 10187 for (i = 0; i <= fontMenu_lastBuiltin; ++i) { 10188 init_Dres2(misc.face_size, i); 10189 } 10190 10191#define ALLOC_FONTLIST(name,which,field) \ 10192 init_Sres(misc.default_xft.field);\ 10193 allocFontList(wnew,\ 10194 name,\ 10195 &(wnew->work.fonts),\ 10196 which,\ 10197 wnew->misc.default_xft.field,\ 10198 True) 10199 10200 ALLOC_FONTLIST(XtNfaceName, fNorm, f_n); 10201 10202#if OPT_WIDE_CHARS 10203 ALLOC_FONTLIST(XtNfaceNameDoublesize, fWide, f_w); 10204#endif 10205 10206#undef ALLOC_FONTLIST 10207 10208#endif 10209 10210 /* 10211 * Process X11 (XLFD) font specifications. 10212 */ 10213#define ALLOC_FONTLIST(name,which,field) \ 10214 init_Sres(misc.default_font.field);\ 10215 allocFontList(wnew,\ 10216 name,\ 10217 &(wnew->work.fonts),\ 10218 which,\ 10219 wnew->misc.default_font.field,\ 10220 False) 10221 10222 ALLOC_FONTLIST(XtNfont, fNorm, f_n); 10223 ALLOC_FONTLIST(XtNboldFont, fBold, f_b); 10224 10225 DefaultFontNames[fNorm] = x_strdup(DefaultFontN(wnew)); 10226 DefaultFontNames[fBold] = x_strdup(DefaultFontB(wnew)); 10227 10228#if OPT_WIDE_CHARS 10229 ALLOC_FONTLIST(XtNwideFont, fWide, f_w); 10230 ALLOC_FONTLIST(XtNwideBoldFont, fWBold, f_wb); 10231 10232 DefaultFontNames[fWide] = x_strdup(DefaultFontW(wnew)); 10233 DefaultFontNames[fWBold] = x_strdup(DefaultFontWB(wnew)); 10234#endif 10235 10236#undef ALLOC_FONTLIST 10237 10238 screen->EscapeFontName() = NULL; 10239 screen->SelectFontName() = NULL; 10240 10241 screen->menu_font_number = fontMenu_default; 10242 init_Sres(screen.initial_font); 10243 if (screen->initial_font != 0) { 10244 int result = xtermGetFont(screen->initial_font); 10245 if (result >= 0) 10246 screen->menu_font_number = result; 10247 } 10248#if OPT_BROKEN_OSC 10249 init_Bres(screen.brokenLinuxOSC); 10250#endif 10251 10252#if OPT_BROKEN_ST 10253 init_Bres(screen.brokenStringTerm); 10254#endif 10255 10256#if OPT_C1_PRINT 10257 init_Bres(screen.c1_printable); 10258#endif 10259 10260#if OPT_CLIP_BOLD 10261 init_Bres(screen.use_border_clipping); 10262 init_Bres(screen.use_clipping); 10263#endif 10264 10265#if OPT_DEC_CHRSET 10266 init_Bres(screen.font_doublesize); 10267 init_Ires(screen.cache_doublesize); 10268 if (screen->cache_doublesize > NUM_CHRSET) 10269 screen->cache_doublesize = NUM_CHRSET; 10270 if (screen->cache_doublesize == 0) 10271 screen->font_doublesize = False; 10272 TRACE(("Doublesize%s enabled, up to %d fonts\n", 10273 screen->font_doublesize ? "" : " not", 10274 screen->cache_doublesize)); 10275#endif 10276#if OPT_DEC_RECTOPS 10277 init_Ires(screen.checksum_ext0); 10278 screen->checksum_ext = screen->checksum_ext0; 10279#endif 10280 10281#if OPT_ISO_COLORS 10282 init_Ires(screen.veryBoldColors); 10283 init_Bres(screen.boldColors); 10284 init_Bres(screen.colorAttrMode); 10285 init_Bres(screen.colorBDMode); 10286 init_Bres(screen.colorBLMode); 10287 init_Bres(screen.colorMode); 10288 init_Bres(screen.colorULMode); 10289 init_Bres(screen.italicULMode); 10290 init_Bres(screen.colorRVMode); 10291 10292#if OPT_WIDE_ATTRS 10293 init_Bres(screen.colorITMode); 10294#endif 10295#if OPT_DIRECT_COLOR 10296 init_Bres(screen.direct_color); 10297#endif 10298 10299 TRACE(("...will fake resources for color%d to color%d\n", 10300 MIN_ANSI_COLORS, 10301 NUM_ANSI_COLORS - 1)); 10302 10303 for (i = 0, color_ok = False; i < MAXCOLORS; i++) { 10304 /* 10305 * Xt has a hardcoded limit on the maximum number of resources that can 10306 * be used in a widget. If we configured both luit (which implies 10307 * wide-characters) and 256-colors, it goes over that limit. Most 10308 * people would not need a resource-file with 256-colors; the default 10309 * values in our table are sufficient. Fake the resource setting by 10310 * copying the default value from the table. The #define's can be 10311 * overridden to make these true resources. 10312 */ 10313 if (i >= MIN_ANSI_COLORS && i < NUM_ANSI_COLORS) { 10314 screen->Acolors[i].resource = 10315 x_strtrim(fake_resources[i - MIN_ANSI_COLORS].default_addr); 10316 if (screen->Acolors[i].resource == 0) 10317 screen->Acolors[i].resource = XtDefaultForeground; 10318 } else { 10319 screen->Acolors[i] = TScreenOf(request)->Acolors[i]; 10320 screen->Acolors[i].resource = 10321 x_strtrim(screen->Acolors[i].resource); 10322 } 10323 10324 TRACE(("Acolors[%d] = %s\n", i, screen->Acolors[i].resource)); 10325 screen->Acolors[i].mode = False; 10326 if (DftFg(Acolors[i])) { 10327 screen->Acolors[i].value = T_COLOR(screen, TEXT_FG); 10328 screen->Acolors[i].mode = True; 10329 } else if (DftBg(Acolors[i])) { 10330 screen->Acolors[i].value = T_COLOR(screen, TEXT_BG); 10331 screen->Acolors[i].mode = True; 10332 } else { 10333 color_ok = True; 10334 } 10335 } 10336 10337 /* 10338 * Check if we're trying to use color in a monochrome screen. Disable 10339 * color in that case, since that would make ANSI colors unusable. A 4-bit 10340 * or 8-bit display is usable, so we do not have to check for anything more 10341 * specific. 10342 */ 10343 if (color_ok) { 10344 if (getVisualDepth(wnew) <= 1) { 10345 TRACE(("disabling color since screen is monochrome\n")); 10346 color_ok = False; 10347 } 10348 } 10349 10350 /* If none of the colors are anything other than the foreground or 10351 * background, we'll assume this isn't color, no matter what the colorMode 10352 * resource says. (There doesn't seem to be any good way to determine if 10353 * the resource lookup failed versus the user having misconfigured this). 10354 */ 10355 if (!color_ok) { 10356 screen->colorMode = False; 10357 TRACE(("All colors are foreground or background: disable colorMode\n")); 10358 } 10359 wnew->sgr_foreground = -1; 10360 wnew->sgr_background = -1; 10361 wnew->sgr_38_xcolors = False; 10362 clrDirectFG(wnew->flags); 10363 clrDirectFG(wnew->flags); 10364#endif /* OPT_ISO_COLORS */ 10365 10366 /* 10367 * Decode the resources that control the behavior on multiple mouse clicks. 10368 * A single click is always bound to normal character selection, but the 10369 * other flavors can be changed. 10370 */ 10371 for (i = 0; i < NSELECTUNITS; ++i) { 10372 int ck = (i + 1); 10373 screen->maxClicks = ck; 10374 if (i == Select_CHAR) 10375 screen->selectMap[i] = Select_CHAR; 10376 else if (TScreenOf(request)->onClick[i] != 0) 10377 ParseOnClicks(wnew, request, (unsigned) i); 10378 else if (i <= Select_LINE) 10379 screen->selectMap[i] = (SelectUnit) i; 10380 else 10381 break; 10382#if OPT_XRES_QUERY 10383 init_Sres(screen.onClick[i]); 10384#endif 10385 TRACE(("on%dClicks %s=%d\n", ck, 10386 NonNull(TScreenOf(request)->onClick[i]), 10387 screen->selectMap[i])); 10388 if (screen->selectMap[i] == NSELECTUNITS) 10389 break; 10390 } 10391 TRACE(("maxClicks %d\n", screen->maxClicks)); 10392 10393 init_Tres(MOUSE_FG); 10394 init_Tres(MOUSE_BG); 10395 init_Tres(TEXT_CURSOR); 10396#if OPT_HIGHLIGHT_COLOR 10397 init_Tres(HIGHLIGHT_BG); 10398 init_Tres(HIGHLIGHT_FG); 10399 init_Bres(screen.hilite_reverse); 10400 init_Mres(screen.hilite_color); 10401 if (screen->hilite_color == Maybe) { 10402 screen->hilite_color = False; 10403 /* 10404 * If the highlight text/background are both set, and if they are 10405 * not equal to either the text/background or background/text, then 10406 * set the highlightColorMode automatically. 10407 */ 10408 if (!DftFg(Tcolors[HIGHLIGHT_BG]) 10409 && !DftBg(Tcolors[HIGHLIGHT_FG]) 10410 && !TxtFg(Tcolors[HIGHLIGHT_BG]) 10411 && !TxtBg(Tcolors[HIGHLIGHT_FG]) 10412 && !TxtBg(Tcolors[HIGHLIGHT_BG]) 10413 && !TxtFg(Tcolors[HIGHLIGHT_FG])) { 10414 TRACE(("...setting hilite_color automatically\n")); 10415 screen->hilite_color = True; 10416 } 10417 } 10418#endif 10419 10420#if OPT_TEK4014 10421 /* 10422 * The Tek4014 window has no separate resources for foreground, background 10423 * and cursor color. Since xterm always creates the vt100 widget first, we 10424 * can set the Tektronix colors here. That lets us use escape sequences to 10425 * set its dynamic colors and get consistent behavior whether or not the 10426 * window is displayed. 10427 */ 10428 screen->Tcolors[TEK_BG] = screen->Tcolors[TEXT_BG]; 10429 screen->Tcolors[TEK_FG] = screen->Tcolors[TEXT_FG]; 10430 screen->Tcolors[TEK_CURSOR] = screen->Tcolors[TEXT_CURSOR]; 10431#endif 10432 10433#ifdef SCROLLBAR_RIGHT 10434 init_Bres(misc.useRight); 10435#endif 10436 10437#if OPT_RENDERFONT 10438 init_Ires(misc.limit_fontsets); 10439 wnew->work.max_fontsets = (unsigned) wnew->misc.limit_fontsets; 10440 10441 init_Sres(misc.render_font_s); 10442 wnew->work.render_font = 10443 (Boolean) extendedBoolean(wnew->misc.render_font_s, 10444 tblRenderFont, erLast); 10445 if (wnew->work.render_font == erDefault) { 10446 if (IsEmpty(CurrentXftFont(wnew))) { 10447 free((void *) CurrentXftFont(wnew)); 10448 CurrentXftFont(wnew) = x_strdup(DEFFACENAME_AUTO); 10449 TRACE(("will allow runtime switch to render_font using \"%s\"\n", 10450 CurrentXftFont(wnew))); 10451 } else { 10452 wnew->work.render_font = erTrue; 10453 TRACE(("initially using TrueType font\n")); 10454 } 10455 } else if (wnew->work.render_font == erDefaultOff) { 10456 wnew->work.render_font = erFalse; 10457 } 10458 /* minor tweak to make debug traces consistent: */ 10459 if (wnew->work.render_font) { 10460 if (IsEmpty(CurrentXftFont(wnew))) { 10461 wnew->work.render_font = False; 10462 TRACE(("reset render_font since there is no face_name\n")); 10463 } 10464 } 10465#endif 10466 10467#if OPT_WIDE_CHARS 10468 /* setup data for next call */ 10469 init_Sres(screen.utf8_mode_s); 10470 request->screen.utf8_mode = 10471 extendedBoolean(request->screen.utf8_mode_s, tblUtf8Mode, uLast); 10472 10473 init_Sres(screen.utf8_fonts_s); 10474 request->screen.utf8_fonts = 10475 extendedBoolean(request->screen.utf8_fonts_s, tblUtf8Mode, uLast); 10476 10477 init_Sres(screen.utf8_title_s); 10478 request->screen.utf8_title = 10479 extendedBoolean(request->screen.utf8_title_s, tblUtf8Mode, uLast); 10480 10481 /* 10482 * Make a copy in the input/request so that DefaultFontN() works for 10483 * the "CHECKFONT" option. 10484 */ 10485 copyFontList(&(request->work.fonts.x11.list_n), 10486 wnew->work.fonts.x11.list_n); 10487 10488 VTInitialize_locale(request); 10489 init_Bres(screen.normalized_c); 10490 init_Bres(screen.utf8_latin1); 10491 init_Bres(screen.utf8_weblike); 10492 10493#if OPT_LUIT_PROG 10494 init_Bres(misc.callfilter); 10495 init_Bres(misc.use_encoding); 10496 init_Sres(misc.locale_str); 10497 init_Sres(misc.localefilter); 10498#endif 10499 10500 init_Ires(screen.utf8_inparse); 10501 init_Ires(screen.utf8_mode); 10502 init_Ires(screen.utf8_fonts); 10503 init_Ires(screen.utf8_title); 10504 init_Ires(screen.max_combining); 10505 10506 init_Ires(screen.utf8_always); /* from utf8_mode, used in doparse */ 10507 10508 if (screen->max_combining < 0) { 10509 screen->max_combining = 0; 10510 } 10511 if (screen->max_combining > 5) { 10512 screen->max_combining = 5; 10513 } 10514 10515 init_Bres(screen.vt100_graphics); 10516 init_Bres(screen.wide_chars); 10517 init_Bres(misc.mk_width); 10518 init_Bres(misc.cjk_width); 10519 10520 init_Ires(misc.mk_samplesize); 10521 init_Ires(misc.mk_samplepass); 10522 10523 if (wnew->misc.mk_samplesize > 0xffff) 10524 wnew->misc.mk_samplesize = 0xffff; 10525 if (wnew->misc.mk_samplesize < 0) 10526 wnew->misc.mk_samplesize = 0; 10527 10528 if (wnew->misc.mk_samplepass > wnew->misc.mk_samplesize) 10529 wnew->misc.mk_samplepass = wnew->misc.mk_samplesize; 10530 if (wnew->misc.mk_samplepass < 0) 10531 wnew->misc.mk_samplepass = 0; 10532 10533 if (TScreenOf(request)->utf8_mode) { 10534 TRACE(("setting wide_chars on\n")); 10535 screen->wide_chars = True; 10536 } else { 10537 TRACE(("setting utf8_mode to 0\n")); 10538 screen->utf8_mode = uFalse; 10539 } 10540 mk_wcwidth_init(screen->utf8_mode); 10541 TRACE(("initialized UTF-8 mode to %d\n", screen->utf8_mode)); 10542 10543#if OPT_MINI_LUIT 10544 if (TScreenOf(request)->latin9_mode) { 10545 screen->latin9_mode = True; 10546 } 10547 if (TScreenOf(request)->unicode_font) { 10548 screen->unicode_font = True; 10549 } 10550 TRACE(("initialized Latin9 mode to %d\n", screen->latin9_mode)); 10551 TRACE(("initialized unicode_font to %d\n", screen->unicode_font)); 10552#endif 10553 10554 decode_wcwidth(wnew); 10555 xtermSaveVTFonts(wnew); 10556#endif /* OPT_WIDE_CHARS */ 10557 10558 init_Sres(screen.eight_bit_meta_s); 10559 wnew->screen.eight_bit_meta = 10560 extendedBoolean(request->screen.eight_bit_meta_s, tbl8BitMeta, ebLast); 10561 if (wnew->screen.eight_bit_meta == ebLocale) { 10562#if OPT_WIDE_CHARS 10563 if (xtermEnvUTF8()) { 10564 wnew->screen.eight_bit_meta = ebFalse; 10565 TRACE(("...eightBitMeta is false due to locale\n")); 10566 } else 10567#endif /* OPT_WIDE_CHARS */ 10568 { 10569 wnew->screen.eight_bit_meta = ebTrue; 10570 TRACE(("...eightBitMeta is true due to locale\n")); 10571 } 10572 } 10573 10574 init_Bres(screen.always_bold_mode); 10575 init_Bres(screen.bold_mode); 10576 init_Bres(screen.underline); 10577 10578 wnew->cur_foreground = 0; 10579 wnew->cur_background = 0; 10580 10581 wnew->keyboard.flags = MODE_SRM; 10582 10583 if (screen->backarrow_key) 10584 wnew->keyboard.flags |= MODE_DECBKM; 10585 TRACE(("initialized DECBKM %s\n", 10586 BtoS(wnew->keyboard.flags & MODE_DECBKM))); 10587 10588#if OPT_SIXEL_GRAPHICS 10589 init_Bres(screen.sixel_scrolling); 10590 if (screen->sixel_scrolling) 10591 wnew->keyboard.flags |= MODE_DECSDM; 10592 TRACE(("initialized DECSDM %s\n", 10593 BtoS(wnew->keyboard.flags & MODE_DECSDM))); 10594#endif 10595 10596#if OPT_GRAPHICS 10597 init_Sres(screen.graph_termid); 10598 screen->graphics_termid = decodeTerminalID(TScreenOf(request)->graph_termid); 10599 switch (screen->graphics_termid) { 10600 case 125: 10601 case 240: 10602 case 241: 10603 case 330: 10604 case 340: 10605 case 382: 10606 break; 10607 default: 10608 screen->graphics_termid = 0; 10609 break; 10610 } 10611 TRACE(("graph_termid '%s' -> graphics_termid %d\n", 10612 screen->graph_termid, 10613 screen->graphics_termid)); 10614 10615 init_Ires(screen.numcolorregisters); 10616 TRACE(("initialized NUM_COLOR_REGISTERS to resource default: %d\n", 10617 screen->numcolorregisters)); 10618 10619 init_Bres(screen.privatecolorregisters); /* FIXME: should this be off unconditionally here? */ 10620 TRACE(("initialized PRIVATE_COLOR_REGISTERS to resource default: %s\n", 10621 BtoS(screen->privatecolorregisters))); 10622#endif 10623 10624#if OPT_GRAPHICS 10625 { 10626 int native_w, native_h; 10627 10628 switch (GraphicsTermId(screen)) { 10629 case 125: 10630 native_w = 768; 10631 native_h = 460; 10632 break; 10633 case 240: 10634 /* FALLTHRU */ 10635 case 241: 10636 native_w = 800; 10637 native_h = 460; 10638 break; 10639 case 330: 10640 /* FALLTHRU */ 10641 case 340: 10642 native_w = 800; 10643 native_h = 480; 10644 break; 10645 default: 10646 native_w = 800; 10647 native_h = 480; 10648 break; 10649 case 382: 10650 native_w = 960; 10651 native_h = 750; 10652 break; 10653 } 10654 10655# if OPT_REGIS_GRAPHICS 10656 init_Sres(screen.graphics_regis_default_font); 10657 TRACE(("default ReGIS font: %s\n", 10658 screen->graphics_regis_default_font)); 10659 10660 init_Sres(screen.graphics_regis_screensize); 10661 screen->graphics_regis_def_high = 1000; 10662 screen->graphics_regis_def_wide = 1000; 10663 if (!x_strcasecmp(screen->graphics_regis_screensize, "auto")) { 10664 TRACE(("setting default ReGIS screensize based on graphics_id %d\n", 10665 GraphicsTermId(screen))); 10666 screen->graphics_regis_def_high = (Dimension) native_h; 10667 screen->graphics_regis_def_wide = (Dimension) native_w; 10668 } else { 10669 int conf_high; 10670 int conf_wide; 10671 char ignore; 10672 10673 if (sscanf(screen->graphics_regis_screensize, 10674 "%dx%d%c", 10675 &conf_wide, 10676 &conf_high, 10677 &ignore) == 2) { 10678 if (conf_high > 0 && conf_wide > 0) { 10679 screen->graphics_regis_def_high = 10680 (Dimension) conf_high; 10681 screen->graphics_regis_def_wide = 10682 (Dimension) conf_wide; 10683 } else { 10684 TRACE(("ignoring invalid regisScreenSize %s\n", 10685 screen->graphics_regis_screensize)); 10686 } 10687 } else { 10688 TRACE(("ignoring invalid regisScreenSize %s\n", 10689 screen->graphics_regis_screensize)); 10690 } 10691 } 10692 TRACE(("default ReGIS graphics screensize %dx%d\n", 10693 (int) screen->graphics_regis_def_wide, 10694 (int) screen->graphics_regis_def_high)); 10695# endif 10696 10697 init_Sres(screen.graphics_max_size); 10698 screen->graphics_max_high = 1000; 10699 screen->graphics_max_wide = 1000; 10700 if (!x_strcasecmp(screen->graphics_max_size, "auto")) { 10701 TRACE(("setting max graphics screensize based on graphics_id %d\n", 10702 GraphicsTermId(screen))); 10703 screen->graphics_max_high = (Dimension) native_h; 10704 screen->graphics_max_wide = (Dimension) native_w; 10705 } else { 10706 int conf_high; 10707 int conf_wide; 10708 char ignore; 10709 10710 if (sscanf(screen->graphics_max_size, 10711 "%dx%d%c", 10712 &conf_wide, 10713 &conf_high, 10714 &ignore) == 2) { 10715 if (conf_high > 0 && conf_wide > 0) { 10716 screen->graphics_max_high = (Dimension) conf_high; 10717 screen->graphics_max_wide = (Dimension) conf_wide; 10718 } else { 10719 TRACE(("ignoring invalid maxGraphicSize %s\n", 10720 screen->graphics_max_size)); 10721 } 10722 } else { 10723 TRACE(("ignoring invalid maxGraphicSize %s\n", 10724 screen->graphics_max_size)); 10725 } 10726 } 10727# if OPT_REGIS_GRAPHICS 10728 /* Make sure the max is large enough for the default ReGIS size. */ 10729 if (screen->graphics_regis_def_high > 10730 screen->graphics_max_high) { 10731 screen->graphics_max_high = 10732 screen->graphics_regis_def_high; 10733 } 10734 if (screen->graphics_regis_def_wide > 10735 screen->graphics_max_wide) { 10736 screen->graphics_max_wide = 10737 screen->graphics_regis_def_wide; 10738 } 10739# endif 10740 TRACE(("max graphics screensize %dx%d\n", 10741 (int) screen->graphics_max_wide, 10742 (int) screen->graphics_max_high)); 10743 } 10744#endif 10745 10746#if OPT_SIXEL_GRAPHICS 10747 init_Bres(screen.sixel_scrolls_right); 10748#endif 10749#if OPT_PRINT_GRAPHICS 10750 init_Bres(screen.graphics_print_to_host); 10751 init_Bres(screen.graphics_expanded_print_mode); 10752 init_Bres(screen.graphics_print_color_mode); 10753 init_Bres(screen.graphics_print_color_syntax); 10754 init_Bres(screen.graphics_print_background_mode); 10755 init_Bres(screen.graphics_rotated_print_mode); 10756#endif 10757 10758#if OPT_STATUS_LINE 10759 init_Sres(screen.status_fmt); 10760#endif 10761 10762 /* look for focus related events on the shell, because we need 10763 * to care about the shell's border being part of our focus. 10764 */ 10765 TRACE(("adding event handlers for my_parent %p\n", (void *) my_parent)); 10766 XtAddEventHandler(my_parent, EnterWindowMask, False, 10767 HandleEnterWindow, (Opaque) NULL); 10768 XtAddEventHandler(my_parent, LeaveWindowMask, False, 10769 HandleLeaveWindow, (Opaque) NULL); 10770 XtAddEventHandler(my_parent, FocusChangeMask, False, 10771 HandleFocusChange, (Opaque) NULL); 10772 XtAddEventHandler((Widget) wnew, 0L, True, 10773 VTNonMaskableEvent, (Opaque) NULL); 10774 XtAddEventHandler((Widget) wnew, PropertyChangeMask, False, 10775 HandleBellPropertyChange, (Opaque) NULL); 10776 10777#if HANDLE_STRUCT_NOTIFY 10778#if OPT_TOOLBAR 10779 wnew->VT100_TB_INFO(menu_bar) = request->VT100_TB_INFO(menu_bar); 10780 init_Ires(VT100_TB_INFO(menu_height)); 10781#endif 10782 XtAddEventHandler(my_parent, MappingNotify | StructureNotifyMask, False, 10783 HandleStructNotify, (Opaque) 0); 10784#endif /* HANDLE_STRUCT_NOTIFY */ 10785 10786 screen->bellInProgress = False; 10787 10788 set_character_class(screen->charClass); 10789#if OPT_REPORT_CCLASS 10790 if (resource.reportCClass) 10791 report_char_class(wnew); 10792#endif 10793 10794 /* create it, but don't realize it */ 10795 ScrollBarOn(wnew, True); 10796 10797 /* make sure that the resize gravity acceptable */ 10798 if (!GravityIsNorthWest(wnew) && 10799 !GravityIsSouthWest(wnew)) { 10800 char value[80]; 10801 String temp[2]; 10802 Cardinal nparams = 1; 10803 10804 sprintf(value, "%d", wnew->misc.resizeGravity); 10805 temp[0] = value; 10806 temp[1] = 0; 10807 XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError", 10808 "unsupported resizeGravity resource value (%s)", 10809 temp, &nparams); 10810 wnew->misc.resizeGravity = SouthWestGravity; 10811 } 10812#ifndef NO_ACTIVE_ICON 10813 screen->whichVwin = &screen->fullVwin; 10814#endif /* NO_ACTIVE_ICON */ 10815 10816 init_Ires(screen.unparse_max); 10817 if ((int) screen->unparse_max < 256) 10818 screen->unparse_max = 256; 10819 screen->unparse_bfr = (IChar *) (void *) XtCalloc(screen->unparse_max, 10820 (Cardinal) sizeof(IChar)); 10821 10822 if (screen->savelines < 0) 10823 screen->savelines = 0; 10824 10825 init_Bres(screen.awaitInput); 10826 10827 wnew->flags = 0; 10828 if (!screen->jumpscroll) 10829 wnew->flags |= SMOOTHSCROLL; 10830 if (wnew->misc.reverseWrap) 10831 wnew->flags |= REVERSEWRAP; 10832 if (wnew->misc.autoWrap) 10833 wnew->flags |= WRAPAROUND; 10834 if (wnew->misc.re_verse != wnew->misc.re_verse0) 10835 wnew->flags |= REVERSE_VIDEO; 10836 if (screen->c132) 10837 wnew->flags |= IN132COLUMNS; 10838 10839 wnew->initflags = wnew->flags; 10840 10841 init_Sres(keyboard.shift_escape_s); 10842 wnew->keyboard.shift_escape = 10843 extendedBoolean(wnew->keyboard.shift_escape_s, tblShift2S, ssLAST); 10844 10845#if OPT_MOD_FKEYS 10846 init_Ires(keyboard.modify_1st.allow_keys); 10847 init_Ires(keyboard.modify_1st.cursor_keys); 10848 init_Ires(keyboard.modify_1st.function_keys); 10849 init_Ires(keyboard.modify_1st.keypad_keys); 10850 init_Ires(keyboard.modify_1st.other_keys); 10851 init_Ires(keyboard.modify_1st.string_keys); 10852 init_Ires(keyboard.format_keys); 10853 wnew->keyboard.modify_now = wnew->keyboard.modify_1st; 10854#endif 10855 10856 init_Ires(misc.appcursorDefault); 10857 if (wnew->misc.appcursorDefault) 10858 wnew->keyboard.flags |= MODE_DECCKM; 10859 10860 init_Ires(misc.appkeypadDefault); 10861 if (wnew->misc.appkeypadDefault) 10862 wnew->keyboard.flags |= MODE_DECKPAM; 10863 10864 initLineData(wnew); 10865#if OPT_WIDE_CHARS 10866 freeFontList(&(request->work.fonts.x11.list_n)); 10867#endif 10868#if OPT_XRES_QUERY 10869 if (resource.reportXRes) 10870 reportResources(wnew); 10871#endif 10872 xtermResetLocale(LC_NUMERIC, saveLocale); 10873 TRACE(("" TRACE_R " VTInitialize\n")); 10874 return; 10875} 10876 10877void 10878releaseCursorGCs(XtermWidget xw) 10879{ 10880 TScreen *screen = TScreenOf(xw); 10881 VTwin *win = WhichVWin(screen); 10882 int n; 10883 10884 for_each_curs_gc(n) { 10885 freeCgs(xw, win, (CgsEnum) n); 10886 } 10887} 10888 10889void 10890releaseWindowGCs(XtermWidget xw, VTwin *win) 10891{ 10892 int n; 10893 10894 for_each_text_gc(n) { 10895 switch (n) { 10896 case gcBorder: 10897 case gcFiller: 10898 break; 10899 default: 10900 freeCgs(xw, win, (CgsEnum) n); 10901 break; 10902 } 10903 } 10904} 10905 10906#define TRACE_FREE_LEAK(name) \ 10907 if (name) { \ 10908 TRACE(("freed " #name ": %p\n", (const void *) name)); \ 10909 FreeAndNull(name); \ 10910 } 10911 10912#define TRACE_FREE_GC(name,part) \ 10913 if (part) { \ 10914 TRACE(("freed %s " #part ": %p\n", name, (const void *) part)); \ 10915 XFreeGC(dpy, part); \ 10916 part = 0; \ 10917 } 10918 10919#if OPT_INPUT_METHOD 10920static void 10921cleanupInputMethod(XtermWidget xw) 10922{ 10923 TInput *input = lookupTInput(xw, (Widget) xw); 10924 10925 if (input && input->xim) { 10926 XCloseIM(input->xim); 10927 input->xim = 0; 10928 TRACE(("freed screen->xim\n")); 10929 } 10930} 10931#else 10932#define cleanupInputMethod(xw) /* nothing */ 10933#endif 10934 10935#ifdef NO_LEAKS 10936#define FREE_VT_WIN(name) freeVTwin(dpy, #name, &(screen->name)) 10937static void 10938freeVTwin(Display *dpy, const char *whichWin, VTwin *win) 10939{ 10940 (void) whichWin; 10941 TRACE_FREE_GC(whichWin, win->filler_gc); 10942 TRACE_FREE_GC(whichWin, win->border_gc); 10943 TRACE_FREE_GC(whichWin, win->marker_gc[0]); 10944 TRACE_FREE_GC(whichWin, win->marker_gc[1]); 10945} 10946#endif 10947 10948static void 10949VTDestroy(Widget w GCC_UNUSED) 10950{ 10951#ifdef NO_LEAKS 10952 XtermWidget xw = (XtermWidget) w; 10953 TScreen *screen = TScreenOf(xw); 10954 Display *dpy = screen->display; 10955 Cardinal n, k; 10956 10957 StopBlinking(xw); 10958 10959 if (screen->scrollWidget) { 10960 XtUninstallTranslations(screen->scrollWidget); 10961 XtDestroyWidget(screen->scrollWidget); 10962 } 10963 10964 while (screen->saved_fifo > 0) { 10965 deleteScrollback(screen); 10966 } 10967 10968 while (screen->save_title != 0) { 10969 SaveTitle *last = screen->save_title; 10970 screen->save_title = last->next; 10971 free(last->iconName); 10972 free(last->windowName); 10973 free(last); 10974 } 10975#ifndef NO_ACTIVE_ICON 10976 TRACE_FREE_LEAK(xw->misc.active_icon_s); 10977#endif 10978#if OPT_ISO_COLORS 10979 TRACE_FREE_LEAK(screen->cmap_data); 10980 for (n = 0; n < MAXCOLORS; n++) { 10981 TRACE_FREE_LEAK(screen->Acolors[n].resource); 10982 } 10983 for (n = 0; n < MAX_SAVED_SGR; n++) { 10984 TRACE_FREE_LEAK(xw->saved_colors.palettes[n]); 10985 } 10986#endif 10987 for (n = 0; n < NCOLORS; n++) { 10988 switch (n) { 10989#if OPT_TEK4014 10990 case TEK_BG: 10991 /* FALLTHRU */ 10992 case TEK_FG: 10993 /* FALLTHRU */ 10994 case TEK_CURSOR: 10995 break; 10996#endif 10997 default: 10998 TRACE_FREE_LEAK(screen->Tcolors[n].resource); 10999 break; 11000 } 11001 } 11002 FreeMarkGCs(xw); 11003 TRACE_FREE_LEAK(screen->unparse_bfr); 11004 TRACE_FREE_LEAK(screen->save_ptr); 11005 TRACE_FREE_LEAK(screen->saveBuf_data); 11006 TRACE_FREE_LEAK(screen->saveBuf_index); 11007 for (n = 0; n < 2; ++n) { 11008 TRACE_FREE_LEAK(screen->editBuf_data[n]); 11009 TRACE_FREE_LEAK(screen->editBuf_index[n]); 11010 } 11011 TRACE_FREE_LEAK(screen->keyboard_dialect); 11012 TRACE_FREE_LEAK(screen->cursor_font_name); 11013 TRACE_FREE_LEAK(screen->pointer_shape); 11014 TRACE_FREE_LEAK(screen->term_id); 11015#if OPT_WIDE_CHARS 11016 TRACE_FREE_LEAK(screen->utf8_mode_s); 11017 TRACE_FREE_LEAK(screen->utf8_fonts_s); 11018 TRACE_FREE_LEAK(screen->utf8_title_s); 11019#if OPT_LUIT_PROG 11020 TRACE_FREE_LEAK(xw->misc.locale_str); 11021 TRACE_FREE_LEAK(xw->misc.localefilter); 11022#endif 11023#endif 11024 TRACE_FREE_LEAK(xw->misc.T_geometry); 11025 TRACE_FREE_LEAK(xw->misc.geo_metry); 11026#if OPT_INPUT_METHOD 11027 cleanupInputMethod(xw); 11028 TRACE_FREE_LEAK(xw->misc.f_x); 11029 TRACE_FREE_LEAK(xw->misc.input_method); 11030 TRACE_FREE_LEAK(xw->misc.preedit_type); 11031#endif 11032 releaseCursorGCs(xw); 11033 releaseWindowGCs(xw, &(screen->fullVwin)); 11034#ifndef NO_ACTIVE_ICON 11035 XFreeFont(screen->display, getIconicFont(screen)->fs); 11036 releaseWindowGCs(xw, &(screen->iconVwin)); 11037#endif 11038 XtUninstallTranslations((Widget) xw); 11039#if OPT_TOOLBAR 11040 XtUninstallTranslations((Widget) XtParent(xw)); 11041#endif 11042 XtUninstallTranslations((Widget) SHELL_OF(xw)); 11043 11044 if (screen->hidden_cursor) 11045 XFreeCursor(screen->display, screen->hidden_cursor); 11046 11047 xtermCloseFonts(xw, screen->fnts); 11048#if OPT_WIDE_ATTRS 11049 xtermCloseFonts(xw, screen->ifnts); 11050#endif 11051 noleaks_cachedCgs(xw); 11052 free_termcap(xw); 11053 11054 FREE_VT_WIN(fullVwin); 11055#ifndef NO_ACTIVE_ICON 11056 FREE_VT_WIN(iconVwin); 11057#endif /* NO_ACTIVE_ICON */ 11058 11059 TRACE_FREE_LEAK(screen->selection_targets_8bit); 11060#if OPT_SELECT_REGEX 11061 for (n = 0; n < NSELECTUNITS; ++n) { 11062 if (screen->selectMap[n] == Select_REGEX) { 11063 TRACE_FREE_LEAK(screen->selectExpr[n]); 11064 } 11065 } 11066#endif 11067 11068#if OPT_RENDERFONT 11069 for (n = 0; n < NMENUFONTS; ++n) { 11070 int e; 11071 for (e = 0; e < fMAX; ++e) { 11072 xtermCloseXft(screen, getMyXftFont(xw, e, (int) n)); 11073 } 11074 } 11075 discardRenderDraw(screen); 11076 { 11077 ListXftFonts *p; 11078 while ((p = screen->list_xft_fonts) != 0) { 11079 screen->list_xft_fonts = p->next; 11080 free(p); 11081 } 11082 } 11083#endif 11084 11085 /* free things allocated via init_Sres or Init_Sres2 */ 11086#ifndef NO_ACTIVE_ICON 11087 TRACE_FREE_LEAK(screen->icon_fontname); 11088#endif 11089#ifdef ALLOWLOGGING 11090 TRACE_FREE_LEAK(screen->logfile); 11091#endif 11092 TRACE_FREE_LEAK(screen->eight_bit_meta_s); 11093 TRACE_FREE_LEAK(screen->charClass); 11094 TRACE_FREE_LEAK(screen->answer_back); 11095 TRACE_FREE_LEAK(screen->printer_state.printer_command); 11096 TRACE_FREE_LEAK(screen->disallowedColorOps); 11097 TRACE_FREE_LEAK(screen->disallowedFontOps); 11098 TRACE_FREE_LEAK(screen->disallowedMouseOps); 11099 TRACE_FREE_LEAK(screen->disallowedPasteControls); 11100 TRACE_FREE_LEAK(screen->disallowedTcapOps); 11101 TRACE_FREE_LEAK(screen->disallowedWinOps); 11102 TRACE_FREE_LEAK(screen->default_string); 11103 TRACE_FREE_LEAK(screen->eightbit_select_types); 11104 11105#if OPT_WIDE_CHARS 11106 TRACE_FREE_LEAK(screen->utf8_select_types); 11107#endif 11108 11109#if 0 11110 for (n = fontMenu_font1; n <= fontMenu_lastBuiltin; n++) { 11111 TRACE_FREE_LEAK(screen->MenuFontName(n)); 11112 } 11113#endif 11114 11115 TRACE_FREE_LEAK(screen->initial_font); 11116 11117#if OPT_LUIT_PROG 11118 TRACE_FREE_LEAK(xw->misc.locale_str); 11119 TRACE_FREE_LEAK(xw->misc.localefilter); 11120#endif 11121 11122#if OPT_RENDERFONT 11123 TRACE_FREE_LEAK(xw->misc.default_xft.f_n); 11124#if OPT_WIDE_CHARS 11125 TRACE_FREE_LEAK(xw->misc.default_xft.f_w); 11126#endif 11127 TRACE_FREE_LEAK(xw->misc.render_font_s); 11128#endif 11129 11130 TRACE_FREE_LEAK(xw->misc.default_font.f_n); 11131 TRACE_FREE_LEAK(xw->misc.default_font.f_b); 11132 11133#if OPT_WIDE_CHARS 11134 TRACE_FREE_LEAK(xw->misc.default_font.f_w); 11135 TRACE_FREE_LEAK(xw->misc.default_font.f_wb); 11136#endif 11137 11138 TRACE_FREE_LEAK(xw->work.wm_name); 11139 freeFontLists(&(xw->work.fonts.x11)); 11140#if OPT_RENDERFONT 11141 freeFontLists(&(xw->work.fonts.xft)); 11142#endif 11143 11144 xtermFontName(NULL); 11145#if OPT_LOAD_VTFONTS || OPT_WIDE_CHARS 11146 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_n); 11147 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_b); 11148#if OPT_WIDE_CHARS 11149 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_w); 11150 TRACE_FREE_LEAK(screen->cacheVTFonts.default_font.f_wb); 11151#endif 11152 freeFontLists(&(screen->cacheVTFonts.fonts.x11)); 11153 for (n = 0; n < NMENUFONTS; ++n) { 11154 for (k = 0; k < fMAX; ++k) { 11155 if (screen->menu_font_names[n][k] != 11156 screen->cacheVTFonts.menu_font_names[n][k]) { 11157 if (screen->menu_font_names[n][k] != _Font_Selected_) { 11158 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 11159 } 11160 TRACE_FREE_LEAK(screen->cacheVTFonts.menu_font_names[n][k]); 11161 } else { 11162 TRACE_FREE_LEAK(screen->menu_font_names[n][k]); 11163 } 11164 } 11165 } 11166#endif 11167 11168#if OPT_BLINK_CURS 11169 TRACE_FREE_LEAK(screen->cursor_blink_s); 11170#endif 11171 11172#if OPT_REGIS_GRAPHICS 11173 TRACE_FREE_LEAK(screen->graphics_regis_default_font); 11174 TRACE_FREE_LEAK(screen->graphics_regis_screensize); 11175#endif 11176#if OPT_GRAPHICS 11177 TRACE_FREE_LEAK(screen->graph_termid); 11178 TRACE_FREE_LEAK(screen->graphics_max_size); 11179#endif 11180 11181 for (n = 0; n < NSELECTUNITS; ++n) { 11182#if OPT_SELECT_REGEX 11183 TRACE_FREE_LEAK(screen->selectExpr[n]); 11184#endif 11185#if OPT_XRES_QUERY 11186 TRACE_FREE_LEAK(screen->onClick[n]); 11187#endif 11188 } 11189 11190 XtFree((void *) (screen->selection_atoms)); 11191 11192 for (n = 0; n < MAX_SELECTIONS; ++n) { 11193 free(screen->selected_cells[n].data_buffer); 11194 } 11195 11196 if (defaultTranslations != xtermClassRec.core_class.tm_table) { 11197 TRACE_FREE_LEAK(defaultTranslations); 11198 } 11199 TRACE_FREE_LEAK(xtermClassRec.core_class.tm_table); 11200 TRACE_FREE_LEAK(xw->keyboard.shift_escape_s); 11201 TRACE_FREE_LEAK(xw->keyboard.extra_translations); 11202 TRACE_FREE_LEAK(xw->keyboard.shell_translations); 11203 TRACE_FREE_LEAK(xw->keyboard.xterm_translations); 11204 TRACE_FREE_LEAK(xw->keyboard.print_translations); 11205 UnmapSelections(xw); 11206 11207 XtFree((void *) (xw->visInfo)); 11208 11209#if OPT_WIDE_CHARS 11210 FreeTypedBuffer(XChar2b); 11211 FreeTypedBuffer(char); 11212#endif 11213#if OPT_RENDERFONT 11214#if OPT_RENDERWIDE 11215 FreeTypedBuffer(XftCharSpec); 11216#else 11217 FreeTypedBuffer(XftChar8); 11218#endif 11219#endif 11220 11221 TRACE_FREE_LEAK(myState.print_area); 11222 TRACE_FREE_LEAK(myState.string_area); 11223 memset(&myState, 0, sizeof(myState)); 11224 11225#endif /* defined(NO_LEAKS) */ 11226} 11227 11228#ifndef NO_ACTIVE_ICON 11229static void * 11230getProperty(Display *dpy, 11231 Window w, 11232 Atom req_type, 11233 const char *prop_name) 11234{ 11235 Atom property; 11236 Atom actual_return_type; 11237 int actual_format_return = 0; 11238 unsigned long nitems_return = 0; 11239 unsigned long bytes_after_return = 0; 11240 unsigned char *prop_return = 0; 11241 long long_length = 1024; 11242 size_t limit; 11243 char *result = 0; 11244 11245 TRACE(("getProperty %s(%s)\n", prop_name, 11246 req_type ? TraceAtomName(dpy, req_type) : "?")); 11247 property = XInternAtom(dpy, prop_name, False); 11248 11249 if (!xtermGetWinProp(dpy, 11250 w, 11251 property, 11252 0L, 11253 long_length, 11254 req_type, 11255 &actual_return_type, 11256 &actual_format_return, 11257 &nitems_return, 11258 &bytes_after_return, 11259 &prop_return)) { 11260 TRACE((".. Cannot get %s property.\n", prop_name)); 11261 } else if (prop_return != 0) { 11262 11263 if (nitems_return != 0 && 11264 actual_format_return != 0 && 11265 actual_return_type == req_type) { 11266 /* 11267 * Null-terminate the result to make string handling easier. 11268 * The format==8 corresponds to strings, and the number of items 11269 * is the number of characters. 11270 */ 11271 if (actual_format_return == 8) { 11272 limit = nitems_return; 11273 } else { 11274 /* manpage is misleading - X really uses 'long', not 32-bits */ 11275 limit = sizeof(long) * nitems_return; 11276 } 11277 if ((result = malloc(limit + 1)) != 0) { 11278 memcpy(result, prop_return, limit); 11279 result[limit] = '\0'; 11280 } 11281 TRACE(("... result %s\n", result ? ("ok") : "null")); 11282 } 11283 XFree(prop_return); 11284 } else { 11285 TRACE((".. no property returned\n")); 11286 } 11287 return (void *) result; 11288} 11289 11290/* 11291 * Active icons are supported by fvwm. This feature is not supported by 11292 * metacity (gnome) or kwin (kde). Both metacity and kwin support (in 11293 * incompatible ways, e.g., one uses the icon theme as a fallback for window 11294 * decorations but the other does not, etc, ...) an icon as part of the window 11295 * decoration (usually on the upper-left of the window). 11296 * 11297 * In either case, xterm's icon will only be shown in the window decorations if 11298 * xterm does not use the active icon feature. 11299 * 11300 * This function (tries to) determine the window manager's name, so that we can 11301 * provide a useful automatic default for active icons. It is based on reading 11302 * wmctrl, which covers most of EWMH and ICCM. 11303 */ 11304static char * 11305getWindowManagerName(XtermWidget xw) 11306{ 11307 TScreen *screen = TScreenOf(xw); 11308 Display *dpy = screen->display; 11309 Window *sup_window = NULL; 11310 char *result = 0; 11311 11312 TRACE(("getWindowManagerName\n")); 11313#define getWinProp(type, name) \ 11314 (Window *)getProperty(dpy, DefaultRootWindow(dpy), type, name) 11315 if ((sup_window = getWinProp(XA_WINDOW, "_NET_SUPPORTING_WM_CHECK")) == 0) { 11316 sup_window = getWinProp(XA_CARDINAL, "_WIN_SUPPORTING_WM_CHECK"); 11317 } 11318 11319 /* 11320 * If we found the supporting window, get the property containing the 11321 * window manager's name. EWMH defines _NET_WM_NAME, while ICCM defines 11322 * WM_CLASS. There is no standard for the names stored there; 11323 * conventionally it is mixed case. In practice, the former is more often 11324 * set; the latter is not given (or is a lowercased version of the former). 11325 */ 11326 if (sup_window != 0) { 11327#define getStringProp(type,name) \ 11328 (char *)getProperty(dpy, *sup_window, type, name) 11329 if ((result = getStringProp(XA_UTF8_STRING(dpy), "_NET_WM_NAME")) == 0 11330 && (result = getStringProp(XA_STRING, "_NET_WM_NAME")) == 0 11331 && (result = getStringProp(XA_STRING, "WM_CLASS")) == 0) { 11332 TRACE(("... window manager does not tell its name\n")); 11333 } 11334 free(sup_window); 11335 } else { 11336 TRACE(("... Cannot get window manager info properties\n")); 11337 } 11338 if (result == 0) 11339 result = x_strdup("unknown"); 11340 TRACE(("... window manager name is %s\n", result)); 11341 return result; 11342} 11343 11344static Boolean 11345discount_frame_extents(XtermWidget xw, int *high, int *wide) 11346{ 11347 TScreen *screen = TScreenOf(xw); 11348 Display *dpy = screen->display; 11349 11350 Atom atom_supported = XInternAtom(dpy, "_NET_FRAME_EXTENTS", False); 11351 Atom actual_type; 11352 int actual_format; 11353 long long_offset = 0; 11354 long long_length = 128; /* number of items to ask for at a time */ 11355 unsigned long nitems; 11356 unsigned long bytes_after; 11357 unsigned char *args; 11358 Boolean rc; 11359 11360 rc = xtermGetWinProp(dpy, 11361 VShellWindow(xw), 11362 atom_supported, 11363 long_offset, 11364 long_length, 11365 XA_CARDINAL, /* req_type */ 11366 &actual_type, /* actual_type_return */ 11367 &actual_format, /* actual_format_return */ 11368 &nitems, /* nitems_return */ 11369 &bytes_after, /* bytes_after_return */ 11370 &args /* prop_return */ 11371 ); 11372 11373 if (rc && args && (nitems == 4) && (actual_format == 32)) { 11374 long *extents = (long *) (void *) args; 11375 11376 TRACE(("_NET_FRAME_EXTENTS:\n")); 11377 TRACE((" left: %ld\n", extents[0])); 11378 TRACE((" right: %ld\n", extents[1])); 11379 TRACE((" top: %ld\n", extents[2])); 11380 TRACE((" bottom: %ld\n", extents[3])); 11381 11382 if (!x_strncasecmp(xw->work.wm_name, "gnome shell", 11)) { 11383 *wide -= (int) (extents[0] + extents[1]); /* -= (left+right) */ 11384 *high -= (int) (extents[2] + extents[3]); /* -= (top+bottom) */ 11385 TRACE(("...applied extents %d,%d\n", *high, *wide)); 11386 } else if (!x_strncasecmp(xw->work.wm_name, "compiz", 6)) { 11387 /* Ubuntu 16.04 is really off-by-one */ 11388 *wide -= (int) (extents[0] + extents[1] - 1); 11389 *high -= (int) (extents[2] + extents[3] - 1); 11390 TRACE(("...applied extents %d,%d\n", *high, *wide)); 11391 } else if (!x_strncasecmp(xw->work.wm_name, "fvwm", 4)) { 11392 TRACE(("...skipping extents\n")); 11393 } else { 11394 TRACE(("...ignoring extents\n")); 11395 rc = False; 11396 } 11397 XFree(args); 11398 } else { 11399 rc = False; 11400 } 11401 return rc; 11402} 11403#endif /* !NO_ACTIVE_ICON */ 11404 11405void 11406initBorderGC(XtermWidget xw, VTwin *win) 11407{ 11408 TScreen *screen = TScreenOf(xw); 11409 Pixel filler; 11410 11411 TRACE(("initBorderGC(%s) core bg %#lx, bd %#lx text fg %#lx, bg %#lx %s\n", 11412 (win == &(screen->fullVwin)) ? "full" : "icon", 11413 xw->core.background_pixel, 11414 xw->core.border_pixel, 11415 T_COLOR(screen, TEXT_FG), 11416 T_COLOR(screen, TEXT_BG), 11417 xw->misc.re_verse ? "reverse" : "normal")); 11418 if (xw->misc.color_inner_border 11419 && (xw->core.background_pixel != xw->core.border_pixel)) { 11420 /* 11421 * By default, try to match the inner window's background. 11422 */ 11423 if ((xw->core.background_pixel == T_COLOR(screen, TEXT_BG)) && 11424 (xw->core.border_pixel == T_COLOR(screen, TEXT_FG))) { 11425 filler = T_COLOR(screen, TEXT_BG); 11426 } else { 11427 filler = xw->core.border_pixel; 11428 } 11429 TRACE((" border %#lx\n", filler)); 11430 setCgsFore(xw, win, gcBorder, filler); 11431 setCgsBack(xw, win, gcBorder, filler); 11432 win->border_gc = getCgsGC(xw, win, gcBorder); 11433 } 11434#if USE_DOUBLE_BUFFER 11435 else if (resource.buffered) { 11436 filler = T_COLOR(screen, TEXT_BG); 11437 TRACE((" border %#lx (buffered)\n", filler)); 11438 setCgsFore(xw, win, gcBorder, filler); 11439 setCgsBack(xw, win, gcBorder, filler); 11440 win->border_gc = getCgsGC(xw, win, gcBorder); 11441 } 11442#endif 11443 else { 11444 TRACE((" border unused\n")); 11445 win->border_gc = 0; 11446 } 11447 11448 /* 11449 * Initialize a GC for double-buffering, needed for XFillRectangle call 11450 * in xtermClear2(). When not double-buffering, the XClearArea call works, 11451 * without requiring a separate GC. 11452 */ 11453#if USE_DOUBLE_BUFFER 11454 if (resource.buffered) { 11455 filler = (((xw->flags & BG_COLOR) && (xw->cur_background >= 0)) 11456 ? getXtermBG(xw, xw->flags, xw->cur_background) 11457 : T_COLOR(screen, TEXT_BG)); 11458 11459 TRACE((" filler %#lx %s\n", 11460 filler, 11461 xw->misc.re_verse ? "reverse" : "normal")); 11462 11463 setCgsFore(xw, win, gcFiller, filler); 11464 setCgsBack(xw, win, gcFiller, filler); 11465 11466 win->filler_gc = getCgsGC(xw, win, gcFiller); 11467 } 11468#endif 11469} 11470#if USE_DOUBLE_BUFFER 11471static Boolean 11472allocateDbe(XtermWidget xw, VTwin *target) 11473{ 11474 TScreen *screen = TScreenOf(xw); 11475 Boolean result = False; 11476 11477 target->drawable = target->window; 11478 11479 if (resource.buffered) { 11480 Window win = target->window; 11481 Drawable d; 11482 int major, minor; 11483 if (XdbeQueryExtension(XtDisplay(xw), &major, &minor)) { 11484 d = XdbeAllocateBackBufferName(XtDisplay(xw), win, 11485 (XdbeSwapAction) XdbeCopied); 11486 if (d == None) { 11487 fprintf(stderr, "Couldn't allocate a back buffer!\n"); 11488 exit(3); 11489 } 11490 target->drawable = d; 11491 screen->needSwap = 1; 11492 TRACE(("initialized double-buffering\n")); 11493 result = True; 11494 } else { 11495 resource.buffered = False; 11496 } 11497 } 11498 return result; 11499} 11500#endif /* USE_DOUBLE_BUFFER */ 11501 11502/*ARGSUSED*/ 11503static void 11504VTRealize(Widget w, 11505 XtValueMask * valuemask, 11506 XSetWindowAttributes * values) 11507{ 11508 XtermWidget xw = (XtermWidget) w; 11509 TScreen *screen = TScreenOf(xw); 11510 11511 const VTFontNames *myfont; 11512 struct Xinerama_geometry pos; 11513 int pr; 11514 Atom pid_atom; 11515 int i; 11516 11517 TRACE(("VTRealize " TRACE_L "\n")); 11518 11519 TabReset(xw->tabs); 11520 11521 if (screen->menu_font_number == fontMenu_default) { 11522 myfont = defaultVTFontNames(xw); 11523 } else { 11524 myfont = xtermFontName(screen->MenuFontName(screen->menu_font_number)); 11525 } 11526 memset(screen->fnts, 0, sizeof(screen->fnts)); 11527 11528 if (!xtermLoadFont(xw, 11529 myfont, 11530 False, 11531 screen->menu_font_number)) { 11532 if (XmuCompareISOLatin1(myfont->f_n, DEFFONT) != 0) { 11533 char *use_font = x_strdup(DEFFONT); 11534 xtermWarning("unable to open font \"%s\", trying \"%s\"....\n", 11535 myfont->f_n, use_font); 11536 (void) xtermLoadFont(xw, 11537 xtermFontName(use_font), 11538 False, 11539 screen->menu_font_number); 11540 screen->MenuFontName(screen->menu_font_number) = use_font; 11541 } 11542 } 11543 11544 /* really screwed if we couldn't open default font */ 11545 if (!GetNormalFont(screen, fNorm)->fs) { 11546 xtermWarning("unable to locate a suitable font\n"); 11547 Exit(1); 11548 } 11549#if OPT_WIDE_CHARS 11550 if (screen->utf8_mode) { 11551 TRACE(("check if this is a wide font, if not try again\n")); 11552 if (xtermLoadWideFonts(xw, False)) { 11553 SetVTFont(xw, screen->menu_font_number, True, NULL); 11554 /* we will not be able to switch to ISO-8859-1 */ 11555 if (!screen->mergedVTFonts) { 11556 screen->utf8_fonts = uAlways; 11557 update_font_utf8_fonts(); 11558 } 11559 } 11560 } 11561#endif 11562 11563 xtermSetupPointer(xw, screen->pointer_shape); 11564 11565 /* set defaults */ 11566 pos.x = 1; 11567 pos.y = 1; 11568 pos.w = 80; 11569 pos.h = 24; 11570 11571 TRACE(("parsing geo_metry %s\n", NonNull(xw->misc.geo_metry))); 11572 pr = XParseXineramaGeometry(screen->display, xw->misc.geo_metry, &pos); 11573 TRACE(("... position %d,%d size %dx%d\n", pos.y, pos.x, pos.h, pos.w)); 11574 11575 set_max_col(screen, (int) (pos.w - 1)); /* units in character cells */ 11576 set_max_row(screen, (int) (pos.h - 1)); /* units in character cells */ 11577 xtermUpdateFontInfo(xw, False); 11578 11579 pos.w = screen->fullVwin.fullwidth; 11580 pos.h = screen->fullVwin.fullheight; 11581 11582 TRACE(("... BorderWidth: widget %d parent %d shell %d\n", 11583 BorderWidth(xw), 11584 BorderWidth(XtParent(xw)), 11585 BorderWidth(SHELL_OF(xw)))); 11586 11587 if ((pr & XValue) && (XNegative & pr)) { 11588 pos.x = (Position) (pos.x + (pos.scr_w 11589 - (int) pos.w 11590 - (BorderWidth(XtParent(xw)) * 2))); 11591 } 11592 if ((pr & YValue) && (YNegative & pr)) { 11593 pos.y = (Position) (pos.y + (pos.scr_h 11594 - (int) pos.h 11595 - (BorderWidth(XtParent(xw)) * 2))); 11596 } 11597 pos.x = (Position) (pos.x + pos.scr_x); 11598 pos.y = (Position) (pos.y + pos.scr_y); 11599 11600 /* set up size hints for window manager; min 1 char by 1 char */ 11601 getXtermSizeHints(xw); 11602 xtermSizeHints(xw, (xw->misc.scrollbar 11603 ? (screen->scrollWidget->core.width 11604 + BorderWidth(screen->scrollWidget)) 11605 : 0)); 11606 11607 xw->hints.x = pos.x; 11608 xw->hints.y = pos.y; 11609#if OPT_MAXIMIZE 11610 /* assure single-increment resize for fullscreen */ 11611 if (xw->work.ewmh[0].mode) { 11612 xw->hints.width_inc = 1; 11613 xw->hints.height_inc = 1; 11614 } 11615#endif 11616 if ((XValue & pr) || (YValue & pr)) { 11617 xw->hints.flags |= USSize | USPosition; 11618 xw->hints.flags |= PWinGravity; 11619 switch (pr & (XNegative | YNegative)) { 11620 case 0: 11621 xw->hints.win_gravity = NorthWestGravity; 11622 break; 11623 case XNegative: 11624 xw->hints.win_gravity = NorthEastGravity; 11625 break; 11626 case YNegative: 11627 xw->hints.win_gravity = SouthWestGravity; 11628 break; 11629 default: 11630 xw->hints.win_gravity = SouthEastGravity; 11631 break; 11632 } 11633 } else { 11634 /* set a default size, but do *not* set position */ 11635 xw->hints.flags |= PSize; 11636 } 11637 xw->hints.height = xw->hints.base_height 11638 + xw->hints.height_inc * MaxRows(screen); 11639 xw->hints.width = xw->hints.base_width 11640 + xw->hints.width_inc * MaxCols(screen); 11641 11642 if ((WidthValue & pr) || (HeightValue & pr)) 11643 xw->hints.flags |= USSize; 11644 else 11645 xw->hints.flags |= PSize; 11646 11647 /* 11648 * Note that the size-hints are for the shell, while the resize-request 11649 * is for the vt100 widget. They are not the same size. 11650 */ 11651 (void) REQ_RESIZE((Widget) xw, 11652 (Dimension) pos.w, (Dimension) pos.h, 11653 &xw->core.width, &xw->core.height); 11654 11655 /* XXX This is bogus. We are parsing geometries too late. This 11656 * is information that the shell widget ought to have before we get 11657 * realized, so that it can do the right thing. 11658 */ 11659 if (xw->hints.flags & USPosition) 11660 XMoveWindow(XtDisplay(xw), VShellWindow(xw), 11661 xw->hints.x, xw->hints.y); 11662 11663 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 11664 TRACE_HINTS(&xw->hints); 11665 XSetWMNormalHints(XtDisplay(xw), VShellWindow(xw), &xw->hints); 11666 TRACE(("%s@%d -- ", __FILE__, __LINE__)); 11667 TRACE_WM_HINTS(xw); 11668 11669 if ((pid_atom = XInternAtom(XtDisplay(xw), "_NET_WM_PID", False)) != None) { 11670 /* XChangeProperty format 32 really is "long" */ 11671 unsigned long pid_l = (unsigned long) getpid(); 11672 TRACE(("Setting _NET_WM_PID property to %lu\n", pid_l)); 11673 XChangeProperty(XtDisplay(xw), VShellWindow(xw), 11674 pid_atom, XA_CARDINAL, 32, PropModeReplace, 11675 (unsigned char *) &pid_l, 1); 11676 } 11677 11678 XFlush(XtDisplay(xw)); /* get it out to window manager */ 11679 11680 /* use ForgetGravity instead of SouthWestGravity because translating 11681 the Expose events for ConfigureNotifys is too hard */ 11682 values->bit_gravity = (GravityIsNorthWest(xw) 11683 ? NorthWestGravity 11684 : ForgetGravity); 11685 screen->fullVwin.window = XtWindow(xw) = 11686 XCreateWindow(XtDisplay(xw), XtWindow(XtParent(xw)), 11687 xw->core.x, xw->core.y, 11688 xw->core.width, xw->core.height, BorderWidth(xw), 11689 (int) xw->core.depth, 11690 InputOutput, CopyFromParent, 11691 *valuemask | CWBitGravity, values); 11692#if USE_DOUBLE_BUFFER 11693 if (allocateDbe(xw, &(screen->fullVwin))) { 11694 screen->needSwap = 1; 11695 TRACE(("initialized full double-buffering\n")); 11696 } else { 11697 resource.buffered = False; 11698 screen->fullVwin.drawable = screen->fullVwin.window; 11699 } 11700#endif /* USE_DOUBLE_BUFFER */ 11701 screen->event_mask = values->event_mask; 11702 11703#ifndef NO_ACTIVE_ICON 11704 /* 11705 * Normally, the font-number for icon fonts does not correspond with any of 11706 * the menu-selectable fonts. If we cannot load the font given for the 11707 * iconFont resource, try with font1 aka "Unreadable". 11708 */ 11709 screen->icon_fontnum = -1; 11710 if (getIconicFont(screen)->fs == 0) { 11711 getIconicFont(screen)->fs = 11712 xtermLoadQueryFont(xw, screen->MenuFontName(fontMenu_font1)); 11713 ReportIcons(("%susing font1 '%s' as iconFont\n", 11714 (getIconicFont(screen)->fs 11715 ? "" 11716 : "NOT "), 11717 screen->MenuFontName(fontMenu_font1))); 11718 } 11719#if OPT_RENDERFONT 11720 /* 11721 * If we still have no result from iconFont resource (perhaps because fonts 11722 * are missing) but are using Xft, try to use that instead. We prefer 11723 * bitmap fonts in any case, since scaled fonts are usually less readable, 11724 * particularly at small sizes. 11725 */ 11726 if (UsingRenderFont(xw) 11727 && getIconicFont(screen)->fs == 0) { 11728 screen->icon_fontnum = fontMenu_default; 11729 getIconicFont(screen)->fs = GetNormalFont(screen, fNorm)->fs; /* need for next-if */ 11730 ReportIcons(("using TrueType font as iconFont\n")); 11731 } 11732#endif 11733 xw->work.wm_name = getWindowManagerName(xw); 11734 if ((xw->work.active_icon == eiDefault) && getIconicFont(screen)->fs) { 11735 ReportIcons(("window manager name is %s\n", xw->work.wm_name)); 11736 if (x_strncasecmp(xw->work.wm_name, "fvwm", 4) && 11737 x_strncasecmp(xw->work.wm_name, "window maker", 12)) { 11738 xw->work.active_icon = eiFalse; 11739 TRACE(("... disable active_icon\n")); 11740 } 11741 } 11742 TRACE((".. if active_icon (%d), get its font\n", xw->work.active_icon)); 11743 if (xw->work.active_icon && getIconicFont(screen)->fs) { 11744 int iconX = 0, iconY = 0; 11745 Widget shell = SHELL_OF(xw); 11746 VTwin *win = &(screen->iconVwin); 11747 int save_fontnum = screen->menu_font_number; 11748 11749 ReportIcons(("initializing active-icon %d\n", screen->icon_fontnum)); 11750 screen->menu_font_number = screen->icon_fontnum; 11751 XtVaGetValues(shell, 11752 XtNiconX, &iconX, 11753 XtNiconY, &iconY, 11754 (XtPointer) 0); 11755 xtermComputeFontInfo(xw, &(screen->iconVwin), 11756 getIconicFont(screen)->fs, 0); 11757 screen->menu_font_number = save_fontnum; 11758 11759 /* since only one client is permitted to select for Button 11760 * events, we have to let the window manager get 'em... 11761 */ 11762 values->event_mask &= ~(ButtonPressMask | ButtonReleaseMask); 11763 values->border_pixel = xw->misc.icon_border_pixel; 11764 11765 screen->iconVwin.window = 11766 XCreateWindow(XtDisplay(xw), 11767 RootWindowOfScreen(XtScreen(shell)), 11768 iconX, iconY, 11769 screen->iconVwin.fullwidth, 11770 screen->iconVwin.fullheight, 11771 xw->misc.icon_border_width, 11772 (int) xw->core.depth, 11773 InputOutput, CopyFromParent, 11774 *valuemask | CWBitGravity | CWBorderPixel, 11775 values); 11776#if USE_DOUBLE_BUFFER 11777 if (allocateDbe(xw, &(screen->iconVwin))) { 11778 TRACE(("initialized icon double-buffering\n")); 11779 } else { 11780 resource.buffered = False; 11781 screen->iconVwin.drawable = screen->iconVwin.window; 11782 screen->fullVwin.drawable = screen->fullVwin.window; 11783 } 11784#endif /* USE_DOUBLE_BUFFER */ 11785 XtVaSetValues(shell, 11786 XtNiconWindow, screen->iconVwin.window, 11787 (XtPointer) 0); 11788 XtRegisterDrawable(XtDisplay(xw), screen->iconVwin.window, w); 11789 11790 setCgsFont(xw, win, gcNorm, getIconicFont(screen)); 11791 setCgsFore(xw, win, gcNorm, T_COLOR(screen, TEXT_FG)); 11792 setCgsBack(xw, win, gcNorm, T_COLOR(screen, TEXT_BG)); 11793 11794 copyCgs(xw, win, gcBold, gcNorm); 11795 11796 setCgsFont(xw, win, gcNormReverse, getIconicFont(screen)); 11797 setCgsFore(xw, win, gcNormReverse, T_COLOR(screen, TEXT_BG)); 11798 setCgsBack(xw, win, gcNormReverse, T_COLOR(screen, TEXT_FG)); 11799 11800 copyCgs(xw, win, gcBoldReverse, gcNormReverse); 11801 11802 initBorderGC(xw, win); 11803 11804#if OPT_TOOLBAR 11805 /* 11806 * Toolbar is initialized before we get here. Enable the menu item 11807 * and set it properly. 11808 */ 11809 SetItemSensitivity(vtMenuEntries[vtMenu_activeicon].widget, True); 11810 update_activeicon(); 11811#endif 11812 } else { 11813 ReportIcons(("disabled active-icon\n")); 11814 xw->work.active_icon = eiFalse; 11815 } 11816#endif /* NO_ACTIVE_ICON */ 11817 11818#if OPT_INPUT_METHOD 11819 VTInitI18N(xw); 11820#endif 11821#if OPT_NUM_LOCK 11822 VTInitModifiers(xw); 11823#if OPT_EXTRA_PASTE 11824 if (xw->keyboard.extra_translations) { 11825 XtOverrideTranslations((Widget) xw, 11826 XtParseTranslationTable(xw->keyboard.extra_translations)); 11827 } 11828#endif 11829#endif 11830 11831 set_cursor_gcs(xw); 11832 initBorderGC(xw, &(screen->fullVwin)); 11833 11834 /* Reset variables used by ANSI emulation. */ 11835 11836 resetCharsets(screen); 11837 11838 XDefineCursor(screen->display, VShellWindow(xw), screen->pointer_cursor); 11839 11840 set_cur_col(screen, 0); 11841 set_cur_row(screen, 0); 11842 set_max_col(screen, Width(screen) / screen->fullVwin.f_width - 1); 11843 set_max_row(screen, Height(screen) / screen->fullVwin.f_height - 1); 11844 resetMarginMode(xw); 11845 11846 memset(screen->sc, 0, sizeof(screen->sc)); 11847 11848 /* Mark screen buffer as unallocated. We wait until the run loop so 11849 that the child process does not fork and exec with all the dynamic 11850 memory it will never use. If we were to do it here, the 11851 swap space for new process would be huge for huge savelines. */ 11852#if OPT_TEK4014 11853 if (!tekWidget) /* if not called after fork */ 11854#endif 11855 { 11856 screen->visbuf = NULL; 11857 screen->saveBuf_index = NULL; 11858 } 11859 11860 ResetWrap(screen); 11861 screen->scrolls = screen->incopy = 0; 11862 xtermSetCursorBox(screen); 11863 11864 screen->savedlines = 0; 11865 11866 for (i = 0; i < 2; ++i) { 11867 screen->whichBuf = !screen->whichBuf; 11868 CursorSave(xw); 11869 } 11870 11871#ifndef NO_ACTIVE_ICON 11872 if (!xw->work.active_icon) 11873#endif 11874 xtermLoadIcon(xw, resource.icon_hint); 11875 11876 /* 11877 * Do this last, since it may change the layout via a resize. 11878 */ 11879 if (xw->misc.scrollbar) { 11880 screen->fullVwin.sb_info.width = 0; 11881 ScrollBarOn(xw, False); 11882 } 11883 11884 xtermSetWinSize(xw); 11885 TRACE(("" TRACE_R " VTRealize\n")); 11886} 11887 11888#if OPT_INPUT_METHOD 11889 11890/* limit this feature to recent XFree86 since X11R6.x core dumps */ 11891#if defined(XtSpecificationRelease) && XtSpecificationRelease >= 6 && defined(X_HAVE_UTF8_STRING) 11892#define USE_XIM_INSTANTIATE_CB 11893 11894static void 11895xim_instantiate_cb(Display *display, 11896 XPointer client_data GCC_UNUSED, 11897 XPointer call_data GCC_UNUSED) 11898{ 11899 XtermWidget xw = term; 11900 11901 TRACE(("xim_instantiate_cb client=%p, call=%p\n", client_data, call_data)); 11902 11903 if (display == XtDisplay(xw)) { 11904 VTInitI18N(xw); 11905 } 11906} 11907 11908static void 11909xim_destroy_cb(XIM im GCC_UNUSED, 11910 XPointer client_data GCC_UNUSED, 11911 XPointer call_data GCC_UNUSED) 11912{ 11913 XtermWidget xw = term; 11914 TInput *input = lookupTInput(xw, (Widget) xw); 11915 11916 TRACE(("xim_destroy_cb im=%lx, client=%p, call=%p\n", 11917 (long) im, client_data, call_data)); 11918 if (input) 11919 input->xic = NULL; 11920 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 11921 xim_instantiate_cb, NULL); 11922} 11923#endif /* X11R6+ */ 11924 11925static Boolean 11926xim_create_fs(XtermWidget xw) 11927{ 11928 XFontStruct **fonts; 11929 char **font_name_list; 11930 char **missing_charset_list; 11931 char *def_string; 11932 int missing_charset_count; 11933 unsigned i, j; 11934 11935 if (xw->work.xim_fs == 0) { 11936 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 11937 xw->misc.f_x, 11938 &missing_charset_list, 11939 &missing_charset_count, 11940 &def_string); 11941 if (xw->work.xim_fs == NULL) { 11942 xtermWarning("Preparation of font set " 11943 "\"%s\" for XIM failed.\n", xw->misc.f_x); 11944 xw->work.xim_fs = XCreateFontSet(XtDisplay(xw), 11945 DEFXIMFONT, 11946 &missing_charset_list, 11947 &missing_charset_count, 11948 &def_string); 11949 } 11950 } 11951 if (xw->work.xim_fs == NULL) { 11952 xtermWarning("Preparation of default font set " 11953 "\"%s\" for XIM failed.\n", DEFXIMFONT); 11954 cleanupInputMethod(xw); 11955 xw->work.cannot_im = True; 11956 } else { 11957 (void) XExtentsOfFontSet(xw->work.xim_fs); 11958 j = (unsigned) XFontsOfFontSet(xw->work.xim_fs, &fonts, &font_name_list); 11959 for (i = 0, xw->work.xim_fs_ascent = 0; i < j; i++) { 11960 if (xw->work.xim_fs_ascent < (*fonts)->ascent) 11961 xw->work.xim_fs_ascent = (*fonts)->ascent; 11962 } 11963 } 11964 return (Boolean) !(xw->work.cannot_im); 11965} 11966 11967static void 11968xim_create_xic(XtermWidget xw, Widget theInput) 11969{ 11970 Display *myDisplay = XtDisplay(theInput); 11971 Window myWindow = XtWindow(theInput); 11972 unsigned i, j; 11973 char *p = NULL, *s, *t, *ns, *end, buf[32]; 11974 XIMStyles *xim_styles; 11975 XIMStyle input_style = 0; 11976 Bool found; 11977 static struct { 11978 const char *name; 11979 unsigned long code; 11980 } known_style[] = { 11981 { 11982 "OverTheSpot", (XIMPreeditPosition | XIMStatusNothing) 11983 }, 11984 { 11985 "OffTheSpot", (XIMPreeditArea | XIMStatusArea) 11986 }, 11987 { 11988 "Root", (XIMPreeditNothing | XIMStatusNothing) 11989 }, 11990 }; 11991 TInput *input = lookupTInput(xw, theInput); 11992 11993 if (xw->work.cannot_im) { 11994 return; 11995 } 11996 11997 if (input == 0) { 11998 for (i = 0; i < NINPUTWIDGETS; ++i) { 11999 if (xw->work.inputs[i].w == 0) { 12000 input = xw->work.inputs + i; 12001 input->w = theInput; 12002 break; 12003 } 12004 } 12005 } 12006 12007 if (input == 0) { 12008 xtermWarning("attempted to add too many input widgets\n"); 12009 return; 12010 } 12011 12012 TRACE(("xim_real_init\n")); 12013 12014 if (IsEmpty(xw->misc.input_method)) { 12015 if ((p = XSetLocaleModifiers("")) != NULL && *p) { 12016 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 12017 } 12018 } else { 12019 s = xw->misc.input_method; 12020 i = 5 + (unsigned) strlen(s); 12021 12022 t = (char *) MyStackAlloc(i, buf); 12023 if (t == NULL) { 12024 SysError(ERROR_VINIT); 12025 } else { 12026 12027 for (ns = s; ns && *s;) { 12028 while (*s && isspace(CharOf(*s))) 12029 s++; 12030 if (!*s) 12031 break; 12032 if ((ns = end = strchr(s, ',')) == 0) 12033 end = s + strlen(s); 12034 while ((end != s) && isspace(CharOf(end[-1]))) 12035 end--; 12036 12037 if (end != s) { 12038 strcpy(t, "@im="); 12039 strncat(t, s, (size_t) (end - s)); 12040 12041 if ((p = XSetLocaleModifiers(t)) != 0 && *p 12042 && (input->xim = XOpenIM(myDisplay, 12043 NULL, 12044 NULL, 12045 NULL)) != 0) { 12046 break; 12047 } 12048 12049 } 12050 s = ns + 1; 12051 } 12052 MyStackFree(t, buf); 12053 } 12054 } 12055 12056 if (input->xim == NULL 12057 && (p = XSetLocaleModifiers("@im=none")) != NULL 12058 && *p) { 12059 input->xim = XOpenIM(myDisplay, NULL, NULL, NULL); 12060 } 12061 12062 if (!input->xim) { 12063 xtermWarning("Failed to open input method\n"); 12064 return; 12065 } 12066 TRACE(("VTInitI18N opened input method:%s\n", NonNull(p))); 12067 12068 if (XGetIMValues(input->xim, XNQueryInputStyle, &xim_styles, (void *) 0) 12069 || !xim_styles 12070 || !xim_styles->count_styles) { 12071 xtermWarning("input method doesn't support any style\n"); 12072 cleanupInputMethod(xw); 12073 xw->work.cannot_im = True; 12074 return; 12075 } 12076 12077 found = False; 12078 for (s = xw->misc.preedit_type; s && !found;) { 12079 while (*s && isspace(CharOf(*s))) 12080 s++; 12081 if (!*s) 12082 break; 12083 if ((ns = end = strchr(s, ',')) != 0) 12084 ns++; 12085 else 12086 end = s + strlen(s); 12087 while ((end != s) && isspace(CharOf(end[-1]))) 12088 end--; 12089 12090 if (end != s) { /* just in case we have a spurious comma */ 12091 TRACE(("looking for style '%.*s'\n", (int) (end - s), s)); 12092 for (i = 0; i < XtNumber(known_style); i++) { 12093 if ((int) strlen(known_style[i].name) == (end - s) 12094 && !strncmp(s, known_style[i].name, (size_t) (end - s))) { 12095 input_style = known_style[i].code; 12096 for (j = 0; j < xim_styles->count_styles; j++) { 12097 if (input_style == xim_styles->supported_styles[j]) { 12098 found = True; 12099 break; 12100 } 12101 } 12102 if (found) 12103 break; 12104 } 12105 } 12106 } 12107 12108 s = ns; 12109 } 12110 XFree(xim_styles); 12111 12112 if (!found) { 12113 xtermWarning("input method doesn't support my preedit type (%s)\n", 12114 xw->misc.preedit_type); 12115 cleanupInputMethod(xw); 12116 xw->work.cannot_im = True; 12117 return; 12118 } 12119 12120 /* 12121 * Check for styles we do not yet support. 12122 */ 12123 TRACE(("input_style %#lx\n", input_style)); 12124 if (input_style == (XIMPreeditArea | XIMStatusArea)) { 12125 xtermWarning("This program doesn't support the 'OffTheSpot' preedit type\n"); 12126 cleanupInputMethod(xw); 12127 xw->work.cannot_im = True; 12128 return; 12129 } 12130 12131 /* 12132 * For XIMPreeditPosition (or OverTheSpot), XIM client has to 12133 * prepare a font. 12134 * The font has to be locale-dependent XFontSet, whereas 12135 * XTerm use Unicode font. This leads a problem that the 12136 * same font cannot be used for XIM preedit. 12137 */ 12138 if (input_style != (XIMPreeditNothing | XIMStatusNothing)) { 12139 XVaNestedList p_list; 12140 XPoint spot = 12141 {0, 0}; 12142 12143 if (xim_create_fs(xw)) { 12144 p_list = XVaCreateNestedList(0, 12145 XNSpotLocation, &spot, 12146 XNFontSet, xw->work.xim_fs, 12147 (void *) 0); 12148 input->xic = XCreateIC(input->xim, 12149 XNInputStyle, input_style, 12150 XNClientWindow, myWindow, 12151 XNFocusWindow, myWindow, 12152 XNPreeditAttributes, p_list, 12153 (void *) 0); 12154 } 12155 } else { 12156 input->xic = XCreateIC(input->xim, XNInputStyle, input_style, 12157 XNClientWindow, myWindow, 12158 XNFocusWindow, myWindow, 12159 (void *) 0); 12160 } 12161 12162 if (!input->xic) { 12163 xtermWarning("Failed to create input context\n"); 12164 cleanupInputMethod(xw); 12165 } 12166#if defined(USE_XIM_INSTANTIATE_CB) 12167 else { 12168 XIMCallback destroy_cb; 12169 12170 destroy_cb.callback = xim_destroy_cb; 12171 destroy_cb.client_data = NULL; 12172 if (XSetIMValues(input->xim, 12173 XNDestroyCallback, 12174 &destroy_cb, 12175 (void *) 0)) { 12176 xtermWarning("Could not set destroy callback to IM\n"); 12177 } 12178 } 12179#endif 12180 12181 return; 12182} 12183 12184static void 12185xim_real_init(XtermWidget xw) 12186{ 12187 xim_create_xic(xw, (Widget) xw); 12188} 12189 12190static void 12191VTInitI18N(XtermWidget xw) 12192{ 12193 if (xw->misc.open_im) { 12194 xim_real_init(xw); 12195 12196#if defined(USE_XIM_INSTANTIATE_CB) 12197 if (lookupTInput(xw, (Widget) xw) == NULL 12198 && !xw->work.cannot_im 12199 && xw->misc.retry_im-- > 0) { 12200 sleep(3); 12201 XRegisterIMInstantiateCallback(XtDisplay(xw), NULL, NULL, NULL, 12202 xim_instantiate_cb, NULL); 12203 } 12204#endif 12205 } 12206} 12207 12208TInput * 12209lookupTInput(XtermWidget xw, Widget w) 12210{ 12211 TInput *result = 0; 12212 unsigned n; 12213 12214 for (n = 0; n < NINPUTWIDGETS; ++n) { 12215 if (xw->work.inputs[n].w == w) { 12216 result = xw->work.inputs + n; 12217 break; 12218 } 12219 } 12220 12221 return result; 12222} 12223#endif /* OPT_INPUT_METHOD */ 12224 12225static void 12226set_cursor_outline_gc(XtermWidget xw, 12227 Bool filled, 12228 Pixel fg, 12229 Pixel bg, 12230 Pixel cc) 12231{ 12232 TScreen *screen = TScreenOf(xw); 12233 VTwin *win = WhichVWin(screen); 12234 CgsEnum cgsId = gcVTcursOutline; 12235 12236 if (cc == bg) 12237 cc = fg; 12238 12239 if (filled) { 12240 setCgsFore(xw, win, cgsId, bg); 12241 setCgsBack(xw, win, cgsId, cc); 12242 } else { 12243 setCgsFore(xw, win, cgsId, cc); 12244 setCgsBack(xw, win, cgsId, bg); 12245 } 12246} 12247 12248static Boolean 12249VTSetValues(Widget cur, 12250 Widget request GCC_UNUSED, 12251 Widget wnew, 12252 ArgList args GCC_UNUSED, 12253 Cardinal *num_args GCC_UNUSED) 12254{ 12255 XtermWidget curvt = (XtermWidget) cur; 12256 XtermWidget newvt = (XtermWidget) wnew; 12257 Boolean refresh_needed = False; 12258 Boolean fonts_redone = False; 12259 12260 if ((T_COLOR(TScreenOf(curvt), TEXT_BG) != 12261 T_COLOR(TScreenOf(newvt), TEXT_BG)) || 12262 (T_COLOR(TScreenOf(curvt), TEXT_FG) != 12263 T_COLOR(TScreenOf(newvt), TEXT_FG)) || 12264 (TScreenOf(curvt)->MenuFontName(TScreenOf(curvt)->menu_font_number) != 12265 TScreenOf(newvt)->MenuFontName(TScreenOf(newvt)->menu_font_number)) || 12266 strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 12267 if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 12268 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(newvt); 12269 } 12270 if (xtermLoadFont(newvt, 12271 xtermFontName(TScreenOf(newvt)->MenuFontName(TScreenOf(curvt)->menu_font_number)), 12272 True, TScreenOf(newvt)->menu_font_number)) { 12273 /* resizing does the redisplay, so don't ask for it here */ 12274 refresh_needed = True; 12275 fonts_redone = True; 12276 } else if (strcmp(DefaultFontN(curvt), DefaultFontN(newvt))) { 12277 TScreenOf(newvt)->MenuFontName(fontMenu_default) = DefaultFontN(curvt); 12278 } 12279 } 12280 if (!fonts_redone 12281 && (T_COLOR(TScreenOf(curvt), TEXT_CURSOR) != 12282 T_COLOR(TScreenOf(newvt), TEXT_CURSOR))) { 12283 if (set_cursor_gcs(newvt)) 12284 refresh_needed = True; 12285 } 12286 if (curvt->misc.re_verse != newvt->misc.re_verse) { 12287 newvt->flags ^= REVERSE_VIDEO; 12288 ReverseVideo(newvt); 12289 /* ReverseVideo toggles */ 12290 newvt->misc.re_verse = (Boolean) (!newvt->misc.re_verse); 12291 refresh_needed = True; 12292 } 12293 if ((T_COLOR(TScreenOf(curvt), MOUSE_FG) != 12294 T_COLOR(TScreenOf(newvt), MOUSE_FG)) || 12295 (T_COLOR(TScreenOf(curvt), MOUSE_BG) != 12296 T_COLOR(TScreenOf(newvt), MOUSE_BG))) { 12297 recolor_cursor(TScreenOf(newvt), 12298 TScreenOf(newvt)->pointer_cursor, 12299 T_COLOR(TScreenOf(newvt), MOUSE_FG), 12300 T_COLOR(TScreenOf(newvt), MOUSE_BG)); 12301 refresh_needed = True; 12302 } 12303 if (curvt->misc.scrollbar != newvt->misc.scrollbar) { 12304 ToggleScrollBar(newvt); 12305 } 12306 12307 return refresh_needed; 12308} 12309 12310/* 12311 * Given a font-slot and information about selection/reverse, find the 12312 * corresponding cached-GC slot. 12313 */ 12314#if OPT_WIDE_ATTRS 12315static int 12316reverseCgs(XtermWidget xw, unsigned attr_flags, Bool hilite, int font) 12317{ 12318 TScreen *screen = TScreenOf(xw); 12319 CgsEnum result = gcMAX; 12320 12321 (void) screen; 12322 if (ReverseOrHilite(screen, attr_flags, hilite)) { 12323 switch (font) { 12324 case fNorm: 12325 result = gcNormReverse; 12326 break; 12327 case fBold: 12328 result = gcBoldReverse; 12329 break; 12330#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 12331 case fItal: 12332 result = gcNormReverse; /* FIXME */ 12333 break; 12334#endif 12335#if OPT_WIDE_CHARS 12336 case fWide: 12337 result = gcWideReverse; 12338 break; 12339 case fWBold: 12340 result = gcWBoldReverse; 12341 break; 12342 case fWItal: 12343 result = gcWideReverse; /* FIXME */ 12344 break; 12345#endif 12346 } 12347 } else { 12348 switch (font) { 12349 case fNorm: 12350 result = gcNorm; 12351 break; 12352 case fBold: 12353 result = gcBold; 12354 break; 12355#if OPT_WIDE_ATTRS || OPT_RENDERWIDE 12356 case fItal: 12357 result = gcNorm; /* FIXME */ 12358 break; 12359#endif 12360#if OPT_WIDE_CHARS 12361 case fWide: 12362 result = gcWide; 12363 break; 12364 case fWBold: 12365 result = gcWBold; 12366 break; 12367 case fWItal: 12368 result = gcWide; /* FIXME */ 12369 break; 12370#endif 12371 } 12372 } 12373 return (int) result; 12374} 12375#endif 12376 12377#define setGC(code) set_at = __LINE__, currentCgs = code 12378 12379#define OutsideSelection(screen,srow,scol) \ 12380 ((srow) > (screen)->endH.row || \ 12381 ((srow) == (screen)->endH.row && \ 12382 (scol) >= (screen)->endH.col) || \ 12383 (srow) < (screen)->startH.row || \ 12384 ((srow) == (screen)->startH.row && \ 12385 (scol) < (screen)->startH.col)) 12386 12387/* 12388 * Shows cursor at new cursor position in screen. 12389 */ 12390void 12391ShowCursor(XtermWidget xw) 12392{ 12393 TScreen *screen = TScreenOf(xw); 12394 XTermDraw params; 12395 IChar base; 12396 unsigned flags; 12397 CellColor fg_bg = initCColor; 12398 GC currentGC; 12399 GC outlineGC; 12400 CgsEnum currentCgs = gcMAX; 12401 VTwin *currentWin = WhichVWin(screen); 12402 int set_at; 12403 Bool in_selection; 12404 Bool reversed; 12405 Bool filled; 12406 Pixel fg_pix; 12407 Pixel bg_pix; 12408 Pixel tmp; 12409#if OPT_HIGHLIGHT_COLOR 12410 Pixel selbg_pix = T_COLOR(screen, HIGHLIGHT_BG); 12411 Pixel selfg_pix = T_COLOR(screen, HIGHLIGHT_FG); 12412 Boolean use_selbg; 12413 Boolean use_selfg; 12414#endif 12415#if OPT_WIDE_CHARS 12416 int my_col = 0; 12417#endif 12418 int cursor_col; 12419 CLineData *ld = 0; 12420 12421 if (screen->cursor_state == BLINKED_OFF) 12422 return; 12423 12424 if (screen->eventMode != NORMAL) 12425 return; 12426 12427 if (INX2ROW(screen, screen->cur_row) > screen->max_row) 12428 return; 12429 12430 screen->cursorp.row = screen->cur_row; 12431 cursor_col = screen->cursorp.col = screen->cur_col; 12432 screen->cursor_moved = False; 12433 12434#ifndef NO_ACTIVE_ICON 12435 if (IsIcon(screen)) { 12436 screen->cursor_state = ON; 12437 return; 12438 } 12439#endif /* NO_ACTIVE_ICON */ 12440 12441 ld = getLineData(screen, screen->cur_row); 12442 12443 base = ld->charData[cursor_col]; 12444 flags = ld->attribs[cursor_col]; 12445 12446 if_OPT_WIDE_CHARS(screen, { 12447 if (base == HIDDEN_CHAR && cursor_col > 0) { 12448 /* if cursor points to non-initial part of wide character, 12449 * back it up 12450 */ 12451 --cursor_col; 12452 base = ld->charData[cursor_col]; 12453 } 12454 my_col = cursor_col; 12455 if (base == 0) 12456 base = ' '; 12457 if (isWide((int) base)) 12458 my_col += 1; 12459 }); 12460 12461 if (base == 0) { 12462 base = ' '; 12463 } 12464#if OPT_ISO_COLORS 12465#ifdef EXP_BOGUS_FG 12466 /* 12467 * If the cursor happens to be on blanks, and we have not set both 12468 * foreground and background color, do not treat it as a colored cell. 12469 */ 12470 if (base == ' ') { 12471 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 12472 TRACE(("ShowCursor - do not treat as a colored cell\n")); 12473 flags &= ~(FG_COLOR | BG_COLOR); 12474 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 12475 TRACE(("ShowCursor - should we treat as a colored cell?\n")); 12476 if (!(xw->flags & FG_COLOR)) { 12477 if (CheckBogusForeground(screen, "ShowCursor")) { 12478 flags &= ~(FG_COLOR | BG_COLOR); 12479 } 12480 } 12481 } 12482 } 12483#else /* !EXP_BOGUS_FG */ 12484 /* 12485 * If the cursor happens to be on blanks, and the foreground color is set 12486 * but not the background, do not treat it as a colored cell. 12487 */ 12488 if ((flags & TERM_COLOR_FLAGS(xw)) == FG_COLOR 12489 && base == ' ') { 12490 flags &= ~TERM_COLOR_FLAGS(xw); 12491 } 12492#endif 12493#endif 12494 12495 /* 12496 * Compare the current cell to the last set of colors used for the 12497 * cursor and update the GC's if needed. 12498 */ 12499 (void) fg_bg; 12500 if_OPT_ISO_COLORS(screen, { 12501 fg_bg = ld->color[cursor_col]; 12502 }); 12503 12504 fg_pix = getXtermFG(xw, flags, (int) extract_fg(xw, fg_bg, flags)); 12505 bg_pix = getXtermBG(xw, flags, (int) extract_bg(xw, fg_bg, flags)); 12506 12507 /* 12508 * If we happen to have the same foreground/background colors, choose 12509 * a workable foreground color from which we can obtain a visible cursor. 12510 */ 12511 if (fg_pix == bg_pix) { 12512 long bg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_BG)); 12513 long fg_diff = (long) (bg_pix - T_COLOR(TScreenOf(xw), TEXT_FG)); 12514 if (bg_diff < 0) 12515 bg_diff = -bg_diff; 12516 if (fg_diff < 0) 12517 fg_diff = -fg_diff; 12518 if (bg_diff < fg_diff) { 12519 fg_pix = T_COLOR(TScreenOf(xw), TEXT_FG); 12520 } else { 12521 fg_pix = T_COLOR(TScreenOf(xw), TEXT_BG); 12522 } 12523 } 12524 12525 if (OutsideSelection(screen, screen->cur_row, screen->cur_col)) 12526 in_selection = False; 12527 else 12528 in_selection = True; 12529 12530 reversed = ReverseOrHilite(screen, flags, in_selection); 12531 12532 /* This is like updatedXtermGC(), except that we have to worry about 12533 * whether the window has focus, since in that case we want just an 12534 * outline for the cursor. 12535 */ 12536 filled = (screen->select || screen->always_highlight) && isCursorBlock(screen); 12537#if OPT_HIGHLIGHT_COLOR 12538 use_selbg = isNotForeground(xw, fg_pix, bg_pix, selbg_pix); 12539 use_selfg = isNotBackground(xw, fg_pix, bg_pix, selfg_pix); 12540#endif 12541 if (filled) { 12542 if (reversed) { /* text is reverse video */ 12543 if (getCgsGC(xw, currentWin, gcVTcursNormal)) { 12544 setGC(gcVTcursNormal); 12545 } else { 12546 if (flags & BOLDATTR(screen)) { 12547 setGC(gcBold); 12548 } else { 12549 setGC(gcNorm); 12550 } 12551 } 12552 EXCHANGE(fg_pix, bg_pix, tmp); 12553#if OPT_HIGHLIGHT_COLOR 12554 if (screen->hilite_reverse) { 12555 if (use_selbg && !use_selfg) 12556 fg_pix = bg_pix; 12557 if (use_selfg && !use_selbg) 12558 bg_pix = fg_pix; 12559 if (use_selbg) 12560 bg_pix = selbg_pix; 12561 if (use_selfg) 12562 fg_pix = selfg_pix; 12563 } 12564#endif 12565 } else { /* normal video */ 12566 if (getCgsGC(xw, currentWin, gcVTcursReverse)) { 12567 setGC(gcVTcursReverse); 12568 } else { 12569 if (flags & BOLDATTR(screen)) { 12570 setGC(gcBoldReverse); 12571 } else { 12572 setGC(gcNormReverse); 12573 } 12574 } 12575 } 12576 12577#define CUR_XX T_COLOR(screen, TEXT_CURSOR) 12578#define CGS_FG getCgsFore(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 12579#define CGS_BG getCgsBack(xw, currentWin, getCgsGC(xw, currentWin, currentCgs)) 12580 12581#define FIX_311 (CUR_XX == (reversed ? xw->dft_background : xw->dft_foreground)) 12582#define FIX_328 (CUR_XX == bg_pix) 12583#define FIX_330 (FIX_328 && reversed && in_selection) 12584 12585 if (FIX_330 || FIX_311) { 12586 setCgsBack(xw, currentWin, currentCgs, fg_pix); 12587 } 12588 setCgsFore(xw, currentWin, currentCgs, bg_pix); 12589 } else { /* not selected */ 12590 if (reversed) { /* text is reverse video */ 12591 EXCHANGE(fg_pix, bg_pix, tmp); 12592 setGC(gcNormReverse); 12593 } else { /* normal video */ 12594 setGC(gcNorm); 12595 } 12596#if OPT_HIGHLIGHT_COLOR 12597 if (screen->hilite_reverse) { 12598 if (in_selection && !reversed) { 12599 /* EMPTY */ 12600 /* really INVERSE ... */ 12601 ; 12602 } else if (in_selection || reversed) { 12603 if (use_selbg) { 12604 if (use_selfg) { 12605 bg_pix = fg_pix; 12606 } else { 12607 fg_pix = bg_pix; 12608 bg_pix = selbg_pix; 12609 } 12610 } 12611 if (use_selfg) { 12612 fg_pix = selfg_pix; 12613 } 12614 } 12615 } else { 12616 if (in_selection) { 12617 if (use_selbg) { 12618 bg_pix = selbg_pix; 12619 } 12620 if (use_selfg) { 12621 fg_pix = selfg_pix; 12622 } 12623 } 12624 } 12625#endif 12626 setCgsFore(xw, currentWin, currentCgs, fg_pix); 12627 setCgsBack(xw, currentWin, currentCgs, bg_pix); 12628 } 12629 12630 if (screen->cursor_busy == 0 12631 && (screen->cursor_state != ON || screen->cursor_GC != set_at)) { 12632 int x, y; 12633 12634 screen->cursor_GC = set_at; 12635 TRACE(("ShowCursor calling drawXtermText cur(%d,%d) %s-%s, set_at %d\n", 12636 screen->cur_row, screen->cur_col, 12637 (filled ? "filled" : "outline"), 12638 (isCursorBlock(screen) ? "box" : 12639 isCursorUnderline(screen) ? "underline" : "bar"), 12640 set_at)); 12641 12642 currentGC = getCgsGC(xw, currentWin, currentCgs); 12643 x = LineCursorX(screen, ld, cursor_col); 12644 y = CursorY(screen, screen->cur_row); 12645 12646 if (!isCursorBlock(screen)) { 12647 /* 12648 * Overriding the combination of filled, reversed, in_selection is 12649 * too complicated since the underline or bar and the text-cell use 12650 * different rules. Just redraw the text-cell, and draw the 12651 * underline or bar on top of it. 12652 */ 12653 HideCursor(xw); 12654 12655 /* 12656 * Our current-GC is likely to have been modified in HideCursor(). 12657 * Set up a new request. 12658 */ 12659 if (filled) { 12660 if (FIX_330 || FIX_311) { 12661 setCgsBack(xw, currentWin, currentCgs, fg_pix); 12662 } 12663 setCgsFore(xw, currentWin, currentCgs, bg_pix); 12664 } else { 12665 setCgsFore(xw, currentWin, currentCgs, fg_pix); 12666 setCgsBack(xw, currentWin, currentCgs, bg_pix); 12667 } 12668 } 12669 12670 /* 12671 * Update the outline-gc, to keep the cursor color distinct from the 12672 * background color. 12673 */ 12674 set_cursor_outline_gc(xw, 12675 filled, 12676 fg_pix, 12677 bg_pix, 12678 T_COLOR(screen, TEXT_CURSOR)); 12679 12680 outlineGC = getCgsGC(xw, currentWin, gcVTcursOutline); 12681 if (outlineGC == 0) 12682 outlineGC = currentGC; 12683 12684 if (isCursorUnderline(screen)) { 12685 12686 /* 12687 * Finally, draw the underline. 12688 */ 12689 screen->box->x = (short) x; 12690 screen->box->y = (short) (y + FontHeight(screen) - 2); 12691 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12692 screen->box, NBOX, CoordModePrevious); 12693 } else if (isCursorBar(screen)) { 12694 12695 /* 12696 * Or draw the bar. 12697 */ 12698 screen->box->x = (short) x; 12699 screen->box->y = (short) y; 12700 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12701 screen->box, NBOX, CoordModePrevious); 12702 } else { 12703#if OPT_WIDE_ATTRS 12704 int italics_on = ((ld->attribs[cursor_col] & ATR_ITALIC) != 0); 12705 int italics_off = ((xw->flags & ATR_ITALIC) != 0); 12706 int fix_italics = (italics_on != italics_off); 12707 int which_font = ((xw->flags & BOLD) ? fBold : fNorm); 12708 MyGetFont getter = italics_on ? getItalicFont : getNormalFont; 12709 12710 if_OPT_WIDE_CHARS(screen, { 12711 if (isWide((int) base)) { 12712 which_font = ((xw->flags & BOLD) ? fWBold : fWide); 12713 } 12714 }); 12715 12716 if (fix_italics && UseItalicFont(screen)) { 12717 xtermLoadItalics(xw); 12718 setCgsFont(xw, currentWin, currentCgs, 12719 getter(screen, which_font)); 12720 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 12721 ? getItalicFont 12722 : getNormalFont); 12723 } 12724 currentGC = getCgsGC(xw, currentWin, currentCgs); 12725#endif /* OPT_WIDE_ATTRS */ 12726 12727 /* *INDENT-EQLS* */ 12728 params.xw = xw; 12729 params.attr_flags = (flags & DRAWX_MASK); 12730 params.draw_flags = 0; 12731 params.this_chrset = LineCharSet(screen, ld); 12732 params.real_chrset = CSET_SWL; 12733 params.on_wide = 0; 12734 12735 drawXtermText(¶ms, 12736 currentGC, x, y, 12737 &base, 1); 12738 12739#if OPT_WIDE_CHARS 12740 if_OPT_WIDE_CHARS(screen, { 12741 size_t off; 12742 12743 /* *INDENT-EQLS* */ 12744 params.draw_flags = NOBACKGROUND; 12745 params.on_wide = isWide((int) base); 12746 12747 for_each_combData(off, ld) { 12748 if (!(ld->combData[off][my_col])) 12749 break; 12750 drawXtermText(¶ms, 12751 currentGC, x, y, 12752 ld->combData[off] + my_col, 1); 12753 } 12754 }); 12755#endif 12756 12757 if (!filled) { 12758 screen->box->x = (short) x; 12759 screen->box->y = (short) y; 12760 XDrawLines(screen->display, VDrawable(screen), outlineGC, 12761 screen->box, NBOX, CoordModePrevious); 12762 } 12763#if OPT_WIDE_ATTRS 12764 if (fix_italics && UseItalicFont(screen)) { 12765 setCgsFont(xw, currentWin, currentCgs, 12766 getter(screen, which_font)); 12767 } 12768#endif 12769 } 12770 } 12771 screen->cursor_state = ON; 12772 12773 return; 12774} 12775 12776/* 12777 * hide cursor at previous cursor position in screen. 12778 */ 12779void 12780HideCursor(XtermWidget xw) 12781{ 12782 TScreen *screen = TScreenOf(xw); 12783 XTermDraw params; 12784 GC currentGC; 12785 int x, y; 12786 IChar base; 12787 unsigned flags; 12788 CellColor fg_bg = initCColor; 12789 Bool in_selection; 12790#if OPT_WIDE_CHARS 12791 int my_col = 0; 12792#endif 12793 int cursor_col; 12794 CLineData *ld = 0; 12795#if OPT_WIDE_ATTRS 12796 int which_Cgs = gcMAX; 12797 unsigned attr_flags; 12798 int which_font = fNorm; 12799 MyGetFont getter = getNormalFont; 12800#endif 12801 12802 if (screen->cursor_state == OFF) 12803 return; 12804 if (INX2ROW(screen, screen->cursorp.row) > screen->max_row) 12805 return; 12806 12807 cursor_col = screen->cursorp.col; 12808 12809#ifndef NO_ACTIVE_ICON 12810 if (IsIcon(screen)) { 12811 screen->cursor_state = OFF; 12812 return; 12813 } 12814#endif /* NO_ACTIVE_ICON */ 12815 12816 ld = getLineData(screen, screen->cursorp.row); 12817 12818 base = ld->charData[cursor_col]; 12819 flags = ld->attribs[cursor_col]; 12820 12821 if_OPT_WIDE_CHARS(screen, { 12822 if (base == HIDDEN_CHAR && cursor_col > 0) { 12823 /* if cursor points to non-initial part of wide character, 12824 * back it up 12825 */ 12826 --cursor_col; 12827 base = ld->charData[cursor_col]; 12828 } 12829 my_col = cursor_col; 12830 if (base == 0) 12831 base = ' '; 12832 if (isWide((int) base)) 12833 my_col += 1; 12834 }); 12835 12836 if (base == 0) { 12837 base = ' '; 12838 } 12839#ifdef EXP_BOGUS_FG 12840 /* 12841 * If the cursor happens to be on blanks, and we have not set both 12842 * foreground and background color, do not treat it as a colored cell. 12843 */ 12844#if OPT_ISO_COLORS 12845 if (base == ' ') { 12846 if ((flags & (FG_COLOR | BG_COLOR)) == BG_COLOR) { 12847 TRACE(("HideCursor - do not treat as a colored cell\n")); 12848 flags &= ~(FG_COLOR | BG_COLOR); 12849 } else if ((flags & (FG_COLOR | BG_COLOR)) == FG_COLOR) { 12850 TRACE(("HideCursor - should we treat as a colored cell?\n")); 12851 if (!(xw->flags & FG_COLOR)) 12852 if (CheckBogusForeground(screen, "HideCursor")) 12853 flags &= ~(FG_COLOR | BG_COLOR); 12854 } 12855 } 12856#endif 12857#endif 12858 12859 /* 12860 * Compare the current cell to the last set of colors used for the 12861 * cursor and update the GC's if needed. 12862 */ 12863 if_OPT_ISO_COLORS(screen, { 12864 fg_bg = ld->color[cursor_col]; 12865 }); 12866 12867 if (OutsideSelection(screen, screen->cursorp.row, screen->cursorp.col)) 12868 in_selection = False; 12869 else 12870 in_selection = True; 12871 12872#if OPT_WIDE_ATTRS 12873 attr_flags = ld->attribs[cursor_col]; 12874 if ((attr_flags & ATR_ITALIC) ^ (xw->flags & ATR_ITALIC)) { 12875 which_font = ((attr_flags & BOLD) ? fBold : fNorm); 12876 if ((attr_flags & ATR_ITALIC) && UseItalicFont(screen)) 12877 getter = getItalicFont; 12878 12879 if_OPT_WIDE_CHARS(screen, { 12880 if (isWide((int) base)) { 12881 which_font = ((attr_flags & BOLD) ? fWBold : fWide); 12882 } 12883 }); 12884 12885 which_Cgs = reverseCgs(xw, attr_flags, in_selection, which_font); 12886 if (which_Cgs != gcMAX) { 12887 setCgsFont(xw, WhichVWin(screen), 12888 (CgsEnum) which_Cgs, 12889 getter(screen, which_font)); 12890 getter = (((xw->flags & ATR_ITALIC) && UseItalicFont(screen)) 12891 ? getItalicFont 12892 : getNormalFont); 12893 } 12894 } 12895#endif 12896 12897 currentGC = updatedXtermGC(xw, flags, fg_bg, in_selection); 12898 12899 TRACE(("HideCursor calling drawXtermText cur(%d,%d)\n", 12900 screen->cursorp.row, screen->cursorp.col)); 12901 12902 x = LineCursorX(screen, ld, cursor_col); 12903 y = CursorY(screen, screen->cursorp.row); 12904 12905 /* *INDENT-EQLS* */ 12906 params.xw = xw; 12907 params.attr_flags = (flags & DRAWX_MASK); 12908 params.draw_flags = 0; 12909 params.this_chrset = LineCharSet(screen, ld); 12910 params.real_chrset = CSET_SWL; 12911 params.on_wide = 0; 12912 12913 drawXtermText(¶ms, 12914 currentGC, x, y, 12915 &base, 1); 12916 12917#if OPT_WIDE_CHARS 12918 if_OPT_WIDE_CHARS(screen, { 12919 size_t off; 12920 12921 /* *INDENT-EQLS* */ 12922 params.draw_flags = NOBACKGROUND; 12923 params.on_wide = isWide((int) base); 12924 12925 for_each_combData(off, ld) { 12926 if (!(ld->combData[off][my_col])) 12927 break; 12928 drawXtermText(¶ms, 12929 currentGC, x, y, 12930 ld->combData[off] + my_col, 1); 12931 } 12932 }); 12933#endif 12934 screen->cursor_state = OFF; 12935 12936#if OPT_WIDE_ATTRS 12937 if (which_Cgs != gcMAX) { 12938 setCgsFont(xw, WhichVWin(screen), 12939 (CgsEnum) which_Cgs, 12940 getter(screen, which_font)); 12941 } 12942#endif 12943 resetXtermGC(xw, flags, in_selection); 12944 12945 refresh_displayed_graphics(xw, 12946 screen->cursorp.col, 12947 screen->cursorp.row, 12948 1, 1); 12949 12950 return; 12951} 12952 12953#if OPT_BLINK_CURS || OPT_BLINK_TEXT 12954static void 12955StartBlinking(XtermWidget xw) 12956{ 12957 TScreen *screen = TScreenOf(xw); 12958 12959 if (screen->blink_timer == 0) { 12960 unsigned long interval = (unsigned long) ((screen->cursor_state == ON) 12961 ? screen->blink_on 12962 : screen->blink_off); 12963 if (interval == 0) /* wow! */ 12964 interval = 1; /* let's humor him anyway */ 12965 screen->blink_timer = XtAppAddTimeOut(app_con, 12966 interval, 12967 HandleBlinking, 12968 xw); 12969 } 12970} 12971 12972static void 12973StopBlinking(XtermWidget xw) 12974{ 12975 TScreen *screen = TScreenOf(xw); 12976 12977 if (screen->blink_timer) { 12978 XtRemoveTimeOut(screen->blink_timer); 12979 screen->blink_timer = 0; 12980 reallyStopBlinking(xw); 12981 } else { 12982 screen->blink_timer = 0; 12983 } 12984} 12985 12986#if OPT_BLINK_TEXT 12987Bool 12988LineHasBlinking(TScreen *screen, CLineData *ld) 12989{ 12990 Bool result = False; 12991 if (ld != 0) { 12992 int col; 12993 12994 for (col = 0; col < MaxCols(screen); ++col) { 12995 if (ld->attribs[col] & BLINK) { 12996 result = True; 12997 break; 12998 } 12999 } 13000 } 13001 return result; 13002} 13003#endif 13004 13005/* 13006 * Blink the cursor by alternately showing/hiding cursor. We leave the timer 13007 * running all the time (even though that's a little inefficient) to make the 13008 * logic simple. 13009 */ 13010static void 13011HandleBlinking(XtPointer closure, XtIntervalId * id GCC_UNUSED) 13012{ 13013 XtermWidget xw = (XtermWidget) closure; 13014 TScreen *screen = TScreenOf(xw); 13015 Bool resume = False; 13016 13017 screen->blink_timer = 0; 13018 screen->blink_state = !screen->blink_state; 13019 13020#if OPT_BLINK_CURS 13021 if (DoStartBlinking(screen)) { 13022 if (screen->cursor_state == ON) { 13023 if (screen->select || screen->always_highlight) { 13024 HideCursor(xw); 13025 if (screen->cursor_state == OFF) 13026 screen->cursor_state = BLINKED_OFF; 13027 } 13028 } else if (screen->cursor_state == BLINKED_OFF) { 13029 screen->cursor_state = OFF; 13030 ShowCursor(xw); 13031 if (screen->cursor_state == OFF) 13032 screen->cursor_state = BLINKED_OFF; 13033 } 13034 resume = True; 13035 } 13036#endif 13037 13038#if OPT_BLINK_TEXT 13039 /* 13040 * Inspect the lines on the current screen to see if any have the BLINK flag 13041 * associated with them. Prune off any that have had the corresponding 13042 * cells reset. If any are left, repaint those lines with ScrnRefresh(). 13043 */ 13044 if (!(screen->blink_as_bold)) { 13045 int row; 13046 int start_row = LastRowNumber(screen); 13047 int first_row = start_row; 13048 int last_row = -1; 13049 13050 for (row = start_row; row >= 0; row--) { 13051 LineData *ld = getLineData(screen, ROW2INX(screen, row)); 13052 13053 if (ld != 0 && LineTstBlinked(ld)) { 13054 if (LineHasBlinking(screen, ld)) { 13055 resume = True; 13056 if (row > last_row) 13057 last_row = row; 13058 if (row < first_row) 13059 first_row = row; 13060 } else { 13061 LineClrBlinked(ld); 13062 } 13063 } 13064 } 13065 /* 13066 * FIXME: this could be a little more efficient, e.g,. by limiting the 13067 * columns which are updated. 13068 */ 13069 if (first_row <= last_row) { 13070 ScrnRefresh(xw, 13071 first_row, 13072 0, 13073 last_row + 1 - first_row, 13074 MaxCols(screen), 13075 True); 13076 } 13077 } 13078#endif 13079 13080 /* 13081 * If either the cursor or text is blinking, restart the timer. 13082 */ 13083 if (resume) 13084 StartBlinking(xw); 13085} 13086#endif /* OPT_BLINK_CURS || OPT_BLINK_TEXT */ 13087 13088void 13089RestartBlinking(XtermWidget xw) 13090{ 13091#if OPT_BLINK_CURS || OPT_BLINK_TEXT 13092 TScreen *screen = TScreenOf(xw); 13093 13094 if (screen->blink_timer == 0) { 13095 Bool resume = False; 13096 13097#if OPT_BLINK_CURS 13098 if (DoStartBlinking(screen)) { 13099 resume = True; 13100 } 13101#endif 13102#if OPT_BLINK_TEXT 13103 if (!resume) { 13104 int row; 13105 13106 for (row = screen->max_row; row >= 0; row--) { 13107 CLineData *ld = getLineData(screen, ROW2INX(screen, row)); 13108 13109 if (ld != 0 && LineTstBlinked(ld)) { 13110 if (LineHasBlinking(screen, ld)) { 13111 resume = True; 13112 break; 13113 } 13114 } 13115 } 13116 } 13117#endif 13118 if (resume) 13119 StartBlinking(xw); 13120 } 13121#else 13122 (void) xw; 13123#endif 13124} 13125 13126/* 13127 * Implement soft or hard (full) reset of the VTxxx emulation. There are a 13128 * couple of differences from real DEC VTxxx terminals (to avoid breaking 13129 * applications which have come to rely on xterm doing this): 13130 * 13131 * + autowrap mode should be reset (instead it's reset to the resource 13132 * default). 13133 * + the popup menu offers a choice of resetting the savedLines, or not. 13134 * (but the control sequence does this anyway). 13135 */ 13136static void 13137ReallyReset(XtermWidget xw, Bool full, Bool saved) 13138{ 13139 TScreen *screen = TScreenOf(xw); 13140 IFlags saveflags = xw->flags; 13141 13142 TRACE(("ReallyReset %s, %s\n", 13143 full ? "hard" : "soft", 13144 saved ? "clear savedLines" : "keep savedLines")); 13145 13146 if (!XtIsRealized((Widget) xw) || (CURRENT_EMU() != (Widget) xw)) { 13147 Bell(xw, XkbBI_MinorError, 0); 13148 return; 13149 } 13150 13151 if (saved) { 13152 screen->savedlines = 0; 13153 ScrollBarDrawThumb(xw, 0); 13154 } 13155 13156 /* make cursor visible */ 13157 screen->cursor_set = ON; 13158 InitCursorShape(screen, screen); 13159 xtermSetCursorBox(screen); 13160#if OPT_BLINK_CURS 13161 screen->cursor_blink = screen->cursor_blink_i; 13162 screen->cursor_blink_esc = 0; 13163 TRACE(("cursor_shape:%d blinks:%d\n", 13164 screen->cursor_shape, 13165 screen->cursor_blink)); 13166#endif 13167 13168 /* reset scrolling region */ 13169 resetMarginMode(xw); 13170 13171 bitclr(&xw->flags, ORIGIN); 13172 13173 if_OPT_ISO_COLORS(screen, { 13174 static char empty[1]; 13175 reset_SGR_Colors(xw); 13176 if (ResetAnsiColorRequest(xw, empty, 0)) 13177 xtermRepaint(xw); 13178 }); 13179 13180 /* Reset character-sets to initial state */ 13181 resetCharsets(screen); 13182 13183#if OPT_MOD_FKEYS 13184 /* Reset modifier-resources to initial state */ 13185 xw->keyboard.modify_now = xw->keyboard.modify_1st; 13186#endif 13187#if OPT_DEC_RECTOPS 13188 screen->checksum_ext = screen->checksum_ext0; 13189#endif 13190 13191 /* Reset DECSCA */ 13192 bitclr(&xw->flags, PROTECTED); 13193 screen->protected_mode = OFF_PROTECT; 13194 13195 if (full) { /* RIS */ 13196 if (screen->bellOnReset) 13197 Bell(xw, XkbBI_TerminalBell, 0); 13198 13199 reset_displayed_graphics(screen); 13200 13201 /* reset the mouse mode */ 13202 screen->send_mouse_pos = MOUSE_OFF; 13203 screen->send_focus_pos = OFF; 13204 screen->extend_coords = 0; 13205 screen->waitingForTrackInfo = False; 13206 screen->eventMode = NORMAL; 13207 13208 xtermShowPointer(xw, True); 13209 13210 TabReset(xw->tabs); 13211 xw->keyboard.flags = MODE_SRM; 13212 13213 guard_keyboard_type = False; 13214 screen->old_fkeys = screen->old_fkeys0; 13215 decode_keyboard_type(xw, &resource); 13216 update_keyboard_type(); 13217 13218#if OPT_INITIAL_ERASE 13219 if (xw->keyboard.reset_DECBKM == 1) 13220 xw->keyboard.flags |= MODE_DECBKM; 13221 else if (xw->keyboard.reset_DECBKM == 2) 13222#endif 13223 if (TScreenOf(xw)->backarrow_key) 13224 xw->keyboard.flags |= MODE_DECBKM; 13225 TRACE(("full reset DECBKM %s\n", 13226 BtoS(xw->keyboard.flags & MODE_DECBKM))); 13227 13228#if OPT_SCROLL_LOCK 13229 xtermClearLEDs(screen); 13230#endif 13231 screen->title_modes = screen->title_modes0; 13232 screen->pointer_mode = screen->pointer_mode0; 13233#if OPT_SIXEL_GRAPHICS 13234 if (TScreenOf(xw)->sixel_scrolling) 13235 xw->keyboard.flags |= MODE_DECSDM; 13236 TRACE(("full reset DECSDM to %s (resource default is %s)\n", 13237 BtoS(xw->keyboard.flags & MODE_DECSDM), 13238 BtoS(TScreenOf(xw)->sixel_scrolling))); 13239#endif 13240 13241#if OPT_GRAPHICS 13242 screen->privatecolorregisters = TScreenOf(xw)->privatecolorregisters; 13243 TRACE(("full reset PRIVATE_COLOR_REGISTERS to %s (resource default is %s)\n", 13244 BtoS(screen->privatecolorregisters), 13245 BtoS(TScreenOf(xw)->privatecolorregisters))); 13246#endif 13247 13248#if OPT_SIXEL_GRAPHICS 13249 screen->sixel_scrolls_right = TScreenOf(xw)->sixel_scrolls_right; 13250 TRACE(("full reset SIXEL_SCROLLS_RIGHT to %s (resource default is %s)\n", 13251 BtoS(screen->sixel_scrolls_right), 13252 BtoS(TScreenOf(xw)->sixel_scrolls_right))); 13253#endif 13254 13255 update_appcursor(); 13256 update_appkeypad(); 13257 update_decbkm(); 13258 update_decsdm(); 13259 show_8bit_control(False); 13260 reset_decudk(xw); 13261 13262 FromAlternate(xw); 13263 ClearScreen(xw); 13264 screen->cursor_state = OFF; 13265 13266 if (xw->flags & REVERSE_VIDEO) 13267 ReverseVideo(xw); 13268 ResetItalics(xw); 13269 xw->flags = xw->initflags; 13270 13271 update_reversevideo(); 13272 update_autowrap(); 13273 update_reversewrap(); 13274 update_autolinefeed(); 13275 13276 screen->jumpscroll = (Boolean) (!(xw->flags & SMOOTHSCROLL)); 13277 update_jumpscroll(); 13278 13279#if OPT_DEC_RECTOPS 13280 screen->cur_decsace = 0; 13281#endif 13282#if OPT_PASTE64 || OPT_READLINE 13283 screen->paste_brackets = OFF; 13284#endif 13285#if OPT_READLINE 13286 screen->click1_moves = OFF; 13287 screen->paste_moves = OFF; 13288 screen->dclick3_deletes = OFF; 13289 screen->paste_quotes = OFF; 13290 screen->paste_literal_nl = OFF; 13291#endif /* OPT_READLINE */ 13292 13293 if (screen->c132 && (saveflags & IN132COLUMNS)) { 13294 TRACE(("Making resize-request to restore 80-columns %dx%d\n", 13295 MaxRows(screen), MaxCols(screen))); 13296 RequestResize(xw, MaxRows(screen), 80, True); 13297 repairSizeHints(); 13298 XSync(screen->display, False); /* synchronize */ 13299 if (xtermAppPending()) 13300 xevents(xw); 13301 } 13302 13303 CursorSet(screen, 0, 0, xw->flags); 13304 CursorSave(xw); 13305 } else { /* DECSTR */ 13306 /* 13307 * There's a tiny difference, to accommodate usage of xterm. 13308 * We reset autowrap to the resource values rather than turning 13309 * it off. 13310 */ 13311 UIntClr(xw->keyboard.flags, (MODE_DECCKM | MODE_KAM | MODE_DECKPAM)); 13312 bitcpy(&xw->flags, xw->initflags, WRAPAROUND | REVERSEWRAP); 13313 bitclr(&xw->flags, INSERT | INVERSE | BOLD | BLINK | UNDERLINE | INVISIBLE); 13314 ResetItalics(xw); 13315 if_OPT_ISO_COLORS(screen, { 13316 reset_SGR_Colors(xw); 13317 }); 13318 update_appcursor(); 13319 update_autowrap(); 13320 update_reversewrap(); 13321 13322 CursorSave(xw); 13323 screen->sc[screen->whichBuf].row = 13324 screen->sc[screen->whichBuf].col = 0; 13325 } 13326} 13327 13328void 13329VTReset(XtermWidget xw, Bool full, Bool saved) 13330{ 13331 ReallyReset(xw, full, saved); 13332 13333 FreeAndNull(myState.string_area); 13334 FreeAndNull(myState.print_area); 13335 13336 longjmp(vtjmpbuf, 1); /* force ground state in parser */ 13337} 13338 13339typedef enum { 13340 ccLO, 13341 ccDASH, 13342 ccHI, 13343 ccCOLON, 13344 ccID, 13345 ccCOMMA 13346} CCLASS; 13347 13348/* 13349 * set_character_class - takes a string of the form 13350 * 13351 * low[-high][:id][,low[-high][:id][...]] 13352 * 13353 * and sets the indicated ranges to the indicated values. 13354 */ 13355static int 13356set_character_class(char *s) 13357{ 13358#define FMT "%s in range string \"%s\" (position %d)\n" 13359 13360 TRACE(("set_character_class(%s) " TRACE_L "\n", NonNull(s))); 13361 if (IsEmpty(s)) { 13362 TRACE((TRACE_R " ERR set_character_class\n")); 13363 return -1; 13364 } else { 13365 CCLASS state = ccLO; 13366 int arg[3]; 13367 int i; 13368 int len = (int) strlen(s); 13369 13370 arg[0] = 13371 arg[1] = 13372 arg[2] = -1; 13373 13374 for (i = 0; i < len; ++i) { 13375 int ch = CharOf(s[i]); 13376 char *t = 0; 13377 long value = 0; 13378 13379 if (isspace(ch)) 13380 continue; 13381 13382 switch (state) { 13383 case ccLO: 13384 case ccHI: 13385 case ccID: 13386 if (!isdigit(ch)) { 13387 xtermWarning(FMT, "missing number", s, i); 13388 TRACE((TRACE_R " ERR set_character_class\n")); 13389 return (-1); 13390 } 13391 value = strtol(s + i, &t, 0); 13392 i = (int) (t - s - 1); 13393 break; 13394 case ccDASH: 13395 case ccCOLON: 13396 case ccCOMMA: 13397 break; 13398 } 13399 13400 switch (state) { 13401 case ccLO: 13402 arg[0] = 13403 arg[1] = (int) value; 13404 arg[2] = -1; 13405 state = ccDASH; 13406 break; 13407 13408 case ccDASH: 13409 if (ch == '-') { 13410 state = ccHI; 13411 } else { 13412 goto parse_class; 13413 } 13414 break; 13415 13416 case ccHI: 13417 arg[1] = (int) value; 13418 state = ccCOLON; 13419 break; 13420 13421 parse_class: 13422 case ccCOLON: 13423 if (ch == ':') { 13424 state = ccID; 13425 } else if (ch == ',') { 13426 goto apply_class; 13427 } else { 13428 xtermWarning(FMT, "unexpected character", s, i); 13429 TRACE((TRACE_R " ERR set_character_class\n")); 13430 return (-1); 13431 } 13432 break; 13433 13434 case ccID: 13435 arg[2] = (int) value; 13436 state = ccCOMMA; 13437 break; 13438 13439 apply_class: 13440 case ccCOMMA: 13441 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 13442 xtermWarning(FMT, "bad range", s, i); 13443 TRACE((TRACE_R " ERR set_character_class\n")); 13444 return -1; 13445 } 13446 state = ccLO; 13447 break; 13448 } 13449 } 13450 if (state >= ccDASH) { 13451 if (SetCharacterClassRange(arg[0], arg[1], arg[2]) != 0) { 13452 xtermWarning(FMT, "bad range", s, i); 13453 TRACE((TRACE_R " ERR set_character_class\n")); 13454 return -1; 13455 } 13456 } 13457 } 13458 13459 TRACE((TRACE_R " OK set_character_class\n")); 13460 return (0); 13461#undef FMT 13462} 13463 13464void 13465getKeymapResources(Widget w, 13466 const char *mapName, 13467 const char *mapClass, 13468 const char *type, 13469 void *result, 13470 size_t size) 13471{ 13472 XtResource key_resources[1]; 13473 key_resources[0].resource_name = XtNtranslations; 13474 key_resources[0].resource_class = XtCTranslations; 13475 key_resources[0].resource_type = (char *) type; 13476 key_resources[0].resource_size = (Cardinal) size; 13477 key_resources[0].resource_offset = 0; 13478 key_resources[0].default_type = key_resources[0].resource_type; 13479 key_resources[0].default_addr = 0; 13480 XtGetSubresources(w, (XtPointer) result, mapName, mapClass, 13481 key_resources, (Cardinal) 1, NULL, (Cardinal) 0); 13482} 13483 13484/* ARGSUSED */ 13485static void 13486HandleKeymapChange(Widget w, 13487 XEvent *event GCC_UNUSED, 13488 String *params, 13489 Cardinal *param_count) 13490{ 13491 static XtTranslations keymap, original; 13492 13493 TRACE(("HandleKeymapChange(%#lx, %s)\n", 13494 (unsigned long) w, 13495 (*param_count 13496 ? params[0] 13497 : "missing"))); 13498 13499 if (*param_count != 1) 13500 return; 13501 13502 if (original == NULL) { 13503 TRACE(("...saving original keymap-translations\n")); 13504 original = w->core.tm.translations; 13505 } 13506 13507 if (strcmp(params[0], "None") == 0) { 13508 TRACE(("...restoring original keymap-translations\n")); 13509 XtOverrideTranslations(w, original); 13510 } else { 13511 char mapName[1000]; 13512 char mapClass[1000]; 13513 char *pmapName; 13514 char *pmapClass; 13515 size_t len; 13516 13517 len = strlen(params[0]) + 7; 13518 13519 pmapName = (char *) MyStackAlloc(len, mapName); 13520 pmapClass = (char *) MyStackAlloc(len, mapClass); 13521 if (pmapName == NULL 13522 || pmapClass == NULL) { 13523 SysError(ERROR_KMMALLOC1); 13524 } else { 13525 13526 (void) sprintf(pmapName, "%sKeymap", params[0]); 13527 (void) strcpy(pmapClass, pmapName); 13528 if (islower(CharOf(pmapClass[0]))) 13529 pmapClass[0] = x_toupper(pmapClass[0]); 13530 getKeymapResources(w, pmapName, pmapClass, XtRTranslationTable, 13531 &keymap, sizeof(keymap)); 13532 if (keymap != NULL) { 13533 TRACE(("...applying keymap \"%s\"\n", pmapName)); 13534 XtOverrideTranslations(w, keymap); 13535 } else { 13536 TRACE(("...found no match for keymap \"%s\"\n", pmapName)); 13537 } 13538 13539 MyStackFree(pmapName, mapName); 13540 MyStackFree(pmapClass, mapClass); 13541 } 13542 } 13543} 13544 13545/* ARGSUSED */ 13546static void 13547HandleBell(Widget w GCC_UNUSED, 13548 XEvent *event GCC_UNUSED, 13549 String *params, /* [0] = volume */ 13550 Cardinal *param_count) /* 0 or 1 */ 13551{ 13552 int percent = (*param_count) ? atoi(params[0]) : 0; 13553 13554 Bell(term, XkbBI_TerminalBell, percent); 13555} 13556 13557/* ARGSUSED */ 13558static void 13559HandleVisualBell(Widget w GCC_UNUSED, 13560 XEvent *event GCC_UNUSED, 13561 String *params GCC_UNUSED, 13562 Cardinal *param_count GCC_UNUSED) 13563{ 13564 VisualBell(); 13565} 13566 13567/* ARGSUSED */ 13568static void 13569HandleIgnore(Widget w, 13570 XEvent *event, 13571 String *params GCC_UNUSED, 13572 Cardinal *param_count GCC_UNUSED) 13573{ 13574 XtermWidget xw; 13575 13576 TRACE(("Handle ignore for %p %s\n", 13577 (void *) w, visibleEventType(event->type))); 13578 if ((xw = getXtermWidget(w)) != 0) { 13579 /* do nothing, but check for funny escape sequences */ 13580 switch (event->type) { 13581 case ButtonPress: 13582 case ButtonRelease: 13583 case MotionNotify: 13584 (void) SendMousePosition(xw, event); 13585 break; 13586 } 13587 } 13588} 13589 13590/* ARGSUSED */ 13591static void 13592DoSetSelectedFont(Widget w, 13593 XtPointer client_data GCC_UNUSED, 13594 Atom *selection GCC_UNUSED, 13595 Atom *type, 13596 XtPointer value, 13597 unsigned long *length, 13598 int *format) 13599{ 13600 XtermWidget xw = getXtermWidget(w); 13601 13602 if (xw == 0) { 13603 xtermWarning("unexpected widget in DoSetSelectedFont\n"); 13604 } else if (*type != XA_STRING || *format != 8) { 13605 Bell(xw, XkbBI_MinorError, 0); 13606 } else { 13607 Boolean failed = False; 13608 int oldFont = TScreenOf(xw)->menu_font_number; 13609 char *save = TScreenOf(xw)->SelectFontName(); 13610 char *val; 13611 char *test; 13612 unsigned len = (unsigned) *length; 13613 unsigned tst; 13614 13615 /* 13616 * Some versions of X deliver null-terminated selections, some do not. 13617 */ 13618 for (tst = 0; tst < len; ++tst) { 13619 if (((char *) value)[tst] == '\0') { 13620 len = tst; 13621 break; 13622 } 13623 } 13624 13625 if (len > 0 && (val = TypeMallocN(char, len + 1)) != 0) { 13626 char *used; 13627 13628 memcpy(val, value, (size_t) len); 13629 val[len] = '\0'; 13630 used = x_strtrim(val); 13631 TRACE(("DoSetSelectedFont(%s)\n", used)); 13632 /* Do some sanity checking to avoid sending a long selection 13633 back to the server in an OpenFont that is unlikely to succeed. 13634 XLFD allows up to 255 characters and no control characters; 13635 we are a little more liberal here. */ 13636 if (len < 1000 13637 && used != 0 13638 && !strchr(used, '\n') 13639 && (test = x_strdup(used)) != 0) { 13640 TScreenOf(xw)->SelectFontName() = test; 13641 if (!xtermLoadFont(xw, 13642 xtermFontName(used), 13643 True, 13644 fontMenu_fontsel)) { 13645 failed = True; 13646 free(test); 13647 TScreenOf(xw)->SelectFontName() = save; 13648 } 13649 } else { 13650 failed = True; 13651 } 13652 if (failed) { 13653 (void) xtermLoadFont(xw, 13654 xtermFontName(TScreenOf(xw)->MenuFontName(oldFont)), 13655 True, 13656 oldFont); 13657 Bell(xw, XkbBI_MinorError, 0); 13658 } 13659 free(used); 13660 free(val); 13661 } 13662 } 13663} 13664 13665void 13666FindFontSelection(XtermWidget xw, const char *atom_name, Bool justprobe) 13667{ 13668 TScreen *screen = TScreenOf(xw); 13669 static AtomPtr *atoms; 13670 static unsigned int atomCount = 0; 13671 AtomPtr *pAtom; 13672 unsigned a; 13673 Atom target; 13674 13675 if (!atom_name) 13676 atom_name = ((screen->mappedSelect && atomCount) 13677 ? screen->mappedSelect[0] 13678 : "PRIMARY"); 13679 TRACE(("FindFontSelection(%s)\n", atom_name)); 13680 13681 for (pAtom = atoms, a = atomCount; a; a--, pAtom++) { 13682 if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) { 13683 TRACE(("...found atom %d:%s\n", a + 1, atom_name)); 13684 break; 13685 } 13686 } 13687 if (!a) { 13688 atoms = TypeXtReallocN(AtomPtr, atoms, atomCount + 1); 13689 *(pAtom = &atoms[atomCount]) = XmuMakeAtom(atom_name); 13690 ++atomCount; 13691 TRACE(("...added atom %d:%s\n", atomCount, atom_name)); 13692 } 13693 13694 target = XmuInternAtom(XtDisplay(xw), *pAtom); 13695 if (justprobe) { 13696 screen->SelectFontName() = 13697 XGetSelectionOwner(XtDisplay(xw), target) ? _Font_Selected_ : 0; 13698 TRACE(("...selected fontname '%s'\n", 13699 NonNull(screen->SelectFontName()))); 13700 } else { 13701 XtGetSelectionValue((Widget) xw, target, XA_STRING, 13702 DoSetSelectedFont, NULL, 13703 XtLastTimestampProcessed(XtDisplay(xw))); 13704 } 13705 return; 13706} 13707 13708Bool 13709set_cursor_gcs(XtermWidget xw) 13710{ 13711 TScreen *screen = TScreenOf(xw); 13712 VTwin *win = WhichVWin(screen); 13713 13714 Pixel cc = T_COLOR(screen, TEXT_CURSOR); 13715 Pixel fg = T_COLOR(screen, TEXT_FG); 13716 Pixel bg = T_COLOR(screen, TEXT_BG); 13717 Bool changed = False; 13718 13719 /* 13720 * Let's see, there are three things that have "color": 13721 * 13722 * background 13723 * text 13724 * cursorblock 13725 * 13726 * And, there are four situations when drawing a cursor, if we decide 13727 * that we like have a solid block of cursor color with the letter 13728 * that it is highlighting shown in the background color to make it 13729 * stand out: 13730 * 13731 * selected window, normal video - background on cursor 13732 * selected window, reverse video - foreground on cursor 13733 * unselected window, normal video - foreground on background 13734 * unselected window, reverse video - background on foreground 13735 * 13736 * Since the last two are really just normalGC and reverseGC, we only 13737 * need two new GC's. Under monochrome, we get the same effect as 13738 * above by setting cursor color to foreground. 13739 */ 13740 13741 TRACE(("set_cursor_gcs cc=%#lx, fg=%#lx, bg=%#lx\n", cc, fg, bg)); 13742 if (win != 0 && (cc != bg)) { 13743 Pixel xx = ((fg == cc) ? bg : cc); 13744 13745 /* set the fonts to the current one */ 13746 setCgsFont(xw, win, gcVTcursNormal, 0); 13747 setCgsFont(xw, win, gcVTcursFilled, 0); 13748 setCgsFont(xw, win, gcVTcursReverse, 0); 13749 setCgsFont(xw, win, gcVTcursOutline, 0); 13750 13751 /* we have a colored cursor */ 13752 setCgsFore(xw, win, gcVTcursNormal, fg); 13753 setCgsBack(xw, win, gcVTcursNormal, xx); 13754 13755 setCgsFore(xw, win, gcVTcursFilled, xx); 13756 setCgsBack(xw, win, gcVTcursFilled, fg); 13757 13758 if (screen->always_highlight) { 13759 /* both GC's use the same color */ 13760 setCgsFore(xw, win, gcVTcursReverse, bg); 13761 setCgsBack(xw, win, gcVTcursReverse, cc); 13762 } else { 13763 setCgsFore(xw, win, gcVTcursReverse, bg); 13764 setCgsBack(xw, win, gcVTcursReverse, cc); 13765 } 13766 set_cursor_outline_gc(xw, screen->always_highlight, fg, bg, cc); 13767 changed = True; 13768 FreeMarkGCs(xw); 13769 } 13770 13771 if (changed) { 13772 TRACE(("...set_cursor_gcs - done\n")); 13773 } 13774 return changed; 13775} 13776 13777/* 13778 * Build up the default translations string, allowing the user to suppress 13779 * some of the features. 13780 */ 13781void 13782VTInitTranslations(void) 13783{ 13784 /* *INDENT-OFF* */ 13785 static struct { 13786 Boolean wanted; 13787 const char *name; 13788 const char *value; 13789 } table[] = { 13790#define DATA(name,value) { False, name, value } 13791 DATA("select", 13792"\ 13793 Shift <KeyPress> Select:select-cursor-start() select-cursor-end(SELECT, CUT_BUFFER0) \n\ 13794 Shift <KeyPress> Insert:insert-selection(SELECT, CUT_BUFFER0) \n\ 13795" 13796 ), 13797#if OPT_MAXIMIZE 13798 DATA("fullscreen", 13799"\ 13800 Alt <Key>Return:fullscreen() \n\ 13801" 13802 ), 13803#endif 13804#if OPT_SCROLL_LOCK 13805 DATA("scroll-lock", 13806"\ 13807 <KeyRelease> Scroll_Lock:scroll-lock() \n\ 13808" 13809 ), 13810#endif 13811#if OPT_SHIFT_FONTS 13812 DATA("shift-fonts", 13813"\ 13814 Shift~Ctrl <KeyPress> KP_Add:larger-vt-font() \n\ 13815 Shift Ctrl <KeyPress> KP_Add:smaller-vt-font() \n\ 13816 Shift <KeyPress> KP_Subtract:smaller-vt-font() \n\ 13817" 13818 ), 13819#endif 13820 DATA("paging", 13821"\ 13822 Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\ 13823 Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\ 13824" 13825 ), 13826 /* This must be the last set mentioning "KeyPress" */ 13827 DATA("keypress", 13828"\ 13829 ~Meta <KeyPress>:insert-seven-bit() \n\ 13830 Meta <KeyPress>:insert-eight-bit() \n\ 13831" 13832 ), 13833 DATA("popup-menu", 13834"\ 13835 !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13836 !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13837 !Lock Ctrl @Num_Lock <Btn1Down>:popup-menu(mainMenu) \n\ 13838 ! @Num_Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ 13839 !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13840 !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13841 !Lock Ctrl @Num_Lock <Btn2Down>:popup-menu(vtMenu) \n\ 13842 ! @Num_Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\ 13843 !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13844 !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13845 !Lock Ctrl @Num_Lock <Btn3Down>:popup-menu(fontMenu) \n\ 13846 ! @Num_Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\ 13847" 13848 ), 13849 /* PROCURA added "Meta <Btn2Down>:clear-saved-lines()" */ 13850 DATA("reset", 13851"\ 13852 Meta <Btn2Down>:clear-saved-lines() \n\ 13853" 13854 ), 13855 DATA("select", 13856"\ 13857 ~Meta <Btn1Down>:select-start() \n\ 13858 ~Meta <Btn1Motion>:select-extend() \n\ 13859 ~Ctrl ~Meta <Btn2Down>:ignore() \n\ 13860 ~Ctrl ~Meta <Btn2Up>:insert-selection(SELECT, CUT_BUFFER0) \n\ 13861 ~Ctrl ~Meta <Btn3Down>:start-extend() \n\ 13862 ~Meta <Btn3Motion>:select-extend() \n\ 13863 <BtnUp>:select-end(SELECT, CUT_BUFFER0) \n\ 13864" 13865 ), 13866 DATA("wheel-mouse", 13867"\ 13868 Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13869 Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13870 Lock @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13871 @Num_Lock Ctrl <Btn4Down>:scroll-back(1,halfpage,m) \n\ 13872 <Btn4Down>:scroll-back(5,line,m) \n\ 13873 Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13874 Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13875 Lock @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13876 @Num_Lock Ctrl <Btn5Down>:scroll-forw(1,halfpage,m) \n\ 13877 <Btn5Down>:scroll-forw(5,line,m) \n\ 13878" 13879 ), 13880 DATA("pointer", 13881"\ 13882 <BtnMotion>:pointer-motion() \n\ 13883 <BtnDown>:pointer-button() \n\ 13884 <BtnUp>:pointer-button() \n\ 13885" 13886 ), 13887 DATA("default", 13888"\ 13889 <BtnUp>:ignore() \n\ 13890" 13891 ) 13892 }; 13893#undef DATA 13894 /* *INDENT-ON* */ 13895 13896 char *result = 0; 13897 13898 int pass; 13899 Cardinal item; 13900 13901 TRACE(("VTInitTranslations\n")); 13902 for (item = 0; item < XtNumber(table); ++item) { 13903 table[item].wanted = True; 13904 } 13905#if OPT_MAXIMIZE 13906 /* 13907 * As a special case, allow for disabling the alt-enter translation if 13908 * the resource settings prevent fullscreen from being used. We would 13909 * do the same for scroll-lock and shift-fonts if they were application 13910 * resources too, rather than in the widget. 13911 */ 13912 if (resource.fullscreen == esNever) { 13913 for (item = 0; item < XtNumber(table); ++item) { 13914 if (!strcmp(table[item].name, "fullscreen")) { 13915 table[item].wanted = False; 13916 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 13917 } 13918 } 13919 } 13920#endif 13921 if (!IsEmpty(resource.omitTranslation)) { 13922 char *value; 13923 const char *source = resource.omitTranslation; 13924 13925 while (*source != '\0' && (value = ParseList(&source)) != 0) { 13926 size_t len = strlen(value); 13927 13928 TRACE(("parsed:%s\n", value)); 13929 for (item = 0; item < XtNumber(table); ++item) { 13930 if (strlen(table[item].name) >= len 13931 && x_strncasecmp(table[item].name, 13932 value, 13933 (unsigned) len) == 0) { 13934 table[item].wanted = False; 13935 TRACE(("omit(%s):\n%s\n", table[item].name, table[item].value)); 13936 /* continue: "select", for instance is two chunks */ 13937 } 13938 } 13939 free(value); 13940 } 13941 } 13942 13943 for (pass = 0; pass < 2; ++pass) { 13944 size_t needed = 0; 13945 for (item = 0; item < XtNumber(table); ++item) { 13946 if (table[item].wanted) { 13947 if (pass) { 13948 strcat(result, table[item].value); 13949 } else { 13950 needed += strlen(table[item].value) + 1; 13951 } 13952 } 13953 } 13954 if (!pass) { 13955 result = XtMalloc((Cardinal) needed); 13956 *result = '\0'; 13957 } 13958 } 13959 13960 TRACE(("result:\n%s\n", result)); 13961 13962 defaultTranslations = result; 13963 free((void *) xtermClassRec.core_class.tm_table); 13964 xtermClassRec.core_class.tm_table = result; 13965} 13966 13967#ifdef NO_LEAKS 13968void 13969noleaks_charproc(void) 13970{ 13971 free(v_buffer); 13972} 13973#endif 13974