diff options
Diffstat (limited to 'vendor/x11iraf/xgterm/charproc.c')
-rw-r--r-- | vendor/x11iraf/xgterm/charproc.c | 3877 |
1 files changed, 3877 insertions, 0 deletions
diff --git a/vendor/x11iraf/xgterm/charproc.c b/vendor/x11iraf/xgterm/charproc.c new file mode 100644 index 00000000..51a44c9d --- /dev/null +++ b/vendor/x11iraf/xgterm/charproc.c @@ -0,0 +1,3877 @@ +/* + * $XConsortium: charproc.c,v 1.180 94/04/17 20:23:25 hersh Exp $ + */ +/* + +Copyright (c) 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ +/* + * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital Equipment + * Corporation not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* charproc.c */ + +#include "ptyx.h" +#include "VTparse.h" +#include "data.h" +#include "error.h" +#include "menu.h" +#include "main.h" +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/cursorfont.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Converters.h> +#ifdef I18N +#include <X11/Xaw/XawImP.h> +#endif +#include <stdio.h> +#include <errno.h> +#include <setjmp.h> +#include <ctype.h> + + +/* + * Check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN. + * Note that this macro may evaluate its argument more than once. + */ +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define E_TEST(err) ((err) == EAGAIN || (err) == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define E_TEST(err) ((err) == EAGAIN) +#else +#define E_TEST(err) ((err) == EWOULDBLOCK) +#endif +#endif + +extern jmp_buf VTend; + +extern XtAppContext app_con; +extern Widget toplevel; +extern void exit(); +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#else +extern char *malloc(); +extern char *realloc(); +#endif + + +static void VTallocbuf(); +static int finput(); +static void dotext(); +static void WriteText(); +static int in_put(); +static void do_read(), do_write(); +static void ToAlternate(); +static void FromAlternate(); +static void update_font_info(); + +static void bitset(), bitclr(); + +#define DEFAULT -1 +#define TEXT_BUF_SIZE 1024 +#define TRACKTIMESEC 4L +#define TRACKTIMEUSEC 0L +#define BELLSUPPRESSMSEC 200 + +#define XtNalwaysHighlight "alwaysHighlight" +#define XtNappcursorDefault "appcursorDefault" +#define XtNappkeypadDefault "appkeypadDefault" +#define XtNbellSuppressTime "bellSuppressTime" +#define XtNboldFont "boldFont" +#define XtNc132 "c132" +#define XtNcharClass "charClass" +#define XtNcurses "curses" +#define XtNhpLowerleftBugCompat "hpLowerleftBugCompat" +#define XtNcursorColor "cursorColor" +#define XtNcutNewline "cutNewline" +#define XtNcutToBeginningOfLine "cutToBeginningOfLine" +#define XtNeightBitInput "eightBitInput" +#define XtNeightBitOutput "eightBitOutput" +#define XtNgeometry "geometry" +#define XtNtekGeometry "tekGeometry" +#define XtNinternalBorder "internalBorder" +#define XtNjumpScroll "jumpScroll" +#ifdef ALLOWLOGGING +#define XtNlogFile "logFile" +#define XtNlogging "logging" +#define XtNlogInhibit "logInhibit" +#endif +#define XtNloginShell "loginShell" +#define XtNmarginBell "marginBell" +#define XtNpointerColor "pointerColor" +#define XtNpointerColorBackground "pointerColorBackground" +#define XtNpointerShape "pointerShape" +#define XtNmultiClickTime "multiClickTime" +#define XtNmultiScroll "multiScroll" +#define XtNnMarginBell "nMarginBell" +#define XtNresizeGravity "resizeGravity" +#define XtNreverseWrap "reverseWrap" +#define XtNautoWrap "autoWrap" +#define XtNsaveLines "saveLines" +#define XtNscrollBar "scrollBar" +#define XtNscrollTtyOutput "scrollTtyOutput" +#define XtNscrollKey "scrollKey" +#define XtNscrollLines "scrollLines" +#define XtNscrollPos "scrollPos" +#define XtNsignalInhibit "signalInhibit" +#define XtNtekInhibit "tekInhibit" +#define XtNtekStartup "tekStartup" +#define XtNtiteInhibit "titeInhibit" +#define XtNunderLine "underLine" +#define XtNvisualBell "visualBell" +#define XtNallowSendEvents "allowSendEvents" +#define XtNcolor0 "color0" +#define XtNcolor1 "color1" +#define XtNcolor2 "color2" +#define XtNcolor3 "color3" +#define XtNcolor4 "color4" +#define XtNcolor5 "color5" +#define XtNcolor6 "color6" +#define XtNcolor7 "color7" +#define XtNcolor8 "color8" +#define XtNcolor9 "color9" +#define XtNcolor10 "color10" +#define XtNcolor11 "color11" +#define XtNcolor12 "color12" +#define XtNcolor13 "color13" +#define XtNcolor14 "color14" +#define XtNcolor15 "color15" +#define XtNcolorBD "colorBD" +#define XtNcolorUL "colorUL" +#define XtNdynamicColors "dynamicColors" +#define XtNscrollBarRight "scrollBarRight" + +#define XtCAlwaysHighlight "AlwaysHighlight" +#define XtCAppcursorDefault "AppcursorDefault" +#define XtCAppkeypadDefault "AppkeypadDefault" +#define XtCBellSuppressTime "BellSuppressTime" +#define XtCBoldFont "BoldFont" +#define XtCC132 "C132" +#define XtCCharClass "CharClass" +#define XtCCurses "Curses" +#define XtCHpLowerleftBugCompat "HpLowerleftBugCompat" +#define XtCCutNewline "CutNewline" +#define XtCCutToBeginningOfLine "CutToBeginningOfLine" +#define XtCEightBitInput "EightBitInput" +#define XtCEightBitOutput "EightBitOutput" +#define XtCGeometry "Geometry" +#define XtCJumpScroll "JumpScroll" +#ifdef ALLOWLOGGING +#define XtCLogfile "Logfile" +#define XtCLogging "Logging" +#define XtCLogInhibit "LogInhibit" +#endif +#define XtCLoginShell "LoginShell" +#define XtCMarginBell "MarginBell" +#define XtCMultiClickTime "MultiClickTime" +#define XtCMultiScroll "MultiScroll" +#define XtCColumn "Column" +#define XtCResizeGravity "ResizeGravity" +#define XtCReverseWrap "ReverseWrap" +#define XtCAutoWrap "AutoWrap" +#define XtCSaveLines "SaveLines" +#define XtCScrollBar "ScrollBar" +#define XtCScrollLines "ScrollLines" +#define XtCScrollPos "ScrollPos" +#define XtCScrollCond "ScrollCond" +#define XtCSignalInhibit "SignalInhibit" +#define XtCTekInhibit "TekInhibit" +#define XtCTekStartup "TekStartup" +#define XtCTiteInhibit "TiteInhibit" +#define XtCUnderLine "UnderLine" +#define XtCVisualBell "VisualBell" +#define XtCAllowSendEvents "AllowSendEvents" +#define XtCDynamicColors "DynamicColors" +#define XtCScrollBarRight "ScrollBarRight" + +#define doinput() (bcnt-- > 0 ? *bptr++ : in_put()) + +static int nparam; +static ANSI reply; +static int param[NPARAM]; + +static unsigned long ctotal; +static unsigned long ntotal; +static jmp_buf vtjmpbuf; + +extern int groundtable[]; +extern int csitable[]; +extern int dectable[]; +extern int eigtable[]; +extern int esctable[]; +extern int iestable[]; +extern int igntable[]; +extern int scrtable[]; +extern int scstable[]; + + +/* event handlers */ +extern void HandleKeyPressed(), HandleEightBitKeyPressed(); +extern void HandleStringEvent(); +extern void HandleEnterWindow(); +extern void HandleLeaveWindow(); +extern void HandleBellPropertyChange(); +extern void HandleFocusChange(); +static void HandleKeymapChange(); +extern void HandleInsertSelection(); +extern void HandleSelectStart(), HandleKeyboardSelectStart(); +extern void HandleSelectExtend(), HandleSelectSet(); +extern void HandleSelectEnd(), HandleKeyboardSelectEnd(); +extern void HandleStartExtend(), HandleKeyboardStartExtend(); +static void HandleBell(); +static void HandleVisualBell(); +static void HandleIgnore(); +extern void HandleSecure(); +extern void HandleScrollForward(); +extern void HandleScrollBack(); +extern void HandleCreateMenu(), HandlePopupMenu(); +extern void HandleSetFont(); +extern void SetVTFont(); + +extern void ViButton(), DiredButton(); +extern Boolean SendMousePosition(); +extern void ScrnSetAttributes(); + +/* + * NOTE: VTInitialize zeros out the entire ".screen" component of the + * XgtermWidget, so make sure to add an assignment statement in VTInitialize() + * for each new ".screen" field added to this resource list. + */ + +/* Defaults */ +static Boolean defaultFALSE = FALSE; +static Boolean defaultTRUE = TRUE; +static int defaultBorderWidth = DEFBORDERWIDTH; +static int defaultIntBorder = DEFBORDER; +static int defaultSaveLines = SAVELINES; +static int defaultScrollLines = SCROLLLINES; +static int defaultNMarginBell = N_MARGINBELL; +static int defaultMultiClickTime = MULTICLICKTIME; +static int defaultBellSuppressTime = BELLSUPPRESSMSEC; +static char * _Font_Selected_ = "yes"; /* string is arbitrary */ + +/* + * Warning, the following must be kept under 1024 bytes or else some + * compilers (particularly AT&T 6386 SVR3.2) will barf). Workaround is to + * declare a static buffer and copy in at run time (the the Athena text widget + * does). Yuck. + */ +static char defaultTranslations[] = +"\ + Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\ + Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\ +Shift <KeyPress> Select:select-cursor-start() select-cursor-end(PRIMARY, CUT_BUFFER0) \n\ +Shift <KeyPress> Insert:insert-selection(PRIMARY, CUT_BUFFER0) \n\ + ~Meta <KeyPress>:insert-seven-bit() \n\ + Meta <KeyPress>:insert-eight-bit() \n\ + !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ + !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\ + ~Meta <Btn1Down>:select-start() \n\ + ~Meta <Btn1Motion>:select-extend() \n\ + !Ctrl <Btn2Down>:popup-menu(fontMenu) \n\ + !Lock Ctrl <Btn2Down>:popup-menu(fontMenu) \n\ + ~Ctrl ~Meta <Btn2Down>:ignore() \n\ + ~Ctrl ~Meta <Btn2Up>:insert-selection(PRIMARY, CUT_BUFFER0) \n\ + !Ctrl <Btn3Down>:popup-menu(vtMenu) \n\ + !Lock Ctrl <Btn3Down>:popup-menu(vtMenu) \n\ + ~Ctrl ~Meta <Btn3Down>:start-extend() \n\ + ~Meta <Btn3Motion>:select-extend() \n\ + <BtnUp>:select-end(PRIMARY, CUT_BUFFER0) \n\ + <BtnDown>:bell(0) \ +"; + +static XtActionsRec actionsList[] = { + { "bell", HandleBell }, + { "create-menu", HandleCreateMenu }, + { "ignore", HandleIgnore }, + { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */ + { "insert-seven-bit", HandleKeyPressed }, + { "insert-eight-bit", HandleEightBitKeyPressed }, + { "insert-selection", HandleInsertSelection }, + { "keymap", HandleKeymapChange }, + { "popup-menu", HandlePopupMenu }, + { "secure", HandleSecure }, + { "select-start", HandleSelectStart }, + { "select-extend", HandleSelectExtend }, + { "select-end", HandleSelectEnd }, + { "select-set", HandleSelectSet }, + { "select-cursor-start", HandleKeyboardSelectStart }, + { "select-cursor-end", HandleKeyboardSelectEnd }, + { "set-vt-font", HandleSetFont }, + { "start-extend", HandleStartExtend }, + { "start-cursor-extend", HandleKeyboardStartExtend }, + { "string", HandleStringEvent }, + { "scroll-forw", HandleScrollForward }, + { "scroll-back", HandleScrollBack }, + /* menu actions */ + { "allow-send-events", HandleAllowSends }, + { "set-visual-bell", HandleSetVisualBell }, +#ifdef ALLOWLOGGING + { "set-logging", HandleLogging }, +#endif + { "redraw", HandleRedraw }, + { "send-signal", HandleSendSignal }, + { "quit", HandleQuit }, + { "set-scrollbar", HandleScrollbar }, + { "set-jumpscroll", HandleJumpscroll }, + { "set-reverse-video", HandleReverseVideo }, + { "set-autowrap", HandleAutoWrap }, + { "set-reversewrap", HandleReverseWrap }, + { "set-autolinefeed", HandleAutoLineFeed }, + { "set-appcursor", HandleAppCursor }, + { "set-appkeypad", HandleAppKeypad }, + { "set-scroll-on-key", HandleScrollKey }, + { "set-scroll-on-tty-output", HandleScrollTtyOutput }, + { "set-allow132", HandleAllow132 }, + { "set-cursesemul", HandleCursesEmul }, + { "set-marginbell", HandleMarginBell }, + { "set-altscreen", HandleAltScreen }, + { "soft-reset", HandleSoftReset }, + { "hard-reset", HandleHardReset }, + { "clear-saved-lines", HandleClearSavedLines }, + { "set-terminal-type", HandleSetTerminalType }, + { "set-visibility", HandleVisibility }, + { "tek-page", HandleTekPage }, + { "tek-reset", HandleTekReset }, + { "tek-copy", HandleTekCopy }, + { "visual-bell", HandleVisualBell }, + { "dired-button", DiredButton }, + { "vi-button", ViButton }, +}; + +static XtResource resources[] = { +{XtNfont, XtCFont, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, misc.f_n), XtRString, + DEFFONT}, +{XtNboldFont, XtCBoldFont, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, misc.f_b), XtRString, + DEFBOLDFONT}, +{XtNc132, XtCC132, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.c132), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNcharClass, XtCCharClass, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, screen.charClass), + XtRString, (XtPointer) NULL}, +{XtNcurses, XtCCurses, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.curses), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNhpLowerleftBugCompat, XtCHpLowerleftBugCompat, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.hp_ll_bc), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNcutNewline, XtCCutNewline, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.cutNewline), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.cutToBeginningOfLine), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, core.background_pixel), + XtRString, "XtDefaultBackground"}, +{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.foreground), + XtRString, "XtDefaultForeground"}, +{XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.cursorcolor), + XtRString, "XtDefaultForeground"}, +{XtNeightBitInput, XtCEightBitInput, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.input_eight_bits), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNeightBitOutput, XtCEightBitOutput, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.output_eight_bits), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNgeometry,XtCGeometry, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, misc.geo_metry), + XtRString, (XtPointer) NULL}, +{XtNalwaysHighlight,XtCAlwaysHighlight,XtRBoolean, + sizeof(Boolean),XtOffsetOf(XgtermWidgetRec, screen.always_highlight), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNappcursorDefault,XtCAppcursorDefault,XtRBoolean, + sizeof(Boolean),XtOffsetOf(XgtermWidgetRec, misc.appcursorDefault), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNappkeypadDefault,XtCAppkeypadDefault,XtRBoolean, + sizeof(Boolean),XtOffsetOf(XgtermWidgetRec, misc.appkeypadDefault), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNbellSuppressTime, XtCBellSuppressTime, XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.bellSuppressTime), + XtRInt, (XtPointer) &defaultBellSuppressTime}, +{XtNtekGeometry,XtCGeometry, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, misc.T_geometry), + XtRString, (XtPointer) NULL}, +{XtNalwaysHighlight,XtCAlwaysHighlight,XtRBoolean, + sizeof(Boolean),XtOffset(XgtermWidget, screen.always_highlight), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNinternalBorder,XtCBorderWidth,XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.border), + XtRInt, (XtPointer) &defaultIntBorder}, +{XtNjumpScroll, XtCJumpScroll, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.jumpscroll), + XtRBoolean, (XtPointer) &defaultTRUE}, +#ifdef ALLOWLOGGING +{XtNlogFile, XtCLogfile, XtRString, sizeof(char *), + XtOffsetOf(XgtermWidgetRec, screen.logfile), + XtRString, (XtPointer) NULL}, +{XtNlogging, XtCLogging, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.log_on), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNlogInhibit, XtCLogInhibit, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.logInhibit), + XtRBoolean, (XtPointer) &defaultFALSE}, +#endif +{XtNloginShell, XtCLoginShell, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.login_shell), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNmarginBell, XtCMarginBell, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.marginbell), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNpointerColor, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.mousecolor), + XtRString, "XtDefaultForeground"}, +{XtNpointerColorBackground, XtCBackground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.mousecolorback), + XtRString, "XtDefaultBackground"}, +{XtNpointerShape,XtCCursor, XtRCursor, sizeof(Cursor), + XtOffsetOf(XgtermWidgetRec, screen.pointer_cursor), + XtRString, (XtPointer) "xterm"}, +{XtNmultiClickTime,XtCMultiClickTime, XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.multiClickTime), + XtRInt, (XtPointer) &defaultMultiClickTime}, +{XtNmultiScroll,XtCMultiScroll, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.multiscroll), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNnMarginBell,XtCColumn, XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.nmarginbell), + XtRInt, (XtPointer) &defaultNMarginBell}, +{XtNreverseVideo,XtCReverseVideo,XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.re_verse), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity), + XtOffsetOf(XgtermWidgetRec, misc.resizeGravity), + XtRImmediate, (XtPointer) SouthWestGravity}, +{XtNreverseWrap,XtCReverseWrap, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.reverseWrap), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNautoWrap,XtCAutoWrap, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.autoWrap), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNsaveLines, XtCSaveLines, XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.savelines), + XtRInt, (XtPointer) &defaultSaveLines}, +{XtNscrollBar, XtCScrollBar, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.scrollbar), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNscrollTtyOutput,XtCScrollCond, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.scrollttyoutput), + XtRBoolean, (XtPointer) &defaultTRUE}, +{XtNscrollKey, XtCScrollCond, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.scrollkey), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNscrollLines, XtCScrollLines, XtRInt, sizeof(int), + XtOffsetOf(XgtermWidgetRec, screen.scrolllines), + XtRInt, (XtPointer) &defaultScrollLines}, +{XtNsignalInhibit,XtCSignalInhibit,XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.signalInhibit), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNtekInhibit, XtCTekInhibit, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.tekInhibit), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNtekStartup, XtCTekStartup, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.TekEmu), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNtiteInhibit, XtCTiteInhibit, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.titeInhibit), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNunderLine, XtCUnderLine, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.underline), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.visualbell), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNallowSendEvents, XtCAllowSendEvents, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, screen.allowSendEvents), + XtRBoolean, (XtPointer) &defaultTRUE}, +{"font1", "Font1", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font1]), + XtRString, (XtPointer) NULL}, +{"font2", "Font2", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font2]), + XtRString, (XtPointer) NULL}, +{"font3", "Font3", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font3]), + XtRString, (XtPointer) NULL}, +{"font4", "Font4", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font4]), + XtRString, (XtPointer) NULL}, +{"font5", "Font5", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font5]), + XtRString, (XtPointer) NULL}, +{"font6", "Font6", XtRString, sizeof(String), + XtOffsetOf(XgtermWidgetRec, screen.menu_font_names[fontMenu_font6]), + XtRString, (XtPointer) NULL}, +#ifdef I18N + {XtNinputMethod, XtCInputMethod, XtRString, sizeof(char*), + XtOffsetOf(XgtermWidgetRec, misc.input_method), + XtRString, (XtPointer)NULL}, + {XtNpreeditType, XtCPreeditType, XtRString, sizeof(char*), + XtOffsetOf(XgtermWidgetRec, misc.preedit_type), + XtRString, (XtPointer)"Root"}, + {XtNopenIm, XtCOpenIm, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.open_im), + XtRImmediate, (XtPointer)TRUE}, +#endif +{XtNcolor0, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_0]), + XtRString, "XtDefaultForeground"}, +{XtNcolor1, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_1]), + XtRString, "XtDefaultForeground"}, +{XtNcolor2, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_2]), + XtRString, "XtDefaultForeground"}, +{XtNcolor3, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_3]), + XtRString, "XtDefaultForeground"}, +{XtNcolor4, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_4]), + XtRString, "XtDefaultForeground"}, +{XtNcolor5, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_5]), + XtRString, "XtDefaultForeground"}, +{XtNcolor6, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_6]), + XtRString, "XtDefaultForeground"}, +{XtNcolor7, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_7]), + XtRString, "XtDefaultForeground"}, +{XtNcolor8, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_8]), + XtRString, "XtDefaultForeground"}, +{XtNcolor9, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_9]), + XtRString, "XtDefaultForeground"}, +{XtNcolor10, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_10]), + XtRString, "XtDefaultForeground"}, +{XtNcolor11, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_11]), + XtRString, "XtDefaultForeground"}, +{XtNcolor12, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_12]), + XtRString, "XtDefaultForeground"}, +{XtNcolor13, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_13]), + XtRString, "XtDefaultForeground"}, +{XtNcolor14, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_14]), + XtRString, "XtDefaultForeground"}, +{XtNcolor15, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_15]), + XtRString, "XtDefaultForeground"}, +{XtNcolorBD, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_BD]), + XtRString, "XtDefaultForeground"}, +{XtNcolorUL, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XgtermWidgetRec, screen.colors[COLOR_UL]), + XtRString, "XtDefaultForeground"}, +{XtNdynamicColors, XtCDynamicColors, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.dynamicColors), + XtRBoolean, (XtPointer) &defaultFALSE}, +{XtNscrollBarRight, XtCScrollBarRight, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XgtermWidgetRec, misc.sb_right), + XtRBoolean, (XtPointer) &defaultFALSE}, +}; + +static void VTClassInit(); +static void VTInitialize(); +static void VTRealize(); +static void VTExpose(); +static void VTResize(); +static void VTDestroy(); +static Boolean VTSetValues(); +#ifdef I18N +static void VTInitI18N(); +#endif + +static WidgetClassRec xgtermClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) &widgetClassRec, + /* class_name */ "VT100", + /* widget_size */ sizeof(XgtermWidgetRec), + /* class_initialize */ VTClassInit, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ VTInitialize, + /* initialize_hook */ NULL, + /* realize */ VTRealize, + /* actions */ actionsList, + /* num_actions */ XtNumber(actionsList), + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ FALSE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ VTDestroy, + /* resize */ VTResize, + /* expose */ VTExpose, + /* set_values */ VTSetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ NULL, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_offsets */ NULL, + /* tm_table */ defaultTranslations, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + } +}; + +WidgetClass xgtermWidgetClass = (WidgetClass)&xgtermClassRec; + +static void VTparse() +{ + register TScreen *screen = &term->screen; + register int *parsestate = groundtable; + register unsigned int c; + register unsigned char *cp; + register int row, col, top, bot, scstype; + extern int TrackMouse(); + + if(setjmp(vtjmpbuf)) + parsestate = groundtable; + for( ; ; ) { + switch (parsestate[c = doinput()]) { + case CASE_PRINT: + /* printable characters */ + top = bcnt > TEXT_BUF_SIZE ? TEXT_BUF_SIZE : bcnt; + cp = bptr; + *--bptr = c; + while(top > 0 && isprint(*cp & 0x7f)) { + top--; + bcnt--; + cp++; + } + if(screen->curss) { + dotext(screen, term->flags, + screen->gsets[screen->curss], bptr, bptr + 1, + term->cur_foreground, + term->cur_background ); + screen->curss = 0; + bptr++; + } + if(bptr < cp) + dotext(screen, term->flags, + screen->gsets[screen->curgl], bptr, cp, + term->cur_foreground, + term->cur_background ); + bptr = cp; + break; + + case CASE_GROUND_STATE: + /* exit ignore mode */ + parsestate = groundtable; + break; + + case CASE_IGNORE_STATE: + /* Ies: ignore anything else */ + parsestate = igntable; + break; + + case CASE_IGNORE_ESC: + /* Ign: escape */ + parsestate = iestable; + break; + + case CASE_IGNORE: + /* Ignore character */ + break; + + case CASE_BELL: + /* bell */ + Bell(); + break; + + case CASE_BS: + /* backspace */ + CursorBack(screen, 1); + break; + + case CASE_CR: + /* carriage return */ + CarriageReturn(screen); + parsestate = groundtable; + break; + + case CASE_ESC: + /* escape */ + parsestate = esctable; + break; + + case CASE_VMOT: + /* + * form feed, line feed, vertical tab + */ + Index(screen, 1); + if (term->flags & LINEFEED) + CarriageReturn(screen); + if (XtAppPending(app_con) || + GetBytesAvailable (ConnectionNumber(screen->display)) > 0) + xevents(); + parsestate = groundtable; + break; + + case CASE_TAB: + /* tab */ + screen->cur_col = TabNext(term->tabs, screen->cur_col); + if (screen->cur_col > screen->max_col) + screen->cur_col = screen->max_col; + break; + + case CASE_SI: + screen->curgl = 0; + break; + + case CASE_SO: + screen->curgl = 1; + break; + + case CASE_SCR_STATE: + /* enter scr state */ + parsestate = scrtable; + break; + + case CASE_SCS0_STATE: + /* enter scs state 0 */ + scstype = 0; + parsestate = scstable; + break; + + case CASE_SCS1_STATE: + /* enter scs state 1 */ + scstype = 1; + parsestate = scstable; + break; + + case CASE_SCS2_STATE: + /* enter scs state 2 */ + scstype = 2; + parsestate = scstable; + break; + + case CASE_SCS3_STATE: + /* enter scs state 3 */ + scstype = 3; + parsestate = scstable; + break; + + case CASE_ESC_IGNORE: + /* unknown escape sequence */ + parsestate = eigtable; + break; + + case CASE_ESC_DIGIT: + /* digit in csi or dec mode */ + if((row = param[nparam - 1]) == DEFAULT) + row = 0; + param[nparam - 1] = 10 * row + (c - '0'); + break; + + case CASE_ESC_SEMI: + /* semicolon in csi or dec mode */ + param[nparam++] = DEFAULT; + break; + + case CASE_DEC_STATE: + /* enter dec mode */ + parsestate = dectable; + break; + + case CASE_ICH: + /* ICH */ + if((row = param[0]) < 1) + row = 1; + InsertChar(screen, row); + parsestate = groundtable; + break; + + case CASE_CUU: + /* CUU */ + if((row = param[0]) < 1) + row = 1; + CursorUp(screen, row); + parsestate = groundtable; + break; + + case CASE_CUD: + /* CUD */ + if((row = param[0]) < 1) + row = 1; + CursorDown(screen, row); + parsestate = groundtable; + break; + + case CASE_CUF: + /* CUF */ + if((row = param[0]) < 1) + row = 1; + CursorForward(screen, row); + parsestate = groundtable; + break; + + case CASE_CUB: + /* CUB */ + if((row = param[0]) < 1) + row = 1; + CursorBack(screen, row); + parsestate = groundtable; + break; + + case CASE_CUP: + /* CUP | HVP */ + if((row = param[0]) < 1) + row = 1; + if(nparam < 2 || (col = param[1]) < 1) + col = 1; + CursorSet(screen, row-1, col-1, term->flags); + parsestate = groundtable; + break; + + case CASE_HP_BUGGY_LL: + /* Some HP-UX applications have the bug that they + assume ESC F goes to the lower left corner of + the screen, regardless of what terminfo says. */ + if (screen->hp_ll_bc) + CursorSet(screen, screen->max_row, 0, term->flags); + parsestate = groundtable; + break; + + case CASE_ED: + /* ED */ + switch (param[0]) { + case DEFAULT: + case 0: + ClearBelow(screen); + break; + + case 1: + ClearAbove(screen); + break; + + case 2: + ClearScreen(screen); + CursorSet(screen, 0, 0, term->flags); + break; + } + parsestate = groundtable; + break; + + case CASE_EL: + /* EL */ + switch (param[0]) { + case DEFAULT: + case 0: + ClearRight(screen); + break; + case 1: + ClearLeft(screen); + break; + case 2: + ClearLine(screen); + break; + } + parsestate = groundtable; + break; + + case CASE_IL: + /* IL */ + if((row = param[0]) < 1) + row = 1; + InsertLine(screen, row); + parsestate = groundtable; + break; + + case CASE_DL: + /* DL */ + if((row = param[0]) < 1) + row = 1; + DeleteLine(screen, row); + parsestate = groundtable; + break; + + case CASE_DCH: + /* DCH */ + if((row = param[0]) < 1) + row = 1; + DeleteChar(screen, row); + parsestate = groundtable; + break; + + case CASE_TRACK_MOUSE: + /* Track mouse as long as in window and between + specified rows */ + TrackMouse(param[0], param[2]-1, param[1]-1, + param[3]-1, param[4]-2); + break; + + case CASE_DECID: + param[0] = -1; /* Default ID parameter */ + /* Fall through into ... */ + case CASE_DA1: + /* DA1 */ + if (param[0] <= 0) { /* less than means DEFAULT */ + reply.a_type = CSI; + reply.a_pintro = '?'; + reply.a_nparam = 2; + reply.a_param[0] = 1; /* VT102 */ + reply.a_param[1] = 2; /* VT102 */ + reply.a_inters = 0; + reply.a_final = 'c'; + unparseseq(&reply, screen->respond); + } + parsestate = groundtable; + break; + + case CASE_TBC: + /* TBC */ + if ((row = param[0]) <= 0) /* less than means default */ + TabClear(term->tabs, screen->cur_col); + else if (row == 3) + TabZonk(term->tabs); + parsestate = groundtable; + break; + + case CASE_SET: + /* SET */ + ansi_modes(term, bitset); + parsestate = groundtable; + break; + + case CASE_RST: + /* RST */ + ansi_modes(term, bitclr); + parsestate = groundtable; + break; + + case CASE_SGR: + /* SGR */ + for (row=0; row<nparam; ++row) { + switch (param[row]) { + case DEFAULT: + case 0: + term->flags &= + ~(INVERSE|BOLD|UNDERLINE|FG_COLOR|BG_COLOR); + break; + case 1: + case 5: /* Blink, really. */ + term->flags |= BOLD; + if (term->misc.dynamicColors) { + if (!(term->flags & FG_COLOR) || + (term->cur_foreground==COLOR_UL)) { + term->flags |= FG_COLOR; + term->cur_foreground = COLOR_BD; + } else { /* Set highlight bit */ + if (term->cur_foreground < 8) + term->cur_foreground |= 8; + } + } + break; + case 4: /* Underscore */ + term->flags |= UNDERLINE; + if (term->misc.dynamicColors) { +/**/ if (!(term->flags & FG_COLOR)) { + term->flags |= FG_COLOR; + term->cur_foreground = COLOR_UL; + } + } + break; + case 7: + term->flags |= INVERSE; + break; + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + term->flags |= FG_COLOR; + term->cur_foreground = param[row] - 30; + /* Set highlight bit if bold on */ + if (term->flags & BOLD) + term->cur_foreground |= 8; + break; + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + term->flags |= BG_COLOR; + term->cur_background = param[row] - 40; + break; + } + } + parsestate = groundtable; + break; + + case CASE_CPR: + /* CPR */ + if ((row = param[0]) == 5) { + reply.a_type = CSI; + reply.a_pintro = 0; + reply.a_nparam = 1; + reply.a_param[0] = 0; + reply.a_inters = 0; + reply.a_final = 'n'; + unparseseq(&reply, screen->respond); + } else if (row == 6) { + reply.a_type = CSI; + reply.a_pintro = 0; + reply.a_nparam = 2; + reply.a_param[0] = screen->cur_row+1; + reply.a_param[1] = screen->cur_col+1; + reply.a_inters = 0; + reply.a_final = 'R'; + unparseseq(&reply, screen->respond); + } + parsestate = groundtable; + break; + + case CASE_HP_MEM_LOCK: + case CASE_HP_MEM_UNLOCK: + if(screen->scroll_amt) + FlushScroll(screen); + if (parsestate[c] == CASE_HP_MEM_LOCK) + screen->top_marg = screen->cur_row; + else + screen->top_marg = 0; + parsestate = groundtable; + break; + + case CASE_DECSTBM: + /* DECSTBM - set scrolling region */ + if((top = param[0]) < 1) + top = 1; + if(nparam < 2 || (bot = param[1]) == DEFAULT + || bot > screen->max_row + 1 + || bot == 0) + bot = screen->max_row+1; + if (bot > top) { + if(screen->scroll_amt) + FlushScroll(screen); + screen->top_marg = top-1; + screen->bot_marg = bot-1; + CursorSet(screen, 0, 0, term->flags); + } + parsestate = groundtable; + break; + + case CASE_SUNREQTPARM: + /* Escape commands or query functions used by the + * SunView shelltool (ttysw widget). Most of these + * are currently stubbed out. + */ + if ((row = param[0]) == DEFAULT) + row = 18; + switch (row) { + case 1: + /* open */ + break; + case 2: + /* close */ + break; + case 3: + /* move */ + break; + case 4: + /* resize */ + break; + case 5: + /* front */ + break; + case 6: + /* back */ + break; + case 7: + /* refresh */ + break; + case 11: + /* report if open or iconic by sending + * \E[1t or \E[2t. + */ + break; + case 13: + /* report position by sending \E[3;TOP;LEFTt + */ + break; + case 14: + /* report size in pixels by sending \E[4;HT;WIDTHt. + */ + break; + case 18: + /* report size in characters by sending + * \E[8;ROWS;COLSt. + */ + reply.a_type = ESC; + reply.a_pintro = '['; + reply.a_nparam = 3; + reply.a_param[0] = 8; + reply.a_param[1] = screen->max_row + 1; + reply.a_param[2] = screen->max_col + 1; + reply.a_inters = 0; + reply.a_final = 't'; + unparseseq(&reply, screen->respond); + break; + case 20: + /* report icon label by sending \E]Llabel\E\. + */ + break; + case 21: + /* report tool header by sending \E]llabel\E\. + */ + break; + } + parsestate = groundtable; + break; + + case CASE_DECREQTPARM: + /* DECREQTPARM */ + if ((row = param[0]) == DEFAULT) + row = 0; + if (row == 0 || row == 1) { + reply.a_type = CSI; + reply.a_pintro = 0; + reply.a_nparam = 7; + reply.a_param[0] = row + 2; + reply.a_param[1] = 1; /* no parity */ + reply.a_param[2] = 1; /* eight bits */ + reply.a_param[3] = 112; /* transmit 9600 baud */ + reply.a_param[4] = 112; /* receive 9600 baud */ + reply.a_param[5] = 1; /* clock multiplier ? */ + reply.a_param[6] = 0; /* STP flags ? */ + reply.a_inters = 0; + reply.a_final = 'x'; + unparseseq(&reply, screen->respond); + } + parsestate = groundtable; + break; + + case CASE_DECSET: + /* DECSET */ + dpmodes(term, bitset); + parsestate = groundtable; + break; + + case CASE_DECRST: + /* DECRST */ + dpmodes(term, bitclr); + parsestate = groundtable; + break; + + case CASE_DECALN: + /* DECALN */ + if(screen->cursor_state) + HideCursor(); + for(row = screen->max_row ; row >= 0 ; row--) { + memset(screen->buf[4 * row + 1], 0, + col = screen->max_col + 1); + for(cp = (unsigned char *)screen->buf[4 * row] ; col > 0 ; col--) + *cp++ = (unsigned char) 'E'; + } + ScrnRefresh(screen, 0, 0, screen->max_row + 1, + screen->max_col + 1, False); + parsestate = groundtable; + break; + + case CASE_GSETS: + screen->gsets[scstype] = c; + parsestate = groundtable; + break; + + case CASE_DECSC: + /* DECSC */ + CursorSave(term, &screen->sc); + parsestate = groundtable; + break; + + case CASE_DECRC: + /* DECRC */ + CursorRestore(term, &screen->sc); + parsestate = groundtable; + break; + + case CASE_DECKPAM: + /* DECKPAM */ + term->keyboard.flags |= KYPD_APL; + update_appkeypad(); + parsestate = groundtable; + break; + + case CASE_DECKPNM: + /* DECKPNM */ + term->keyboard.flags &= ~KYPD_APL; + update_appkeypad(); + parsestate = groundtable; + break; + + case CASE_IND: + /* IND */ + Index(screen, 1); + if (XtAppPending(app_con) || + GetBytesAvailable (ConnectionNumber(screen->display)) > 0) + xevents(); + parsestate = groundtable; + break; + + case CASE_NEL: + /* NEL */ + Index(screen, 1); + CarriageReturn(screen); + + if (XtAppPending(app_con) || + GetBytesAvailable (ConnectionNumber(screen->display)) > 0) + xevents(); + parsestate = groundtable; + break; + + case CASE_HTS: + /* HTS */ + TabSet(term->tabs, screen->cur_col); + parsestate = groundtable; + break; + + case CASE_RI: + /* RI */ + RevIndex(screen, 1); + parsestate = groundtable; + break; + + case CASE_SS2: + /* SS2 */ + screen->curss = 2; + parsestate = groundtable; + break; + + case CASE_SS3: + /* SS3 */ + screen->curss = 3; + parsestate = groundtable; + break; + + case CASE_CSI_STATE: + /* enter csi state */ + nparam = 1; + param[0] = DEFAULT; + parsestate = csitable; + break; + + case CASE_OSC: + /* Operating System Command: ESC ] */ + do_osc(finput); + parsestate = groundtable; + break; + + case CASE_RIS: + /* RIS */ + VTReset(TRUE); + parsestate = groundtable; + break; + + case CASE_LS2: + /* LS2 */ + screen->curgl = 2; + parsestate = groundtable; + break; + + case CASE_LS3: + /* LS3 */ + screen->curgl = 3; + parsestate = groundtable; + break; + + case CASE_LS3R: + /* LS3R */ + screen->curgr = 3; + parsestate = groundtable; + break; + + case CASE_LS2R: + /* LS2R */ + screen->curgr = 2; + parsestate = groundtable; + break; + + case CASE_LS1R: + /* LS1R */ + screen->curgr = 1; + parsestate = groundtable; + break; + + case CASE_XGTERM_SAVE: + savemodes(term); + parsestate = groundtable; + break; + + case CASE_XGTERM_RESTORE: + restoremodes(term); + parsestate = groundtable; + break; + + default: + printf ("VTParse: unknown state....\n"); + } + } +} + +static finput() +{ + return(doinput()); +} + + +static char *v_buffer; /* pointer to physical buffer */ +static char *v_bufstr = NULL; /* beginning of area to write */ +static char *v_bufptr; /* end of area to write */ +static char *v_bufend; /* end of physical buffer */ + +/**/ +static XtIntervalId input_handler = (XtIntervalId) NULL; +static XtIntervalId output_handler = (XtIntervalId) NULL; +static int pty_read_bytes = 0; +#define ptymask() (v_bufptr > v_bufstr ? pty_mask : 0) + +/* Write data to the pty as typed by the user, pasted with the mouse, + or generated by us in response to a query ESC sequence. */ + +v_write(f, d, len) + int f; + char *d; + int len; +{ + int riten; + int c = len; + + if (v_bufstr == NULL && len > 0) { + v_buffer = XtMalloc(len); + v_bufstr = v_buffer; + v_bufptr = v_buffer; + v_bufend = v_buffer + len; + } +#ifdef DEBUG + if (debug) { + fprintf(stderr, "v_write called with %d bytes (%d left over)", + len, v_bufptr - v_bufstr); + if (len > 1 && len < 10) fprintf(stderr, " \"%.*s\"", len, d); + fprintf(stderr, "\n"); + } +#endif + + if ((1 << f) != pty_mask) + return(write(f, d, len)); + + /* + * Append to the block we already have. + * Always doing this simplifies the code, and + * isn't too bad, either. If this is a short + * block, it isn't too expensive, and if this is + * a long block, we won't be able to write it all + * anyway. + */ + + if (len > 0) { + if (v_bufend < v_bufptr + len) { /* we've run out of room */ + if (v_bufstr != v_buffer) { + /* there is unused space, move everything down */ + /* possibly overlapping memmove here */ +#ifdef DEBUG + if (debug) + fprintf(stderr, "moving data down %d\n", + v_bufstr - v_buffer); +#endif + memmove( v_buffer, v_bufstr, v_bufptr - v_bufstr); + v_bufptr -= v_bufstr - v_buffer; + v_bufstr = v_buffer; + } + if (v_bufend < v_bufptr + len) { + /* still won't fit: get more space */ + /* Don't use XtRealloc because an error is not fatal. */ + int size = v_bufptr - v_buffer; /* save across realloc */ + v_buffer = realloc(v_buffer, size + len); + if (v_buffer) { +#ifdef DEBUG + if (debug) + fprintf(stderr, "expanded buffer to %d\n", + size + len); +#endif + v_bufstr = v_buffer; + v_bufptr = v_buffer + size; + v_bufend = v_bufptr + len; + } else { + /* no memory: ignore entire write request */ + fprintf(stderr, "%s: cannot allocate buffer space\n", + xgterm_name); + v_buffer = v_bufstr; /* restore clobbered pointer */ + c = 0; + } + } + } + if (v_bufend >= v_bufptr + len) { + /* new stuff will fit */ + memmove( v_bufptr, d, len); + v_bufptr += len; + } + } + + /* + * Write out as much of the buffer as we can. + * Be careful not to overflow the pty's input silo. + * We are conservative here and only write + * a small amount at a time. + * + * If we can't push all the data into the pty yet, we expect write + * to return a non-negative number less than the length requested + * (if some data written) or -1 and set errno to EAGAIN, + * EWOULDBLOCK, or EINTR (if no data written). + * + * (Not all systems do this, sigh, so the code is actually + * a little more forgiving.) + */ + +#define MAX_PTY_WRITE 128 /* 1/2 POSIX minimum MAX_INPUT */ + + if (v_bufptr > v_bufstr) { + riten = write(f, v_bufstr, v_bufptr - v_bufstr <= MAX_PTY_WRITE ? + v_bufptr - v_bufstr : MAX_PTY_WRITE); + if (riten < 0) { +#ifdef DEBUG + if (debug) perror("write"); +#endif + riten = 0; + } +#ifdef DEBUG + if (debug) + fprintf(stderr, "write called with %d, wrote %d\n", + v_bufptr - v_bufstr <= MAX_PTY_WRITE ? + v_bufptr - v_bufstr : MAX_PTY_WRITE, + riten); +#endif + v_bufstr += riten; + if (v_bufstr >= v_bufptr) /* we wrote it all */ + v_bufstr = v_bufptr = v_buffer; + } + + /* + * If we have lots of unused memory allocated, return it + */ + if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */ + /* save pointers across realloc */ + int start = v_bufstr - v_buffer; + int size = v_bufptr - v_buffer; + int allocsize = size ? size : 1; + + v_buffer = realloc(v_buffer, allocsize); + if (v_buffer) { + v_bufstr = v_buffer + start; + v_bufptr = v_buffer + size; + v_bufend = v_buffer + allocsize; +#ifdef DEBUG + if (debug) + fprintf(stderr, "shrunk buffer to %d\n", allocsize); +#endif + } else { + /* should we print a warning if couldn't return memory? */ + v_buffer = v_bufstr - start; /* restore clobbered pointer */ + } + } + + /* If there is still data left to write post an event handler to + * write the rest of the buffer. Otherwise remove any old handler. + */ + if (v_bufptr > v_bufstr) { + if (!output_handler) + output_handler = XtAppAddInput (app_con, f, + (XtPointer)XtInputWriteMask, do_write, (XtPointer)NULL); + } else if (output_handler) { + XtRemoveInput (output_handler); + output_handler = (XtIntervalId) NULL; + } + + return(c); +} + + +/* in_put -- Process input from all sources (terminal pty i/o, X events, and + * timers). This is called after the input pty data buffer has been processed + * and we are ready for more input, and it returns when new input data has + * been received from the client. + */ +static int +in_put() +{ + register TScreen *screen = &term->screen; + register XtInputMask mask; + + /* Enable pty input. */ + if (!input_handler) + init_ttyio (screen->respond); + + /* Process events until we get some input data to return to our caller. + */ + do { + /* Pty input events are processed first - this is necessary for the + * jump scroll feature to work properly. + */ + if (bcnt <= 0 && pty_read_bytes < 4096) { + mask = (XtIMAlternateInput | XtIMTimer); + while (bcnt <= 0 && (XtAppPending(app_con) & mask)) + XtAppProcessEvent (app_con, mask); + if (bcnt > 0) + goto done; + } + + /* Update the screen. */ + if (screen->scroll_amt) + FlushScroll (screen); + if (screen->cursor_set && (screen->cursor_col != screen->cur_col + || screen->cursor_row != screen->cur_row)) { + if (screen->cursor_state) + HideCursor(); + ShowCursor(); + } else if (screen->cursor_set != screen->cursor_state) { + if (screen->cursor_set) + ShowCursor(); + else + HideCursor(); + } + while (!gt_flush()) + ; + XFlush (XtDisplay(term)); + + /* Process any queued up X events. */ + while (XtAppPending(app_con) & (XtIMXEvent|XtIMTimer)) + XtAppProcessEvent (app_con, XtIMXEvent|XtIMTimer); + + /* Wait for and process the next input event. */ + XtAppProcessEvent (app_con, XtIMAll); + pty_read_bytes = 0; + + } while (bcnt <= 0); + +done: + /* Disable pty input except when in this routine. */ + XtRemoveInput (input_handler); + input_handler = (XtIntervalId) NULL; + + /* Return the next input char. */ + bcnt--; + return (*bptr++); +} + + +/* do_read -- Called to read input data from the client pty. We merely read + * the data into the global input data buffer and return. The data is + * processed out of the buffer elsewhere. + */ +static void +do_read (w, fd, id) + XtPointer w; + int *fd; + XtInputId *id; +{ + register TScreen *screen = &term->screen; + + /* Don't read any more data until the input buffer is empty. */ + if (bcnt > 0) + return; + +#ifdef ALLOWLOGGING + if (screen->logging) + FlushLog(screen); +#endif + + bcnt = read (*fd, (char *)(bptr = buffer), BUF_SIZE); + if (bcnt > 0 && screen->logging) + write (screen->logfd, buffer, bcnt); + + if (bcnt < 0) { + if (errno == EIO) + Cleanup (0); + else if (!E_TEST(errno)) + Panic ("input: read returned unexpected error (%d)\n", errno); + } else if (bcnt == 0) { + Panic ("input: read returned zero\n", 0); + + } else { + /* read from pty was successful */ + + /* Let gtermio remove any graphics text. */ + bcnt = gt_input (bptr, bcnt); + gt_flush(); + + if (bcnt <= 0) { + bcnt = 0; + return; + } + + if (!screen->output_eight_bits) { + register int bc = bcnt; + register Char *b = bptr; + + for (; bc > 0; bc--, b++) { + *b &= (Char) 0x7f; + } + } + + if (screen->scrollWidget && screen->scrollttyoutput && + screen->topline < 0) + WindowScroll(screen, 0); /* Scroll to bottom */ + + pty_read_bytes += bcnt; + } +} + + +/* do_write -- Called to write buffered client output when there is data + * queued and the output file is ready for writing. + */ +static void +do_write (w, fd, id) + XtPointer w; + int *fd; + XtInputId *id; +{ + v_write (*fd, 0, 0); +} + +/* init_ttyio -- Initialize tty i/o. Called by the main when the terminal + * file descriptor has been obtained. + */ +init_ttyio (pty) + int pty; +{ + if (pty < 0) { + Panic ("init_ttyio: invalid pty=%d\n", pty); + + } else if (!input_handler) { + input_handler = XtAppAddInput (app_con, pty, + (XtPointer)XtInputReadMask, do_read, (XtPointer)NULL); + } +} + + +/* + * process a string of characters according to the character set indicated + * by charset. worry about end of line conditions (wraparound if selected). + */ +static void +dotext(screen, flags, charset, buf, ptr, fg, bg) + register TScreen *screen; + unsigned flags, fg, bg; + char charset; + char *buf; /* start of characters to process */ + char *ptr; /* end */ +{ + register char *s; + register int len; + register int n; + register int next_col; + + switch (charset) { + case 'A': /* United Kingdom set */ + for (s=buf; s<ptr; ++s) + if (*s == '#') + *s = '\036'; /* UK pound sign*/ + break; + + case 'B': /* ASCII set */ + break; + + case '0': /* special graphics (line drawing) */ + for (s=buf; s<ptr; ++s) + if (*s>=0x5f && *s<=0x7e) + *s = *s == 0x5f ? 0x7f : *s - 0x5f; + break; + + default: /* any character sets we don't recognize*/ + return; + } + + len = ptr - buf; + ptr = buf; + while (len > 0) { + n = screen->max_col - screen->cur_col +1; + if (n <= 1) { + if (screen->do_wrap && (flags&WRAPAROUND)) { + /* mark that we had to wrap this line */ + ScrnSetAttributes(screen, screen->cur_row, 0, + LINEWRAPPED, LINEWRAPPED, 1); + Index(screen, 1); + screen->cur_col = 0; + screen->do_wrap = 0; + n = screen->max_col+1; + } else + n = 1; + } + if (len < n) + n = len; + next_col = screen->cur_col + n; + WriteText(screen, ptr, n, flags, fg, bg); + /* + * the call to WriteText updates screen->cur_col. + * If screen->cur_col != next_col, we must have + * hit the right margin, so set the do_wrap flag. + */ + screen->do_wrap = (screen->cur_col < next_col); + len -= n; + ptr += n; + } +} + +/* + * write a string str of length len onto the screen at + * the current cursor position. update cursor position. + */ +static void +WriteText(screen, str, len, flags, fg, bg) + register TScreen *screen; + register char *str; + register int len; + unsigned flags, fg, bg; +{ + register int cx, cy; + register unsigned fgs = flags; + register Pixel fg_pix, bg_pix; + GC currentGC; + + fg_pix = (fgs & FG_COLOR) ? screen->colors[fg] : + screen->foreground; + bg_pix = (fgs & BG_COLOR) ? screen->colors[bg] : + term->core.background_pixel; + + if(screen->cur_row - screen->topline <= screen->max_row) { + /* + if(screen->cur_row == screen->cursor_row && screen->cur_col <= + screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1) + screen->cursor_state = OFF; + */ + if(screen->cursor_state) + HideCursor(); + + /* + * make sure that the correct GC is current + */ + + if (fgs & INVERSE) { + if (fgs & BOLD) currentGC = screen->reverseboldGC; + else currentGC = screen->reverseGC; + + if (term->misc.dynamicColors) { + XSetForeground(screen->display, currentGC, bg_pix); + XSetBackground(screen->display, currentGC, fg_pix); + } + + } else { /* not bold */ + if (fgs & BOLD) currentGC = screen->normalboldGC; + else currentGC = screen->normalGC; + + if (term->misc.dynamicColors) { + XSetForeground(screen->display, currentGC, fg_pix); + XSetBackground(screen->display, currentGC, bg_pix); + } + } + + if (fgs & INSERT) + InsertChar(screen, len); + if (!(AddToRefresh(screen))) { + if(screen->scroll_amt) + FlushScroll(screen); + cx = CursorX(screen, screen->cur_col); + cy = CursorY(screen, screen->cur_row)+screen->fnt_norm->ascent; + XDrawImageString(screen->display, TextWindow(screen), currentGC, + cx, cy, str, len); + + if((fgs & BOLD) && screen->enbolden) + if (currentGC == screen->normalGC || screen->reverseGC) + XDrawString(screen->display, TextWindow(screen), + currentGC,cx + 1, cy, str, len); + + if((fgs & UNDERLINE) && screen->underline) + XDrawLine(screen->display, TextWindow(screen), currentGC, + cx, cy+1, + cx + len * FontWidth(screen), cy+1); + /* + * the following statements compile data to compute the average + * number of characters written on each call to XText. The data + * may be examined via the use of a "hidden" escape sequence. + */ + ctotal += len; + ++ntotal; + } + } + ScreenWrite(screen, str, flags, fg, bg, len); + CursorForward(screen, len); +} + +/* + * process ANSI modes set, reset + */ +ansi_modes(termw, func) + XgtermWidget termw; + int (*func)(); +{ + register int i; + + for (i=0; i<nparam; ++i) { + switch (param[i]) { + case 4: /* IRM */ + (*func)(&termw->flags, INSERT); + break; + + case 20: /* LNM */ + (*func)(&termw->flags, LINEFEED); + update_autolinefeed(); + break; + } + } +} + +/* + * process DEC private modes set, reset + */ +dpmodes(termw, func) + XgtermWidget termw; + void (*func)(); +{ + register TScreen *screen = &termw->screen; + register int i, j; + + for (i=0; i<nparam; ++i) { + switch (param[i]) { + case 1: /* DECCKM */ + (*func)(&termw->keyboard.flags, CURSOR_APL); + update_appcursor(); + break; + case 2: /* ANSI/VT52 mode */ + if (func == bitset) { + screen->gsets[0] = + screen->gsets[1] = + screen->gsets[2] = + screen->gsets[3] = 'B'; + screen->curgl = 0; + screen->curgr = 2; + } + break; + case 3: /* DECCOLM */ + if(screen->c132) { + ClearScreen(screen); + CursorSet(screen, 0, 0, termw->flags); + if((j = func == bitset ? 132 : 80) != + ((termw->flags & IN132COLUMNS) ? 132 : 80) || + j != screen->max_col + 1) { + Dimension replyWidth, replyHeight; + XtGeometryResult status; + + if (term->misc.sb_right) { + status = XtMakeResizeRequest ( + (Widget) termw, + (Dimension)FontWidth(screen) * j + + 2*screen->border, + (Dimension) FontHeight(screen) + * (screen->max_row + 1) + + 2 * screen->border, + &replyWidth, &replyHeight); + } else { + status = XtMakeResizeRequest ( + (Widget) termw, + (Dimension)FontWidth(screen) * j + + 2*screen->border + + screen->scrollbar, + (Dimension) FontHeight(screen) + * (screen->max_row + 1) + + 2 * screen->border, + &replyWidth, &replyHeight); + } + + if (status == XtGeometryYes || + status == XtGeometryDone) { + ScreenResize (&termw->screen, + replyWidth, + replyHeight, + &termw->flags); + } + } + (*func)(&termw->flags, IN132COLUMNS); + } + break; + case 4: /* DECSCLM (slow scroll) */ + if (func == bitset) { + screen->jumpscroll = 0; + if (screen->scroll_amt) + FlushScroll(screen); + } else + screen->jumpscroll = 1; + (*func)(&termw->flags, SMOOTHSCROLL); + update_jumpscroll(); + break; + case 5: /* DECSCNM */ + j = termw->flags; + (*func)(&termw->flags, REVERSE_VIDEO); + if ((termw->flags ^ j) & REVERSE_VIDEO) + ReverseVideo(termw); + /* update_reversevideo done in RevVid */ + break; + + case 6: /* DECOM */ + (*func)(&termw->flags, ORIGIN); + CursorSet(screen, 0, 0, termw->flags); + break; + + case 7: /* DECAWM */ + (*func)(&termw->flags, WRAPAROUND); + update_autowrap(); + break; + case 8: /* DECARM */ + /* ignore autorepeat */ + break; + case 9: /* MIT bogus sequence */ + if(func == bitset) + screen->send_mouse_pos = 1; + else + screen->send_mouse_pos = 0; + break; + case 38: /* DECTEK */ + if(func == bitset && !(screen->inhibit & I_TEK)) { +#ifdef ALLOWLOGGING + if(screen->logging) { + FlushLog(screen); + screen->logstart = Tbuffer; + } +#endif + /* Enable gtermio as if a GS had been seen, + * but in xterm emulation mode (no trailers). + * Call gt_input to pass any buffered input + * following the DECTEK on to gtermio. + */ + switch_modes (0); + gt_set_ginmode_trailers (NULL); + while (!gt_flush()) + ; + } + break; + case 40: /* 132 column mode */ + screen->c132 = (func == bitset); + update_allow132(); + break; + case 41: /* curses hack */ + screen->curses = (func == bitset); + update_cursesemul(); + break; + case 44: /* margin bell */ + screen->marginbell = (func == bitset); + if(!screen->marginbell) + screen->bellarmed = -1; + update_marginbell(); + break; + case 45: /* reverse wraparound */ + (*func)(&termw->flags, REVERSEWRAP); + update_reversewrap(); + break; +#ifdef ALLOWLOGGING + case 46: /* logging */ +#ifdef ALLOWLOGFILEONOFF + /* + * if this feature is enabled, logging may be + * enabled and disabled via escape sequences. + */ + if(func == bitset) + StartLog(screen); + else + CloseLog(screen); +#else + Bell(); + Bell(); +#endif /* ALLOWLOGFILEONOFF */ + break; +#endif + case 47: /* alternate buffer */ + if (!termw->misc.titeInhibit) { + if(func == bitset) + ToAlternate(screen); + else + FromAlternate(screen); + } + break; + case 1000: /* xgterm bogus sequence */ + if(func == bitset) + screen->send_mouse_pos = 2; + else + screen->send_mouse_pos = 0; + break; + case 1001: /* xgterm sequence w/hilite tracking */ + if(func == bitset) + screen->send_mouse_pos = 3; + else + screen->send_mouse_pos = 0; + break; + } + } +} + +/* + * process xgterm private modes save + */ +savemodes(termw) + XgtermWidget termw; +{ + register TScreen *screen = &termw->screen; + register int i; + + for (i = 0; i < nparam; i++) { + switch (param[i]) { + case 1: /* DECCKM */ + screen->save_modes[0] = termw->keyboard.flags & + CURSOR_APL; + break; + case 3: /* DECCOLM */ + if(screen->c132) + screen->save_modes[1] = termw->flags & IN132COLUMNS; + break; + case 4: /* DECSCLM (slow scroll) */ + screen->save_modes[2] = termw->flags & SMOOTHSCROLL; + break; + case 5: /* DECSCNM */ + screen->save_modes[3] = termw->flags & REVERSE_VIDEO; + break; + case 6: /* DECOM */ + screen->save_modes[4] = termw->flags & ORIGIN; + break; + + case 7: /* DECAWM */ + screen->save_modes[5] = termw->flags & WRAPAROUND; + break; + case 8: /* DECARM */ + /* ignore autorepeat */ + break; + case 9: /* mouse bogus sequence */ + screen->save_modes[7] = screen->send_mouse_pos; + break; + case 40: /* 132 column mode */ + screen->save_modes[8] = screen->c132; + break; + case 41: /* curses hack */ + screen->save_modes[9] = screen->curses; + break; + case 44: /* margin bell */ + screen->save_modes[12] = screen->marginbell; + break; + case 45: /* reverse wraparound */ + screen->save_modes[13] = termw->flags & REVERSEWRAP; + break; +#ifdef ALLOWLOGGING + case 46: /* logging */ + screen->save_modes[14] = screen->logging; + break; +#endif + case 47: /* alternate buffer */ + screen->save_modes[15] = screen->alternate; + break; + case 1000: /* mouse bogus sequence */ + case 1001: + screen->save_modes[7] = screen->send_mouse_pos; + break; + } + } +} + +/* + * process xgterm private modes restore + */ +restoremodes(termw) + XgtermWidget termw; +{ + register TScreen *screen = &termw->screen; + register int i, j; + + for (i = 0; i < nparam; i++) { + switch (param[i]) { + case 1: /* DECCKM */ + termw->keyboard.flags &= ~CURSOR_APL; + termw->keyboard.flags |= screen->save_modes[0] & + CURSOR_APL; + update_appcursor(); + break; + case 3: /* DECCOLM */ + if(screen->c132) { + ClearScreen(screen); + CursorSet(screen, 0, 0, termw->flags); + if((j = (screen->save_modes[1] & IN132COLUMNS) + ? 132 : 80) != ((termw->flags & IN132COLUMNS) + ? 132 : 80) || j != screen->max_col + 1) { + Dimension replyWidth, replyHeight; + XtGeometryResult status; + status = XtMakeResizeRequest ( + (Widget) termw, + (Dimension) FontWidth(screen) * j + + 2*screen->border + + screen->scrollbar, + (Dimension) FontHeight(screen) + * (screen->max_row + 1) + + 2*screen->border, + &replyWidth, &replyHeight); + + if (status == XtGeometryYes || + status == XtGeometryDone) { + ScreenResize (&termw->screen, + replyWidth, + replyHeight, + &termw->flags); + } + } + termw->flags &= ~IN132COLUMNS; + termw->flags |= screen->save_modes[1] & + IN132COLUMNS; + } + break; + case 4: /* DECSCLM (slow scroll) */ + if (screen->save_modes[2] & SMOOTHSCROLL) { + screen->jumpscroll = 0; + if (screen->scroll_amt) + FlushScroll(screen); + } else + screen->jumpscroll = 1; + termw->flags &= ~SMOOTHSCROLL; + termw->flags |= screen->save_modes[2] & SMOOTHSCROLL; + update_jumpscroll(); + break; + case 5: /* DECSCNM */ + if((screen->save_modes[3] ^ termw->flags) & REVERSE_VIDEO) { + termw->flags &= ~REVERSE_VIDEO; + termw->flags |= screen->save_modes[3] & REVERSE_VIDEO; + ReverseVideo(termw); + /* update_reversevideo done in RevVid */ + } + break; + case 6: /* DECOM */ + termw->flags &= ~ORIGIN; + termw->flags |= screen->save_modes[4] & ORIGIN; + CursorSet(screen, 0, 0, termw->flags); + break; + + case 7: /* DECAWM */ + termw->flags &= ~WRAPAROUND; + termw->flags |= screen->save_modes[5] & WRAPAROUND; + update_autowrap(); + break; + case 8: /* DECARM */ + /* ignore autorepeat */ + break; + case 9: /* MIT bogus sequence */ + screen->send_mouse_pos = screen->save_modes[7]; + break; + case 40: /* 132 column mode */ + screen->c132 = screen->save_modes[8]; + update_allow132(); + break; + case 41: /* curses hack */ + screen->curses = screen->save_modes[9]; + update_cursesemul(); + break; + case 44: /* margin bell */ + if(!(screen->marginbell = screen->save_modes[12])) + screen->bellarmed = -1; + update_marginbell(); + break; + case 45: /* reverse wraparound */ + termw->flags &= ~REVERSEWRAP; + termw->flags |= screen->save_modes[13] & REVERSEWRAP; + update_reversewrap(); + break; +#ifdef ALLOWLOGGING + case 46: /* logging */ +#ifdef ALLOWLOGFILEONOFF + if(screen->save_modes[14]) + StartLog(screen); + else + CloseLog(screen); +#endif /* ALLOWLOGFILEONOFF */ + /* update_logging done by StartLog and CloseLog */ + break; +#endif + case 47: /* alternate buffer */ + if (!termw->misc.titeInhibit) { + if(screen->save_modes[15]) + ToAlternate(screen); + else + FromAlternate(screen); + /* update_altscreen done by ToAlt and FromAlt */ + } + break; + case 1000: /* mouse bogus sequence */ + case 1001: + screen->send_mouse_pos = screen->save_modes[7]; + break; + } + } +} + +/* + * set a bit in a word given a pointer to the word and a mask. + */ +static void bitset(p, mask) + unsigned *p; + int mask; +{ + *p |= mask; +} + +/* + * clear a bit in a word given a pointer to the word and a mask. + */ +static void bitclr(p, mask) + unsigned *p; + int mask; +{ + *p &= ~mask; +} + +unparseseq(ap, fd) + register ANSI *ap; + int fd; +{ + register int c; + register int i; + register int inters; + + c = ap->a_type; + if (c>=0x80 && c<=0x9F) { + unparseputc(ESC, fd); + c -= 0x40; + } + unparseputc(c, fd); + c = ap->a_type; + if (c==ESC || c==DCS || c==CSI || c==OSC || c==PM || c==APC) { + if (ap->a_pintro != 0) + unparseputc((char) ap->a_pintro, fd); + for (i=0; i<ap->a_nparam; ++i) { + if (i != 0) + unparseputc(';', fd); + unparseputn((unsigned int) ap->a_param[i], fd); + } + inters = ap->a_inters; + for (i=3; i>=0; --i) { + c = (inters >> (8*i)) & 0xff; + if (c != 0) + unparseputc(c, fd); + } + unparseputc((char) ap->a_final, fd); + } +} + +unparseputn(n, fd) +unsigned int n; +int fd; +{ + unsigned int q; + + q = n/10; + if (q != 0) + unparseputn(q, fd); + unparseputc((char) ('0' + (n%10)), fd); +} + +unparseputc(c, fd) +char c; +int fd; +{ + char buf[2]; + register i = 1; + extern XgtermWidget term; + + if((buf[0] = c) == '\r' && (term->flags & LINEFEED)) { + buf[1] = '\n'; + i++; + } + v_write(fd, buf, i); +} + +unparsefputs (s, fd) + register char *s; + int fd; +{ + if (s) { + while (*s) unparseputc (*s++, fd); + } +} + +static void SwitchBufs(); + +static void +ToAlternate(screen) +register TScreen *screen; +{ + extern ScrnBuf Allocate(); + + if(screen->alternate) + return; + if(!screen->altbuf) + screen->altbuf = Allocate(screen->max_row + 1, screen->max_col + + 1, &screen->abuf_address); + SwitchBufs(screen); + screen->alternate = TRUE; + update_altscreen(); +} + +static void +FromAlternate(screen) +register TScreen *screen; +{ + if(!screen->alternate) + return; + screen->alternate = FALSE; + SwitchBufs(screen); + update_altscreen(); +} + +static void +SwitchBufs(screen) + register TScreen *screen; +{ + register int rows, top; + + if(screen->cursor_state) + HideCursor(); + rows = screen->max_row + 1; + SwitchBufPtrs(screen); + TrackText(0, 0, 0, 0); /* remove any highlighting */ + if((top = -screen->topline) <= screen->max_row) { + if(screen->scroll_amt) + FlushScroll(screen); + if(top == 0) + XClearWindow(screen->display, TextWindow(screen)); + else + if (term->misc.sb_right) { + XClearArea( + screen->display, + TextWindow(screen), + (int) screen->border, + (int) top * FontHeight(screen) + screen->border, + (unsigned) Width(screen), + (unsigned) (screen->max_row - top + 1) + * FontHeight(screen), + FALSE); + } else { + XClearArea( + screen->display, + TextWindow(screen), + (int) screen->border + screen->scrollbar, + (int) top * FontHeight(screen) + screen->border, + (unsigned) Width(screen), + (unsigned) (screen->max_row - top + 1) + * FontHeight(screen), + FALSE); + } + } + ScrnRefresh(screen, 0, 0, rows, screen->max_col + 1, False); +} + +/* swap buffer line pointers between alt and regular screens */ + +SwitchBufPtrs(screen) + register TScreen *screen; +{ + register int rows = screen->max_row + 1; + char *save [4 * MAX_ROWS]; + + memmove( (char *)save, (char *)screen->buf, 4 * sizeof(char *) * rows); + memmove( (char *)screen->buf, (char *)screen->altbuf, + 4 * sizeof(char *) * rows); + memmove( (char *)screen->altbuf, (char *)save, 4 * sizeof(char *) * rows); +} + +VTRun() +{ + register TScreen *screen = &term->screen; + register int i; + + XtRealizeWidget (term->core.parent); + if (!screen->TekEmu) + set_vt_visibility (TRUE); +/* + if (!screen->Vshow) + set_vt_visibility (TRUE); +*/ + + update_vttekmode(); + update_vtshow(); + update_tekshow(); + set_vthide_sensitivity(); + + if (screen->allbuf == NULL) VTallocbuf (); + + screen->cursor_state = OFF; + screen->cursor_set = ON; + + bcnt = 0; + bptr = buffer; + while(Tpushb > Tpushback) { + *bptr++ = *--Tpushb; + bcnt++; + } + bcnt += (i = Tbcnt); + for( ; i > 0 ; i--) + *bptr++ = *Tbptr++; + bptr = buffer; + if(!setjmp(VTend)) + VTparse(); + HideCursor(); + screen->cursor_set = OFF; +} + +/*ARGSUSED*/ +static void VTExpose(w, event, region) + Widget w; + XEvent *event; + Region region; +{ + register TScreen *screen = &term->screen; + +#ifdef DEBUG + if(debug) + fputs("Expose\n", stderr); +#endif /* DEBUG */ + if (event->type == Expose) + HandleExposure (screen, event); +} + +static void VTGraphicsOrNoExpose (event) + XEvent *event; +{ + register TScreen *screen = &term->screen; + if (screen->incopy <= 0) { + screen->incopy = 1; + if (screen->scrolls > 0) + screen->scrolls--; + } + if (event->type == GraphicsExpose) + if (HandleExposure (screen, event)) + screen->cursor_state = OFF; + if ((event->type == NoExpose) || ((XGraphicsExposeEvent *)event)->count == 0) { + if (screen->incopy <= 0 && screen->scrolls > 0) + screen->scrolls--; + if (screen->scrolls) + screen->incopy = -1; + else + screen->incopy = 0; + } +} + +/*ARGSUSED*/ +static void VTNonMaskableEvent (w, closure, event, cont) +Widget w; /* unused */ +XtPointer closure; /* unused */ +XEvent *event; +Boolean *cont; /* unused */ +{ + switch (event->type) { + case GraphicsExpose: + case NoExpose: + VTGraphicsOrNoExpose (event); + break; + } +} + + + + +static void VTResize(w) + Widget w; +{ + if (XtIsRealized(w)) + ScreenResize (&term->screen, term->core.width, term->core.height, + &term->flags); +} + + +extern Atom wm_delete_window; /* for ICCCM delete window */ + +static String xgterm_trans = + "<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\ + <MappingNotify>: KeyboardMapping()\n"; + +int VTInit () +{ + register TScreen *screen = &term->screen; + Widget vtparent = term->core.parent; + + XtRealizeWidget (vtparent); + XtOverrideTranslations(vtparent, XtParseTranslationTable(xgterm_trans)); + (void) XSetWMProtocols (XtDisplay(vtparent), XtWindow(vtparent), + &wm_delete_window, 1); + + if (screen->allbuf == NULL) VTallocbuf (); + return (1); +} + +static void VTallocbuf () +{ + register TScreen *screen = &term->screen; + int nrows = screen->max_row + 1; + extern ScrnBuf Allocate(); + + /* allocate screen buffer now, if necessary. */ + if (screen->scrollWidget) + nrows += screen->savelines; + screen->allbuf = Allocate (nrows, screen->max_col + 1, + &screen->sbuf_address); + if (screen->scrollWidget) + screen->buf = &screen->allbuf[4 * screen->savelines]; + else + screen->buf = screen->allbuf; + return; +} + +static void VTClassInit () +{ + XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity, + (XtConvertArgList) NULL, (Cardinal) 0); +} + + +/* ARGSUSED */ +static void VTInitialize (wrequest, wnew, args, num_args) + Widget wrequest, wnew; + ArgList args; + Cardinal *num_args; +{ + XgtermWidget request = (XgtermWidget) wrequest; + XgtermWidget new = (XgtermWidget) wnew; + int i; + + /* Zero out the entire "screen" component of "new" widget, + then do field-by-field assigment of "screen" fields + that are named in the resource list. */ + + memset ((char *) &new->screen, 0, sizeof(new->screen)); + new->screen.c132 = request->screen.c132; + new->screen.curses = request->screen.curses; + new->screen.hp_ll_bc = request->screen.hp_ll_bc; + new->screen.foreground = request->screen.foreground; + new->screen.cursorcolor = request->screen.cursorcolor; + new->screen.border = request->screen.border; + new->screen.jumpscroll = request->screen.jumpscroll; +#ifdef ALLOWLOGGING + new->screen.logfile = request->screen.logfile; +#endif + new->screen.marginbell = request->screen.marginbell; + new->screen.mousecolor = request->screen.mousecolor; + new->screen.mousecolorback = request->screen.mousecolorback; + new->screen.multiscroll = request->screen.multiscroll; + new->screen.nmarginbell = request->screen.nmarginbell; + new->screen.savelines = request->screen.savelines; + new->screen.scrolllines = request->screen.scrolllines; + new->screen.scrollttyoutput = request->screen.scrollttyoutput; + new->screen.scrollkey = request->screen.scrollkey; + new->screen.underline = request->screen.underline; + new->screen.visualbell = request->screen.visualbell; + new->screen.TekEmu = request->screen.TekEmu; + new->misc.re_verse = request->misc.re_verse; + new->screen.multiClickTime = request->screen.multiClickTime; + new->screen.bellSuppressTime = request->screen.bellSuppressTime; + new->screen.charClass = request->screen.charClass; + new->screen.cutNewline = request->screen.cutNewline; + new->screen.cutToBeginningOfLine = request->screen.cutToBeginningOfLine; + new->screen.always_highlight = request->screen.always_highlight; + new->screen.pointer_cursor = request->screen.pointer_cursor; + new->screen.input_eight_bits = request->screen.input_eight_bits; + new->screen.output_eight_bits = request->screen.output_eight_bits; + new->screen.allowSendEvents = request->screen.allowSendEvents; + new->misc.titeInhibit = request->misc.titeInhibit; + for (i = fontMenu_font1; i <= fontMenu_lastBuiltin; i++) { + new->screen.menu_font_names[i] = request->screen.menu_font_names[i]; + } + /* set default in realize proc */ + new->screen.menu_font_names[fontMenu_fontdefault] = NULL; + new->screen.menu_font_names[fontMenu_fontescape] = NULL; + new->screen.menu_font_names[fontMenu_fontsel] = NULL; + new->screen.menu_font_number = fontMenu_fontdefault; + + for (i = 0; i < MAXCOLORS; i++) { + new->screen.colors[i] = request->screen.colors[i]; + } + + /* + * The definition of -rv now is that it changes the definition of + * XtDefaultForeground and XtDefaultBackground. So, we no longer + * need to do anything special. + */ + new->keyboard.flags = 0; + new->screen.display = new->core.screen->display; + new->core.height = new->core.width = 1; + /* dummy values so that we don't try to Realize the parent shell + with height or width of 0, which is illegal in X. The real + size is computed in the xgtermWidget's Realize proc, + but the shell's Realize proc is called first, and must see + a valid size. */ + + /* look for focus related events on the shell, because we need + * to care about the shell's border being part of our focus. + */ + XtAddEventHandler(XtParent(new), FocusChangeMask, FALSE, + HandleFocusChange, (Opaque)NULL); + XtAddEventHandler((Widget)new, 0L, TRUE, + VTNonMaskableEvent, (Opaque)NULL); + XtAddEventHandler((Widget)new, PropertyChangeMask, FALSE, + HandleBellPropertyChange, (Opaque)NULL); + + /* These apply to vt100 window events. */ + XtAddEventHandler (wnew, EnterWindowMask, FALSE, HandleEnterWindow, + (Opaque)NULL); + XtAddEventHandler (wnew, LeaveWindowMask, FALSE, HandleLeaveWindow, + (Opaque)NULL); + + new->screen.bellInProgress = FALSE; + set_character_class (new->screen.charClass); + + /* create it, but don't realize it */ + ScrollBarOn (new, TRUE, FALSE); + + /* make sure that the resize gravity acceptable */ + if ( new->misc.resizeGravity != NorthWestGravity && + new->misc.resizeGravity != SouthWestGravity) { + Cardinal nparams = 1; + + XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XGtermError", + "unsupported resizeGravity resource value (%d)", + (String *) &(new->misc.resizeGravity), &nparams); + new->misc.resizeGravity = SouthWestGravity; + } + + return; +} + + +static void VTDestroy (w) +Widget w; +{ + XtFree(((XgtermWidget)w)->screen.selection); +} + +/*ARGSUSED*/ +static void VTRealize (w, valuemask, values) + Widget w; + XtValueMask *valuemask; + XSetWindowAttributes *values; +{ + unsigned int width, height; + register TScreen *screen = &term->screen; + int xpos, ypos, pr; + XSizeHints sizehints; + int scrollbar_width; + + TabReset (term->tabs); + + screen->menu_font_names[fontMenu_fontdefault] = term->misc.f_n; + screen->fnt_norm = screen->fnt_bold = NULL; + if (!LoadNewFont(screen, term->misc.f_n, term->misc.f_b, False, 0)) { + if (XmuCompareISOLatin1(term->misc.f_n, "fixed") != 0) { + fprintf (stderr, + "%s: unable to open font \"%s\", trying \"fixed\"....\n", + xgterm_name, term->misc.f_n); + (void) LoadNewFont (screen, "fixed", NULL, False, 0); + screen->menu_font_names[fontMenu_fontdefault] = "fixed"; + } + } + + /* really screwed if we couldn't open default font */ + if (!screen->fnt_norm) { + fprintf (stderr, "%s: unable to locate a suitable font\n", + xgterm_name); + Exit (1); + } + + /* making cursor */ + if (!screen->pointer_cursor) + screen->pointer_cursor = make_colored_cursor(XC_xterm, + screen->mousecolor, + screen->mousecolorback); + else + recolor_cursor (screen->pointer_cursor, + screen->mousecolor, screen->mousecolorback); + + scrollbar_width = (term->misc.scrollbar || term->misc.sb_right ? + screen->scrollWidget->core.width /* + + screen->scrollWidget->core.border_width */ : 0); + + /* set defaults */ + xpos = 1; ypos = 1; width = 80; height = 24; + pr = XParseGeometry (term->misc.geo_metry, &xpos, &ypos, + &width, &height); + screen->max_col = (width - 1); /* units in character cells */ + screen->max_row = (height - 1); /* units in character cells */ + update_font_info (&term->screen, False); + + width = screen->fullVwin.fullwidth; + height = screen->fullVwin.fullheight; + + if ((pr & XValue) && (XNegative&pr)) + xpos += DisplayWidth(screen->display, DefaultScreen(screen->display)) + - width - (term->core.parent->core.border_width * 2); + if ((pr & YValue) && (YNegative&pr)) + ypos += DisplayHeight(screen->display,DefaultScreen(screen->display)) + - height - (term->core.parent->core.border_width * 2); + + /* set up size hints for window manager; min 1 char by 1 char */ + sizehints.base_width = 2 * screen->border + scrollbar_width; + sizehints.base_height = 2 * screen->border; + sizehints.width_inc = FontWidth(screen); + sizehints.height_inc = FontHeight(screen); + sizehints.min_width = sizehints.base_width + sizehints.width_inc; + sizehints.min_height = sizehints.base_height + sizehints.height_inc; + sizehints.flags = (PBaseSize|PMinSize|PResizeInc); + sizehints.x = xpos; + sizehints.y = ypos; + if ((XValue&pr) || (YValue&pr)) { + sizehints.flags |= USSize|USPosition; + sizehints.flags |= PWinGravity; + switch (pr & (XNegative | YNegative)) { + case 0: + sizehints.win_gravity = NorthWestGravity; + break; + case XNegative: + sizehints.win_gravity = NorthEastGravity; + break; + case YNegative: + sizehints.win_gravity = SouthWestGravity; + break; + default: + sizehints.win_gravity = SouthEastGravity; + break; + } + } else { + /* set a default size, but do *not* set position */ + sizehints.flags |= PSize; + } + sizehints.width = width; + sizehints.height = height; + if ((WidthValue&pr) || (HeightValue&pr)) + sizehints.flags |= USSize; + else sizehints.flags |= PSize; + + (void) XtMakeResizeRequest((Widget) term, + (Dimension)width, (Dimension)height, + &term->core.width, &term->core.height); + + /* XXX This is bogus. We are parsing geometries too late. This + * is information that the shell widget ought to have before we get + * realized, so that it can do the right thing. + */ + if (sizehints.flags & USPosition) + XMoveWindow (XtDisplay(term), term->core.parent->core.window, + sizehints.x, sizehints.y); + + XSetWMNormalHints (XtDisplay(term), term->core.parent->core.window, + &sizehints); + XFlush (XtDisplay(term)); /* get it out to window manager */ + + /* use ForgetGravity instead of SouthWestGravity because translating + the Expose events for ConfigureNotifys is too hard */ + values->bit_gravity = term->misc.resizeGravity == NorthWestGravity ? + NorthWestGravity : ForgetGravity; + term->screen.fullVwin.window = term->core.window = + XCreateWindow(XtDisplay(term), XtWindow(term->core.parent), + term->core.x, term->core.y, + term->core.width, term->core.height, term->core.border_width, + (int) term->core.depth, + InputOutput, CopyFromParent, + *valuemask|CWBitGravity, values); + +/* +#ifdef I18N + VTInitI18N(); +#endif +*/ + + set_cursor_gcs (screen); + + /* Reset variables used by ANSI emulation. */ + + screen->gsets[0] = 'B'; /* ASCII_G */ + screen->gsets[1] = 'B'; + screen->gsets[2] = 'B'; /* DEC supplemental. */ + screen->gsets[3] = 'B'; + screen->curgl = 0; /* G0 => GL. */ + screen->curgr = 2; /* G2 => GR. */ + screen->curss = 0; /* No single shift. */ + + XDefineCursor(screen->display, VShellWindow, screen->pointer_cursor); + + screen->cur_col = screen->cur_row = 0; + screen->max_col = Width(screen)/screen->fullVwin.f_width - 1; + screen->top_marg = 0; + screen->bot_marg = screen->max_row = Height(screen) / + screen->fullVwin.f_height - 1; + + screen->sc.row = screen->sc.col = screen->sc.flags = 0; + + /* Mark screen buffer as unallocated. We wait until the run loop so + that the child process does not fork and exec with all the dynamic + memory it will never use. If we were to do it here, the + swap space for new process would be huge for huge savelines. */ + screen->buf = screen->allbuf = NULL; + + screen->do_wrap = 0; + screen->scrolls = screen->incopy = 0; + set_vt_box (screen); + + screen->savedlines = 0; + + if (term->misc.scrollbar || term->misc.sb_right ) { + screen->scrollbar = 0; + ScrollBarOn (term, FALSE, TRUE); + } + CursorSave (term, &screen->sc); + return; +} + +#ifdef I18N + +static void VTInitI18N() +{ + int i, + ic_cnt = 0; + char *p, + *s, + *ns, + *end, + tmp[1024], + buf[32]; + XIM xim; + XIMStyles *xim_styles; + XIMStyle input_style; + Boolean found; + + term->screen.xic = NULL; + + if (!term->misc.open_im) return; + + if (term->misc.input_method) { + strcpy(tmp, term->misc.input_method); + for(s=tmp; *s;) { + while (*s && isspace(*s)) s++; + if (!*s) break; + if (!(ns = end = index(s, ','))) + end = s + strlen(s); + while (isspace(*end)) end--; + *end = '\0'; + + strcpy(buf, "@im="); + strcat(buf, s); + if ((p = XSetLocaleModifiers(buf)) != NULL && *p + && (xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL)) != NULL) + break; + + s = ns + 1; + } + } else { + if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) + xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL); + } + + if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p) + xim = XOpenIM(XtDisplay(term), NULL, NULL, NULL); + + if (!xim) { + fprintf(stderr, "Failed to open input method"); + return; + } + + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) + || !xim_styles) { + fprintf(stderr, "input method doesn't support any style\n"); + XCloseIM(xim); + return; + } + + found = False; + strcpy(tmp, term->misc.preedit_type); + for(s = tmp; s && !found;) { + while (*s && isspace(*s)) s++; + if (!*s) break; + if (ns = end = index(s, ',')) + ns++; + else + end = s + strlen(s); + while (isspace(*end)) end--; + *end = '\0'; + + if (!strcmp(s, "OverTheSpot")) { + input_style = (XIMPreeditPosition | XIMStatusArea); + } else if (!strcmp(s, "OffTheSpot")) { + input_style = (XIMPreeditArea | XIMStatusArea); + } else if (!strcmp(s, "Root")) { + input_style = (XIMPreeditNothing | XIMStatusNothing); + } + for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) + if (input_style == xim_styles->supported_styles[i]) { + found = True; + break; + } + + s = ns; + } + XFree(xim_styles); + + if (!found) { + fprintf(stderr, "input method doesn't support my preedit type\n"); + XCloseIM(xim); + return; + } + + /* + * This program only understands the Root preedit_style yet + * Then misc.preedit_type should default to: + * "OverTheSpot,OffTheSpot,Root" + * + * /MaF + */ + if (input_style != (XIMPreeditNothing | XIMStatusNothing)) { + fprintf(stderr,"This program only supports the 'Root' preedit type\n"); + XCloseIM(xim); + return; + } + + term->screen.xic = XCreateIC(xim, XNInputStyle, input_style, + XNClientWindow, term->core.window, + XNFocusWindow, term->core.window, + NULL); + + if (!term->screen.xic) { + fprintf(stderr,"Failed to create input context\n"); + XCloseIM(xim); + } + + return; +} + +#endif + + +static Boolean VTSetValues (cur, request, new, args, num_args) + Widget cur, request, new; + ArgList args; + Cardinal *num_args; +{ + XgtermWidget curvt = (XgtermWidget) cur; + XgtermWidget newvt = (XgtermWidget) new; + Boolean refresh_needed = FALSE; + Boolean fonts_redone = FALSE; + + if(curvt->core.background_pixel != newvt->core.background_pixel + || curvt->screen.foreground != newvt->screen.foreground + || curvt->screen.menu_font_names[curvt->screen.menu_font_number] + != newvt->screen.menu_font_names[newvt->screen.menu_font_number] + || curvt->misc.f_n != newvt->misc.f_n) { + if(curvt->misc.f_n != newvt->misc.f_n) + newvt->screen.menu_font_names[fontMenu_fontdefault] = newvt->misc.f_n; + if (LoadNewFont(&newvt->screen, + newvt->screen.menu_font_names[curvt->screen.menu_font_number], + newvt->screen.menu_font_names[curvt->screen.menu_font_number], + TRUE, newvt->screen.menu_font_number)) { + /* resizing does the redisplay, so don't ask for it here */ + refresh_needed = TRUE; + fonts_redone = TRUE; + } else + if(curvt->misc.f_n != newvt->misc.f_n) + newvt->screen.menu_font_names[fontMenu_fontdefault] = curvt->misc.f_n; + } + if(!fonts_redone + && curvt->screen.cursorcolor != newvt->screen.cursorcolor) { + set_cursor_gcs(&newvt->screen); + refresh_needed = TRUE; + } + if(curvt->misc.re_verse != newvt->misc.re_verse) { + newvt->flags ^= REVERSE_VIDEO; + ReverseVideo(newvt); + newvt->misc.re_verse = !newvt->misc.re_verse; /* ReverseVideo toggles */ + refresh_needed = TRUE; + } + if(curvt->screen.mousecolor != newvt->screen.mousecolor + || curvt->screen.mousecolorback != newvt->screen.mousecolorback) { + recolor_cursor (newvt->screen.pointer_cursor, + newvt->screen.mousecolor, + newvt->screen.mousecolorback); + refresh_needed = TRUE; + } + if ((curvt->misc.scrollbar != newvt->misc.scrollbar) && + (curvt->misc.sb_right != newvt->misc.sb_right)) { + if (newvt->misc.scrollbar || newvt->misc.sb_right) { + ScrollBarOn (newvt, FALSE, FALSE); + } else { + ScrollBarOff (&newvt->screen); + } + update_scrollbar(); + } + + return refresh_needed; +} + +/* + * Shows cursor at new cursor position in screen. + */ +ShowCursor() +{ + register TScreen *screen = &term->screen; + register int x, y, flags; + Char c; + GC currentGC; + Boolean in_selection; + + if (eventMode != NORMAL) return; + + if (screen->cur_row - screen->topline > screen->max_row) + return; + c = screen->buf[y = 4 * (screen->cursor_row = screen->cur_row)] + [x = screen->cursor_col = screen->cur_col]; + flags = screen->buf[y + 1][x]; + if (c == 0) + c = ' '; + + if (screen->cur_row > screen->endHRow || + (screen->cur_row == screen->endHRow && + screen->cur_col >= screen->endHCol) || + screen->cur_row < screen->startHRow || + (screen->cur_row == screen->startHRow && + screen->cur_col < screen->startHCol)) + in_selection = False; + else + in_selection = True; + + if(screen->select || screen->always_highlight) { + if (( (flags & INVERSE) && !in_selection) || + (!(flags & INVERSE) && in_selection)){ + /* text is reverse video */ + if (screen->cursorGC) { + currentGC = screen->cursorGC; + } else { + if (flags & BOLD) { + currentGC = screen->normalboldGC; + } else { + currentGC = screen->normalGC; + } + } + } else { /* normal video */ + if (screen->reversecursorGC) { + currentGC = screen->reversecursorGC; + } else { + if (flags & BOLD) { + currentGC = screen->reverseboldGC; + } else { + currentGC = screen->reverseGC; + } + } + } +#if 0 + /*RFB*/ + if ( flags & BG_COLOR ) + XSetForeground( screen->display, currentGC, + screen->colors[ term->cur_background ]); + if ( flags & FG_COLOR ) + XSetBackground( screen->display, currentGC, + screen->colors[ term->cur_foreground ]); + /**********************************************************/ + /* */ + /* we test "flags and background" before calling */ + /* XSetForeground; */ + /* */ + /* it looks funny, but we're in reverse video and the */ + /* color we're setting it to is the current background */ + /* color! */ + /* */ + /**********************************************************/ + /*RFB*/ +#endif + } else { /* not selected */ + if (( (flags & INVERSE) && !in_selection) || + (!(flags & INVERSE) && in_selection)) { + /* text is reverse video */ + currentGC = screen->reverseGC; + } else { /* normal video */ + currentGC = screen->normalGC; + } +#if 0 + /*RFB*/ + if ( flags & FG_COLOR ) + XSetForeground( screen->display, currentGC, + screen->colors[ term->cur_foreground ]); + if ( flags & BG_COLOR ) + XSetBackground( screen->display, currentGC, + screen->colors[ term->cur_background ]); + /*RFB*/ +#endif + } + + x = CursorX (screen, screen->cur_col); + y = CursorY(screen, screen->cur_row) + + screen->fnt_norm->ascent; + XDrawImageString(screen->display, TextWindow(screen), currentGC, + x, y, (char *) &c, 1); + + if((flags & BOLD) && screen->enbolden) /* no bold font */ + XDrawString(screen->display, TextWindow(screen), currentGC, + x + 1, y, (char *) &c, 1); + if((flags & UNDERLINE) && screen->underline) + XDrawLine(screen->display, TextWindow(screen), currentGC, + x, y+1, x + FontWidth(screen), y+1); + if (!screen->select && !screen->always_highlight) { + screen->box->x = x; + screen->box->y = y - screen->fnt_norm->ascent; + XDrawLines (screen->display, TextWindow(screen), + screen->cursoroutlineGC ? screen->cursoroutlineGC + : currentGC, + screen->box, NBOX, CoordModePrevious); + } + screen->cursor_state = ON; +} + +/* + * hide cursor at previous cursor position in screen. + */ +HideCursor() +{ + register TScreen *screen = &term->screen; + GC currentGC; + register int x, y, flags, fg, bg; + register Pixel fg_pix, bg_pix; + char c; + Boolean in_selection; + + if(screen->cursor_row - screen->topline > screen->max_row) + return; + c = screen->buf[y = 4 * screen->cursor_row][x = screen->cursor_col]; + flags = screen->buf[y + 1][x]; + fg = screen->buf[y + 2][x]; + bg = screen->buf[y + 3][x]; + + fg_pix = (flags&FG_COLOR) ? screen->colors[fg] : + screen->foreground; + bg_pix = (flags&BG_COLOR) ? screen->colors[bg] : + term->core.background_pixel; + + if (screen->cursor_row > screen->endHRow || + (screen->cursor_row == screen->endHRow && + screen->cursor_col >= screen->endHCol) || + screen->cursor_row < screen->startHRow || + (screen->cursor_row == screen->startHRow && + screen->cursor_col < screen->startHCol)) + in_selection = False; + else + in_selection = True; + + if (( (flags & INVERSE) && !in_selection) || + (!(flags & INVERSE) && in_selection)) { + if(flags & BOLD) + currentGC = screen->reverseboldGC; + else + currentGC = screen->reverseGC; + if (term->misc.dynamicColors) { + XSetForeground(screen->display, currentGC, bg_pix); + XSetBackground(screen->display, currentGC, fg_pix); + } + } else { + if(flags & BOLD) + currentGC = screen->normalboldGC; + else + currentGC = screen->normalGC; + if (term->misc.dynamicColors) { + XSetForeground(screen->display, currentGC, fg_pix); + XSetBackground(screen->display, currentGC, bg_pix); + } + } + + if (c == 0) + c = ' '; + x = CursorX (screen, screen->cursor_col); + y = (((screen->cursor_row - screen->topline) * FontHeight(screen))) + + screen->border; + y = y+screen->fnt_norm->ascent; + XDrawImageString(screen->display, TextWindow(screen), currentGC, + x, y, &c, 1); + if((flags & BOLD) && screen->enbolden) + XDrawString(screen->display, TextWindow(screen), currentGC, + x + 1, y, &c, 1); + if((flags & UNDERLINE) && screen->underline) + XDrawLine(screen->display, TextWindow(screen), currentGC, + x, y+1, x + FontWidth(screen), y+1); + screen->cursor_state = OFF; +} + +VTReset(full) + Boolean full; +{ + register TScreen *screen = &term->screen; + + /* reset scrolling region */ + screen->top_marg = 0; + screen->bot_marg = screen->max_row; + term->flags &= ~ORIGIN; + if(full) { + TabReset (term->tabs); + term->keyboard.flags = 0; + update_appcursor(); + update_appkeypad(); + screen->gsets[0] = 'B'; + screen->gsets[1] = 'B'; + screen->gsets[2] = 'B'; + screen->gsets[3] = 'B'; + screen->curgl = 0; + screen->curgr = 2; + screen->curss = 0; + FromAlternate(screen); + ClearScreen(screen); + screen->cursor_state = OFF; + if (term->flags & REVERSE_VIDEO) + ReverseVideo(term); + + term->flags = term->initflags; + update_reversevideo(); + update_autowrap(); + update_reversewrap(); + update_autolinefeed(); + screen->jumpscroll = !(term->flags & SMOOTHSCROLL); + update_jumpscroll(); + if(screen->c132 && (term->flags & IN132COLUMNS)) { + Dimension junk; + + if (term->misc.sb_right) { + XtMakeResizeRequest( + (Widget) term, + (Dimension) 80*FontWidth(screen) + + 2 * screen->border, + (Dimension) FontHeight(screen) + * (screen->max_row + 1) + 2 * screen->border, + &junk, &junk); + } else { + XtMakeResizeRequest( + (Widget) term, + (Dimension) 80*FontWidth(screen) + + 2 * screen->border + screen->scrollbar, + (Dimension) FontHeight(screen) + * (screen->max_row + 1) + 2 * screen->border, + &junk, &junk); + } + XSync(screen->display, FALSE); /* synchronize */ + if(XtAppPending(app_con)) + xevents(); + } + CursorSet(screen, 0, 0, term->flags); + } + longjmp(vtjmpbuf, 1); /* force ground state in parser */ +} + + + +/* + * set_character_class - takes a string of the form + * + * low[-high]:val[,low[-high]:val[...]] + * + * and sets the indicated ranges to the indicated values. + */ + +int set_character_class (s) + register char *s; +{ + register int i; /* iterator, index into s */ + int len; /* length of s */ + int acc; /* accumulator */ + int low, high; /* bounds of range [0..127] */ + int base; /* 8, 10, 16 (octal, decimal, hex) */ + int numbers; /* count of numbers per range */ + int digits; /* count of digits in a number */ + static char *errfmt = "%s: %s in range string \"%s\" (position %d)\n"; + extern char *ProgramName; + + if (!s || !s[0]) return -1; + + base = 10; /* in case we ever add octal, hex */ + low = high = -1; /* out of range */ + + for (i = 0, len = strlen (s), acc = 0, numbers = digits = 0; + i < len; i++) { + char c = s[i]; + + if (isspace(c)) { + continue; + } else if (isdigit(c)) { + acc = acc * base + (c - '0'); + digits++; + continue; + } else if (c == '-') { + low = acc; + acc = 0; + if (digits == 0) { + fprintf (stderr, errfmt, ProgramName, "missing number", s, i); + return (-1); + } + digits = 0; + numbers++; + continue; + } else if (c == ':') { + if (numbers == 0) + low = acc; + else if (numbers == 1) + high = acc; + else { + fprintf (stderr, errfmt, ProgramName, "too many numbers", + s, i); + return (-1); + } + digits = 0; + numbers++; + acc = 0; + continue; + } else if (c == ',') { + /* + * now, process it + */ + + if (high < 0) { + high = low; + numbers++; + } + if (numbers != 2) { + fprintf (stderr, errfmt, ProgramName, "bad value number", + s, i); + } else if (SetCharacterClassRange (low, high, acc) != 0) { + fprintf (stderr, errfmt, ProgramName, "bad range", s, i); + } + + low = high = -1; + acc = 0; + digits = 0; + numbers = 0; + continue; + } else { + fprintf (stderr, errfmt, ProgramName, "bad character", s, i); + return (-1); + } /* end if else if ... else */ + + } + + if (low < 0 && high < 0) return (0); + + /* + * now, process it + */ + + if (high < 0) high = low; + if (numbers < 1 || numbers > 2) { + fprintf (stderr, errfmt, ProgramName, "bad value number", s, i); + } else if (SetCharacterClassRange (low, high, acc) != 0) { + fprintf (stderr, errfmt, ProgramName, "bad range", s, i); + } + + return (0); +} + +/* ARGSUSED */ +static void HandleKeymapChange(w, event, params, param_count) + Widget w; + XEvent *event; + String *params; + Cardinal *param_count; +{ + static XtTranslations keymap, original; + static XtResource key_resources[] = { + { XtNtranslations, XtCTranslations, XtRTranslationTable, + sizeof(XtTranslations), 0, XtRTranslationTable, (XtPointer)NULL} + }; + char mapName[1000]; + char mapClass[1000]; + + if (*param_count != 1) return; + + if (original == NULL) original = w->core.tm.translations; + + if (strcmp(params[0], "None") == 0) { + XtOverrideTranslations(w, original); + return; + } + (void) sprintf( mapName, "%sKeymap", params[0] ); + (void) strcpy( mapClass, mapName ); + if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]); + XtGetSubresources( w, (XtPointer)&keymap, mapName, mapClass, + key_resources, (Cardinal)1, NULL, (Cardinal)0 ); + if (keymap != NULL) + XtOverrideTranslations(w, keymap); +} + + +/* ARGSUSED */ +static void HandleBell(w, event, params, param_count) + Widget w; + XEvent *event; /* unused */ + String *params; /* [0] = volume */ + Cardinal *param_count; /* 0 or 1 */ +{ + int percent = (*param_count) ? atoi(params[0]) : 0; + + XBell( XtDisplay(w), percent ); +} + + +/* ARGSUSED */ +static void HandleVisualBell(w, event, params, param_count) + Widget w; + XEvent *event; /* unused */ + String *params; /* unused */ + Cardinal *param_count; /* unused */ +{ + VisualBell(); +} + + +/* ARGSUSED */ +static void HandleIgnore(w, event, params, param_count) + Widget w; + XEvent *event; /* unused */ + String *params; /* unused */ + Cardinal *param_count; /* unused */ +{ + /* do nothing, but check for funny escape sequences */ + (void) SendMousePosition(w, event); +} + + +/* ARGSUSED */ +static void +DoSetSelectedFont(w, client_data, selection, type, value, length, format) + Widget w; + XtPointer client_data; + Atom *selection, *type; + XtPointer value; + unsigned long *length; + int *format; +{ + char *val = (char *)value; + int len; + if (*type != XA_STRING || *format != 8) { + Bell(); + return; + } + len = strlen(val); + if (len > 0) { + if (val[len-1] == '\n') val[len-1] = '\0'; + /* Do some sanity checking to avoid sending a long selection + back to the server in an OpenFont that is unlikely to succeed. + XLFD allows up to 255 characters and no control characters; + we are a little more liberal here. */ + if (len > 1000 || strchr(val, '\n')) + return; + if (!LoadNewFont (&term->screen, val, NULL, True, fontMenu_fontsel)) + Bell(); + } +} + +void FindFontSelection (atom_name, justprobe) + char *atom_name; + Bool justprobe; +{ + static AtomPtr *atoms; + static int atomCount = 0; + AtomPtr *pAtom; + int a; + Atom target; + + if (!atom_name) atom_name = "PRIMARY"; + + for (pAtom = atoms, a = atomCount; a; a--, pAtom++) { + if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) break; + } + if (!a) { + atoms = (AtomPtr*) XtRealloc ((char *)atoms, + sizeof(AtomPtr)*(atomCount+1)); + *(pAtom = &atoms[atomCount++]) = XmuMakeAtom(atom_name); + } + + target = XmuInternAtom(XtDisplay(term), *pAtom); + if (justprobe) { + term->screen.menu_font_names[fontMenu_fontsel] = + XGetSelectionOwner(XtDisplay(term), target) ? _Font_Selected_ : NULL; + } else { + XtGetSelectionValue((Widget)term, target, XA_STRING, + DoSetSelectedFont, NULL, + XtLastTimestampProcessed(XtDisplay(term))); + } + return; +} + + +/* ARGSUSED */ +void HandleSetFont(w, event, params, param_count) + Widget w; + XEvent *event; /* unused */ + String *params; /* unused */ + Cardinal *param_count; /* unused */ +{ + int fontnum; + char *name1 = NULL, *name2 = NULL; + + if (*param_count == 0) { + fontnum = fontMenu_fontdefault; + } else { + int maxparams = 1; /* total number of params allowed */ + + switch (params[0][0]) { + case 'd': case 'D': case '0': + fontnum = fontMenu_fontdefault; break; + case '1': + fontnum = fontMenu_font1; break; + case '2': + fontnum = fontMenu_font2; break; + case '3': + fontnum = fontMenu_font3; break; + case '4': + fontnum = fontMenu_font4; break; + case '5': + fontnum = fontMenu_font5; break; + case '6': + fontnum = fontMenu_font6; break; + case 'e': case 'E': + fontnum = fontMenu_fontescape; maxparams = 3; break; + case 's': case 'S': + fontnum = fontMenu_fontsel; maxparams = 2; break; + default: + Bell(); + return; + } + if (*param_count > maxparams) { /* see if extra args given */ + Bell(); + return; + } + switch (*param_count) { /* assign 'em */ + case 3: + name2 = params[2]; + /* fall through */ + case 2: + name1 = params[1]; + break; + } + } + + SetVTFont (fontnum, True, name1, name2); +} + + +void SetVTFont (i, doresize, name1, name2) + int i; + Bool doresize; + char *name1, *name2; +{ + TScreen *screen = &term->screen; + + if (i < 0 || i >= NMENUFONTS) { + Bell(); + return; + } + if (i == fontMenu_fontsel) { /* go get the selection */ + FindFontSelection (name1, False); /* name1 = atom, name2 is ignored */ + return; + } + if (!name1) name1 = screen->menu_font_names[i]; + if (!LoadNewFont(screen, name1, name2, doresize, i)) { + Bell(); + } + return; +} + + +int LoadNewFont (screen, nfontname, bfontname, doresize, fontnum) + TScreen *screen; + char *nfontname, *bfontname; + Bool doresize; + int fontnum; +{ + XFontStruct *nfs = NULL, *bfs = NULL; + XGCValues xgcv; + unsigned long mask; + GC new_normalGC = NULL, new_normalboldGC = NULL; + GC new_reverseGC = NULL, new_reverseboldGC = NULL; + char *tmpname = NULL; + + if (!nfontname) return 0; + + if (fontnum == fontMenu_fontescape && + nfontname != screen->menu_font_names[fontnum]) { + tmpname = (char *) malloc (strlen(nfontname) + 1); + if (!tmpname) return 0; + strcpy (tmpname, nfontname); + } + + if (!(nfs = XLoadQueryFont (screen->display, nfontname))) goto bad; + if (nfs->ascent + nfs->descent == 0 || nfs->max_bounds.width == 0) + goto bad; /* can't use a 0-sized font */ + + if (!(bfontname && + (bfs = XLoadQueryFont (screen->display, bfontname)))) + bfs = nfs; + else + if (bfs->ascent + bfs->descent == 0 || bfs->max_bounds.width == 0) + goto bad; /* can't use a 0-sized font */ + + mask = (GCFont | GCForeground | GCBackground | GCGraphicsExposures | + GCFunction); + + xgcv.font = nfs->fid; + xgcv.foreground = screen->foreground; + xgcv.background = term->core.background_pixel; + xgcv.graphics_exposures = TRUE; /* default */ + xgcv.function = GXcopy; + + new_normalGC = XtGetGC((Widget)term, mask, &xgcv); + if (!new_normalGC) goto bad; + + if (nfs == bfs) { /* there is no bold font */ + new_normalboldGC = new_normalGC; + } else { + xgcv.font = bfs->fid; + new_normalboldGC = XtGetGC((Widget)term, mask, &xgcv); + if (!new_normalboldGC) goto bad; + } + + xgcv.font = nfs->fid; + xgcv.foreground = term->core.background_pixel; + xgcv.background = screen->foreground; + new_reverseGC = XtGetGC((Widget)term, mask, &xgcv); + if (!new_reverseGC) goto bad; + + if (nfs == bfs) { /* there is no bold font */ + new_reverseboldGC = new_reverseGC; + } else { + xgcv.font = bfs->fid; + new_reverseboldGC = XtGetGC((Widget)term, mask, &xgcv); + if (!new_reverseboldGC) goto bad; + } + + if (screen->normalGC != screen->normalboldGC) + XtReleaseGC ((Widget) term, screen->normalboldGC); + XtReleaseGC ((Widget) term, screen->normalGC); + if (screen->reverseGC != screen->reverseboldGC) + XtReleaseGC ((Widget) term, screen->reverseboldGC); + XtReleaseGC ((Widget) term, screen->reverseGC); + screen->normalGC = new_normalGC; + screen->normalboldGC = new_normalboldGC; + screen->reverseGC = new_reverseGC; + screen->reverseboldGC = new_reverseboldGC; + screen->fnt_norm = nfs; + screen->fnt_bold = bfs; + screen->enbolden = (nfs == bfs); + set_menu_font (False); + screen->menu_font_number = fontnum; + set_menu_font (True); + if (tmpname) { /* if setting escape or sel */ + if (screen->menu_font_names[fontnum]) + free (screen->menu_font_names[fontnum]); + screen->menu_font_names[fontnum] = tmpname; + if (fontnum == fontMenu_fontescape) { + set_sensitivity (term->screen.fontMenu, + fontMenuEntries[fontMenu_fontescape].widget, + TRUE); + } + } + set_cursor_gcs (screen); + update_font_info (screen, doresize); + return 1; + + bad: + if (tmpname) free (tmpname); + if (new_normalGC) + XtReleaseGC ((Widget) term, screen->normalGC); + if (new_normalGC && new_normalGC != new_normalboldGC) + XtReleaseGC ((Widget) term, new_normalboldGC); + if (new_reverseGC) + XtReleaseGC ((Widget) term, new_reverseGC); + if (new_reverseGC && new_reverseGC != new_reverseboldGC) + XtReleaseGC ((Widget) term, new_reverseboldGC); + if (nfs) XFreeFont (screen->display, nfs); + if (bfs && nfs != bfs) XFreeFont (screen->display, bfs); + return 0; +} + +static void +update_font_info (screen, doresize) + TScreen *screen; + Bool doresize; +{ + int i, j, width, height, scrollbar_width; + + screen->fullVwin.f_width = screen->fnt_norm->max_bounds.width; + screen->fullVwin.f_height = (screen->fnt_norm->ascent + + screen->fnt_norm->descent); + scrollbar_width = (term->misc.scrollbar || term->misc.sb_right ? + screen->scrollWidget->core.width + + screen->scrollWidget->core.border_width : 0); + i = 2 * screen->border + scrollbar_width; + j = 2 * screen->border; + width = (screen->max_col + 1) * screen->fullVwin.f_width + i; + height = (screen->max_row + 1) * screen->fullVwin.f_height + j; + screen->fullVwin.fullwidth = width; + screen->fullVwin.fullheight = height; + screen->fullVwin.width = width - i; + screen->fullVwin.height = height - j; + + if (doresize) { + if (VWindow(screen)) { + XClearWindow (screen->display, VWindow(screen)); + } + DoResizeScreen (term); /* set to the new natural size */ + if (screen->scrollWidget) { + if (term->misc.sb_right) + ResizeScrollBar (screen->scrollWidget, + screen->fullVwin.fullwidth - + screen->scrollWidget->core.width - + screen->scrollWidget->core.border_width, 0, + (Height(screen) + screen->border * 2)-1); + else + ResizeScrollBar (screen->scrollWidget, -1, -1, + Height(screen) + screen->border * 2); + } + Redraw (); + } + set_vt_box (screen); +} + +set_vt_box (screen) + TScreen *screen; +{ + XPoint *vp; + + vp = &VTbox[1]; + (vp++)->x = FontWidth(screen) - 1; + (vp++)->y = FontHeight(screen) - 1; + (vp++)->x = -(FontWidth(screen) - 1); + vp->y = -(FontHeight(screen) - 1); + screen->box = VTbox; +} + + +set_cursor_gcs (screen) + TScreen *screen; +{ + XGCValues xgcv; + unsigned long mask; + unsigned long cc = screen->cursorcolor; + unsigned long fg = screen->foreground; + unsigned long bg = term->core.background_pixel; + GC new_cursorGC = NULL, new_reversecursorGC = NULL; + GC new_cursoroutlineGC = NULL; + + /* + * Let's see, there are three things that have "color": + * + * background + * text + * cursorblock + * + * And, there are four situation when drawing a cursor, if we decide + * that we like have a solid block of cursor color with the letter + * that it is highlighting shown in the background color to make it + * stand out: + * + * selected window, normal video - background on cursor + * selected window, reverse video - foreground on cursor + * unselected window, normal video - foreground on background + * unselected window, reverse video - background on foreground + * + * Since the last two are really just normalGC and reverseGC, we only + * need two new GC's. Under monochrome, we get the same effect as + * above by setting cursor color to foreground. + */ + + xgcv.font = screen->fnt_norm->fid; + mask = (GCForeground | GCBackground | GCFont); + if (cc != fg && cc != bg) { + /* we have a colored cursor */ + xgcv.foreground = fg; + xgcv.background = cc; + new_cursorGC = XtGetGC ((Widget) term, mask, &xgcv); + + if (screen->always_highlight) { + new_reversecursorGC = (GC) 0; + new_cursoroutlineGC = (GC) 0; + } else { + xgcv.foreground = bg; + xgcv.background = cc; + new_reversecursorGC = XtGetGC ((Widget) term, mask, &xgcv); + xgcv.foreground = cc; + xgcv.background = bg; + new_cursoroutlineGC = XtGetGC ((Widget) term, mask, &xgcv); + } + } else { + new_cursorGC = (GC) 0; + new_reversecursorGC = (GC) 0; + new_cursoroutlineGC = (GC) 0; + } + if (screen->cursorGC) XtReleaseGC ((Widget)term, screen->cursorGC); + if (screen->reversecursorGC) + XtReleaseGC ((Widget)term, screen->reversecursorGC); + if (screen->cursoroutlineGC) + XtReleaseGC ((Widget)term, screen->cursoroutlineGC); + screen->cursorGC = new_cursorGC; + screen->reversecursorGC = new_reversecursorGC; + screen->cursoroutlineGC = new_cursoroutlineGC; +} |