home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / mxterm.zip / mxterm / charproc.c < prev    next >
C/C++ Source or Header  |  1992-10-17  |  90KB  |  3,220 lines

  1. /*
  2.  * $XConsortium: charproc.c,v 1.176 92/03/13 18:00:30 gildea Exp $
  3.  */
  4.  
  5. /*
  6.  * Copyright 1988 Massachusetts Institute of Technology
  7.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  8.  *
  9.  *                         All Rights Reserved
  10.  *
  11.  * Permission to use, copy, modify, and distribute this software and its
  12.  * documentation for any purpose and without fee is hereby granted,
  13.  * provided that the above copyright notice appear in all copies and that
  14.  * both that copyright notice and this permission notice appear in
  15.  * supporting documentation, and that the name of Digital Equipment
  16.  * Corporation not be used in advertising or publicity pertaining to
  17.  * distribution of the software without specific, written prior permission.
  18.  *
  19.  *
  20.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  21.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  22.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  23.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  25.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  26.  * SOFTWARE.
  27.  */
  28.  
  29. /* charproc.c */
  30.  
  31. #include "ptyx.h"
  32. #include "VTparse.h"
  33. #include "data.h"
  34. #include "error.h"
  35. #include "menu.h"
  36. #include "main.h"
  37. #include <X11/Xos.h>
  38. #include <X11/Xatom.h>
  39. #include <X11/Xutil.h>
  40. #include <X11/cursorfont.h>
  41. #include <X11/StringDefs.h>
  42. #include <X11/Xmu/Atoms.h>
  43. #include <X11/Xmu/CharSet.h>
  44. #include <X11/Xmu/Converters.h>
  45. #include <stdio.h>
  46. #include <errno.h>
  47. #include <setjmp.h>
  48. #include <ctype.h>
  49.  
  50. /*
  51.  * Check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
  52.  * systems are broken and return EWOULDBLOCK when they should return EAGAIN.
  53.  * Note that this macro may evaluate its argument more than once.
  54.  */
  55. #if defined(EAGAIN) && defined(EWOULDBLOCK)
  56. #define E_TEST(err) ((err) == EAGAIN || (err) == EWOULDBLOCK)
  57. #else
  58. #ifdef EAGAIN
  59. #define E_TEST(err) ((err) == EAGAIN)
  60. #else
  61. #define E_TEST(err) ((err) == EWOULDBLOCK)
  62. #endif
  63. #endif
  64.  
  65. extern jmp_buf VTend;
  66.  
  67. extern Widget toplevel;
  68. extern void exit();
  69. extern char *malloc();
  70. extern char *realloc();
  71.  
  72. static void VTallocbuf();
  73. static int finput();
  74. static void dotext();
  75. static void WriteText();
  76.  
  77. static void bitset(), bitclr();
  78.     
  79. #define    DEFAULT        -1
  80. #define    TEXT_BUF_SIZE    256
  81. #define TRACKTIMESEC    4L
  82. #define TRACKTIMEUSEC    0L
  83. #define BELLSUPPRESSMSEC 200
  84.  
  85. #define XtNalwaysHighlight "alwaysHighlight"
  86. #define XtNappcursorDefault "appcursorDefault"
  87. #define XtNappkeypadDefault "appkeypadDefault"
  88. #define XtNbellSuppressTime "bellSuppressTime"
  89. #define XtNboldFont "boldFont"
  90. #define XtNc132 "c132"
  91. #define XtNcharClass "charClass"
  92. #define XtNcurses "curses"
  93. #define XtNcursorColor "cursorColor"
  94. #define XtNcutNewline "cutNewline"
  95. #define XtNcutToBeginningOfLine "cutToBeginningOfLine"
  96. #define XtNeightBitInput "eightBitInput"
  97. #define XtNeightBitOutput "eightBitOutput"
  98. #define XtNgeometry "geometry"
  99. #define XtNtekGeometry "tekGeometry"
  100. #define XtNinternalBorder "internalBorder"
  101. #define XtNjumpScroll "jumpScroll"
  102. #define XtNlogFile "logFile"
  103. #define XtNlogging "logging"
  104. #define XtNlogInhibit "logInhibit"
  105. #define XtNloginShell "loginShell"
  106. #define XtNmarginBell "marginBell"
  107. #define XtNpointerColor "pointerColor"
  108. #define XtNpointerColorBackground "pointerColorBackground"
  109. #define XtNpointerShape "pointerShape"
  110. #define XtNmultiClickTime "multiClickTime"
  111. #define XtNmultiScroll "multiScroll"
  112. #define XtNnMarginBell "nMarginBell"
  113. #define XtNresizeGravity "resizeGravity"
  114. #define XtNreverseWrap "reverseWrap"
  115. #define XtNautoWrap "autoWrap"
  116. #define XtNsaveLines "saveLines"
  117. #define XtNscrollBar "scrollBar"
  118. #define XtNscrollTtyOutput "scrollTtyOutput"
  119. #define XtNscrollKey "scrollKey"
  120. #define XtNscrollLines "scrollLines"
  121. #define XtNscrollPos "scrollPos"
  122. #define XtNsignalInhibit "signalInhibit"
  123. #define XtNtekInhibit "tekInhibit"
  124. #define XtNtekSmall "tekSmall"
  125. #define XtNtekStartup "tekStartup"
  126. #define XtNtiteInhibit "titeInhibit"
  127. #define XtNvisualBell "visualBell"
  128. #define XtNallowSendEvents "allowSendEvents"
  129.  
  130. #define XtCAlwaysHighlight "AlwaysHighlight"
  131. #define XtCAppcursorDefault "AppcursorDefault"
  132. #define XtCAppkeypadDefault "AppkeypadDefault"
  133. #define XtCBellSuppressTime "BellSuppressTime"
  134. #define XtCBoldFont "BoldFont"
  135. #define XtCC132 "C132"
  136. #define XtCCharClass "CharClass"
  137. #define XtCCurses "Curses"
  138. #define XtCCutNewline "CutNewline"
  139. #define XtCCutToBeginningOfLine "CutToBeginningOfLine"
  140. #define XtCEightBitInput "EightBitInput"
  141. #define XtCEightBitOutput "EightBitOutput"
  142. #define XtCGeometry "Geometry"
  143. #define XtCJumpScroll "JumpScroll"
  144. #define XtCLogfile "Logfile"
  145. #define XtCLogging "Logging"
  146. #define XtCLogInhibit "LogInhibit"
  147. #define XtCLoginShell "LoginShell"
  148. #define XtCMarginBell "MarginBell"
  149. #define XtCMultiClickTime "MultiClickTime"
  150. #define XtCMultiScroll "MultiScroll"
  151. #define XtCColumn "Column"
  152. #define XtCResizeGravity "ResizeGravity"
  153. #define XtCReverseWrap "ReverseWrap"
  154. #define XtCAutoWrap "AutoWrap"
  155. #define XtCSaveLines "SaveLines"
  156. #define XtCScrollBar "ScrollBar"
  157. #define XtCScrollLines "ScrollLines"
  158. #define XtCScrollPos "ScrollPos"
  159. #define XtCScrollCond "ScrollCond"
  160. #define XtCSignalInhibit "SignalInhibit"
  161. #define XtCTekInhibit "TekInhibit"
  162. #define XtCTekSmall "TekSmall"
  163. #define XtCTekStartup "TekStartup"
  164. #define XtCTiteInhibit "TiteInhibit"
  165. #define XtCVisualBell "VisualBell"
  166. #define XtCAllowSendEvents "AllowSendEvents"
  167.  
  168. #define    doinput()        (bcnt-- > 0 ? *bptr++ : in_put())
  169.  
  170. static int nparam;
  171. static ANSI reply;
  172. static int param[NPARAM];
  173.  
  174. static unsigned long ctotal;
  175. static unsigned long ntotal;
  176. static jmp_buf vtjmpbuf;
  177.  
  178. extern int groundtable[];
  179. extern int csitable[];
  180. extern int dectable[];
  181. extern int eigtable[];
  182. extern int esctable[];
  183. extern int iestable[];
  184. extern int igntable[];
  185. extern int scrtable[];
  186. extern int scstable[];
  187.  
  188.  
  189. /* event handlers */
  190. extern void HandleKeyPressed(), HandleEightBitKeyPressed();
  191. extern void HandleStringEvent();
  192. extern void HandleEnterWindow();
  193. extern void HandleLeaveWindow();
  194. extern void HandleBellPropertyChange();
  195. extern void HandleFocusChange();
  196. static void HandleKeymapChange();
  197. extern void HandleInsertSelection();
  198. extern void HandleSelectStart(), HandleKeyboardSelectStart();
  199. extern void HandleSelectExtend(), HandleSelectSet();
  200. extern void HandleSelectEnd(), HandleKeyboardSelectEnd();
  201. extern void HandleStartExtend(), HandleKeyboardStartExtend();
  202. static void HandleBell();
  203. static void HandleVisualBell();
  204. static void HandleIgnore();
  205. extern void HandleSecure();
  206. extern void HandleScrollForward();
  207. extern void HandleScrollBack();
  208. extern void HandleCreateMenu(), HandlePopupMenu();
  209. extern void HandleSetFont();
  210. extern void SetVTFont();
  211.  
  212. extern Boolean SendMousePosition();
  213. extern void ScrnSetAttributes();
  214.  
  215. /*
  216.  * NOTE: VTInitialize zeros out the entire ".screen" component of the 
  217.  * XtermWidget, so make sure to add an assignment statement in VTInitialize() 
  218.  * for each new ".screen" field added to this resource list.
  219.  */
  220.  
  221. /* Defaults */
  222. static  Boolean    defaultFALSE       = FALSE;
  223. static  Boolean    defaultTRUE       = TRUE;
  224. static  int    defaultBorderWidth = DEFBORDERWIDTH;
  225. static  int    defaultIntBorder   = DEFBORDER;
  226. static  int    defaultSaveLines   = SAVELINES;
  227. static    int    defaultScrollLines = SCROLLLINES;
  228. static  int    defaultNMarginBell = N_MARGINBELL;
  229. static  int    defaultMultiClickTime = MULTICLICKTIME;
  230. static  int    defaultBellSuppressTime = BELLSUPPRESSMSEC;
  231. static    char *    _Font_Selected_ = "yes";  /* string is arbitrary */
  232.  
  233. /*
  234.  * Warning, the following must be kept under 1024 bytes or else some 
  235.  * compilers (particularly AT&T 6386 SVR3.2) will barf).  Workaround is to
  236.  * declare a static buffer and copy in at run time (the the Athena text widget
  237.  * does).  Yuck.
  238.  */
  239. static char defaultTranslations[] =
  240. "\
  241.  Shift <KeyPress> Prior:scroll-back(1,halfpage) \n\
  242.   Shift <KeyPress> Next:scroll-forw(1,halfpage) \n\
  243. Shift <KeyPress> Select:select-cursor-start() select-cursor-end(PRIMARY, CUT_BUFFER0) \n\
  244. Shift <KeyPress> Insert:insert-selection(PRIMARY, CUT_BUFFER0) \n\
  245.        ~Meta <KeyPress>:insert-seven-bit() \n\
  246.         Meta <KeyPress>:insert-eight-bit() \n\
  247.        !Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
  248.   !Lock Ctrl <Btn1Down>:popup-menu(mainMenu) \n\
  249.        ~Meta <Btn1Down>:select-start() \n\
  250.      ~Meta <Btn1Motion>:select-extend() \n\
  251.        !Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
  252.   !Lock Ctrl <Btn2Down>:popup-menu(vtMenu) \n\
  253.  ~Ctrl ~Meta <Btn2Down>:ignore() \n\
  254.    ~Ctrl ~Meta <Btn2Up>:insert-selection(PRIMARY, CUT_BUFFER0) \n\
  255.        !Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
  256.   !Lock Ctrl <Btn3Down>:popup-menu(fontMenu) \n\
  257.  ~Ctrl ~Meta <Btn3Down>:start-extend() \n\
  258.      ~Meta <Btn3Motion>:select-extend()    \n\
  259.                 <BtnUp>:select-end(PRIMARY, CUT_BUFFER0) \n\
  260.           <BtnDown>:bell(0) \
  261. ";
  262.  
  263. static XtActionsRec actionsList[] = { 
  264.     { "bell",          HandleBell },
  265.     { "create-menu",      HandleCreateMenu },
  266.     { "ignore",          HandleIgnore },
  267.     { "insert",          HandleKeyPressed },  /* alias for insert-seven-bit */
  268.     { "insert-seven-bit", HandleKeyPressed },
  269.     { "insert-eight-bit", HandleEightBitKeyPressed },
  270.     { "insert-selection", HandleInsertSelection },
  271.     { "keymap",       HandleKeymapChange },
  272.     { "popup-menu",      HandlePopupMenu },
  273.     { "secure",          HandleSecure },
  274.     { "select-start",      HandleSelectStart },
  275.     { "select-extend",      HandleSelectExtend },
  276.     { "select-end",      HandleSelectEnd },
  277.     { "select-set",      HandleSelectSet },
  278.     { "select-cursor-start",      HandleKeyboardSelectStart },
  279.     { "select-cursor-end",      HandleKeyboardSelectEnd },
  280.     { "set-vt-font",      HandleSetFont },
  281.     { "start-extend",      HandleStartExtend },
  282.     { "start-cursor-extend",      HandleKeyboardStartExtend },
  283.     { "string",          HandleStringEvent },
  284.     { "scroll-forw",      HandleScrollForward },
  285.     { "scroll-back",      HandleScrollBack },
  286.     /* menu actions */
  287.     { "allow-send-events",    HandleAllowSends },
  288.     { "set-logging",        HandleLogging },
  289.     { "redraw",            HandleRedraw },
  290.     { "send-signal",        HandleSendSignal },
  291.     { "quit",            HandleQuit },
  292.     { "set-scrollbar",        HandleScrollbar },
  293.     { "set-jumpscroll",        HandleJumpscroll },
  294.     { "set-reverse-video",    HandleReverseVideo },
  295.     { "set-autowrap",        HandleAutoWrap },
  296.     { "set-reversewrap",    HandleReverseWrap },
  297.     { "set-autolinefeed",    HandleAutoLineFeed },
  298.     { "set-appcursor",        HandleAppCursor },
  299.     { "set-appkeypad",        HandleAppKeypad },
  300.     { "set-scroll-on-key",    HandleScrollKey },
  301.     { "set-scroll-on-tty-output",    HandleScrollTtyOutput },
  302.     { "set-allow132",        HandleAllow132 },
  303.     { "set-cursesemul",        HandleCursesEmul },
  304.     { "set-marginbell",        HandleMarginBell },
  305.     { "set-altscreen",        HandleAltScreen },
  306.     { "soft-reset",        HandleSoftReset },
  307.     { "hard-reset",        HandleHardReset },
  308.     { "set-terminal-type",    HandleSetTerminalType },
  309.     { "set-visibility",        HandleVisibility },
  310.     { "set-tek-text",        HandleSetTekText },
  311.     { "tek-page",        HandleTekPage },
  312.     { "tek-reset",        HandleTekReset },
  313.     { "tek-copy",        HandleTekCopy },
  314.     { "visual-bell",        HandleVisualBell },
  315. };
  316.  
  317. static XtResource resources[] = {
  318. {XtNfont, XtCFont, XtRString, sizeof(char *),
  319.     XtOffsetOf(XtermWidgetRec, misc.f_n), XtRString,
  320.     DEFFONT},
  321. {XtNboldFont, XtCBoldFont, XtRString, sizeof(char *),
  322.     XtOffsetOf(XtermWidgetRec, misc.f_b), XtRString,
  323.     DEFBOLDFONT},
  324. {XtNc132, XtCC132, XtRBoolean, sizeof(Boolean),
  325.     XtOffsetOf(XtermWidgetRec, screen.c132),
  326.     XtRBoolean, (caddr_t) &defaultFALSE},
  327. {XtNcharClass, XtCCharClass, XtRString, sizeof(char *),
  328.     XtOffsetOf(XtermWidgetRec, screen.charClass),
  329.     XtRString, (caddr_t) NULL},
  330. {XtNcurses, XtCCurses, XtRBoolean, sizeof(Boolean),
  331.     XtOffsetOf(XtermWidgetRec, screen.curses),
  332.     XtRBoolean, (caddr_t) &defaultFALSE},
  333. {XtNcutNewline, XtCCutNewline, XtRBoolean, sizeof(Boolean),
  334.     XtOffsetOf(XtermWidgetRec, screen.cutNewline),
  335.     XtRBoolean, (caddr_t) &defaultTRUE},
  336. {XtNcutToBeginningOfLine, XtCCutToBeginningOfLine, XtRBoolean, sizeof(Boolean),
  337.     XtOffsetOf(XtermWidgetRec, screen.cutToBeginningOfLine),
  338.     XtRBoolean, (caddr_t) &defaultTRUE},
  339. {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
  340.     XtOffsetOf(XtermWidgetRec, core.background_pixel),
  341.     XtRString, "XtDefaultBackground"},
  342. {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  343.     XtOffsetOf(XtermWidgetRec, screen.foreground),
  344.     XtRString, "XtDefaultForeground"},
  345. {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
  346.     XtOffsetOf(XtermWidgetRec, screen.cursorcolor),
  347.     XtRString, "XtDefaultForeground"},
  348. {XtNeightBitInput, XtCEightBitInput, XtRBoolean, sizeof(Boolean),
  349.     XtOffsetOf(XtermWidgetRec, screen.input_eight_bits), 
  350.     XtRBoolean, (caddr_t) &defaultTRUE},
  351. {XtNeightBitOutput, XtCEightBitOutput, XtRBoolean, sizeof(Boolean),
  352.     XtOffsetOf(XtermWidgetRec, screen.output_eight_bits), 
  353.     XtRBoolean, (caddr_t) &defaultTRUE},
  354. {XtNgeometry,XtCGeometry, XtRString, sizeof(char *),
  355.     XtOffsetOf(XtermWidgetRec, misc.geo_metry),
  356.     XtRString, (caddr_t) NULL},
  357. {XtNalwaysHighlight,XtCAlwaysHighlight,XtRBoolean,
  358.         sizeof(Boolean),XtOffsetOf(XtermWidgetRec, screen.always_highlight),
  359.         XtRBoolean, (caddr_t) &defaultFALSE},
  360. {XtNappcursorDefault,XtCAppcursorDefault,XtRBoolean,
  361.         sizeof(Boolean),XtOffsetOf(XtermWidgetRec, misc.appcursorDefault),
  362.         XtRBoolean, (XtPointer) &defaultFALSE},
  363. {XtNappkeypadDefault,XtCAppkeypadDefault,XtRBoolean,
  364.         sizeof(Boolean),XtOffsetOf(XtermWidgetRec, misc.appkeypadDefault),
  365.         XtRBoolean, (XtPointer) &defaultFALSE},
  366. {XtNbellSuppressTime, XtCBellSuppressTime, XtRInt, sizeof(int),
  367.         XtOffsetOf(XtermWidgetRec, screen.bellSuppressTime),
  368.         XtRInt, (XtPointer) &defaultBellSuppressTime},
  369. {XtNtekGeometry,XtCGeometry, XtRString, sizeof(char *),
  370.     XtOffsetOf(XtermWidgetRec, misc.T_geometry),
  371.     XtRString, (caddr_t) NULL},
  372. {XtNinternalBorder,XtCBorderWidth,XtRInt, sizeof(int),
  373.     XtOffsetOf(XtermWidgetRec, screen.border),
  374.     XtRInt, (caddr_t) &defaultIntBorder},
  375. {XtNjumpScroll, XtCJumpScroll, XtRBoolean, sizeof(Boolean),
  376.     XtOffsetOf(XtermWidgetRec, screen.jumpscroll),
  377.     XtRBoolean, (caddr_t) &defaultTRUE},
  378. {XtNlogFile, XtCLogfile, XtRString, sizeof(char *),
  379.     XtOffsetOf(XtermWidgetRec, screen.logfile),
  380.     XtRString, (caddr_t) NULL},
  381. {XtNlogging, XtCLogging, XtRBoolean, sizeof(Boolean),
  382.     XtOffsetOf(XtermWidgetRec, misc.log_on),
  383.     XtRBoolean, (caddr_t) &defaultFALSE},
  384. {XtNlogInhibit, XtCLogInhibit, XtRBoolean, sizeof(Boolean),
  385.     XtOffsetOf(XtermWidgetRec, misc.logInhibit),
  386.     XtRBoolean, (caddr_t) &defaultFALSE},
  387. {XtNloginShell, XtCLoginShell, XtRBoolean, sizeof(Boolean),
  388.     XtOffsetOf(XtermWidgetRec, misc.login_shell),
  389.     XtRBoolean, (caddr_t) &defaultFALSE},
  390. {XtNmarginBell, XtCMarginBell, XtRBoolean, sizeof(Boolean),
  391.     XtOffsetOf(XtermWidgetRec, screen.marginbell),
  392.     XtRBoolean, (caddr_t) &defaultFALSE},
  393. {XtNpointerColor, XtCForeground, XtRPixel, sizeof(Pixel),
  394.     XtOffsetOf(XtermWidgetRec, screen.mousecolor),
  395.     XtRString, "XtDefaultForeground"},
  396. {XtNpointerColorBackground, XtCBackground, XtRPixel, sizeof(Pixel),
  397.     XtOffsetOf(XtermWidgetRec, screen.mousecolorback),
  398.     XtRString, "XtDefaultBackground"},
  399. {XtNpointerShape,XtCCursor, XtRCursor, sizeof(Cursor),
  400.     XtOffsetOf(XtermWidgetRec, screen.pointer_cursor),
  401.     XtRString, (caddr_t) "xterm"},
  402. {XtNmultiClickTime,XtCMultiClickTime, XtRInt, sizeof(int),
  403.     XtOffsetOf(XtermWidgetRec, screen.multiClickTime),
  404.     XtRInt, (caddr_t) &defaultMultiClickTime},
  405. {XtNmultiScroll,XtCMultiScroll, XtRBoolean, sizeof(Boolean),
  406.     XtOffsetOf(XtermWidgetRec, screen.multiscroll),
  407.     XtRBoolean, (caddr_t) &defaultFALSE},
  408. {XtNnMarginBell,XtCColumn, XtRInt, sizeof(int),
  409.     XtOffsetOf(XtermWidgetRec, screen.nmarginbell),
  410.     XtRInt, (caddr_t) &defaultNMarginBell},
  411. {XtNreverseVideo,XtCReverseVideo,XtRBoolean, sizeof(Boolean),
  412.     XtOffsetOf(XtermWidgetRec, misc.re_verse),
  413.     XtRBoolean, (caddr_t) &defaultFALSE},
  414. {XtNresizeGravity, XtCResizeGravity, XtRGravity, sizeof(XtGravity),
  415.     XtOffsetOf(XtermWidgetRec, misc.resizeGravity),
  416.     XtRImmediate, (XtPointer) SouthWestGravity},
  417. {XtNreverseWrap,XtCReverseWrap, XtRBoolean, sizeof(Boolean),
  418.     XtOffsetOf(XtermWidgetRec, misc.reverseWrap),
  419.     XtRBoolean, (caddr_t) &defaultFALSE},
  420. {XtNautoWrap,XtCAutoWrap, XtRBoolean, sizeof(Boolean),
  421.     XtOffsetOf(XtermWidgetRec, misc.autoWrap),
  422.     XtRBoolean, (caddr_t) &defaultTRUE},
  423. {XtNsaveLines, XtCSaveLines, XtRInt, sizeof(int),
  424.     XtOffsetOf(XtermWidgetRec, screen.savelines),
  425.     XtRInt, (caddr_t) &defaultSaveLines},
  426. {XtNscrollBar, XtCScrollBar, XtRBoolean, sizeof(Boolean),
  427.     XtOffsetOf(XtermWidgetRec, misc.scrollbar),
  428.     XtRBoolean, (caddr_t) &defaultFALSE},
  429. {XtNscrollTtyOutput,XtCScrollCond, XtRBoolean, sizeof(Boolean),
  430.     XtOffsetOf(XtermWidgetRec, screen.scrollttyoutput),
  431.     XtRBoolean, (caddr_t) &defaultTRUE},
  432. {XtNscrollKey, XtCScrollCond, XtRBoolean, sizeof(Boolean),
  433.     XtOffsetOf(XtermWidgetRec, screen.scrollkey),
  434.     XtRBoolean, (caddr_t) &defaultFALSE},
  435. {XtNscrollLines, XtCScrollLines, XtRInt, sizeof(int),
  436.     XtOffsetOf(XtermWidgetRec, screen.scrolllines),
  437.     XtRInt, (caddr_t) &defaultScrollLines},
  438. {XtNsignalInhibit,XtCSignalInhibit,XtRBoolean, sizeof(Boolean),
  439.     XtOffsetOf(XtermWidgetRec, misc.signalInhibit),
  440.     XtRBoolean, (caddr_t) &defaultFALSE},
  441. {XtNtekInhibit, XtCTekInhibit, XtRBoolean, sizeof(Boolean),
  442.     XtOffsetOf(XtermWidgetRec, misc.tekInhibit),
  443.     XtRBoolean, (caddr_t) &defaultFALSE},
  444. {XtNtekSmall, XtCTekSmall, XtRBoolean, sizeof(Boolean),
  445.     XtOffsetOf(XtermWidgetRec, misc.tekSmall),
  446.     XtRBoolean, (caddr_t) &defaultFALSE},
  447. {XtNtekStartup, XtCTekStartup, XtRBoolean, sizeof(Boolean),
  448.     XtOffsetOf(XtermWidgetRec, screen.TekEmu),
  449.     XtRBoolean, (caddr_t) &defaultFALSE},
  450. {XtNtiteInhibit, XtCTiteInhibit, XtRBoolean, sizeof(Boolean),
  451.     XtOffsetOf(XtermWidgetRec, misc.titeInhibit),
  452.     XtRBoolean, (caddr_t) &defaultFALSE},
  453. {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof(Boolean),
  454.     XtOffsetOf(XtermWidgetRec, screen.visualbell),
  455.     XtRBoolean, (caddr_t) &defaultFALSE},
  456. {XtNallowSendEvents, XtCAllowSendEvents, XtRBoolean, sizeof(Boolean),
  457.     XtOffsetOf(XtermWidgetRec, screen.allowSendEvents),
  458.     XtRBoolean, (caddr_t) &defaultFALSE},
  459. {"font1", "Font1", XtRString, sizeof(String),
  460.     XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font1]),
  461.     XtRString, (caddr_t) NULL},
  462. {"font2", "Font2", XtRString, sizeof(String),
  463.     XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font2]),
  464.     XtRString, (caddr_t) NULL},
  465. {"font3", "Font3", XtRString, sizeof(String),
  466.     XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font3]),
  467.     XtRString, (caddr_t) NULL},
  468. {"font4", "Font4", XtRString, sizeof(String),
  469.     XtOffsetOf(XtermWidgetRec, screen.menu_font_names[fontMenu_font4]),
  470.     XtRString, (caddr_t) NULL},
  471. };
  472.  
  473. static void VTClassInit();
  474. static void VTInitialize();
  475. static void VTRealize();
  476. static void VTExpose();
  477. static void VTResize();
  478. static void VTDestroy();
  479. static Boolean VTSetValues();
  480.  
  481. static WidgetClassRec xtermClassRec = {
  482.   {
  483. /* core_class fields */    
  484.     /* superclass      */    (WidgetClass) &widgetClassRec,
  485.     /* class_name      */    "VT100",
  486.     /* widget_size      */    sizeof(XtermWidgetRec),
  487.     /* class_initialize   */    VTClassInit,
  488.     /* class_part_initialize */ NULL,
  489.     /* class_inited       */    FALSE,
  490.     /* initialize      */    VTInitialize,
  491.     /* initialize_hook    */    NULL,                
  492.     /* realize          */    VTRealize,
  493.     /* actions          */    actionsList,
  494.     /* num_actions      */    XtNumber(actionsList),
  495.     /* resources      */    resources,
  496.     /* num_resources      */    XtNumber(resources),
  497.     /* xrm_class      */    NULLQUARK,
  498.     /* compress_motion      */    TRUE,
  499.     /* compress_exposure  */    FALSE,
  500.     /* compress_enterleave */   TRUE,
  501.     /* visible_interest      */    FALSE,
  502.     /* destroy          */    VTDestroy,
  503.     /* resize          */    VTResize,
  504.     /* expose          */    VTExpose,
  505.     /* set_values      */    VTSetValues,
  506.     /* set_values_hook    */    NULL,
  507.     /* set_values_almost  */    NULL,
  508.     /* get_values_hook    */    NULL,
  509.     /* accept_focus      */    NULL,
  510.     /* version            */    XtVersion,
  511.     /* callback_offsets   */    NULL,
  512.     /* tm_table           */    defaultTranslations,
  513.     /* query_geometry     */    XtInheritQueryGeometry,
  514.     /* display_accelerator*/    XtInheritDisplayAccelerator,
  515.     /* extension          */    NULL
  516.   }
  517. };
  518.  
  519. WidgetClass xtermWidgetClass = (WidgetClass)&xtermClassRec;
  520.  
  521. static void VTparse()
  522. {
  523.     register TScreen *screen = &term->screen;
  524.     register int *parsestate = groundtable;
  525.     register unsigned int c;
  526.     register unsigned char *cp;
  527.     register int row, col, top, bot, scstype;
  528.     extern int TrackMouse();
  529.  
  530.     if(setjmp(vtjmpbuf))
  531.         parsestate = groundtable;
  532.     for( ; ; ) {
  533.             switch (parsestate[c = doinput()]) {
  534.          case CASE_PRINT:
  535.             /* printable characters */
  536.             top = bcnt > TEXT_BUF_SIZE ? TEXT_BUF_SIZE : bcnt;
  537.             cp = bptr;
  538.             *--bptr = c;
  539.             while(top > 0 && isprint(*cp & 0x7f)) {
  540.                 top--;
  541.                 bcnt--;
  542.                 cp++;
  543.             }
  544.             if(screen->curss) {
  545.                 dotext(screen, term->flags,
  546.                  screen->gsets[screen->curss], bptr, bptr + 1);
  547.                 screen->curss = 0;
  548.                 bptr++;
  549.             }
  550.             if(bptr < cp)
  551.                 dotext(screen, term->flags,
  552.                  screen->gsets[screen->curgl], bptr, cp);
  553.             bptr = cp;
  554.             break;
  555.  
  556.          case CASE_GROUND_STATE:
  557.             /* exit ignore mode */
  558.             parsestate = groundtable;
  559.             break;
  560.  
  561.          case CASE_IGNORE_STATE:
  562.             /* Ies: ignore anything else */
  563.             parsestate = igntable;
  564.             break;
  565.  
  566.          case CASE_IGNORE_ESC:
  567.             /* Ign: escape */
  568.             parsestate = iestable;
  569.             break;
  570.  
  571.          case CASE_IGNORE:
  572.             /* Ignore character */
  573.             break;
  574.  
  575.          case CASE_BELL:
  576.             /* bell */
  577.             Bell();
  578.             break;
  579.  
  580.          case CASE_BS:
  581.             /* backspace */
  582.             CursorBack(screen, 1);
  583.             break;
  584.  
  585.          case CASE_CR:
  586.             /* carriage return */
  587.             CarriageReturn(screen);
  588.             parsestate = groundtable;
  589.             break;
  590.  
  591.          case CASE_ESC:
  592.             /* escape */
  593.             parsestate = esctable;
  594.             break;
  595.  
  596.          case CASE_VMOT:
  597.             /*
  598.              * form feed, line feed, vertical tab
  599.              */
  600.             Index(screen, 1);
  601.             if (term->flags & LINEFEED)
  602.                 CarriageReturn(screen);
  603.             if (QLength(screen->display) > 0 ||
  604.                 GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
  605.               xevents();
  606.             parsestate = groundtable;
  607.             break;
  608.  
  609.          case CASE_TAB:
  610.             /* tab */
  611.             screen->cur_col = TabNext(term->tabs, screen->cur_col);
  612.             if (screen->cur_col > screen->max_col)
  613.                 screen->cur_col = screen->max_col;
  614.             break;
  615.  
  616.          case CASE_SI:
  617.             screen->curgl = 0;
  618.             break;
  619.  
  620.          case CASE_SO:
  621.             screen->curgl = 1;
  622.             break;
  623.  
  624.          case CASE_SCR_STATE:
  625.             /* enter scr state */
  626.             parsestate = scrtable;
  627.             break;
  628.  
  629.          case CASE_SCS0_STATE:
  630.             /* enter scs state 0 */
  631.             scstype = 0;
  632.             parsestate = scstable;
  633.             break;
  634.  
  635.          case CASE_SCS1_STATE:
  636.             /* enter scs state 1 */
  637.             scstype = 1;
  638.             parsestate = scstable;
  639.             break;
  640.  
  641.          case CASE_SCS2_STATE:
  642.             /* enter scs state 2 */
  643.             scstype = 2;
  644.             parsestate = scstable;
  645.             break;
  646.  
  647.          case CASE_SCS3_STATE:
  648.             /* enter scs state 3 */
  649.             scstype = 3;
  650.             parsestate = scstable;
  651.             break;
  652.  
  653.          case CASE_ESC_IGNORE:
  654.             /* unknown escape sequence */
  655.             parsestate = eigtable;
  656.             break;
  657.  
  658.          case CASE_ESC_DIGIT:
  659.             /* digit in csi or dec mode */
  660.             if((row = param[nparam - 1]) == DEFAULT)
  661.                 row = 0;
  662.             param[nparam - 1] = 10 * row + (c - '0');
  663.             break;
  664.  
  665.          case CASE_ESC_SEMI:
  666.             /* semicolon in csi or dec mode */
  667.             param[nparam++] = DEFAULT;
  668.             break;
  669.  
  670.          case CASE_DEC_STATE:
  671.             /* enter dec mode */
  672.             parsestate = dectable;
  673.             break;
  674.  
  675.          case CASE_ICH:
  676.             /* ICH */
  677.             if((row = param[0]) < 1)
  678.                 row = 1;
  679.             InsertChar(screen, row);
  680.             parsestate = groundtable;
  681.             break;
  682.  
  683.          case CASE_CUU:
  684.             /* CUU */
  685.             if((row = param[0]) < 1)
  686.                 row = 1;
  687.             CursorUp(screen, row);
  688.             parsestate = groundtable;
  689.             break;
  690.  
  691.          case CASE_CUD:
  692.             /* CUD */
  693.             if((row = param[0]) < 1)
  694.                 row = 1;
  695.             CursorDown(screen, row);
  696.             parsestate = groundtable;
  697.             break;
  698.  
  699.          case CASE_CUF:
  700.             /* CUF */
  701.             if((row = param[0]) < 1)
  702.                 row = 1;
  703.             CursorForward(screen, row);
  704.             parsestate = groundtable;
  705.             break;
  706.  
  707.          case CASE_CUB:
  708.             /* CUB */
  709.             if((row = param[0]) < 1)
  710.                 row = 1;
  711.             CursorBack(screen, row);
  712.             parsestate = groundtable;
  713.             break;
  714.  
  715.          case CASE_CUP:
  716.             /* CUP | HVP */
  717.             if((row = param[0]) < 1)
  718.                 row = 1;
  719.             if(nparam < 2 || (col = param[1]) < 1)
  720.                 col = 1;
  721.             CursorSet(screen, row-1, col-1, term->flags);
  722.             parsestate = groundtable;
  723.             break;
  724.  
  725.          case CASE_ED:
  726.             /* ED */
  727.             switch (param[0]) {
  728.              case DEFAULT:
  729.              case 0:
  730.                 ClearBelow(screen);
  731.                 break;
  732.  
  733.              case 1:
  734.                 ClearAbove(screen);
  735.                 break;
  736.  
  737.              case 2:
  738.                 ClearScreen(screen);
  739.                 break;
  740.             }
  741.             parsestate = groundtable;
  742.             break;
  743.  
  744.          case CASE_EL:
  745.             /* EL */
  746.             switch (param[0]) {
  747.              case DEFAULT:
  748.              case 0:
  749.                 ClearRight(screen);
  750.                 break;
  751.              case 1:
  752.                 ClearLeft(screen);
  753.                 break;
  754.              case 2:
  755.                 ClearLine(screen);
  756.                 break;
  757.             }
  758.             parsestate = groundtable;
  759.             break;
  760.  
  761.          case CASE_IL:
  762.             /* IL */
  763.             if((row = param[0]) < 1)
  764.                 row = 1;
  765.             InsertLine(screen, row);
  766.             parsestate = groundtable;
  767.             break;
  768.  
  769.          case CASE_DL:
  770.             /* DL */
  771.             if((row = param[0]) < 1)
  772.                 row = 1;
  773.             DeleteLine(screen, row);
  774.             parsestate = groundtable;
  775.             break;
  776.  
  777.          case CASE_DCH:
  778.             /* DCH */
  779.             if((row = param[0]) < 1)
  780.                 row = 1;
  781.             DeleteChar(screen, row);
  782.             parsestate = groundtable;
  783.             break;
  784.  
  785.          case CASE_TRACK_MOUSE:
  786.              /* Track mouse as long as in window and between
  787.                specified rows */
  788.             TrackMouse(param[0], param[2]-1, param[1]-1,
  789.              param[3]-1, param[4]-2);
  790.             break;
  791.  
  792.          case CASE_DECID:
  793.             param[0] = -1;        /* Default ID parameter */
  794.             /* Fall through into ... */
  795.          case CASE_DA1:
  796.             /* DA1 */
  797.             if (param[0] <= 0) {    /* less than means DEFAULT */
  798.                 reply.a_type   = CSI;
  799.                 reply.a_pintro = '?';
  800.                 reply.a_nparam = 2;
  801.                 reply.a_param[0] = 1;        /* VT102 */
  802.                 reply.a_param[1] = 2;        /* VT102 */
  803.                 reply.a_inters = 0;
  804.                 reply.a_final  = 'c';
  805.                 unparseseq(&reply, screen->respond);
  806.             }
  807.             parsestate = groundtable;
  808.             break;
  809.  
  810.          case CASE_TBC:
  811.             /* TBC */
  812.             if ((row = param[0]) <= 0) /* less than means default */
  813.                 TabClear(term->tabs, screen->cur_col);
  814.             else if (row == 3)
  815.                 TabZonk(term->tabs);
  816.             parsestate = groundtable;
  817.             break;
  818.  
  819.          case CASE_SET:
  820.             /* SET */
  821.             ansi_modes(term, bitset);
  822.             parsestate = groundtable;
  823.             break;
  824.  
  825.          case CASE_RST:
  826.             /* RST */
  827.             ansi_modes(term, bitclr);
  828.             parsestate = groundtable;
  829.             break;
  830.  
  831.          case CASE_SGR:
  832.             /* SGR */
  833.             for (row=0; row<nparam; ++row) {
  834.                 switch (param[row]) {
  835.                  case DEFAULT:
  836.                  case 0:
  837.                     term->flags &= ~(INVERSE|BOLD|UNDERLINE);
  838.                     break;
  839.                  case 1:
  840.                  case 5:    /* Blink, really.    */
  841.                     term->flags |= BOLD;
  842.                     break;
  843.                  case 4:    /* Underscore        */
  844.                     term->flags |= UNDERLINE;
  845.                     break;
  846.                  case 7:
  847.                     term->flags |= INVERSE;
  848.                 }
  849.             }
  850.             parsestate = groundtable;
  851.             break;
  852.  
  853.          case CASE_CPR:
  854.             /* CPR */
  855.             if ((row = param[0]) == 5) {
  856.                 reply.a_type = CSI;
  857.                 reply.a_pintro = 0;
  858.                 reply.a_nparam = 1;
  859.                 reply.a_param[0] = 0;
  860.                 reply.a_inters = 0;
  861.                 reply.a_final  = 'n';
  862.                 unparseseq(&reply, screen->respond);
  863.             } else if (row == 6) {
  864.                 reply.a_type = CSI;
  865.                 reply.a_pintro = 0;
  866.                 reply.a_nparam = 2;
  867.                 reply.a_param[0] = screen->cur_row+1;
  868.                 reply.a_param[1] = screen->cur_col+1;
  869.                 reply.a_inters = 0;
  870.                 reply.a_final  = 'R';
  871.                 unparseseq(&reply, screen->respond);
  872.             }
  873.             parsestate = groundtable;
  874.             break;
  875.  
  876.          case CASE_DECSTBM:
  877.             /* DECSTBM - set scrolling region */
  878.             if((top = param[0]) < 1)
  879.                 top = 1;
  880.             if(nparam < 2 || (bot = param[1]) == DEFAULT
  881.                || bot > screen->max_row + 1
  882.                || bot == 0)
  883.                 bot = screen->max_row+1;
  884.             if (bot > top) {
  885.                 if(screen->scroll_amt)
  886.                     FlushScroll(screen);
  887.                 screen->top_marg = top-1;
  888.                 screen->bot_marg = bot-1;
  889.                 CursorSet(screen, 0, 0, term->flags);
  890.             }
  891.             parsestate = groundtable;
  892.             break;
  893.  
  894.          case CASE_DECREQTPARM:
  895.             /* DECREQTPARM */
  896.             if ((row = param[0]) == DEFAULT)
  897.                 row = 0;
  898.             if (row == 0 || row == 1) {
  899.                 reply.a_type = CSI;
  900.                 reply.a_pintro = 0;
  901.                 reply.a_nparam = 7;
  902.                 reply.a_param[0] = row + 2;
  903.                 reply.a_param[1] = 1;    /* no parity */
  904.                 reply.a_param[2] = 1;    /* eight bits */
  905.                 reply.a_param[3] = 112;    /* transmit 9600 baud */
  906.                 reply.a_param[4] = 112;    /* receive 9600 baud */
  907.                 reply.a_param[5] = 1;    /* clock multiplier ? */
  908.                 reply.a_param[6] = 0;    /* STP flags ? */
  909.                 reply.a_inters = 0;
  910.                 reply.a_final  = 'x';
  911.                 unparseseq(&reply, screen->respond);
  912.             }
  913.             parsestate = groundtable;
  914.             break;
  915.  
  916.          case CASE_DECSET:
  917.             /* DECSET */
  918.             dpmodes(term, bitset);
  919.             parsestate = groundtable;
  920.             if(screen->TekEmu)
  921.                 return;
  922.             break;
  923.  
  924.          case CASE_DECRST:
  925.             /* DECRST */
  926.             dpmodes(term, bitclr);
  927.             parsestate = groundtable;
  928.             break;
  929.  
  930.          case CASE_DECALN:
  931.             /* DECALN */
  932.             if(screen->cursor_state)
  933.                 HideCursor();
  934.             for(row = screen->max_row ; row >= 0 ; row--) {
  935.                 bzero(screen->buf[2 * row + 1],
  936.                  col = screen->max_col + 1);
  937.                 for(cp = (unsigned char *)screen->buf[2 * row] ; col > 0 ; col--)
  938.                     *cp++ = (unsigned char) 'E';
  939.             }
  940.             ScrnRefresh(screen, 0, 0, screen->max_row + 1,
  941.              screen->max_col + 1, False);
  942.             parsestate = groundtable;
  943.             break;
  944.  
  945.          case CASE_GSETS:
  946.             screen->gsets[scstype] = c;
  947.             parsestate = groundtable;
  948.             break;
  949.  
  950.          case CASE_DECSC:
  951.             /* DECSC */
  952.             CursorSave(term, &screen->sc);
  953.             parsestate = groundtable;
  954.             break;
  955.  
  956.          case CASE_DECRC:
  957.             /* DECRC */
  958.             CursorRestore(term, &screen->sc);
  959.             parsestate = groundtable;
  960.             break;
  961.  
  962.          case CASE_DECKPAM:
  963.             /* DECKPAM */
  964.             term->keyboard.flags |= KYPD_APL;
  965.             update_appkeypad();
  966.             parsestate = groundtable;
  967.             break;
  968.  
  969.          case CASE_DECKPNM:
  970.             /* DECKPNM */
  971.             term->keyboard.flags &= ~KYPD_APL;
  972.             update_appkeypad();
  973.             parsestate = groundtable;
  974.             break;
  975.  
  976.          case CASE_IND:
  977.             /* IND */
  978.             Index(screen, 1);
  979.             if (QLength(screen->display) > 0 ||
  980.                 GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
  981.               xevents();
  982.             parsestate = groundtable;
  983.             break;
  984.  
  985.          case CASE_NEL:
  986.             /* NEL */
  987.             Index(screen, 1);
  988.             CarriageReturn(screen);
  989.             
  990.             if (QLength(screen->display) > 0 ||
  991.                 GetBytesAvailable (ConnectionNumber(screen->display)) > 0)
  992.               xevents();
  993.             parsestate = groundtable;
  994.             break;
  995.  
  996.          case CASE_HTS:
  997.             /* HTS */
  998.             TabSet(term->tabs, screen->cur_col);
  999.             parsestate = groundtable;
  1000.             break;
  1001.  
  1002.          case CASE_RI:
  1003.             /* RI */
  1004.             RevIndex(screen, 1);
  1005.             parsestate = groundtable;
  1006.             break;
  1007.  
  1008.          case CASE_SS2:
  1009.             /* SS2 */
  1010.             screen->curss = 2;
  1011.             parsestate = groundtable;
  1012.             break;
  1013.  
  1014.          case CASE_SS3:
  1015.             /* SS3 */
  1016.             screen->curss = 3;
  1017.             parsestate = groundtable;
  1018.             break;
  1019.  
  1020.          case CASE_CSI_STATE:
  1021.             /* enter csi state */
  1022.             nparam = 1;
  1023.             param[0] = DEFAULT;
  1024.             parsestate = csitable;
  1025.             break;
  1026.  
  1027.          case CASE_OSC:
  1028.             /* Operating System Command: ESC ] */
  1029.             do_osc(finput);
  1030.             parsestate = groundtable;
  1031.             break;
  1032.  
  1033.          case CASE_RIS:
  1034.             /* RIS */
  1035.             VTReset(TRUE);
  1036.             parsestate = groundtable;
  1037.             break;
  1038.  
  1039.          case CASE_LS2:
  1040.             /* LS2 */
  1041.             screen->curgl = 2;
  1042.             parsestate = groundtable;
  1043.             break;
  1044.  
  1045.          case CASE_LS3:
  1046.             /* LS3 */
  1047.             screen->curgl = 3;
  1048.             parsestate = groundtable;
  1049.             break;
  1050.  
  1051.          case CASE_LS3R:
  1052.             /* LS3R */
  1053.             screen->curgr = 3;
  1054.             parsestate = groundtable;
  1055.             break;
  1056.  
  1057.          case CASE_LS2R:
  1058.             /* LS2R */
  1059.             screen->curgr = 2;
  1060.             parsestate = groundtable;
  1061.             break;
  1062.  
  1063.          case CASE_LS1R:
  1064.             /* LS1R */
  1065.             screen->curgr = 1;
  1066.             parsestate = groundtable;
  1067.             break;
  1068.  
  1069.          case CASE_XTERM_SAVE:
  1070.             savemodes(term);
  1071.             parsestate = groundtable;
  1072.             break;
  1073.  
  1074.          case CASE_XTERM_RESTORE:
  1075.             restoremodes(term);
  1076.             parsestate = groundtable;
  1077.             break;
  1078.         }
  1079.     }
  1080. }
  1081.  
  1082. static finput()
  1083. {
  1084.     return(doinput());
  1085. }
  1086.  
  1087.  
  1088. static char *v_buffer;        /* pointer to physical buffer */
  1089. static char *v_bufstr = NULL;    /* beginning of area to write */
  1090. static char *v_bufptr;        /* end of area to write */
  1091. static char *v_bufend;        /* end of physical buffer */
  1092. #define    ptymask()    (v_bufptr > v_bufstr ? pty_mask : 0)
  1093.  
  1094. /* Write data to the pty as typed by the user, pasted with the mouse,
  1095.    or generated by us in response to a query ESC sequence. */
  1096.  
  1097. v_write(f, d, len)
  1098.     int f;
  1099.     char *d;
  1100.     int len;
  1101. {
  1102.     int riten;
  1103.     int c = len;
  1104.  
  1105.     if (v_bufstr == NULL  &&  len > 0) {
  1106.             v_buffer = XtMalloc(len);
  1107.         v_bufstr = v_buffer;
  1108.         v_bufptr = v_buffer;
  1109.         v_bufend = v_buffer + len;
  1110.     }
  1111. #ifdef DEBUG
  1112.     fprintf(stderr, "v_write called with %d bytes (%d left over)",
  1113.         len, v_bufptr - v_bufstr);
  1114.     if (len > 1  &&  len < 10) fprintf(stderr, " \"%.*s\"", len, d);
  1115.     fprintf(stderr, "\n");
  1116. #endif
  1117.  
  1118.     if ((1 << f) != pty_mask)
  1119.         return(write(f, d, len));
  1120.  
  1121.     /*
  1122.      * Append to the block we already have.
  1123.      * Always doing this simplifies the code, and
  1124.      * isn't too bad, either.  If this is a short
  1125.      * block, it isn't too expensive, and if this is
  1126.      * a long block, we won't be able to write it all
  1127.      * anyway.
  1128.      */
  1129.  
  1130.     if (len > 0) {
  1131.         if (v_bufend < v_bufptr + len) { /* we've run out of room */
  1132.         if (v_bufstr != v_buffer) {
  1133.             /* there is unused space, move everything down */
  1134.             /* possibly overlapping bcopy here */
  1135. #ifdef DEBUG
  1136.             fprintf(stderr, "moving data down %d\n",
  1137.                 v_bufstr - v_buffer);
  1138. #endif
  1139.             bcopy(v_bufstr, v_buffer, v_bufptr - v_bufstr);
  1140.             v_bufptr -= v_bufstr - v_buffer;
  1141.             v_bufstr = v_buffer;
  1142.         }
  1143.         if (v_bufend < v_bufptr + len) {
  1144.             /* still won't fit: get more space */
  1145.             /* Don't use XtRealloc because an error is not fatal. */
  1146.             int size = v_bufptr - v_buffer; /* save across realloc */
  1147.             v_buffer = realloc(v_buffer, size + len);
  1148.             if (v_buffer) {
  1149. #ifdef DEBUG
  1150.             fprintf(stderr, "expanded buffer to %d\n",
  1151.                 size + len);
  1152. #endif
  1153.             v_bufstr = v_buffer;
  1154.             v_bufptr = v_buffer + size;
  1155.             v_bufend = v_bufptr + len;
  1156.             } else {
  1157.             /* no memory: ignore entire write request */
  1158.             fprintf(stderr, "%s: cannot allocate buffer space\n",
  1159.                 xterm_name);
  1160.             v_buffer = v_bufstr; /* restore clobbered pointer */
  1161.             c = 0;
  1162.             }
  1163.         }
  1164.         }
  1165.         if (v_bufend >= v_bufptr + len) {
  1166.         /* new stuff will fit */
  1167.         bcopy(d, v_bufptr, len);
  1168.         v_bufptr += len;
  1169.         }
  1170.     }
  1171.  
  1172.     /*
  1173.      * Write out as much of the buffer as we can.
  1174.      * Be careful not to overflow the pty's input silo.
  1175.      * We are conservative here and only write
  1176.      * a small amount at a time.
  1177.      *
  1178.      * If we can't push all the data into the pty yet, we expect write
  1179.      * to return a non-negative number less than the length requested
  1180.      * (if some data written) or -1 and set errno to EAGAIN,
  1181.      * EWOULDBLOCK, or EINTR (if no data written).
  1182.      *
  1183.      * (Not all systems do this, sigh, so the code is actually
  1184.      * a little more forgiving.)
  1185.      */
  1186.  
  1187. #define MAX_PTY_WRITE 128    /* 1/2 POSIX minimum MAX_INPUT */
  1188.  
  1189.     if (v_bufptr > v_bufstr) {
  1190.         riten = write(f, v_bufstr, v_bufptr - v_bufstr <= MAX_PTY_WRITE ?
  1191.                          v_bufptr - v_bufstr : MAX_PTY_WRITE);
  1192.         if (riten < 0) {
  1193. #ifdef DEBUG
  1194.         perror("write");
  1195. #endif
  1196.         riten = 0;
  1197.         }
  1198. #ifdef DEBUG
  1199.         fprintf(stderr, "write called with %d, wrote %d\n",
  1200.             v_bufptr - v_bufstr <= MAX_PTY_WRITE ?
  1201.             v_bufptr - v_bufstr : MAX_PTY_WRITE,
  1202.             riten);
  1203. #endif
  1204.         v_bufstr += riten;
  1205.         if (v_bufstr >= v_bufptr) /* we wrote it all */
  1206.         v_bufstr = v_bufptr = v_buffer;
  1207.     }
  1208.  
  1209.     /*
  1210.      * If we have lots of unused memory allocated, return it
  1211.      */
  1212.     if (v_bufend - v_bufptr > 1024) { /* arbitrary hysteresis */
  1213.         /* save pointers across realloc */
  1214.         int start = v_bufstr - v_buffer;
  1215.         int size = v_bufptr - v_buffer;
  1216.         int allocsize = size ? size : 1;
  1217.         
  1218.         v_buffer = realloc(v_buffer, allocsize);
  1219.         if (v_buffer) {
  1220.         v_bufstr = v_buffer + start;
  1221.         v_bufptr = v_buffer + size;
  1222.         v_bufend = v_buffer + allocsize;
  1223. #ifdef DEBUG
  1224.         fprintf(stderr, "shrunk buffer to %d\n", allocsize);
  1225. #endif
  1226.         } else {
  1227.         /* should we print a warning if couldn't return memory? */
  1228.         v_buffer = v_bufstr - start; /* restore clobbered pointer */
  1229.         }
  1230.     }
  1231.     return(c);
  1232. }
  1233.  
  1234. static int select_mask;
  1235. static int write_mask;
  1236. static int pty_read_bytes;
  1237.  
  1238. in_put()
  1239. {
  1240.     register TScreen *screen = &term->screen;
  1241.     register int i;
  1242.     static struct timeval select_timeout;
  1243.  
  1244.     for( ; ; ) {
  1245.     if (select_mask & pty_mask && eventMode == NORMAL) {
  1246.         if (screen->logging)
  1247.         FlushLog(screen);
  1248.         bcnt = read(screen->respond, (char *)(bptr = buffer), BUF_SIZE);
  1249.         if (bcnt < 0) {
  1250.         if (errno == EIO)
  1251.             Cleanup (0);
  1252.         else if (!E_TEST(errno))
  1253.             Panic(
  1254.               "input: read returned unexpected error (%d)\n",
  1255.               errno);
  1256.         } else if (bcnt == 0)
  1257.         Panic("input: read returned zero\n", 0);
  1258.         else {
  1259.         /* read from pty was successful */
  1260.         if (!screen->output_eight_bits) {
  1261.             register int bc = bcnt;
  1262.             register Char *b = bptr;
  1263.  
  1264.             for (; bc > 0; bc--, b++) {
  1265.             *b &= (Char) 0x7f;
  1266.             }
  1267.         }
  1268.         if ( screen->scrollWidget && screen->scrollttyoutput &&
  1269.              screen->topline < 0)
  1270.             WindowScroll(screen, 0);  /* Scroll to bottom */
  1271.         pty_read_bytes += bcnt;
  1272.         /* stop speed reading at some point to look for X stuff */
  1273.         /* (4096 is just a random large number.) */
  1274.         if (pty_read_bytes > 4096) {
  1275.             select_mask &= ~pty_mask;
  1276.         }
  1277.         break;
  1278.         }
  1279.     }
  1280.     pty_read_bytes = 0;
  1281.     /* update the screen */
  1282.     if (screen->scroll_amt)
  1283.         FlushScroll(screen);
  1284.     if (screen->cursor_set && (screen->cursor_col != screen->cur_col
  1285.                    || screen->cursor_row != screen->cur_row)) {
  1286.         if (screen->cursor_state)
  1287.         HideCursor();
  1288.         ShowCursor();
  1289.     } else if (screen->cursor_set != screen->cursor_state) {
  1290.         if (screen->cursor_set)
  1291.         ShowCursor();
  1292.         else
  1293.         HideCursor();
  1294.     }
  1295.  
  1296.     XFlush(screen->display); /* always flush writes before waiting */
  1297.  
  1298.     /* Update the masks and, unless X events are already in the queue,
  1299.        wait for I/O to be possible. */
  1300.     select_mask = Select_mask;
  1301.     write_mask = ptymask();
  1302.     select_timeout.tv_sec = 0;
  1303.     select_timeout.tv_usec = 0;
  1304.     i = select(max_plus1, &select_mask, &write_mask, (int *)NULL,
  1305.            QLength(screen->display) ? &select_timeout
  1306.            : (struct timeval *) NULL);
  1307.     if (i < 0) {
  1308.         if (errno != EINTR)
  1309.         SysError(ERROR_SELECT);
  1310.         continue;
  1311.     } 
  1312.  
  1313.     /* if there is room to write more data to the pty, go write more */
  1314.     if (write_mask & ptymask()) {
  1315.         v_write(screen->respond, 0, 0); /* flush buffer */
  1316.     }
  1317.  
  1318.     /* if there are X events already in our queue, it
  1319.        counts as being readable */
  1320.     if (QLength(screen->display) || (select_mask & X_mask)) {
  1321.         xevents();
  1322.     }
  1323.  
  1324.     }
  1325.     bcnt--;
  1326.     return(*bptr++);
  1327. }
  1328.  
  1329. /*
  1330.  * process a string of characters according to the character set indicated
  1331.  * by charset.  worry about end of line conditions (wraparound if selected).
  1332.  */
  1333. static void
  1334. dotext(screen, flags, charset, buf, ptr)
  1335.     register TScreen    *screen;
  1336.     unsigned    flags;
  1337.     char    charset;
  1338.     char    *buf;        /* start of characters to process */
  1339.     char    *ptr;        /* end */
  1340. {
  1341.     register char    *s;
  1342.     register int    len;
  1343.     register int    n;
  1344.     register int    next_col;
  1345.  
  1346.     switch (charset) {
  1347.     case 'A':    /* United Kingdom set            */
  1348.         for (s=buf; s<ptr; ++s)
  1349.             if (*s == '#')
  1350.                 *s = '\036';    /* UK pound sign*/
  1351.         break;
  1352.  
  1353.     case 'B':    /* ASCII set                */
  1354.         break;
  1355.  
  1356.     case '0':    /* special graphics (line drawing)    */
  1357.         for (s=buf; s<ptr; ++s)
  1358.             if (*s>=0x5f && *s<=0x7e)
  1359.                 *s = *s == 0x5f ? 0x7f : *s - 0x5f;
  1360.         break;
  1361.  
  1362.     default:    /* any character sets we don't recognize*/
  1363.         return;
  1364.     }
  1365.  
  1366.     len = ptr - buf; 
  1367.     ptr = buf;
  1368.     while (len > 0) {
  1369.         n = screen->max_col - screen->cur_col +1;
  1370.         if (n <= 1) {
  1371.             if (screen->do_wrap && (flags&WRAPAROUND)) {
  1372.                 /* mark that we had to wrap this line */
  1373.                 ScrnSetAttributes(screen, screen->cur_row, 0,
  1374.                           LINEWRAPPED, LINEWRAPPED, 1);
  1375.                 Index(screen, 1);
  1376.                 screen->cur_col = 0;
  1377.                 screen->do_wrap = 0;
  1378.                 n = screen->max_col+1;
  1379.             } else
  1380.                 n = 1;
  1381.         }
  1382.         if (len < n)
  1383.             n = len;
  1384.         next_col = screen->cur_col + n;
  1385.         WriteText(screen, ptr, n, flags);
  1386.         /*
  1387.          * the call to WriteText updates screen->cur_col.
  1388.          * If screen->cur_col != next_col, we must have
  1389.          * hit the right margin, so set the do_wrap flag.
  1390.          */
  1391.         screen->do_wrap = (screen->cur_col < next_col);
  1392.         len -= n;
  1393.         ptr += n;
  1394.     }
  1395. }
  1396.  
  1397. /*
  1398.  * write a string str of length len onto the screen at
  1399.  * the current cursor position.  update cursor position.
  1400.  */
  1401. static void
  1402. WriteText(screen, str, len, flags)
  1403.     register TScreen    *screen;
  1404.     register char    *str;
  1405.     register int    len;
  1406.     unsigned        flags;
  1407. {
  1408.     register int cx, cy;
  1409.     register unsigned fgs = flags;
  1410.     GC    currentGC;
  1411.  
  1412.    if(screen->cur_row - screen->topline <= screen->max_row) {
  1413.     /*
  1414.     if(screen->cur_row == screen->cursor_row && screen->cur_col <=
  1415.      screen->cursor_col && screen->cursor_col <= screen->cur_col + len - 1)
  1416.         screen->cursor_state = OFF;
  1417.      */
  1418.     if(screen->cursor_state)
  1419.         HideCursor();
  1420.  
  1421.     /*
  1422.      *    make sure that the correct GC is current
  1423.      */
  1424.  
  1425.     if (fgs & BOLD)
  1426.         if (fgs & INVERSE)
  1427.             currentGC = screen->reverseboldGC;
  1428.         else    currentGC = screen->normalboldGC;
  1429.     else  /* not bold */
  1430.         if (fgs & INVERSE)
  1431.             currentGC = screen->reverseGC;
  1432.         else    currentGC = screen->normalGC;
  1433.  
  1434.     if (fgs & INSERT)
  1435.         InsertChar(screen, len);
  1436.       if (!(AddToRefresh(screen))) {
  1437.         if(screen->scroll_amt)
  1438.             FlushScroll(screen);
  1439.     cx = CursorX(screen, screen->cur_col);
  1440.     cy = CursorY(screen, screen->cur_row)+screen->fnt_norm->ascent;
  1441.      XDrawImageString(screen->display, TextWindow(screen), currentGC,
  1442.             cx, cy, str, len);
  1443.  
  1444.     if((fgs & BOLD) && screen->enbolden) 
  1445.         if (currentGC == screen->normalGC || screen->reverseGC)
  1446.             XDrawString(screen->display, TextWindow(screen),
  1447.                       currentGC,cx + 1, cy, str, len);
  1448.  
  1449.     if(fgs & UNDERLINE) 
  1450.         XDrawLine(screen->display, TextWindow(screen), currentGC,
  1451.             cx, cy+1,
  1452.             cx + len * FontWidth(screen), cy+1);
  1453.     /*
  1454.      * the following statements compile data to compute the average 
  1455.      * number of characters written on each call to XText.  The data
  1456.      * may be examined via the use of a "hidden" escape sequence.
  1457.      */
  1458.     ctotal += len;
  1459.     ++ntotal;
  1460.       }
  1461.     }
  1462.     ScreenWrite(screen, str, flags, len);
  1463.     CursorForward(screen, len);
  1464. }
  1465.  
  1466. /*
  1467.  * process ANSI modes set, reset
  1468.  */
  1469. ansi_modes(termw, func)
  1470.     XtermWidget    termw;
  1471.     int        (*func)();
  1472. {
  1473.     register int    i;
  1474.  
  1475.     for (i=0; i<nparam; ++i) {
  1476.         switch (param[i]) {
  1477.         case 4:            /* IRM                */
  1478.             (*func)(&termw->flags, INSERT);
  1479.             break;
  1480.  
  1481.         case 20:        /* LNM                */
  1482.             (*func)(&termw->flags, LINEFEED);
  1483.             update_autolinefeed();
  1484.             break;
  1485.         }
  1486.     }
  1487. }
  1488.  
  1489. /*
  1490.  * process DEC private modes set, reset
  1491.  */
  1492. dpmodes(termw, func)
  1493.     XtermWidget    termw;
  1494.     void (*func)();
  1495. {
  1496.     register TScreen    *screen    = &termw->screen;
  1497.     register int    i, j;
  1498.  
  1499.     for (i=0; i<nparam; ++i) {
  1500.         switch (param[i]) {
  1501.         case 1:            /* DECCKM            */
  1502.             (*func)(&termw->keyboard.flags, CURSOR_APL);
  1503.             update_appcursor();
  1504.             break;
  1505.         case 2:            /* ANSI/VT52 mode        */
  1506.             if (func == bitset) {
  1507.                 screen->gsets[0] =
  1508.                     screen->gsets[1] =
  1509.                     screen->gsets[2] =
  1510.                     screen->gsets[3] = 'B';
  1511.                 screen->curgl = 0;
  1512.                 screen->curgr = 2;
  1513.             }
  1514.             break;
  1515.         case 3:            /* DECCOLM            */
  1516.             if(screen->c132) {
  1517.                 ClearScreen(screen);
  1518.                 CursorSet(screen, 0, 0, termw->flags);
  1519.                 if((j = func == bitset ? 132 : 80) !=
  1520.                  ((termw->flags & IN132COLUMNS) ? 132 : 80) ||
  1521.                  j != screen->max_col + 1) {
  1522.                         Dimension replyWidth, replyHeight;
  1523.                     XtGeometryResult status;
  1524.  
  1525.                     status = XtMakeResizeRequest (
  1526.                         (Widget) termw, 
  1527.                         (Dimension) FontWidth(screen) * j
  1528.                             + 2*screen->border
  1529.                         + screen->scrollbar,
  1530.                         (Dimension) FontHeight(screen)
  1531.                         * (screen->max_row + 1)
  1532.                         + 2 * screen->border,
  1533.                         &replyWidth, &replyHeight);
  1534.  
  1535.                     if (status == XtGeometryYes ||
  1536.                         status == XtGeometryDone) {
  1537.                         ScreenResize (&termw->screen,
  1538.                               replyWidth,
  1539.                               replyHeight,
  1540.                               &termw->flags);
  1541.                     }
  1542.                 }
  1543.                 (*func)(&termw->flags, IN132COLUMNS);
  1544.             }
  1545.             break;
  1546.         case 4:            /* DECSCLM (slow scroll)    */
  1547.             if (func == bitset) {
  1548.                 screen->jumpscroll = 0;
  1549.                 if (screen->scroll_amt)
  1550.                     FlushScroll(screen);
  1551.             } else
  1552.                 screen->jumpscroll = 1;
  1553.             (*func)(&termw->flags, SMOOTHSCROLL);
  1554.             update_jumpscroll();
  1555.             break;
  1556.         case 5:            /* DECSCNM            */
  1557.             j = termw->flags;
  1558.             (*func)(&termw->flags, REVERSE_VIDEO);
  1559.             if ((termw->flags ^ j) & REVERSE_VIDEO)
  1560.                 ReverseVideo(termw);
  1561.             /* update_reversevideo done in RevVid */
  1562.             break;
  1563.  
  1564.         case 6:            /* DECOM            */
  1565.             (*func)(&termw->flags, ORIGIN);
  1566.             CursorSet(screen, 0, 0, termw->flags);
  1567.             break;
  1568.  
  1569.         case 7:            /* DECAWM            */
  1570.             (*func)(&termw->flags, WRAPAROUND);
  1571.             update_autowrap();
  1572.             break;
  1573.         case 8:            /* DECARM            */
  1574.             /* ignore autorepeat */
  1575.             break;
  1576.         case 9:            /* MIT bogus sequence        */
  1577.             if(func == bitset)
  1578.                 screen->send_mouse_pos = 1;
  1579.             else
  1580.                 screen->send_mouse_pos = 0;
  1581.             break;
  1582.         case 38:        /* DECTEK            */
  1583.             if(func == bitset && !(screen->inhibit & I_TEK)) {
  1584.                 if(screen->logging) {
  1585.                     FlushLog(screen);
  1586.                     screen->logstart = Tbuffer;
  1587.                 }
  1588.                 screen->TekEmu = TRUE;
  1589.             }
  1590.             break;
  1591.         case 40:        /* 132 column mode        */
  1592.             screen->c132 = (func == bitset);
  1593.             update_allow132();
  1594.             break;
  1595.         case 41:        /* curses hack            */
  1596.             screen->curses = (func == bitset);
  1597.             update_cursesemul();
  1598.             break;
  1599.         case 44:        /* margin bell            */
  1600.             screen->marginbell = (func == bitset);
  1601.             if(!screen->marginbell)
  1602.                 screen->bellarmed = -1;
  1603.             update_marginbell();
  1604.             break;
  1605.         case 45:        /* reverse wraparound    */
  1606.             (*func)(&termw->flags, REVERSEWRAP);
  1607.             update_reversewrap();
  1608.             break;
  1609.         case 46:        /* logging        */
  1610. #ifdef ALLOWLOGFILEONOFF
  1611.             /*
  1612.              * if this feature is enabled, logging may be 
  1613.              * enabled and disabled via escape sequences.
  1614.              */
  1615.             if(func == bitset)
  1616.                 StartLog(screen);
  1617.             else
  1618.                 CloseLog(screen);
  1619. #else
  1620.             Bell();
  1621.             Bell();
  1622. #endif /* ALLOWLOGFILEONOFF */
  1623.             break;
  1624.         case 47:        /* alternate buffer */
  1625.             if (!termw->misc.titeInhibit) {
  1626.                 if(func == bitset)
  1627.                 ToAlternate(screen);
  1628.                 else
  1629.                 FromAlternate(screen);
  1630.             }
  1631.             break;
  1632.         case 1000:        /* xterm bogus sequence        */
  1633.             if(func == bitset)
  1634.                 screen->send_mouse_pos = 2;
  1635.             else
  1636.                 screen->send_mouse_pos = 0;
  1637.             break;
  1638.         case 1001:        /* xterm sequence w/hilite tracking */
  1639.             if(func == bitset)
  1640.                 screen->send_mouse_pos = 3;
  1641.             else
  1642.                 screen->send_mouse_pos = 0;
  1643.             break;
  1644.         }
  1645.     }
  1646. }
  1647.  
  1648. /*
  1649.  * process xterm private modes save
  1650.  */
  1651. savemodes(termw)
  1652.     XtermWidget termw;
  1653. {
  1654.     register TScreen    *screen    = &termw->screen;
  1655.     register int i;
  1656.  
  1657.     for (i = 0; i < nparam; i++) {
  1658.         switch (param[i]) {
  1659.         case 1:            /* DECCKM            */
  1660.             screen->save_modes[0] = termw->keyboard.flags &
  1661.              CURSOR_APL;
  1662.             break;
  1663.         case 3:            /* DECCOLM            */
  1664.             if(screen->c132)
  1665.                 screen->save_modes[1] = termw->flags & IN132COLUMNS;
  1666.             break;
  1667.         case 4:            /* DECSCLM (slow scroll)    */
  1668.             screen->save_modes[2] = termw->flags & SMOOTHSCROLL;
  1669.             break;
  1670.         case 5:            /* DECSCNM            */
  1671.             screen->save_modes[3] = termw->flags & REVERSE_VIDEO;
  1672.             break;
  1673.         case 6:            /* DECOM            */
  1674.             screen->save_modes[4] = termw->flags & ORIGIN;
  1675.             break;
  1676.  
  1677.         case 7:            /* DECAWM            */
  1678.             screen->save_modes[5] = termw->flags & WRAPAROUND;
  1679.             break;
  1680.         case 8:            /* DECARM            */
  1681.             /* ignore autorepeat */
  1682.             break;
  1683.         case 9:            /* mouse bogus sequence */
  1684.             screen->save_modes[7] = screen->send_mouse_pos;
  1685.             break;
  1686.         case 40:        /* 132 column mode        */
  1687.             screen->save_modes[8] = screen->c132;
  1688.             break;
  1689.         case 41:        /* curses hack            */
  1690.             screen->save_modes[9] = screen->curses;
  1691.             break;
  1692.         case 44:        /* margin bell            */
  1693.             screen->save_modes[12] = screen->marginbell;
  1694.             break;
  1695.         case 45:        /* reverse wraparound    */
  1696.             screen->save_modes[13] = termw->flags & REVERSEWRAP;
  1697.             break;
  1698.         case 46:        /* logging        */
  1699.             screen->save_modes[14] = screen->logging;
  1700.             break;
  1701.         case 47:        /* alternate buffer        */
  1702.             screen->save_modes[15] = screen->alternate;
  1703.             break;
  1704.         case 1000:        /* mouse bogus sequence        */
  1705.         case 1001:
  1706.             screen->save_modes[7] = screen->send_mouse_pos;
  1707.             break;
  1708.         }
  1709.     }
  1710. }
  1711.  
  1712. /*
  1713.  * process xterm private modes restore
  1714.  */
  1715. restoremodes(termw)
  1716.     XtermWidget termw;
  1717. {
  1718.     register TScreen    *screen    = &termw->screen;
  1719.     register int i, j;
  1720.  
  1721.     for (i = 0; i < nparam; i++) {
  1722.         switch (param[i]) {
  1723.         case 1:            /* DECCKM            */
  1724.             termw->keyboard.flags &= ~CURSOR_APL;
  1725.             termw->keyboard.flags |= screen->save_modes[0] &
  1726.              CURSOR_APL;
  1727.             update_appcursor();
  1728.             break;
  1729.         case 3:            /* DECCOLM            */
  1730.             if(screen->c132) {
  1731.                 ClearScreen(screen);
  1732.                 CursorSet(screen, 0, 0, termw->flags);
  1733.                 if((j = (screen->save_modes[1] & IN132COLUMNS)
  1734.                  ? 132 : 80) != ((termw->flags & IN132COLUMNS)
  1735.                  ? 132 : 80) || j != screen->max_col + 1) {
  1736.                         Dimension replyWidth, replyHeight;
  1737.                     XtGeometryResult status;
  1738.                     status = XtMakeResizeRequest (
  1739.                         (Widget) termw,
  1740.                         (Dimension) FontWidth(screen) * j 
  1741.                         + 2*screen->border
  1742.                         + screen->scrollbar,
  1743.                         (Dimension) FontHeight(screen)
  1744.                         * (screen->max_row + 1)
  1745.                         + 2*screen->border,
  1746.                         &replyWidth, &replyHeight);
  1747.  
  1748.                     if (status == XtGeometryYes ||
  1749.                         status == XtGeometryDone) {
  1750.                         ScreenResize (&termw->screen,
  1751.                               replyWidth,
  1752.                               replyHeight,
  1753.                               &termw->flags);
  1754.                     }
  1755.                 }
  1756.                 termw->flags &= ~IN132COLUMNS;
  1757.                 termw->flags |= screen->save_modes[1] &
  1758.                  IN132COLUMNS;
  1759.             }
  1760.             break;
  1761.         case 4:            /* DECSCLM (slow scroll)    */
  1762.             if (screen->save_modes[2] & SMOOTHSCROLL) {
  1763.                 screen->jumpscroll = 0;
  1764.                 if (screen->scroll_amt)
  1765.                     FlushScroll(screen);
  1766.             } else
  1767.                 screen->jumpscroll = 1;
  1768.             termw->flags &= ~SMOOTHSCROLL;
  1769.             termw->flags |= screen->save_modes[2] & SMOOTHSCROLL;
  1770.             update_jumpscroll();
  1771.             break;
  1772.         case 5:            /* DECSCNM            */
  1773.             if((screen->save_modes[3] ^ termw->flags) & REVERSE_VIDEO) {
  1774.                 termw->flags &= ~REVERSE_VIDEO;
  1775.                 termw->flags |= screen->save_modes[3] & REVERSE_VIDEO;
  1776.                 ReverseVideo(termw);
  1777.                 /* update_reversevideo done in RevVid */
  1778.             }
  1779.             break;
  1780.         case 6:            /* DECOM            */
  1781.             termw->flags &= ~ORIGIN;
  1782.             termw->flags |= screen->save_modes[4] & ORIGIN;
  1783.             CursorSet(screen, 0, 0, termw->flags);
  1784.             break;
  1785.  
  1786.         case 7:            /* DECAWM            */
  1787.             termw->flags &= ~WRAPAROUND;
  1788.             termw->flags |= screen->save_modes[5] & WRAPAROUND;
  1789.             update_autowrap();
  1790.             break;
  1791.         case 8:            /* DECARM            */
  1792.             /* ignore autorepeat */
  1793.             break;
  1794.         case 9:            /* MIT bogus sequence        */
  1795.             screen->send_mouse_pos = screen->save_modes[7];
  1796.             break;
  1797.         case 40:        /* 132 column mode        */
  1798.             screen->c132 = screen->save_modes[8];
  1799.             update_allow132();
  1800.             break;
  1801.         case 41:        /* curses hack            */
  1802.             screen->curses = screen->save_modes[9];
  1803.             update_cursesemul();
  1804.             break;
  1805.         case 44:        /* margin bell            */
  1806.             if(!(screen->marginbell = screen->save_modes[12]))
  1807.                 screen->bellarmed = -1;
  1808.             update_marginbell();
  1809.             break;
  1810.         case 45:        /* reverse wraparound    */
  1811.             termw->flags &= ~REVERSEWRAP;
  1812.             termw->flags |= screen->save_modes[13] & REVERSEWRAP;
  1813.             update_reversewrap();
  1814.             break;
  1815.         case 46:        /* logging        */
  1816. #ifdef ALLOWLOGFILEONOFF
  1817.             if(screen->save_modes[14])
  1818.                 StartLog(screen);
  1819.             else
  1820.                 CloseLog(screen);
  1821. #endif /* ALLOWLOGFILEONOFF */
  1822.             /* update_logging done by StartLog and CloseLog */
  1823.             break;
  1824.         case 47:        /* alternate buffer */
  1825.             if (!termw->misc.titeInhibit) {
  1826.                 if(screen->save_modes[15])
  1827.                 ToAlternate(screen);
  1828.                 else
  1829.                 FromAlternate(screen);
  1830.                 /* update_altscreen done by ToAlt and FromAlt */
  1831.             }
  1832.             break;
  1833.         case 1000:        /* mouse bogus sequence        */
  1834.         case 1001:
  1835.             screen->send_mouse_pos = screen->save_modes[7];
  1836.             break;
  1837.         }
  1838.     }
  1839. }
  1840.  
  1841. /*
  1842.  * set a bit in a word given a pointer to the word and a mask.
  1843.  */
  1844. static void bitset(p, mask)
  1845.     unsigned *p;
  1846.     int mask;
  1847. {
  1848.     *p |= mask;
  1849. }
  1850.  
  1851. /*
  1852.  * clear a bit in a word given a pointer to the word and a mask.
  1853.  */
  1854. static void bitclr(p, mask)
  1855.     unsigned *p;
  1856.     int mask;
  1857. {
  1858.     *p &= ~mask;
  1859. }
  1860.  
  1861. unparseseq(ap, fd)
  1862.     register ANSI *ap;
  1863.     int fd;
  1864. {
  1865.     register int    c;
  1866.     register int    i;
  1867.     register int    inters;
  1868.  
  1869.     c = ap->a_type;
  1870.     if (c>=0x80 && c<=0x9F) {
  1871.         unparseputc(ESC, fd);
  1872.         c -= 0x40;
  1873.     }
  1874.     unparseputc(c, fd);
  1875.     c = ap->a_type;
  1876.     if (c==ESC || c==DCS || c==CSI || c==OSC || c==PM || c==APC) {
  1877.         if (ap->a_pintro != 0)
  1878.             unparseputc((char) ap->a_pintro, fd);
  1879.         for (i=0; i<ap->a_nparam; ++i) {
  1880.             if (i != 0)
  1881.                 unparseputc(';', fd);
  1882.             unparseputn((unsigned int) ap->a_param[i], fd);
  1883.         }
  1884.         inters = ap->a_inters;
  1885.         for (i=3; i>=0; --i) {
  1886.             c = (inters >> (8*i)) & 0xff;
  1887.             if (c != 0)
  1888.                 unparseputc(c, fd);
  1889.         }
  1890.         unparseputc((char) ap->a_final, fd);
  1891.     }
  1892. }
  1893.  
  1894. unparseputn(n, fd)
  1895. unsigned int    n;
  1896. int fd;
  1897. {
  1898.     unsigned int    q;
  1899.  
  1900.     q = n/10;
  1901.     if (q != 0)
  1902.         unparseputn(q, fd);
  1903.     unparseputc((char) ('0' + (n%10)), fd);
  1904. }
  1905.  
  1906. unparseputc(c, fd)
  1907. char c;
  1908. int fd;
  1909. {
  1910.     char    buf[2];
  1911.     register i = 1;
  1912.     extern XtermWidget term;
  1913.  
  1914.     if((buf[0] = c) == '\r' && (term->flags & LINEFEED)) {
  1915.         buf[1] = '\n';
  1916.         i++;
  1917.     }
  1918.     v_write(fd, buf, i);
  1919. }
  1920.  
  1921. unparsefputs (s, fd)
  1922.     register char *s;
  1923.     int fd;
  1924. {
  1925.     if (s) {
  1926.     while (*s) unparseputc (*s++, fd);
  1927.     }
  1928. }
  1929.  
  1930. static void SwitchBufs();
  1931.  
  1932. ToAlternate(screen)
  1933. register TScreen *screen;
  1934. {
  1935.     extern ScrnBuf Allocate();
  1936.  
  1937.     if(screen->alternate)
  1938.         return;
  1939.     if(!screen->altbuf)
  1940.         screen->altbuf = Allocate(screen->max_row + 1, screen->max_col
  1941.          + 1, &screen->abuf_address);
  1942.     SwitchBufs(screen);
  1943.     screen->alternate = TRUE;
  1944.     update_altscreen();
  1945. }
  1946.  
  1947. FromAlternate(screen)
  1948. register TScreen *screen;
  1949. {
  1950.     if(!screen->alternate)
  1951.         return;
  1952.     screen->alternate = FALSE;
  1953.     SwitchBufs(screen);
  1954.     update_altscreen();
  1955. }
  1956.  
  1957. static void
  1958. SwitchBufs(screen)
  1959.     register TScreen *screen;
  1960. {
  1961.     register int rows, top;
  1962.  
  1963.     if(screen->cursor_state)
  1964.         HideCursor();
  1965.     rows = screen->max_row + 1;
  1966.     SwitchBufPtrs(screen);
  1967.     TrackText(0, 0, 0, 0);    /* remove any highlighting */
  1968.     if((top = -screen->topline) <= screen->max_row) {
  1969.         if(screen->scroll_amt)
  1970.             FlushScroll(screen);
  1971.         if(top == 0)
  1972.             XClearWindow(screen->display, TextWindow(screen));
  1973.         else
  1974.             XClearArea(
  1975.                 screen->display,
  1976.                 TextWindow(screen),
  1977.                 (int) screen->border + screen->scrollbar,
  1978.                 (int) top * FontHeight(screen) + screen->border,
  1979.                 (unsigned) Width(screen),
  1980.                 (unsigned) (screen->max_row - top + 1)
  1981.                 * FontHeight(screen),
  1982.                 FALSE);
  1983.     }
  1984.     ScrnRefresh(screen, 0, 0, rows, screen->max_col + 1, False);
  1985. }
  1986.  
  1987. /* swap buffer line pointers between alt and regular screens */
  1988.  
  1989. SwitchBufPtrs(screen)
  1990.     register TScreen *screen;
  1991. {
  1992.     register int rows = screen->max_row + 1;
  1993.     char *save [2 * MAX_ROWS];
  1994.  
  1995.     bcopy((char *)screen->buf, (char *)save, 2 * sizeof(char *) * rows);
  1996.     bcopy((char *)screen->altbuf, (char *)screen->buf,
  1997.       2 * sizeof(char *) * rows);
  1998.     bcopy((char *)save, (char *)screen->altbuf, 2 * sizeof(char *) * rows);
  1999. }
  2000.  
  2001. VTRun()
  2002. {
  2003.     register TScreen *screen = &term->screen;
  2004.     register int i;
  2005.     
  2006.     if (!screen->Vshow) {
  2007.         set_vt_visibility (TRUE);
  2008.     } 
  2009.     update_vttekmode();
  2010.     update_vtshow();
  2011.     update_tekshow();
  2012.     set_vthide_sensitivity();
  2013.  
  2014.     if (screen->allbuf == NULL) VTallocbuf ();
  2015.  
  2016.     screen->cursor_state = OFF;
  2017.     screen->cursor_set = ON;
  2018.  
  2019.     bcnt = 0;
  2020.     bptr = buffer;
  2021.     while(Tpushb > Tpushback) {
  2022.         *bptr++ = *--Tpushb;
  2023.         bcnt++;
  2024.     }
  2025.     bcnt += (i = Tbcnt);
  2026.     for( ; i > 0 ; i--)
  2027.         *bptr++ = *Tbptr++;
  2028.     bptr = buffer;
  2029.     if(!setjmp(VTend))
  2030.         VTparse();
  2031.     HideCursor();
  2032.     screen->cursor_set = OFF;
  2033. }
  2034.  
  2035. /*ARGSUSED*/
  2036. static void VTExpose(w, event, region)
  2037.     Widget w;
  2038.     XEvent *event;
  2039.     Region region;
  2040. {
  2041.     register TScreen *screen = &term->screen;
  2042.  
  2043. #ifdef DEBUG
  2044.     if(debug)
  2045.         fputs("Expose\n", stderr);
  2046. #endif    /* DEBUG */
  2047.     if (event->type == Expose)
  2048.         HandleExposure (screen, event);
  2049. }
  2050.  
  2051. static void VTGraphicsOrNoExpose (event)
  2052.     XEvent *event;
  2053. {
  2054.     register TScreen *screen = &term->screen;
  2055.     if (screen->incopy <= 0) {
  2056.         screen->incopy = 1;
  2057.         if (screen->scrolls > 0)
  2058.             screen->scrolls--;
  2059.     }
  2060.     if (event->type == GraphicsExpose)
  2061.       if (HandleExposure (screen, event))
  2062.         screen->cursor_state = OFF;
  2063.     if ((event->type == NoExpose) || ((XGraphicsExposeEvent *)event)->count == 0) {
  2064.         if (screen->incopy <= 0 && screen->scrolls > 0)
  2065.             screen->scrolls--;
  2066.         if (screen->scrolls)
  2067.             screen->incopy = -1;
  2068.         else
  2069.             screen->incopy = 0;
  2070.     }
  2071. }
  2072.  
  2073. /*ARGSUSED*/
  2074. static void VTNonMaskableEvent (w, closure, event, cont)
  2075. Widget w;            /* unused */
  2076. XtPointer closure;        /* unused */
  2077. XEvent *event;
  2078. Boolean *cont;            /* unused */
  2079. {
  2080.     switch (event->type) {
  2081.        case GraphicsExpose:
  2082.        case NoExpose:
  2083.       VTGraphicsOrNoExpose (event);
  2084.       break;
  2085.       }
  2086. }
  2087.  
  2088.  
  2089.  
  2090.  
  2091. static void VTResize(w)
  2092.     Widget w;
  2093. {
  2094.     if (XtIsRealized(w))
  2095.       ScreenResize (&term->screen, term->core.width, term->core.height,
  2096.             &term->flags);
  2097. }
  2098.  
  2099.                 
  2100. extern Atom wm_delete_window;    /* for ICCCM delete window */
  2101.  
  2102. static String xterm_trans =
  2103.     "<ClientMessage>WM_PROTOCOLS: DeleteWindow()\n\
  2104.      <MappingNotify>: KeyboardMapping()\n";
  2105.  
  2106. int VTInit ()
  2107. {
  2108.     register TScreen *screen = &term->screen;
  2109.     Widget vtparent = term->core.parent;
  2110.  
  2111.     XtRealizeWidget (vtparent);
  2112.     XtOverrideTranslations(vtparent, XtParseTranslationTable(xterm_trans));
  2113.     (void) XSetWMProtocols (XtDisplay(vtparent), XtWindow(vtparent),
  2114.                 &wm_delete_window, 1);
  2115.  
  2116.     if (screen->allbuf == NULL) VTallocbuf ();
  2117.     return (1);
  2118. }
  2119.  
  2120. static void VTallocbuf ()
  2121. {
  2122.     register TScreen *screen = &term->screen;
  2123.     int nrows = screen->max_row + 1;
  2124.     extern ScrnBuf Allocate();
  2125.  
  2126.     /* allocate screen buffer now, if necessary. */
  2127.     if (screen->scrollWidget)
  2128.       nrows += screen->savelines;
  2129.     screen->allbuf = Allocate (nrows, screen->max_col + 1,
  2130.      &screen->sbuf_address);
  2131.     if (screen->scrollWidget)
  2132.       screen->buf = &screen->allbuf[2 * screen->savelines];
  2133.     else
  2134.       screen->buf = screen->allbuf;
  2135.     return;
  2136. }
  2137.  
  2138. static void VTClassInit ()
  2139. {
  2140.     XtAddConverter(XtRString, XtRGravity, XmuCvtStringToGravity,
  2141.            (XtConvertArgList) NULL, (Cardinal) 0);
  2142. }
  2143.  
  2144.  
  2145. /* ARGSUSED */
  2146. static void VTInitialize (wrequest, wnew, args, num_args)
  2147.    Widget wrequest, wnew;
  2148.    ArgList args;
  2149.    Cardinal *num_args;
  2150. {
  2151.    XtermWidget request = (XtermWidget) wrequest;
  2152.    XtermWidget new     = (XtermWidget) wnew;
  2153.    int i;
  2154.  
  2155.    /* Zero out the entire "screen" component of "new" widget,
  2156.       then do field-by-field assigment of "screen" fields
  2157.       that are named in the resource list. */
  2158.  
  2159.    bzero ((char *) &new->screen, sizeof(new->screen));
  2160.    new->screen.c132 = request->screen.c132;
  2161.    new->screen.curses = request->screen.curses;
  2162.    new->screen.foreground = request->screen.foreground;
  2163.    new->screen.cursorcolor = request->screen.cursorcolor;
  2164.    new->screen.border = request->screen.border;
  2165.    new->screen.jumpscroll = request->screen.jumpscroll;
  2166.    new->screen.logfile = request->screen.logfile;
  2167.    new->screen.marginbell = request->screen.marginbell;
  2168.    new->screen.mousecolor = request->screen.mousecolor;
  2169.    new->screen.mousecolorback = request->screen.mousecolorback;
  2170.    new->screen.multiscroll = request->screen.multiscroll;
  2171.    new->screen.nmarginbell = request->screen.nmarginbell;
  2172.    new->screen.savelines = request->screen.savelines;
  2173.    new->screen.scrolllines = request->screen.scrolllines;
  2174.    new->screen.scrollttyoutput = request->screen.scrollttyoutput;
  2175.    new->screen.scrollkey = request->screen.scrollkey;
  2176.    new->screen.visualbell = request->screen.visualbell;
  2177.    new->screen.TekEmu = request->screen.TekEmu;
  2178.    new->misc.re_verse = request->misc.re_verse;
  2179.    new->screen.multiClickTime = request->screen.multiClickTime;
  2180.    new->screen.bellSuppressTime = request->screen.bellSuppressTime;
  2181.    new->screen.charClass = request->screen.charClass;
  2182.    new->screen.cutNewline = request->screen.cutNewline;
  2183.    new->screen.cutToBeginningOfLine = request->screen.cutToBeginningOfLine;
  2184.    new->screen.always_highlight = request->screen.always_highlight;
  2185.    new->screen.pointer_cursor = request->screen.pointer_cursor;
  2186.    new->screen.input_eight_bits = request->screen.input_eight_bits;
  2187.    new->screen.output_eight_bits = request->screen.output_eight_bits;
  2188.    new->screen.allowSendEvents = request->screen.allowSendEvents;
  2189.    new->misc.titeInhibit = request->misc.titeInhibit;
  2190.    for (i = fontMenu_font1; i <= NMENUFONTS; i++) {
  2191.        new->screen.menu_font_names[i] = request->screen.menu_font_names[i];
  2192.    }
  2193.    /* set default in realize proc */
  2194.    new->screen.menu_font_names[fontMenu_fontdefault] = NULL;
  2195.    new->screen.menu_font_names[fontMenu_fontescape] = NULL;
  2196.    new->screen.menu_font_names[fontMenu_fontsel] = NULL;
  2197.    new->screen.menu_font_number = fontMenu_fontdefault;
  2198.  
  2199.     /*
  2200.      * The definition of -rv now is that it changes the definition of 
  2201.      * XtDefaultForeground and XtDefaultBackground.  So, we no longer
  2202.      * need to do anything special.
  2203.      */
  2204.    new->keyboard.flags = 0;
  2205.    new->screen.display = new->core.screen->display;
  2206.    new->core.height = new->core.width = 1;
  2207.       /* dummy values so that we don't try to Realize the parent shell 
  2208.      with height or width of 0, which is illegal in X.  The real
  2209.      size is computed in the xtermWidget's Realize proc,
  2210.      but the shell's Realize proc is called first, and must see
  2211.      a valid size. */
  2212.  
  2213.    /* look for focus related events on the shell, because we need
  2214.     * to care about the shell's border being part of our focus.
  2215.     */
  2216.    XtAddEventHandler(XtParent(new), EnterWindowMask, FALSE,
  2217.         HandleEnterWindow, (Opaque)NULL);
  2218.    XtAddEventHandler(XtParent(new), LeaveWindowMask, FALSE,
  2219.         HandleLeaveWindow, (Opaque)NULL);
  2220.    XtAddEventHandler(XtParent(new), FocusChangeMask, FALSE,
  2221.         HandleFocusChange, (Opaque)NULL);
  2222.    XtAddEventHandler((Widget)new, 0L, TRUE,
  2223.         VTNonMaskableEvent, (Opaque)NULL);
  2224.    XtAddEventHandler((Widget)new, PropertyChangeMask, FALSE,
  2225.              HandleBellPropertyChange, (Opaque)NULL);
  2226.    new->screen.bellInProgress = FALSE;
  2227.  
  2228.    set_character_class (new->screen.charClass);
  2229.  
  2230.    /* create it, but don't realize it */
  2231.    ScrollBarOn (new, TRUE, FALSE);
  2232.  
  2233.    /* make sure that the resize gravity acceptable */
  2234.    if ( new->misc.resizeGravity != NorthWestGravity &&
  2235.         new->misc.resizeGravity != SouthWestGravity) {
  2236.        extern XtAppContext app_con;
  2237.        Cardinal nparams = 1;
  2238.  
  2239.        XtAppWarningMsg(app_con, "rangeError", "resizeGravity", "XTermError",
  2240.                "unsupported resizeGravity resource value (%d)",
  2241.                (String *) &(new->misc.resizeGravity), &nparams);
  2242.        new->misc.resizeGravity = SouthWestGravity;
  2243.    }
  2244.  
  2245.    return;
  2246. }
  2247.  
  2248.  
  2249. static void VTDestroy (w)
  2250. Widget w;
  2251. {
  2252.     XtFree(((XtermWidget)w)->screen.selection);
  2253. }
  2254.  
  2255. /*ARGSUSED*/
  2256. static void VTRealize (w, valuemask, values)
  2257.     Widget w;
  2258.     XtValueMask *valuemask;
  2259.     XSetWindowAttributes *values;
  2260. {
  2261.     unsigned int width, height;
  2262.     register TScreen *screen = &term->screen;
  2263.     int xpos, ypos, pr;
  2264.     XSizeHints        sizehints;
  2265.     int scrollbar_width;
  2266.  
  2267.     TabReset (term->tabs);
  2268.  
  2269.     screen->menu_font_names[fontMenu_fontdefault] = term->misc.f_n;
  2270.     screen->fnt_norm = screen->fnt_bold = NULL;
  2271.     if (!LoadNewFont(screen, term->misc.f_n, term->misc.f_b, False, 0)) {
  2272.         if (XmuCompareISOLatin1(term->misc.f_n, "fixed") != 0) {
  2273.         fprintf (stderr, 
  2274.              "%s:  unable to open font \"%s\", trying \"fixed\"....\n",
  2275.              xterm_name, term->misc.f_n);
  2276.         (void) LoadNewFont (screen, "fixed", NULL, False, 0);
  2277.         screen->menu_font_names[fontMenu_fontdefault] = "fixed";
  2278.         }
  2279.     }
  2280.  
  2281.     /* really screwed if we couldn't open default font */
  2282.     if (!screen->fnt_norm) {
  2283.         fprintf (stderr, "%s:  unable to locate a suitable font\n",
  2284.              xterm_name);
  2285.         Exit (1);
  2286.     }
  2287.  
  2288.     /* making cursor */
  2289.     if (!screen->pointer_cursor) 
  2290.       screen->pointer_cursor = make_colored_cursor(XC_xterm, 
  2291.                                screen->mousecolor,
  2292.                                screen->mousecolorback);
  2293.     else 
  2294.       recolor_cursor (screen->pointer_cursor, 
  2295.               screen->mousecolor, screen->mousecolorback);
  2296.  
  2297.     scrollbar_width = (term->misc.scrollbar ?
  2298.                screen->scrollWidget->core.width /* +
  2299.                screen->scrollWidget->core.border_width */ : 0);
  2300.  
  2301.     /* set defaults */
  2302.     xpos = 1; ypos = 1; width = 80; height = 24;
  2303.     pr = XParseGeometry (term->misc.geo_metry, &xpos, &ypos,
  2304.                  &width, &height);
  2305.     screen->max_col = (width - 1);    /* units in character cells */
  2306.     screen->max_row = (height - 1);    /* units in character cells */
  2307.     update_font_info (&term->screen, False);
  2308.  
  2309.     width = screen->fullVwin.fullwidth;
  2310.     height = screen->fullVwin.fullheight;
  2311.  
  2312.     if ((pr & XValue) && (XNegative&pr)) 
  2313.       xpos += DisplayWidth(screen->display, DefaultScreen(screen->display))
  2314.             - width - (term->core.parent->core.border_width * 2);
  2315.     if ((pr & YValue) && (YNegative&pr))
  2316.       ypos += DisplayHeight(screen->display,DefaultScreen(screen->display))
  2317.             - height - (term->core.parent->core.border_width * 2);
  2318.  
  2319.     /* set up size hints for window manager; min 1 char by 1 char */
  2320.     sizehints.base_width = 2 * screen->border + scrollbar_width;
  2321.     sizehints.base_height = 2 * screen->border;
  2322.     sizehints.width_inc = FontWidth(screen);
  2323.     sizehints.height_inc = FontHeight(screen);
  2324.     sizehints.min_width = sizehints.base_width + sizehints.width_inc;
  2325.     sizehints.min_height = sizehints.base_height + sizehints.height_inc;
  2326.     sizehints.flags = (PBaseSize|PMinSize|PResizeInc);
  2327.     sizehints.x = xpos;
  2328.     sizehints.y = ypos;
  2329.     if ((XValue&pr) || (YValue&pr)) {
  2330.         sizehints.flags |= USSize|USPosition;
  2331.         sizehints.flags |= PWinGravity;
  2332.         switch (pr & (XNegative | YNegative)) {
  2333.           case 0:
  2334.         sizehints.win_gravity = NorthWestGravity;
  2335.         break;
  2336.           case XNegative:
  2337.         sizehints.win_gravity = NorthEastGravity;
  2338.         break;
  2339.           case YNegative:
  2340.         sizehints.win_gravity = SouthWestGravity;
  2341.         break;
  2342.           default:
  2343.         sizehints.win_gravity = SouthEastGravity;
  2344.         break;
  2345.         }
  2346.     } else {
  2347.         /* set a default size, but do *not* set position */
  2348.         sizehints.flags |= PSize;
  2349.     }
  2350.     sizehints.width = width;
  2351.     sizehints.height = height;
  2352.     if ((WidthValue&pr) || (HeightValue&pr)) 
  2353.       sizehints.flags |= USSize;
  2354.     else sizehints.flags |= PSize;
  2355.  
  2356.     (void) XtMakeResizeRequest((Widget) term,
  2357.                    (Dimension)width, (Dimension)height,
  2358.                    &term->core.width, &term->core.height);
  2359.  
  2360.     /* XXX This is bogus.  We are parsing geometries too late.  This
  2361.      * is information that the shell widget ought to have before we get
  2362.      * realized, so that it can do the right thing.
  2363.      */
  2364.         if (sizehints.flags & USPosition)
  2365.         XMoveWindow (XtDisplay(term), term->core.parent->core.window,
  2366.              sizehints.x, sizehints.y);
  2367.  
  2368.     XSetWMNormalHints (XtDisplay(term), term->core.parent->core.window,
  2369.                &sizehints);
  2370.     XFlush (XtDisplay(term));    /* get it out to window manager */
  2371.  
  2372.     /* use ForgetGravity instead of SouthWestGravity because translating
  2373.        the Expose events for ConfigureNotifys is too hard */
  2374.     values->bit_gravity = term->misc.resizeGravity == NorthWestGravity ?
  2375.         NorthWestGravity : ForgetGravity;
  2376.     term->screen.fullVwin.window = term->core.window =
  2377.       XCreateWindow(XtDisplay(term), XtWindow(term->core.parent),
  2378.         term->core.x, term->core.y,
  2379.         term->core.width, term->core.height, term->core.border_width,
  2380.         (int) term->core.depth,
  2381.         InputOutput, CopyFromParent,    
  2382.         *valuemask|CWBitGravity, values);
  2383.  
  2384.     set_cursor_gcs (screen);
  2385.  
  2386.     /* Reset variables used by ANSI emulation. */
  2387.  
  2388.     screen->gsets[0] = 'B';            /* ASCII_G        */
  2389.     screen->gsets[1] = 'B';
  2390.     screen->gsets[2] = 'B';            /* DEC supplemental.    */
  2391.     screen->gsets[3] = 'B';
  2392.     screen->curgl = 0;            /* G0 => GL.        */
  2393.     screen->curgr = 2;            /* G2 => GR.        */
  2394.     screen->curss = 0;            /* No single shift.    */
  2395.  
  2396.     XDefineCursor(screen->display, VShellWindow, screen->pointer_cursor);
  2397.  
  2398.         screen->cur_col = screen->cur_row = 0;
  2399.     screen->max_col = Width(screen)/screen->fullVwin.f_width - 1;
  2400.     screen->top_marg = 0;
  2401.     screen->bot_marg = screen->max_row = Height(screen) /
  2402.                 screen->fullVwin.f_height - 1;
  2403.  
  2404.     screen->sc.row = screen->sc.col = screen->sc.flags = 0;
  2405.  
  2406.     /* Mark screen buffer as unallocated.  We wait until the run loop so
  2407.        that the child process does not fork and exec with all the dynamic
  2408.        memory it will never use.  If we were to do it here, the
  2409.        swap space for new process would be huge for huge savelines. */
  2410.     if (!tekWidget)            /* if not called after fork */
  2411.       screen->buf = screen->allbuf = NULL;
  2412.  
  2413.     screen->do_wrap = 0;
  2414.     screen->scrolls = screen->incopy = 0;
  2415.     set_vt_box (screen);
  2416.  
  2417.     screen->savedlines = 0;
  2418.  
  2419.     if (term->misc.scrollbar) {
  2420.         screen->scrollbar = 0;
  2421.         ScrollBarOn (term, FALSE, TRUE);
  2422.     }
  2423.     CursorSave (term, &screen->sc);
  2424.     return;
  2425. }
  2426.  
  2427. static Boolean VTSetValues (cur, request, new, args, num_args)
  2428.     Widget cur, request, new;
  2429.     ArgList args;
  2430.     Cardinal *num_args;
  2431. {
  2432.     XtermWidget curvt = (XtermWidget) cur;
  2433.     XtermWidget newvt = (XtermWidget) new; 
  2434.     Boolean refresh_needed = FALSE;
  2435.     Boolean fonts_redone = FALSE;
  2436.  
  2437.     if(curvt->core.background_pixel != newvt->core.background_pixel
  2438.        || curvt->screen.foreground != newvt->screen.foreground
  2439.        || curvt->screen.menu_font_names[curvt->screen.menu_font_number]
  2440.           != newvt->screen.menu_font_names[newvt->screen.menu_font_number]
  2441.        || curvt->misc.f_n != newvt->misc.f_n) {
  2442.     if(curvt->misc.f_n != newvt->misc.f_n)
  2443.         newvt->screen.menu_font_names[fontMenu_fontdefault] = newvt->misc.f_n;
  2444.     if (LoadNewFont(&newvt->screen,
  2445.             newvt->screen.menu_font_names[curvt->screen.menu_font_number],
  2446.             newvt->screen.menu_font_names[curvt->screen.menu_font_number],
  2447.             TRUE, newvt->screen.menu_font_number)) {
  2448.         /* resizing does the redisplay, so don't ask for it here */
  2449.         refresh_needed = TRUE;
  2450.         fonts_redone = TRUE;
  2451.     } else
  2452.         if(curvt->misc.f_n != newvt->misc.f_n)
  2453.         newvt->screen.menu_font_names[fontMenu_fontdefault] = curvt->misc.f_n;
  2454.     }
  2455.     if(!fonts_redone
  2456.        && curvt->screen.cursorcolor != newvt->screen.cursorcolor) {
  2457.     set_cursor_gcs(&newvt->screen);
  2458.     refresh_needed = TRUE;
  2459.     }
  2460.     if(curvt->misc.re_verse != newvt->misc.re_verse) {
  2461.     newvt->flags ^= REVERSE_VIDEO;
  2462.     ReverseVideo(newvt);
  2463.     newvt->misc.re_verse = !newvt->misc.re_verse; /* ReverseVideo toggles */
  2464.     refresh_needed = TRUE;
  2465.     }
  2466.     if(curvt->screen.mousecolor != newvt->screen.mousecolor
  2467.        || curvt->screen.mousecolorback != newvt->screen.mousecolorback) {
  2468.     recolor_cursor (newvt->screen.pointer_cursor, 
  2469.             newvt->screen.mousecolor,
  2470.             newvt->screen.mousecolorback);
  2471.     refresh_needed = TRUE;
  2472.     }
  2473.     if (curvt->misc.scrollbar != newvt->misc.scrollbar) {
  2474.     if (newvt->misc.scrollbar) {
  2475.         ScrollBarOn (newvt, FALSE, FALSE);
  2476.     } else {
  2477.         ScrollBarOff (&newvt->screen);
  2478.     }
  2479.     update_scrollbar();
  2480.     }
  2481.  
  2482.     return refresh_needed;
  2483. }
  2484.  
  2485. /*
  2486.  * Shows cursor at new cursor position in screen.
  2487.  */
  2488. ShowCursor()
  2489. {
  2490.     register TScreen *screen = &term->screen;
  2491.     register int x, y, flags;
  2492.     Char c;
  2493.     GC    currentGC;
  2494.     Boolean    in_selection;
  2495.  
  2496.     if (eventMode != NORMAL) return;
  2497.  
  2498.     if (screen->cur_row - screen->topline > screen->max_row)
  2499.         return;
  2500.     c = screen->buf[y = 2 * (screen->cursor_row = screen->cur_row)]
  2501.      [x = screen->cursor_col = screen->cur_col];
  2502.     flags = screen->buf[y + 1][x];
  2503.     if (c == 0)
  2504.         c = ' ';
  2505.  
  2506.     if (screen->cur_row > screen->endHRow ||
  2507.         (screen->cur_row == screen->endHRow &&
  2508.          screen->cur_col >= screen->endHCol) ||
  2509.         screen->cur_row < screen->startHRow ||
  2510.         (screen->cur_row == screen->startHRow &&
  2511.          screen->cur_col < screen->startHCol))
  2512.         in_selection = False;
  2513.     else
  2514.         in_selection = True;
  2515.  
  2516.     if(screen->select || screen->always_highlight) {
  2517.         if (( (flags & INVERSE) && !in_selection) ||
  2518.             (!(flags & INVERSE) &&  in_selection)){
  2519.             /* text is reverse video */
  2520.             if (screen->cursorGC) {
  2521.             currentGC = screen->cursorGC;
  2522.             } else {
  2523.             if (flags & BOLD) {
  2524.                 currentGC = screen->normalboldGC;
  2525.             } else {
  2526.                 currentGC = screen->normalGC;
  2527.             }
  2528.             }
  2529.         } else { /* normal video */
  2530.             if (screen->reversecursorGC) {
  2531.             currentGC = screen->reversecursorGC;
  2532.             } else {
  2533.             if (flags & BOLD) {
  2534.                 currentGC = screen->reverseboldGC;
  2535.             } else {
  2536.                 currentGC = screen->reverseGC;
  2537.             }
  2538.             }
  2539.         }
  2540.     } else { /* not selected */
  2541.         if (( (flags & INVERSE) && !in_selection) ||
  2542.             (!(flags & INVERSE) &&  in_selection)) {
  2543.             /* text is reverse video */
  2544.             currentGC = screen->reverseGC;
  2545.         } else { /* normal video */
  2546.             currentGC = screen->normalGC;
  2547.         }
  2548.         
  2549.     }
  2550.  
  2551.     x = CursorX (screen, screen->cur_col);
  2552.     y = CursorY(screen, screen->cur_row) + 
  2553.       screen->fnt_norm->ascent;
  2554.     XDrawImageString(screen->display, TextWindow(screen), currentGC,
  2555.         x, y, (char *) &c, 1);
  2556.  
  2557.     if((flags & BOLD) && screen->enbolden) /* no bold font */
  2558.         XDrawString(screen->display, TextWindow(screen), currentGC,
  2559.             x + 1, y, (char *) &c, 1);
  2560.     if(flags & UNDERLINE) 
  2561.         XDrawLine(screen->display, TextWindow(screen), currentGC,
  2562.             x, y+1, x + FontWidth(screen), y+1);
  2563.     if (!screen->select && !screen->always_highlight) {
  2564.         screen->box->x = x;
  2565.         screen->box->y = y - screen->fnt_norm->ascent;
  2566.         XDrawLines (screen->display, TextWindow(screen), 
  2567.                 screen->cursoroutlineGC ? screen->cursoroutlineGC 
  2568.                                 : currentGC,
  2569.                 screen->box, NBOX, CoordModePrevious);
  2570.     }
  2571.     screen->cursor_state = ON;
  2572. }
  2573.  
  2574. /*
  2575.  * hide cursor at previous cursor position in screen.
  2576.  */
  2577. HideCursor()
  2578. {
  2579.     register TScreen *screen = &term->screen;
  2580.     GC    currentGC;
  2581.     register int x, y, flags;
  2582.     char c;
  2583.     Boolean    in_selection;
  2584.  
  2585.     if(screen->cursor_row - screen->topline > screen->max_row)
  2586.         return;
  2587.     c = screen->buf[y = 2 * screen->cursor_row][x = screen->cursor_col];
  2588.     flags = screen->buf[y + 1][x];
  2589.  
  2590.     if (screen->cursor_row > screen->endHRow ||
  2591.         (screen->cursor_row == screen->endHRow &&
  2592.          screen->cursor_col >= screen->endHCol) ||
  2593.         screen->cursor_row < screen->startHRow ||
  2594.         (screen->cursor_row == screen->startHRow &&
  2595.          screen->cursor_col < screen->startHCol))
  2596.         in_selection = False;
  2597.     else
  2598.         in_selection = True;
  2599.  
  2600.     if (( (flags & INVERSE) && !in_selection) ||
  2601.         (!(flags & INVERSE) &&  in_selection)) {
  2602.         if(flags & BOLD) {
  2603.             currentGC = screen->reverseboldGC;
  2604.         } else {
  2605.             currentGC = screen->reverseGC;
  2606.         }
  2607.     } else {
  2608.         if(flags & BOLD) {
  2609.             currentGC = screen->normalboldGC;
  2610.         } else {
  2611.             currentGC = screen->normalGC;
  2612.         }
  2613.     }
  2614.  
  2615.     if (c == 0)
  2616.         c = ' ';
  2617.     x = CursorX (screen, screen->cursor_col);
  2618.     y = (((screen->cursor_row - screen->topline) * FontHeight(screen))) +
  2619.      screen->border;
  2620.     y = y+screen->fnt_norm->ascent;
  2621.     XDrawImageString(screen->display, TextWindow(screen), currentGC,
  2622.         x, y, &c, 1);
  2623.     if((flags & BOLD) && screen->enbolden)
  2624.         XDrawString(screen->display, TextWindow(screen), currentGC,
  2625.             x + 1, y, &c, 1);
  2626.     if(flags & UNDERLINE) 
  2627.         XDrawLine(screen->display, TextWindow(screen), currentGC,
  2628.             x, y+1, x + FontWidth(screen), y+1);
  2629.     screen->cursor_state = OFF;
  2630. }
  2631.  
  2632. VTReset(full)
  2633.     Boolean full;
  2634. {
  2635.     register TScreen *screen = &term->screen;
  2636.  
  2637.     /* reset scrolling region */
  2638.     screen->top_marg = 0;
  2639.     screen->bot_marg = screen->max_row;
  2640.     term->flags &= ~ORIGIN;
  2641.     if(full) {
  2642.         TabReset (term->tabs);
  2643.         term->keyboard.flags = 0;
  2644.         update_appcursor();
  2645.         update_appkeypad();
  2646.         screen->gsets[0] = 'B';
  2647.         screen->gsets[1] = 'B';
  2648.         screen->gsets[2] = 'B';
  2649.         screen->gsets[3] = 'B';
  2650.         screen->curgl = 0;
  2651.         screen->curgr = 2;
  2652.         screen->curss = 0;
  2653.         FromAlternate(screen);
  2654.         ClearScreen(screen);
  2655.         screen->cursor_state = OFF;
  2656.         if (term->flags & REVERSE_VIDEO)
  2657.             ReverseVideo(term);
  2658.  
  2659.         term->flags = term->initflags;
  2660.         update_reversevideo();
  2661.         update_autowrap();
  2662.         update_reversewrap();
  2663.         update_autolinefeed();
  2664.         screen->jumpscroll = !(term->flags & SMOOTHSCROLL);
  2665.         update_jumpscroll();
  2666.         if(screen->c132 && (term->flags & IN132COLUMNS)) {
  2667.                 Dimension junk;
  2668.             XtMakeResizeRequest(
  2669.                 (Widget) term,
  2670.                 (Dimension) 80*FontWidth(screen)
  2671.                 + 2 * screen->border + screen->scrollbar,
  2672.                 (Dimension) FontHeight(screen)
  2673.                     * (screen->max_row + 1) + 2 * screen->border,
  2674.                 &junk, &junk);
  2675.             XSync(screen->display, FALSE);    /* synchronize */
  2676.             if(QLength(screen->display) > 0)
  2677.                 xevents();
  2678.         }
  2679.         CursorSet(screen, 0, 0, term->flags);
  2680.     }
  2681.     longjmp(vtjmpbuf, 1);    /* force ground state in parser */
  2682. }
  2683.  
  2684.  
  2685.  
  2686. /*
  2687.  * set_character_class - takes a string of the form
  2688.  * 
  2689.  *                 low[-high]:val[,low[-high]:val[...]]
  2690.  * 
  2691.  * and sets the indicated ranges to the indicated values.
  2692.  */
  2693.  
  2694. int set_character_class (s)
  2695.     register char *s;
  2696. {
  2697.     register int i;            /* iterator, index into s */
  2698.     int len;                /* length of s */
  2699.     int acc;                /* accumulator */
  2700.     int low, high;            /* bounds of range [0..127] */
  2701.     int base;                /* 8, 10, 16 (octal, decimal, hex) */
  2702.     int numbers;            /* count of numbers per range */
  2703.     int digits;                /* count of digits in a number */
  2704.     static char *errfmt = "%s:  %s in range string \"%s\" (position %d)\n";
  2705.     extern char *ProgramName;
  2706.  
  2707.     if (!s || !s[0]) return -1;
  2708.  
  2709.     base = 10;                /* in case we ever add octal, hex */
  2710.     low = high = -1;            /* out of range */
  2711.  
  2712.     for (i = 0, len = strlen (s), acc = 0, numbers = digits = 0;
  2713.      i < len; i++) {
  2714.     char c = s[i];
  2715.  
  2716.     if (isspace(c)) {
  2717.         continue;
  2718.     } else if (isdigit(c)) {
  2719.         acc = acc * base + (c - '0');
  2720.         digits++;
  2721.         continue;
  2722.     } else if (c == '-') {
  2723.         low = acc;
  2724.         acc = 0;
  2725.         if (digits == 0) {
  2726.         fprintf (stderr, errfmt, ProgramName, "missing number", s, i);
  2727.         return (-1);
  2728.         }
  2729.         digits = 0;
  2730.         numbers++;
  2731.         continue;
  2732.     } else if (c == ':') {
  2733.         if (numbers == 0)
  2734.           low = acc;
  2735.         else if (numbers == 1)
  2736.           high = acc;
  2737.         else {
  2738.         fprintf (stderr, errfmt, ProgramName, "too many numbers",
  2739.              s, i);
  2740.         return (-1);
  2741.         }
  2742.         digits = 0;
  2743.         numbers++;
  2744.         acc = 0;
  2745.         continue;
  2746.     } else if (c == ',') {
  2747.         /*
  2748.          * now, process it
  2749.          */
  2750.  
  2751.         if (high < 0) {
  2752.         high = low;
  2753.         numbers++;
  2754.         }
  2755.         if (numbers != 2) {
  2756.         fprintf (stderr, errfmt, ProgramName, "bad value number", 
  2757.              s, i);
  2758.         } else if (SetCharacterClassRange (low, high, acc) != 0) {
  2759.         fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
  2760.         }
  2761.  
  2762.         low = high = -1;
  2763.         acc = 0;
  2764.         digits = 0;
  2765.         numbers = 0;
  2766.         continue;
  2767.     } else {
  2768.         fprintf (stderr, errfmt, ProgramName, "bad character", s, i);
  2769.         return (-1);
  2770.     }                /* end if else if ... else */
  2771.  
  2772.     }
  2773.  
  2774.     if (low < 0 && high < 0) return (0);
  2775.  
  2776.     /*
  2777.      * now, process it
  2778.      */
  2779.  
  2780.     if (high < 0) high = low;
  2781.     if (numbers < 1 || numbers > 2) {
  2782.     fprintf (stderr, errfmt, ProgramName, "bad value number", s, i);
  2783.     } else if (SetCharacterClassRange (low, high, acc) != 0) {
  2784.     fprintf (stderr, errfmt, ProgramName, "bad range", s, i);
  2785.     }
  2786.  
  2787.     return (0);
  2788. }
  2789.  
  2790. /* ARGSUSED */
  2791. static void HandleKeymapChange(w, event, params, param_count)
  2792.     Widget w;
  2793.     XEvent *event;
  2794.     String *params;
  2795.     Cardinal *param_count;
  2796. {
  2797.     static XtTranslations keymap, original;
  2798.     static XtResource key_resources[] = {
  2799.     { XtNtranslations, XtCTranslations, XtRTranslationTable,
  2800.           sizeof(XtTranslations), 0, XtRTranslationTable, (caddr_t)NULL}
  2801.     };
  2802.     char mapName[1000];
  2803.     char mapClass[1000];
  2804.  
  2805.     if (*param_count != 1) return;
  2806.  
  2807.     if (original == NULL) original = w->core.tm.translations;
  2808.  
  2809.     if (strcmp(params[0], "None") == 0) {
  2810.     XtOverrideTranslations(w, original);
  2811.     return;
  2812.     }
  2813.     (void) sprintf( mapName, "%sKeymap", params[0] );
  2814.     (void) strcpy( mapClass, mapName );
  2815.     if (islower(mapClass[0])) mapClass[0] = toupper(mapClass[0]);
  2816.     XtGetSubresources( w, (XtPointer)&keymap, mapName, mapClass,
  2817.                key_resources, (Cardinal)1, NULL, (Cardinal)0 );
  2818.     if (keymap != NULL)
  2819.     XtOverrideTranslations(w, keymap);
  2820. }
  2821.  
  2822.  
  2823. /* ARGSUSED */
  2824. static void HandleBell(w, event, params, param_count)
  2825.     Widget w;
  2826.     XEvent *event;        /* unused */
  2827.     String *params;        /* [0] = volume */
  2828.     Cardinal *param_count;    /* 0 or 1 */
  2829. {
  2830.     int percent = (*param_count) ? atoi(params[0]) : 0;
  2831.  
  2832.     XBell( XtDisplay(w), percent );
  2833. }
  2834.  
  2835.  
  2836. /* ARGSUSED */
  2837. static void HandleVisualBell(w, event, params, param_count)
  2838.     Widget w;
  2839.     XEvent *event;        /* unused */
  2840.     String *params;        /* unused */
  2841.     Cardinal *param_count;    /* unused */
  2842. {
  2843.     VisualBell();
  2844. }
  2845.  
  2846.  
  2847. /* ARGSUSED */
  2848. static void HandleIgnore(w, event, params, param_count)
  2849.     Widget w;
  2850.     XEvent *event;        /* unused */
  2851.     String *params;        /* unused */
  2852.     Cardinal *param_count;    /* unused */
  2853. {
  2854.     /* do nothing, but check for funny escape sequences */
  2855.     (void) SendMousePosition(w, event);
  2856. }
  2857.  
  2858.  
  2859. /* ARGSUSED */
  2860. static void
  2861. DoSetSelectedFont(w, client_data, selection, type, value, length, format)
  2862.     Widget w;
  2863.     XtPointer client_data;
  2864.     Atom *selection, *type;
  2865.     XtPointer value;
  2866.     unsigned long *length;
  2867.     int *format;
  2868. {
  2869.     char *val = (char *)value;
  2870.     int len;
  2871.     if (*type != XA_STRING  ||  *format != 8) {
  2872.     Bell();
  2873.     return;
  2874.     }
  2875.     len = strlen(val);
  2876.     if (len > 0) {
  2877.     if (val[len-1] == '\n') val[len-1] = '\0';
  2878.     /* Do some sanity checking to avoid sending a long selection
  2879.        back to the server in an OpenFont that is unlikely to succeed.
  2880.        XLFD allows up to 255 characters and no control characters;
  2881.        we are a little more liberal here. */
  2882.     if (len > 1000  ||  strchr(val, '\n'))
  2883.         return;
  2884.     if (!LoadNewFont (&term->screen, val, NULL, True, fontMenu_fontsel))
  2885.         Bell();
  2886.     }
  2887. }
  2888.  
  2889. void FindFontSelection (atom_name, justprobe)
  2890.     char *atom_name;
  2891.     Bool justprobe;
  2892. {
  2893.     static AtomPtr *atoms;
  2894.     static int atomCount = 0;
  2895.     AtomPtr *pAtom;
  2896.     int a;
  2897.     Atom target;
  2898.  
  2899.     if (!atom_name) atom_name = "PRIMARY";
  2900.  
  2901.     for (pAtom = atoms, a = atomCount; a; a--, pAtom++) {
  2902.     if (strcmp(atom_name, XmuNameOfAtom(*pAtom)) == 0) break;
  2903.     }
  2904.     if (!a) {
  2905.     atoms = (AtomPtr*) XtRealloc ((char *)atoms,
  2906.                       sizeof(AtomPtr)*(atomCount+1));
  2907.     *(pAtom = &atoms[atomCount++]) = XmuMakeAtom(atom_name);
  2908.     }
  2909.  
  2910.     target = XmuInternAtom(XtDisplay(term), *pAtom);
  2911.     if (justprobe) {
  2912.     term->screen.menu_font_names[fontMenu_fontsel] = 
  2913.       XGetSelectionOwner(XtDisplay(term), target) ? _Font_Selected_ : NULL;
  2914.     } else {
  2915.     XtGetSelectionValue((Widget)term, target, XA_STRING,
  2916.                 DoSetSelectedFont, NULL,
  2917.                 XtLastTimestampProcessed(XtDisplay(term)));
  2918.     }
  2919.     return;
  2920. }
  2921.  
  2922.  
  2923. /* ARGSUSED */
  2924. void HandleSetFont(w, event, params, param_count)
  2925.     Widget w;
  2926.     XEvent *event;        /* unused */
  2927.     String *params;        /* unused */
  2928.     Cardinal *param_count;    /* unused */
  2929. {
  2930.     int fontnum;
  2931.     char *name1 = NULL, *name2 = NULL;
  2932.  
  2933.     if (*param_count == 0) {
  2934.     fontnum = fontMenu_fontdefault;
  2935.     } else {
  2936.     int maxparams = 1;        /* total number of params allowed */
  2937.  
  2938.     switch (params[0][0]) {
  2939.       case 'd': case 'D': case '0':
  2940.         fontnum = fontMenu_fontdefault; break;
  2941.       case '1':
  2942.         fontnum = fontMenu_font1; break;
  2943.       case '2':
  2944.         fontnum = fontMenu_font2; break;
  2945.       case '3':
  2946.         fontnum = fontMenu_font3; break;
  2947.       case '4':
  2948.         fontnum = fontMenu_font4; break;
  2949.       case 'e': case 'E':
  2950.         fontnum = fontMenu_fontescape; maxparams = 3; break;
  2951.       case 's': case 'S':
  2952.         fontnum = fontMenu_fontsel; maxparams = 2; break;
  2953.       default:
  2954.         Bell();
  2955.         return;
  2956.     }
  2957.     if (*param_count > maxparams) {     /* see if extra args given */
  2958.         Bell();
  2959.         return;
  2960.     }
  2961.     switch (*param_count) {        /* assign 'em */
  2962.       case 3:
  2963.         name2 = params[2];
  2964.         /* fall through */
  2965.       case 2:
  2966.         name1 = params[1];
  2967.         break;
  2968.     }
  2969.     }
  2970.  
  2971.     SetVTFont (fontnum, True, name1, name2);
  2972. }
  2973.  
  2974.  
  2975. void SetVTFont (i, doresize, name1, name2)
  2976.     int i;
  2977.     Bool doresize;
  2978.     char *name1, *name2;
  2979. {
  2980.     TScreen *screen = &term->screen;
  2981.  
  2982.     if (i < 0 || i >= NMENUFONTS) {
  2983.     Bell();
  2984.     return;
  2985.     }
  2986.     if (i == fontMenu_fontsel) {    /* go get the selection */
  2987.     FindFontSelection (name1, False);  /* name1 = atom, name2 is ignored */
  2988.     return;
  2989.     }
  2990.     if (!name1) name1 = screen->menu_font_names[i];
  2991.     if (!LoadNewFont(screen, name1, name2, doresize, i)) {
  2992.     Bell();
  2993.     }
  2994.     return;
  2995. }
  2996.  
  2997.  
  2998. int LoadNewFont (screen, nfontname, bfontname, doresize, fontnum)
  2999.     TScreen *screen;
  3000.     char *nfontname, *bfontname;
  3001.     Bool doresize;
  3002.     int fontnum;
  3003. {
  3004.     XFontStruct *nfs = NULL, *bfs = NULL;
  3005.     XGCValues xgcv;
  3006.     unsigned long mask;
  3007.     GC new_normalGC = NULL, new_normalboldGC = NULL;
  3008.     GC new_reverseGC = NULL, new_reverseboldGC = NULL;
  3009.     char *tmpname = NULL;
  3010.  
  3011.     if (!nfontname) return 0;
  3012.  
  3013.     if (fontnum == fontMenu_fontescape &&
  3014.     nfontname != screen->menu_font_names[fontnum]) {
  3015.     tmpname = (char *) malloc (strlen(nfontname) + 1);
  3016.     if (!tmpname) return 0;
  3017.     strcpy (tmpname, nfontname);
  3018.     }
  3019.  
  3020.     if (!(nfs = XLoadQueryFont (screen->display, nfontname))) goto bad;
  3021.  
  3022.     if (!(bfontname && 
  3023.       (bfs = XLoadQueryFont (screen->display, bfontname))))
  3024.       bfs = nfs;
  3025.  
  3026.     mask = (GCFont | GCForeground | GCBackground | GCGraphicsExposures |
  3027.         GCFunction);
  3028.  
  3029.     xgcv.font = nfs->fid;
  3030.     xgcv.foreground = screen->foreground;
  3031.     xgcv.background = term->core.background_pixel;
  3032.     xgcv.graphics_exposures = TRUE;    /* default */
  3033.     xgcv.function = GXcopy;
  3034.  
  3035.     new_normalGC = XtGetGC((Widget)term, mask, &xgcv);
  3036.     if (!new_normalGC) goto bad;
  3037.  
  3038.     if (nfs == bfs) {            /* there is no bold font */
  3039.     new_normalboldGC = new_normalGC;
  3040.     } else {
  3041.     xgcv.font = bfs->fid;
  3042.     new_normalboldGC = XtGetGC((Widget)term, mask, &xgcv);
  3043.     if (!new_normalboldGC) goto bad;
  3044.     }
  3045.  
  3046.     xgcv.font = nfs->fid;
  3047.     xgcv.foreground = term->core.background_pixel;
  3048.     xgcv.background = screen->foreground;
  3049.     new_reverseGC = XtGetGC((Widget)term, mask, &xgcv);
  3050.     if (!new_reverseGC) goto bad;
  3051.  
  3052.     if (nfs == bfs) {            /* there is no bold font */
  3053.     new_reverseboldGC = new_reverseGC;
  3054.     } else {
  3055.     xgcv.font = bfs->fid;
  3056.     new_reverseboldGC = XtGetGC((Widget)term, mask, &xgcv);
  3057.     if (!new_reverseboldGC) goto bad;
  3058.     }
  3059.  
  3060.     if (screen->normalGC != screen->normalboldGC)
  3061.     XtReleaseGC ((Widget) term, screen->normalboldGC);
  3062.     XtReleaseGC ((Widget) term, screen->normalGC);
  3063.     if (screen->reverseGC != screen->reverseboldGC)
  3064.     XtReleaseGC ((Widget) term, screen->reverseboldGC);
  3065.     XtReleaseGC ((Widget) term, screen->reverseGC);
  3066.     screen->normalGC = new_normalGC;
  3067.     screen->normalboldGC = new_normalboldGC;
  3068.     screen->reverseGC = new_reverseGC;
  3069.     screen->reverseboldGC = new_reverseboldGC;
  3070.     screen->fnt_norm = nfs;
  3071.     screen->fnt_bold = bfs;
  3072.     screen->enbolden = (nfs == bfs);
  3073.     set_menu_font (False);
  3074.     screen->menu_font_number = fontnum;
  3075.     set_menu_font (True);
  3076.     if (tmpname) {            /* if setting escape or sel */
  3077.     if (screen->menu_font_names[fontnum])
  3078.       free (screen->menu_font_names[fontnum]);
  3079.     screen->menu_font_names[fontnum] = tmpname;
  3080.     if (fontnum == fontMenu_fontescape) {
  3081.         set_sensitivity (term->screen.fontMenu,
  3082.                  fontMenuEntries[fontMenu_fontescape].widget,
  3083.                  TRUE);
  3084.     }
  3085.     }
  3086.     set_cursor_gcs (screen);
  3087.     update_font_info (screen, doresize);
  3088.     return 1;
  3089.  
  3090.   bad:
  3091.     if (tmpname) free (tmpname);
  3092.     if (new_normalGC)
  3093.       XtReleaseGC ((Widget) term, screen->normalGC);
  3094.     if (new_normalGC && new_normalGC != new_normalboldGC)
  3095.       XtReleaseGC ((Widget) term, new_normalboldGC);
  3096.     if (new_reverseGC)
  3097.       XtReleaseGC ((Widget) term, new_reverseGC);
  3098.     if (new_reverseGC && new_reverseGC != new_reverseboldGC)
  3099.       XtReleaseGC ((Widget) term, new_reverseboldGC);
  3100.     if (nfs) XFreeFont (screen->display, nfs);
  3101.     if (nfs && nfs != bfs) XFreeFont (screen->display, bfs);
  3102.     return 0;
  3103. }
  3104.  
  3105.  
  3106. update_font_info (screen, doresize)
  3107.     TScreen *screen;
  3108.     Bool doresize;
  3109. {
  3110.     int i, j, width, height, scrollbar_width;
  3111.  
  3112.     screen->fullVwin.f_width = screen->fnt_norm->max_bounds.width;
  3113.     screen->fullVwin.f_height = (screen->fnt_norm->ascent +
  3114.                  screen->fnt_norm->descent);
  3115.     scrollbar_width = (term->misc.scrollbar ? 
  3116.                screen->scrollWidget->core.width +
  3117.                screen->scrollWidget->core.border_width : 0);
  3118.     i = 2 * screen->border + scrollbar_width;
  3119.     j = 2 * screen->border;
  3120.     width = (screen->max_col + 1) * screen->fullVwin.f_width + i;
  3121.     height = (screen->max_row + 1) * screen->fullVwin.f_height + j;
  3122.     screen->fullVwin.fullwidth = width;
  3123.     screen->fullVwin.fullheight = height;
  3124.     screen->fullVwin.width = width - i;
  3125.     screen->fullVwin.height = height - j;
  3126.  
  3127.     if (doresize) {
  3128.     if (VWindow(screen)) {
  3129.         XClearWindow (screen->display, VWindow(screen));
  3130.     }
  3131.     DoResizeScreen (term);        /* set to the new natural size */
  3132.     if (screen->scrollWidget)
  3133.       ResizeScrollBar (screen->scrollWidget, -1, -1,
  3134.                Height(screen) + screen->border * 2);
  3135.     Redraw ();
  3136.     }
  3137.     set_vt_box (screen);
  3138. }
  3139.  
  3140. set_vt_box (screen)
  3141.     TScreen *screen;
  3142. {
  3143.     XPoint    *vp;
  3144.  
  3145.     vp = &VTbox[1];
  3146.     (vp++)->x = FontWidth(screen) - 1;
  3147.     (vp++)->y = FontHeight(screen) - 1;
  3148.     (vp++)->x = -(FontWidth(screen) - 1);
  3149.     vp->y = -(FontHeight(screen) - 1);
  3150.     screen->box = VTbox;
  3151. }
  3152.  
  3153.  
  3154. set_cursor_gcs (screen)
  3155.     TScreen *screen;
  3156. {
  3157.     XGCValues xgcv;
  3158.     unsigned long mask;
  3159.     unsigned long cc = screen->cursorcolor;
  3160.     unsigned long fg = screen->foreground;
  3161.     unsigned long bg = term->core.background_pixel;
  3162.     GC new_cursorGC = NULL, new_reversecursorGC = NULL;
  3163.     GC new_cursoroutlineGC = NULL;
  3164.  
  3165.     /*
  3166.      * Let's see, there are three things that have "color":
  3167.      *
  3168.      *     background
  3169.      *     text
  3170.      *     cursorblock
  3171.      *
  3172.      * And, there are four situation when drawing a cursor, if we decide
  3173.      * that we like have a solid block of cursor color with the letter
  3174.      * that it is highlighting shown in the background color to make it
  3175.      * stand out:
  3176.      *
  3177.      *     selected window, normal video - background on cursor
  3178.      *     selected window, reverse video - foreground on cursor
  3179.      *     unselected window, normal video - foreground on background
  3180.      *     unselected window, reverse video - background on foreground
  3181.      *
  3182.      * Since the last two are really just normalGC and reverseGC, we only
  3183.      * need two new GC's.  Under monochrome, we get the same effect as
  3184.      * above by setting cursor color to foreground.
  3185.      */
  3186.  
  3187.     xgcv.font = screen->fnt_norm->fid;
  3188.     mask = (GCForeground | GCBackground | GCFont);
  3189.     if (cc != fg && cc != bg) {
  3190.     /* we have a colored cursor */
  3191.     xgcv.foreground = fg;
  3192.     xgcv.background = cc;
  3193.     new_cursorGC = XtGetGC ((Widget) term, mask, &xgcv);
  3194.  
  3195.     if (screen->always_highlight) {
  3196.         new_reversecursorGC = (GC) 0;
  3197.         new_cursoroutlineGC = (GC) 0;
  3198.     } else {
  3199.         xgcv.foreground = bg;
  3200.         xgcv.background = cc;
  3201.         new_reversecursorGC = XtGetGC ((Widget) term, mask, &xgcv);
  3202.         xgcv.foreground = cc;
  3203.         xgcv.background = bg;
  3204.         new_cursoroutlineGC = XtGetGC ((Widget) term, mask, &xgcv);
  3205.         }
  3206.     } else {
  3207.     new_cursorGC = (GC) 0;
  3208.     new_reversecursorGC = (GC) 0;
  3209.     new_cursoroutlineGC = (GC) 0;
  3210.     }
  3211.     if (screen->cursorGC) XtReleaseGC ((Widget)term, screen->cursorGC);
  3212.     if (screen->reversecursorGC)
  3213.     XtReleaseGC ((Widget)term, screen->reversecursorGC);
  3214.     if (screen->cursoroutlineGC)
  3215.     XtReleaseGC ((Widget)term, screen->cursoroutlineGC);
  3216.     screen->cursorGC = new_cursorGC;
  3217.     screen->reversecursorGC = new_reversecursorGC;
  3218.     screen->cursoroutlineGC = new_cursoroutlineGC;
  3219. }
  3220.