PageRenderTime 53ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/nx-3.5.0/nx-X11/programs/xterm/Tekproc.c

#
C | 1782 lines | 1455 code | 183 blank | 144 comment | 248 complexity | dfd02801e50323896f9d707cb84c75f8 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
  1. /* $XTermId: Tekproc.c,v 1.131 2005/11/03 13:17:27 tom Exp $ */
  2. /*
  3. * $Xorg: Tekproc.c,v 1.5 2001/02/09 02:06:02 xorgcvs Exp $
  4. *
  5. * Warning, there be crufty dragons here.
  6. */
  7. /* $XFree86: xc/programs/xterm/Tekproc.c,v 3.55 2005/11/03 13:17:27 dickey Exp $ */
  8. /*
  9. Copyright 2001-2004,2005 by Thomas E. Dickey
  10. All Rights Reserved
  11. Permission is hereby granted, free of charge, to any person obtaining a
  12. copy of this software and associated documentation files (the
  13. "Software"), to deal in the Software without restriction, including
  14. without limitation the rights to use, copy, modify, merge, publish,
  15. distribute, sublicense, and/or sell copies of the Software, and to
  16. permit persons to whom the Software is furnished to do so, subject to
  17. the following conditions:
  18. The above copyright notice and this permission notice shall be included
  19. in all copies or substantial portions of the Software.
  20. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
  24. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  25. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  26. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. Except as contained in this notice, the name(s) of the above copyright
  28. holders shall not be used in advertising or otherwise to promote the
  29. sale, use or other dealings in this Software without prior written
  30. authorization.
  31. Copyright 1988 The Open Group
  32. Permission to use, copy, modify, distribute, and sell this software and its
  33. documentation for any purpose is hereby granted without fee, provided that
  34. the above copyright notice appear in all copies and that both that
  35. copyright notice and this permission notice appear in supporting
  36. documentation.
  37. The above copyright notice and this permission notice shall be included in
  38. all copies or substantial portions of the Software.
  39. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  40. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  41. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  42. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  43. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  44. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  45. Except as contained in this notice, the name of The Open Group shall not be
  46. used in advertising or otherwise to promote the sale, use or other dealings
  47. in this Software without prior written authorization from The Open Group.
  48. * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  49. *
  50. * All Rights Reserved
  51. *
  52. * Permission to use, copy, modify, and distribute this software and its
  53. * documentation for any purpose and without fee is hereby granted,
  54. * provided that the above copyright notice appear in all copies and that
  55. * both that copyright notice and this permission notice appear in
  56. * supporting documentation, and that the name of Digital Equipment
  57. * Corporation not be used in advertising or publicity pertaining to
  58. * distribution of the software without specific, written prior permission.
  59. *
  60. *
  61. * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  62. * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  63. * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  64. * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  65. * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  66. * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  67. * SOFTWARE.
  68. */
  69. /* Tekproc.c */
  70. #define RES_OFFSET(field) XtOffsetOf(TekWidgetRec, field)
  71. #include <xterm.h>
  72. #include <X11/Xatom.h>
  73. #include <X11/Xutil.h>
  74. #include <X11/cursorfont.h>
  75. #include <X11/Xmu/CharSet.h>
  76. #if OPT_TOOLBAR
  77. #if defined(HAVE_LIB_XAW)
  78. #include <X11/Xaw/Form.h>
  79. #elif defined(HAVE_LIB_XAW3D)
  80. #include <X11/Xaw3d/Form.h>
  81. #elif defined(HAVE_LIB_NEXTAW)
  82. #include <X11/neXtaw/Form.h>
  83. #elif defined(HAVE_LIB_XAWPLUS)
  84. #include <X11/XawPlus/Form.h>
  85. #endif
  86. #endif /* OPT_TOOLBAR */
  87. #include <stdio.h>
  88. #include <ctype.h>
  89. #include <signal.h>
  90. #include <Tekparse.h>
  91. #include <data.h>
  92. #include <error.h>
  93. #include <menu.h>
  94. #define DefaultGCID XGContextFromGC(DefaultGC(screen->display, DefaultScreen(screen->display)))
  95. /* Tek defines */
  96. #define DOTDASHEDLINE 2
  97. #define DOTTEDLINE 1
  98. #define EAST 01
  99. #define LINEMASK 07
  100. #define LONGDASHEDLINE 4
  101. #define MARGIN1 0
  102. #define MARGIN2 1
  103. #define MAX_PTS 150
  104. #define MAX_VTX 300
  105. #define NORTH 04
  106. #define PENDOWN 1
  107. #define PENUP 0
  108. #define SHORTDASHEDLINE 3
  109. #define SOLIDLINE 0
  110. #define SOUTH 010
  111. #define TEKBOTTOMPAD 23
  112. #define TEKDEFHEIGHT 565
  113. #define TEKDEFWIDTH 750
  114. #define TEKHEIGHT 3072
  115. #define TEKHOME ((TekChar[screen->page.fontsize].nlines - 1)\
  116. * TekChar[screen->page.fontsize].vsize)
  117. #define TEKMINHEIGHT 452
  118. #define TEKMINWIDTH 600
  119. #define TEKTOPPAD 34
  120. #define TEKWIDTH 4096
  121. #define WEST 02
  122. #define TekMove(x,y) screen->cur_X = x; screen->cur_Y = y
  123. #define input() Tinput()
  124. #define unput(c) *Tpushback++ = c
  125. /* *INDENT-OFF* */
  126. static struct Tek_Char {
  127. int hsize; /* in Tek units */
  128. int vsize; /* in Tek units */
  129. int charsperline;
  130. int nlines;
  131. } TekChar[TEKNUMFONTS] = {
  132. {56, 88, 74, 35}, /* large */
  133. {51, 82, 81, 38}, /* #2 */
  134. {34, 53, 121, 58}, /* #3 */
  135. {31, 48, 133, 64}, /* small */
  136. };
  137. /* *INDENT-ON* */
  138. static Cursor GINcursor;
  139. static XSegment *line_pt;
  140. static int nplot;
  141. static TekLink Tek0;
  142. static jmp_buf Tekjump;
  143. static TekLink *TekRecord;
  144. static XSegment *Tline;
  145. static Const int *curstate = Talptable;
  146. static Const int *Tparsestate = Talptable;
  147. static char defaultTranslations[] = "\
  148. ~Meta<KeyPress>: insert-seven-bit() \n\
  149. Meta<KeyPress>: insert-eight-bit() \n\
  150. !Ctrl <Btn1Down>: popup-menu(mainMenu) \n\
  151. !Lock Ctrl <Btn1Down>: popup-menu(mainMenu) \n\
  152. !Lock Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\
  153. !Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\
  154. !Ctrl <Btn2Down>: popup-menu(tekMenu) \n\
  155. !Lock Ctrl <Btn2Down>: popup-menu(tekMenu) \n\
  156. !Lock Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\
  157. !Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\
  158. Shift ~Meta<Btn1Down>: gin-press(L) \n\
  159. ~Meta<Btn1Down>: gin-press(l) \n\
  160. Shift ~Meta<Btn2Down>: gin-press(M) \n\
  161. ~Meta<Btn2Down>: gin-press(m) \n\
  162. Shift ~Meta<Btn3Down>: gin-press(R) \n\
  163. ~Meta<Btn3Down>: gin-press(r)";
  164. /* *INDENT-OFF* */
  165. static XtActionsRec actionsList[] = {
  166. { "string", HandleStringEvent },
  167. { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */
  168. { "insert-seven-bit", HandleKeyPressed },
  169. { "insert-eight-bit", HandleEightBitKeyPressed },
  170. { "gin-press", HandleGINInput },
  171. { "secure", HandleSecure },
  172. { "create-menu", HandleCreateMenu },
  173. { "popup-menu", HandlePopupMenu },
  174. /* menu actions */
  175. { "allow-send-events", HandleAllowSends },
  176. { "set-visual-bell", HandleSetVisualBell },
  177. #ifdef ALLOWLOGGING
  178. { "set-logging", HandleLogging },
  179. #endif
  180. { "redraw", HandleRedraw },
  181. { "send-signal", HandleSendSignal },
  182. { "quit", HandleQuit },
  183. { "set-scrollbar", HandleScrollbar },
  184. { "set-jumpscroll", HandleJumpscroll },
  185. { "set-reverse-video", HandleReverseVideo },
  186. { "set-autowrap", HandleAutoWrap },
  187. { "set-reversewrap", HandleReverseWrap },
  188. { "set-autolinefeed", HandleAutoLineFeed },
  189. { "set-appcursor", HandleAppCursor },
  190. { "set-appkeypad", HandleAppKeypad },
  191. { "set-scroll-on-key", HandleScrollKey },
  192. { "set-scroll-on-tty-output", HandleScrollTtyOutput },
  193. { "set-allow132", HandleAllow132 },
  194. { "set-cursesemul", HandleCursesEmul },
  195. { "set-marginbell", HandleMarginBell },
  196. { "set-altscreen", HandleAltScreen },
  197. { "soft-reset", HandleSoftReset },
  198. { "hard-reset", HandleHardReset },
  199. { "set-terminal-type", HandleSetTerminalType },
  200. { "set-visibility", HandleVisibility },
  201. { "set-tek-text", HandleSetTekText },
  202. { "tek-page", HandleTekPage },
  203. { "tek-reset", HandleTekReset },
  204. { "tek-copy", HandleTekCopy },
  205. #if OPT_TOOLBAR
  206. { "set-toolbar", HandleToolbar },
  207. #endif
  208. };
  209. /* *INDENT-ON* */
  210. static Dimension defOne = 1;
  211. #define GIN_TERM_NONE_STR "none"
  212. #define GIN_TERM_CR_STR "CRonly"
  213. #define GIN_TERM_EOT_STR "CR&EOT"
  214. #define GIN_TERM_NONE 0
  215. #define GIN_TERM_CR 1
  216. #define GIN_TERM_EOT 2
  217. #ifdef VMS
  218. #define DFT_FONT_SMALL "FIXED"
  219. #else
  220. #define DFT_FONT_SMALL "6x10"
  221. #endif
  222. static XtResource resources[] =
  223. {
  224. {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
  225. XtOffsetOf(CoreRec, core.width), XtRDimension, (caddr_t) & defOne},
  226. {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
  227. XtOffsetOf(CoreRec, core.height), XtRDimension, (caddr_t) & defOne},
  228. Fres("fontLarge", XtCFont, tek.Tfont[TEK_FONT_LARGE], "9x15"),
  229. Fres("font2", XtCFont, tek.Tfont[TEK_FONT_2], "6x13"),
  230. Fres("font3", XtCFont, tek.Tfont[TEK_FONT_3], "8x13"),
  231. Fres("fontSmall", XtCFont, tek.Tfont[TEK_FONT_SMALL], DFT_FONT_SMALL),
  232. Sres("initialFont", "InitialFont", tek.initial_font, "large"),
  233. Sres("ginTerminator", "GinTerminator", tek.gin_terminator_str, GIN_TERM_NONE_STR),
  234. #if OPT_TOOLBAR
  235. Wres(XtNmenuBar, XtCMenuBar, tek.tb_info.menu_bar, 0),
  236. Ires(XtNmenuHeight, XtCMenuHeight, tek.tb_info.menu_height, 25),
  237. #endif
  238. };
  239. static IChar Tinput(void);
  240. static int getpoint(void);
  241. static void TCursorBack(void);
  242. static void TCursorDown(void);
  243. static void TCursorForward(void);
  244. static void TCursorUp(void);
  245. static void TekBackground(TScreen * screen);
  246. static void TekConfigure(Widget w);
  247. static void TekDraw(int x, int y);
  248. static void TekEnq(unsigned status, int x, int y);
  249. static void TekFlush(void);
  250. static void TekInitialize(Widget request,
  251. Widget wnew,
  252. ArgList args,
  253. Cardinal *num_args);
  254. static void TekPage(void);
  255. static void TekRealize(Widget gw,
  256. XtValueMask * valuemaskp,
  257. XSetWindowAttributes * values);
  258. static WidgetClassRec tekClassRec =
  259. {
  260. {
  261. /* core_class fields */
  262. (WidgetClass) & widgetClassRec, /* superclass */
  263. "Tek4014", /* class_name */
  264. sizeof(TekWidgetRec), /* widget_size */
  265. NULL, /* class_initialize */
  266. NULL, /* class_part_initialize */
  267. False, /* class_inited */
  268. TekInitialize, /* initialize */
  269. NULL, /* initialize_hook */
  270. TekRealize, /* realize */
  271. actionsList, /* actions */
  272. XtNumber(actionsList), /* num_actions */
  273. resources, /* resources */
  274. XtNumber(resources), /* num_resources */
  275. NULLQUARK, /* xrm_class */
  276. True, /* compress_motion */
  277. True, /* compress_exposure */
  278. True, /* compress_enterleave */
  279. False, /* visible_interest */
  280. NULL, /* destroy */
  281. TekConfigure, /* resize */
  282. TekExpose, /* expose */
  283. NULL, /* set_values */
  284. NULL, /* set_values_hook */
  285. XtInheritSetValuesAlmost, /* set_values_almost */
  286. NULL, /* get_values_hook */
  287. NULL, /* accept_focus */
  288. XtVersion, /* version */
  289. NULL, /* callback_offsets */
  290. defaultTranslations, /* tm_table */
  291. XtInheritQueryGeometry, /* query_geometry */
  292. XtInheritDisplayAccelerator, /* display_accelerator */
  293. NULL /* extension */
  294. }
  295. };
  296. #define tekWidgetClass ((WidgetClass)&tekClassRec)
  297. static Bool Tfailed = False;
  298. int
  299. TekInit(void)
  300. {
  301. Widget form_top, menu_top;
  302. if (!Tfailed
  303. && tekWidget == 0) {
  304. TRACE(("TekInit\n"));
  305. /* this causes the Initialize method to be called */
  306. tekshellwidget =
  307. XtCreatePopupShell("tektronix", topLevelShellWidgetClass,
  308. toplevel, ourTopLevelShellArgs,
  309. number_ourTopLevelShellArgs);
  310. SetupMenus(tekshellwidget, &form_top, &menu_top);
  311. /* this causes the Realize method to be called */
  312. tekWidget = (TekWidget)
  313. XtVaCreateManagedWidget("tek4014",
  314. tekWidgetClass, form_top,
  315. #if OPT_TOOLBAR
  316. XtNmenuBar, menu_top,
  317. XtNresizable, True,
  318. XtNfromVert, menu_top,
  319. XtNtop, XawChainTop,
  320. XtNleft, XawChainLeft,
  321. XtNright, XawChainRight,
  322. XtNbottom, XawChainBottom,
  323. #endif
  324. (XtPointer) 0);
  325. #if OPT_TOOLBAR
  326. ShowToolbar(resource.toolBar);
  327. #endif
  328. }
  329. return (!Tfailed);
  330. }
  331. /*
  332. * If we haven't allocated the PtyData struct, do so.
  333. */
  334. int
  335. TekPtyData(void)
  336. {
  337. if (Tpushb == 0) {
  338. if ((Tpushb = TypeMallocN(Char, 10)) == NULL
  339. || (Tline = TypeMallocN(XSegment, MAX_VTX)) == NULL) {
  340. fprintf(stderr, "%s: Not enough core for Tek mode\n", xterm_name);
  341. if (Tpushb)
  342. free(Tpushb);
  343. Tfailed = True;
  344. return 0;
  345. }
  346. }
  347. return 1;
  348. }
  349. static void
  350. Tekparse(void)
  351. {
  352. TScreen *screen = &term->screen;
  353. int x, y;
  354. IChar c = 0;
  355. IChar ch;
  356. int nextstate;
  357. for (;;) {
  358. c = input();
  359. /*
  360. * The parsing tables all have 256 entries. If we're supporting
  361. * wide characters, we handle them by treating them the same as
  362. * printing characters.
  363. */
  364. #if OPT_WIDE_CHARS
  365. if (c > 255) {
  366. nextstate = (Tparsestate == Talptable)
  367. ? CASE_PRINT
  368. : CASE_IGNORE;
  369. } else
  370. #endif
  371. nextstate = Tparsestate[c];
  372. TRACE(("Tekparse %04X -> %d\n", c, nextstate));
  373. switch (nextstate) {
  374. case CASE_REPORT:
  375. TRACE(("case: report address\n"));
  376. if (screen->TekGIN) {
  377. TekGINoff();
  378. TekEnqMouse(0);
  379. } else {
  380. c = 064; /* has hard copy unit */
  381. if (screen->margin == MARGIN2)
  382. c |= 02;
  383. TekEnq(c, screen->cur_X, screen->cur_Y);
  384. }
  385. TekRecord->ptr[-1] = NAK; /* remove from recording */
  386. Tparsestate = curstate;
  387. break;
  388. case CASE_VT_MODE:
  389. TRACE(("case: special return to vt102 mode\n"));
  390. Tparsestate = curstate;
  391. TekRecord->ptr[-1] = NAK; /* remove from recording */
  392. FlushLog(screen);
  393. return;
  394. case CASE_SPT_STATE:
  395. TRACE(("case: Enter Special Point Plot mode\n"));
  396. if (screen->TekGIN)
  397. TekGINoff();
  398. Tparsestate = curstate = Tspttable;
  399. break;
  400. case CASE_GIN:
  401. TRACE(("case: Do Tek GIN mode\n"));
  402. screen->TekGIN = &TekRecord->ptr[-1];
  403. /* Set cross-hair cursor raster array */
  404. if ((GINcursor =
  405. make_colored_cursor(XC_tcross,
  406. T_COLOR(screen, MOUSE_FG),
  407. T_COLOR(screen, MOUSE_BG))) != 0) {
  408. XDefineCursor(screen->display, TWindow(screen),
  409. GINcursor);
  410. }
  411. Tparsestate = Tbyptable; /* Bypass mode */
  412. break;
  413. case CASE_BEL:
  414. TRACE(("case: BEL\n"));
  415. if (screen->TekGIN)
  416. TekGINoff();
  417. if (!TekRefresh)
  418. Bell(XkbBI_TerminalBell, 0);
  419. Tparsestate = curstate; /* clear bypass condition */
  420. break;
  421. case CASE_BS:
  422. TRACE(("case: BS\n"));
  423. if (screen->TekGIN)
  424. TekGINoff();
  425. Tparsestate = curstate; /* clear bypass condition */
  426. TCursorBack();
  427. break;
  428. case CASE_PT_STATE:
  429. TRACE(("case: Enter Tek Point Plot mode\n"));
  430. if (screen->TekGIN)
  431. TekGINoff();
  432. Tparsestate = curstate = Tpttable;
  433. break;
  434. case CASE_PLT_STATE:
  435. TRACE(("case: Enter Tek Plot mode\n"));
  436. if (screen->TekGIN)
  437. TekGINoff();
  438. Tparsestate = curstate = Tplttable;
  439. if ((c = input()) == BEL)
  440. screen->pen = PENDOWN;
  441. else {
  442. unput(c);
  443. screen->pen = PENUP;
  444. }
  445. break;
  446. case CASE_TAB:
  447. TRACE(("case: HT\n"));
  448. if (screen->TekGIN)
  449. TekGINoff();
  450. Tparsestate = curstate; /* clear bypass condition */
  451. TCursorForward();
  452. break;
  453. case CASE_IPL_STATE:
  454. TRACE(("case: Enter Tek Incremental Plot mode\n"));
  455. if (screen->TekGIN)
  456. TekGINoff();
  457. Tparsestate = curstate = Tipltable;
  458. break;
  459. case CASE_ALP_STATE:
  460. TRACE(("case: Enter Tek Alpha mode from any other mode\n"));
  461. if (screen->TekGIN)
  462. TekGINoff();
  463. /* if in one of graphics states, move alpha cursor */
  464. if (nplot > 0) /* flush line VTbuffer */
  465. TekFlush();
  466. Tparsestate = curstate = Talptable;
  467. break;
  468. case CASE_UP:
  469. TRACE(("case: cursor up\n"));
  470. if (screen->TekGIN)
  471. TekGINoff();
  472. Tparsestate = curstate; /* clear bypass condition */
  473. TCursorUp();
  474. break;
  475. case CASE_COPY:
  476. TRACE(("case: make copy\n"));
  477. if (screen->TekGIN)
  478. TekGINoff();
  479. TekCopy();
  480. TekRecord->ptr[-1] = NAK; /* remove from recording */
  481. Tparsestate = curstate; /* clear bypass condition */
  482. break;
  483. case CASE_PAGE:
  484. TRACE(("case: Page Function\n"));
  485. if (screen->TekGIN)
  486. TekGINoff();
  487. TekPage(); /* clear bypass condition */
  488. break;
  489. case CASE_BES_STATE:
  490. TRACE(("case: Byp: an escape char\n"));
  491. Tparsestate = Tbestable;
  492. break;
  493. case CASE_BYP_STATE:
  494. TRACE(("case: set bypass condition\n"));
  495. Tparsestate = Tbyptable;
  496. break;
  497. case CASE_IGNORE:
  498. TRACE(("case: Esc: totally ignore CR, ESC, LF, ~\n"));
  499. break;
  500. case CASE_ASCII:
  501. TRACE(("case: Select ASCII char set\n"));
  502. /* ignore for now */
  503. Tparsestate = curstate;
  504. break;
  505. case CASE_APL:
  506. TRACE(("case: Select APL char set\n"));
  507. /* ignore for now */
  508. Tparsestate = curstate;
  509. break;
  510. case CASE_CHAR_SIZE:
  511. TRACE(("case: character size selector\n"));
  512. TekSetFontSize((int) (c & 03));
  513. Tparsestate = curstate;
  514. break;
  515. case CASE_BEAM_VEC:
  516. TRACE(("case: beam and vector selector\n"));
  517. /* only line types */
  518. if ((c &= LINEMASK) != screen->cur.linetype) {
  519. if (nplot > 0)
  520. TekFlush();
  521. if (c <= TEKNUMLINES)
  522. screen->cur.linetype = c;
  523. }
  524. Tparsestate = curstate;
  525. break;
  526. case CASE_CURSTATE:
  527. Tparsestate = curstate;
  528. break;
  529. case CASE_PENUP:
  530. TRACE(("case: Ipl: penup\n"));
  531. screen->pen = PENUP;
  532. break;
  533. case CASE_PENDOWN:
  534. TRACE(("case: Ipl: pendown\n"));
  535. screen->pen = PENDOWN;
  536. break;
  537. case CASE_IPL_POINT:
  538. TRACE(("case: Ipl: point\n"));
  539. x = screen->cur_X;
  540. y = screen->cur_Y;
  541. if (c & NORTH)
  542. y++;
  543. else if (c & SOUTH)
  544. y--;
  545. if (c & EAST)
  546. x++;
  547. else if (c & WEST)
  548. x--;
  549. if (screen->pen == PENDOWN)
  550. TekDraw(x, y);
  551. else
  552. TekMove(x, y);
  553. break;
  554. case CASE_PLT_VEC:
  555. TRACE(("case: Plt: vector\n"));
  556. unput(c);
  557. if (getpoint()) {
  558. if (screen->pen == PENDOWN) {
  559. TekDraw(screen->cur.x, screen->cur.y);
  560. } else {
  561. TekMove(screen->cur.x, screen->cur.y);
  562. }
  563. screen->pen = PENDOWN;
  564. }
  565. break;
  566. case CASE_PT_POINT:
  567. TRACE(("case: Pt: point\n"));
  568. unput(c);
  569. if (getpoint()) {
  570. TekMove(screen->cur.x, screen->cur.y);
  571. TekDraw(screen->cur.x, screen->cur.y);
  572. }
  573. break;
  574. case CASE_SPT_POINT:
  575. TRACE(("case: Spt: point\n"));
  576. /* ignore intensity character in c */
  577. if (getpoint()) {
  578. TekMove(screen->cur.x, screen->cur.y);
  579. TekDraw(screen->cur.x, screen->cur.y);
  580. }
  581. break;
  582. case CASE_CR:
  583. TRACE(("case: CR\n"));
  584. if (screen->TekGIN)
  585. TekGINoff();
  586. if (nplot > 0) /* flush line VTbuffer */
  587. TekFlush();
  588. screen->cur_X = screen->margin == MARGIN1 ? 0 :
  589. TEKWIDTH / 2;
  590. Tparsestate = curstate = Talptable;
  591. break;
  592. case CASE_ESC_STATE:
  593. TRACE(("case: ESC\n"));
  594. Tparsestate = Tesctable;
  595. break;
  596. case CASE_LF:
  597. TRACE(("case: LF\n"));
  598. if (screen->TekGIN)
  599. TekGINoff();
  600. TCursorDown();
  601. if (!TekRefresh)
  602. do_xevents();
  603. break;
  604. case CASE_SP:
  605. TRACE(("case: SP\n"));
  606. TCursorForward();
  607. break;
  608. case CASE_PRINT:
  609. TRACE(("case: printable character\n"));
  610. ch = c;
  611. c = screen->cur.fontsize;
  612. x = (int) (screen->cur_X * TekScale(screen))
  613. + screen->border;
  614. y = (int) ((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) * TekScale(screen))
  615. + screen->border;
  616. #if OPT_WIDE_CHARS
  617. if (screen->wide_chars
  618. && (ch > 255)) {
  619. XChar2b sbuf;
  620. sbuf.byte2 = CharOf(ch);
  621. sbuf.byte1 = CharOf(ch >> 8);
  622. XDrawImageString16(screen->display,
  623. TWindow(screen),
  624. screen->TnormalGC,
  625. x,
  626. y,
  627. &sbuf,
  628. 1);
  629. } else
  630. #endif
  631. XDrawString(screen->display,
  632. TWindow(screen),
  633. screen->TnormalGC,
  634. x,
  635. y,
  636. (char *) &ch,
  637. 1);
  638. TCursorForward();
  639. break;
  640. case CASE_OSC:
  641. /* FIXME: someone should disentangle the input queues
  642. * of this code so that it can be state-driven.
  643. */
  644. TRACE(("case: do osc escape\n"));
  645. {
  646. Char buf2[512];
  647. IChar c2;
  648. unsigned len = 0;
  649. while ((c2 = input()) != BEL) {
  650. if (!isprint(c2 & 0x7f)
  651. || len + 2 >= (int) sizeof(buf2))
  652. break;
  653. buf2[len++] = c2;
  654. }
  655. buf2[len] = 0;
  656. if (c2 == BEL)
  657. do_osc(buf2, len, BEL);
  658. }
  659. Tparsestate = curstate;
  660. break;
  661. }
  662. }
  663. }
  664. static int rcnt;
  665. static char *rptr;
  666. static PtySelect Tselect_mask;
  667. static IChar
  668. Tinput(void)
  669. {
  670. TScreen *screen = &term->screen;
  671. TekLink *tek;
  672. if (Tpushback > Tpushb)
  673. return (*--Tpushback);
  674. if (TekRefresh) {
  675. if (rcnt-- > 0)
  676. return (*rptr++);
  677. if ((tek = TekRefresh->next) != 0) {
  678. TekRefresh = tek;
  679. rptr = tek->data;
  680. rcnt = tek->count - 1;
  681. TekSetFontSize(tek->fontsize);
  682. return (*rptr++);
  683. }
  684. TekRefresh = (TekLink *) 0;
  685. longjmp(Tekjump, 1);
  686. }
  687. again:
  688. if (VTbuffer->next >= VTbuffer->last) {
  689. int update = VTbuffer->update;
  690. if (nplot > 0) /* flush line */
  691. TekFlush();
  692. #ifdef VMS
  693. Tselect_mask = pty_mask; /* force a read */
  694. #else /* VMS */
  695. XFD_COPYSET(&pty_mask, &Tselect_mask);
  696. #endif /* VMS */
  697. for (;;) {
  698. #ifdef CRAY
  699. struct timeval crocktimeout;
  700. crocktimeout.tv_sec = 0;
  701. crocktimeout.tv_usec = 0;
  702. (void) Select(max_plus1,
  703. &Tselect_mask, NULL, NULL,
  704. &crocktimeout);
  705. #endif
  706. if (readPtyData(screen, &Tselect_mask, VTbuffer)) {
  707. break;
  708. }
  709. if (Ttoggled && curstate == Talptable) {
  710. TCursorToggle(TOGGLE);
  711. Ttoggled = False;
  712. }
  713. if (XtAppPending(app_con) & XtIMXEvent) {
  714. #ifdef VMS
  715. Tselect_mask = X_mask;
  716. #else /* VMS */
  717. XFD_COPYSET(&X_mask, &Tselect_mask);
  718. #endif /* VMS */
  719. } else {
  720. XFlush(screen->display);
  721. #ifdef VMS
  722. Tselect_mask = Select_mask;
  723. #else /* VMS */
  724. XFD_COPYSET(&Select_mask, &Tselect_mask);
  725. if (Select(max_plus1, &Tselect_mask, NULL, NULL, NULL) < 0) {
  726. if (errno != EINTR)
  727. SysError(ERROR_TSELECT);
  728. continue;
  729. }
  730. #endif /* VMS */
  731. }
  732. #ifdef VMS
  733. if (Tselect_mask & X_mask) {
  734. xevents();
  735. if (VTbuffer->update != update)
  736. goto again;
  737. }
  738. #else /* VMS */
  739. if (FD_ISSET(ConnectionNumber(screen->display), &Tselect_mask)) {
  740. xevents();
  741. if (VTbuffer->update != update)
  742. goto again;
  743. }
  744. #endif /* VMS */
  745. }
  746. if (!Ttoggled && curstate == Talptable) {
  747. TCursorToggle(TOGGLE);
  748. Ttoggled = True;
  749. }
  750. }
  751. tek = TekRecord;
  752. if (tek->count >= TEK_LINK_BLOCK_SIZE
  753. || tek->fontsize != screen->cur.fontsize) {
  754. if ((TekRecord = tek->next = CastMalloc(TekLink)) == 0)
  755. Panic("Tinput: malloc error (%d)\n", errno);
  756. tek = tek->next;
  757. tek->next = (TekLink *) 0;
  758. tek->fontsize = screen->cur.fontsize;
  759. tek->count = 0;
  760. tek->ptr = tek->data;
  761. }
  762. tek->count++;
  763. (void) morePtyData(screen, VTbuffer);
  764. return (*tek->ptr++ = nextPtyData(screen, VTbuffer));
  765. }
  766. /* this should become the Tek Widget's Resize proc */
  767. static void
  768. TekConfigure(Widget w)
  769. {
  770. TScreen *screen = &term->screen;
  771. int border = 2 * screen->border;
  772. double d;
  773. if (TWindow(screen))
  774. XClearWindow(screen->display, TWindow(screen));
  775. TWidth(screen) = w->core.width - border;
  776. THeight(screen) = w->core.height - border;
  777. TekScale(screen) = (double) TWidth(screen) / TEKWIDTH;
  778. if ((d = (double) THeight(screen) / (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD))
  779. < TekScale(screen))
  780. TekScale(screen) = d;
  781. TFullWidth(screen) = w->core.width;
  782. TFullHeight(screen) = w->core.height;
  783. }
  784. /*ARGSUSED*/
  785. void
  786. TekExpose(Widget w GCC_UNUSED,
  787. XEvent * event GCC_UNUSED,
  788. Region region GCC_UNUSED)
  789. {
  790. TScreen *screen = &term->screen;
  791. TRACE(("TekExpose\n"));
  792. #ifdef lint
  793. region = region;
  794. #endif
  795. if (!Ttoggled)
  796. TCursorToggle(CLEAR);
  797. Ttoggled = True;
  798. Tpushback = Tpushb;
  799. screen->cur_X = 0;
  800. screen->cur_Y = TEKHOME;
  801. TekSetFontSize(screen->page.fontsize);
  802. screen->cur = screen->page;
  803. screen->margin = MARGIN1;
  804. if (screen->TekGIN) {
  805. screen->TekGIN = NULL;
  806. TekGINoff();
  807. }
  808. TekRefresh = &Tek0;
  809. rptr = TekRefresh->data;
  810. rcnt = TekRefresh->count;
  811. Tparsestate = curstate = Talptable;
  812. TRACE(("TekExpose resets data to replay %d bytes\n", rcnt));
  813. if (waiting_for_initial_map)
  814. first_map_occurred();
  815. if (!screen->waitrefresh)
  816. dorefresh();
  817. }
  818. void
  819. dorefresh(void)
  820. {
  821. TScreen *screen = &term->screen;
  822. static Cursor wait_cursor = None;
  823. if (wait_cursor == None)
  824. wait_cursor = make_colored_cursor(XC_watch,
  825. T_COLOR(screen, MOUSE_FG),
  826. T_COLOR(screen, MOUSE_BG));
  827. XDefineCursor(screen->display, TWindow(screen), wait_cursor);
  828. XFlush(screen->display);
  829. if (!setjmp(Tekjump))
  830. Tekparse();
  831. XDefineCursor(screen->display, TWindow(screen),
  832. (screen->TekGIN && GINcursor) ? GINcursor : screen->arrow);
  833. }
  834. static void
  835. TekPage(void)
  836. {
  837. TScreen *screen = &term->screen;
  838. TekLink *tek;
  839. XClearWindow(screen->display, TWindow(screen));
  840. screen->cur_X = 0;
  841. screen->cur_Y = TEKHOME;
  842. screen->margin = MARGIN1;
  843. screen->page = screen->cur;
  844. if (screen->TekGIN)
  845. TekGINoff();
  846. tek = TekRecord = &Tek0;
  847. tek->fontsize = screen->cur.fontsize;
  848. tek->count = 0;
  849. tek->ptr = tek->data;
  850. tek = tek->next;
  851. if (tek)
  852. do {
  853. TekLink *tek2 = tek->next;
  854. free(tek);
  855. tek = tek2;
  856. } while (tek);
  857. TekRecord->next = (TekLink *) 0;
  858. TekRefresh = (TekLink *) 0;
  859. Ttoggled = True;
  860. Tparsestate = curstate = Talptable; /* Tek Alpha mode */
  861. }
  862. #define EXTRABITS 017
  863. #define FIVEBITS 037
  864. #define HIBITS (FIVEBITS << SHIFTHI)
  865. #define LOBITS (FIVEBITS << SHIFTLO)
  866. #define SHIFTHI 7
  867. #define SHIFTLO 2
  868. #define TWOBITS 03
  869. static int
  870. getpoint(void)
  871. {
  872. int c, x, y, e, lo_y = 0;
  873. TScreen *screen = &term->screen;
  874. x = screen->cur.x;
  875. y = screen->cur.y;
  876. for (;;) {
  877. if ((c = input()) < ' ') { /* control character */
  878. unput(c);
  879. return (0);
  880. }
  881. if (c < '@') { /* Hi X or Hi Y */
  882. if (lo_y) { /* seen a Lo Y, so this must be Hi X */
  883. x &= ~HIBITS;
  884. x |= (c & FIVEBITS) << SHIFTHI;
  885. continue;
  886. }
  887. /* else Hi Y */
  888. y &= ~HIBITS;
  889. y |= (c & FIVEBITS) << SHIFTHI;
  890. continue;
  891. }
  892. if (c < '`') { /* Lo X */
  893. x &= ~LOBITS;
  894. x |= (c & FIVEBITS) << SHIFTLO;
  895. screen->cur.x = x;
  896. screen->cur.y = y;
  897. return (1); /* OK */
  898. }
  899. /* else Lo Y */
  900. if (lo_y) { /* seen a Lo Y, so other must be extra bits */
  901. e = (y >> SHIFTLO) & EXTRABITS;
  902. x &= ~TWOBITS;
  903. x |= e & TWOBITS;
  904. y &= ~TWOBITS;
  905. y |= (e >> SHIFTLO) & TWOBITS;
  906. }
  907. y &= ~LOBITS;
  908. y |= (c & FIVEBITS) << SHIFTLO;
  909. lo_y++;
  910. }
  911. }
  912. static void
  913. TCursorBack(void)
  914. {
  915. TScreen *screen = &term->screen;
  916. struct Tek_Char *t;
  917. int x, l;
  918. x = (screen->cur_X -=
  919. (t = &TekChar[screen->cur.fontsize])->hsize
  920. );
  921. if (((screen->margin == MARGIN1) && (x < 0))
  922. || ((screen->margin == MARGIN2) && (x < TEKWIDTH / 2))) {
  923. if ((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >=
  924. t->nlines) {
  925. screen->margin = !screen->margin;
  926. l = 0;
  927. }
  928. screen->cur_Y = l * t->vsize;
  929. screen->cur_X = (t->charsperline - 1) * t->hsize;
  930. }
  931. }
  932. static void
  933. TCursorForward(void)
  934. {
  935. TScreen *screen = &term->screen;
  936. struct Tek_Char *t;
  937. int l;
  938. if ((screen->cur_X +=
  939. (t = &TekChar[screen->cur.fontsize])->hsize
  940. ) > TEKWIDTH
  941. ) {
  942. if ((l = screen->cur_Y / t->vsize - 1) < 0) {
  943. screen->margin = !screen->margin;
  944. l = t->nlines - 1;
  945. }
  946. screen->cur_Y = l * t->vsize;
  947. screen->cur_X = screen->margin == MARGIN1 ? 0 : TEKWIDTH / 2;
  948. }
  949. }
  950. static void
  951. TCursorUp(void)
  952. {
  953. TScreen *screen = &term->screen;
  954. struct Tek_Char *t;
  955. int l;
  956. t = &TekChar[screen->cur.fontsize];
  957. if ((l = (screen->cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) {
  958. l = 0;
  959. if ((screen->margin = !screen->margin) != MARGIN1) {
  960. if (screen->cur_X < TEKWIDTH / 2)
  961. screen->cur_X += TEKWIDTH / 2;
  962. } else if (screen->cur_X >= TEKWIDTH / 2)
  963. screen->cur_X -= TEKWIDTH / 2;
  964. }
  965. screen->cur_Y = l * t->vsize;
  966. }
  967. static void
  968. TCursorDown(void)
  969. {
  970. TScreen *screen = &term->screen;
  971. struct Tek_Char *t;
  972. int l;
  973. t = &TekChar[screen->cur.fontsize];
  974. if ((l = screen->cur_Y / t->vsize - 1) < 0) {
  975. l = t->nlines - 1;
  976. if ((screen->margin = !screen->margin) != MARGIN1) {
  977. if (screen->cur_X < TEKWIDTH / 2)
  978. screen->cur_X += TEKWIDTH / 2;
  979. } else if (screen->cur_X >= TEKWIDTH / 2)
  980. screen->cur_X -= TEKWIDTH / 2;
  981. }
  982. screen->cur_Y = l * t->vsize;
  983. }
  984. static void
  985. AddToDraw(int x1, int y1, int x2, int y2)
  986. {
  987. TScreen *screen = &term->screen;
  988. XSegment *lp;
  989. TRACE(("AddToDraw (%d,%d) (%d,%d)\n", x1, y1, x2, y2));
  990. if (nplot >= MAX_PTS) {
  991. TekFlush();
  992. }
  993. lp = line_pt++;
  994. lp->x1 = x1 = (int) (x1 * TekScale(screen) + screen->border);
  995. lp->y1 = y1 = (int) ((TEKHEIGHT + TEKTOPPAD - y1) * TekScale(screen) +
  996. screen->border);
  997. lp->x2 = x2 = (int) (x2 * TekScale(screen) + screen->border);
  998. lp->y2 = y2 = (int) ((TEKHEIGHT + TEKTOPPAD - y2) * TekScale(screen) +
  999. screen->border);
  1000. nplot++;
  1001. TRACE(("...AddToDraw %d points\n", nplot));
  1002. }
  1003. static void
  1004. TekDraw(int x, int y)
  1005. {
  1006. TScreen *screen = &term->screen;
  1007. if (nplot == 0 || T_lastx != screen->cur_X || T_lasty != screen->cur_Y) {
  1008. /*
  1009. * We flush on each unconnected line segment if the line
  1010. * type is not solid. This solves a bug in X when drawing
  1011. * points while the line type is not solid.
  1012. */
  1013. if (nplot > 0 && screen->cur.linetype != SOLIDLINE)
  1014. TekFlush();
  1015. }
  1016. AddToDraw(screen->cur_X, screen->cur_Y, x, y);
  1017. T_lastx = screen->cur_X = x;
  1018. T_lasty = screen->cur_Y = y;
  1019. }
  1020. static void
  1021. TekFlush(void)
  1022. {
  1023. TScreen *screen = &term->screen;
  1024. TRACE(("TekFlush\n"));
  1025. XDrawSegments(screen->display, TWindow(screen),
  1026. ((screen->cur.linetype == SOLIDLINE) ? screen->TnormalGC :
  1027. screen->linepat[screen->cur.linetype - 1]),
  1028. Tline, nplot);
  1029. nplot = 0;
  1030. line_pt = Tline;
  1031. }
  1032. void
  1033. TekGINoff(void)
  1034. {
  1035. TScreen *screen = &term->screen;
  1036. TRACE(("TekGINoff\n"));
  1037. XDefineCursor(screen->display, TWindow(screen), screen->arrow);
  1038. if (GINcursor)
  1039. XFreeCursor(screen->display, GINcursor);
  1040. if (screen->TekGIN) {
  1041. *screen->TekGIN = CAN; /* modify recording */
  1042. screen->TekGIN = NULL;
  1043. }
  1044. }
  1045. void
  1046. TekEnqMouse(int c) /* character pressed */
  1047. {
  1048. TScreen *screen = &term->screen;
  1049. int mousex, mousey, rootx, rooty;
  1050. unsigned int mask; /* XQueryPointer */
  1051. Window root, subw;
  1052. TRACE(("TekEnqMouse\n"));
  1053. XQueryPointer(
  1054. screen->display, TWindow(screen),
  1055. &root, &subw,
  1056. &rootx, &rooty,
  1057. &mousex, &mousey,
  1058. &mask);
  1059. if ((mousex = (int) ((mousex - screen->border) / TekScale(screen))) < 0)
  1060. mousex = 0;
  1061. else if (mousex >= TEKWIDTH)
  1062. mousex = TEKWIDTH - 1;
  1063. if ((mousey = (int) (TEKHEIGHT + TEKTOPPAD - (mousey - screen->border) /
  1064. TekScale(screen))) < 0)
  1065. mousey = 0;
  1066. else if (mousey >= TEKHEIGHT)
  1067. mousey = TEKHEIGHT - 1;
  1068. TekEnq((unsigned) c, mousex, mousey);
  1069. }
  1070. static void
  1071. TekEnq(unsigned status,
  1072. int x,
  1073. int y)
  1074. {
  1075. TScreen *screen = &term->screen;
  1076. Char cplot[7];
  1077. int len = 5;
  1078. int adj = (status != 0) ? 0 : 1;
  1079. TRACE(("TekEnq\n"));
  1080. cplot[0] = status;
  1081. /* Translate x and y to Tektronix code */
  1082. cplot[1] = 040 | ((x >> SHIFTHI) & FIVEBITS);
  1083. cplot[2] = 040 | ((x >> SHIFTLO) & FIVEBITS);
  1084. cplot[3] = 040 | ((y >> SHIFTHI) & FIVEBITS);
  1085. cplot[4] = 040 | ((y >> SHIFTLO) & FIVEBITS);
  1086. if (screen->gin_terminator != GIN_TERM_NONE)
  1087. cplot[len++] = '\r';
  1088. if (screen->gin_terminator == GIN_TERM_EOT)
  1089. cplot[len++] = '\004';
  1090. #ifdef VMS
  1091. tt_write(cplot + adj, len - adj);
  1092. #else /* VMS */
  1093. v_write(screen->respond, cplot + adj, (unsigned) (len - adj));
  1094. #endif /* VMS */
  1095. }
  1096. void
  1097. TekRun(void)
  1098. {
  1099. TScreen *screen = &term->screen;
  1100. TRACE(("TekRun ...\n"));
  1101. if (!TWindow(screen) && !TekInit()) {
  1102. if (VWindow(screen)) {
  1103. screen->TekEmu = False;
  1104. return;
  1105. }
  1106. Exit(ERROR_TINIT);
  1107. }
  1108. if (!screen->Tshow) {
  1109. set_tek_visibility(True);
  1110. }
  1111. update_vttekmode();
  1112. update_vtshow();
  1113. update_tekshow();
  1114. set_tekhide_sensitivity();
  1115. Tpushback = Tpushb;
  1116. Ttoggled = True;
  1117. if (!setjmp(Tekend))
  1118. Tekparse();
  1119. if (!Ttoggled) {
  1120. TCursorToggle(TOGGLE);
  1121. Ttoggled = True;
  1122. }
  1123. screen->TekEmu = False;
  1124. }
  1125. #define DOTTED_LENGTH 2
  1126. #define DOT_DASHED_LENGTH 4
  1127. #define SHORT_DASHED_LENGTH 2
  1128. #define LONG_DASHED_LENGTH 2
  1129. static int dash_length[TEKNUMLINES] =
  1130. {
  1131. DOTTED_LENGTH,
  1132. DOT_DASHED_LENGTH,
  1133. SHORT_DASHED_LENGTH,
  1134. LONG_DASHED_LENGTH,
  1135. };
  1136. static unsigned char dotted[DOTTED_LENGTH] =
  1137. {3, 1};
  1138. static unsigned char dot_dashed[DOT_DASHED_LENGTH] =
  1139. {3, 4, 3, 1};
  1140. static unsigned char short_dashed[SHORT_DASHED_LENGTH] =
  1141. {4, 4};
  1142. static unsigned char long_dashed[LONG_DASHED_LENGTH] =
  1143. {4, 7};
  1144. static unsigned char *dashes[TEKNUMLINES] =
  1145. {
  1146. dotted,
  1147. dot_dashed,
  1148. short_dashed,
  1149. long_dashed,
  1150. };
  1151. /*
  1152. * The following is called to create the tekWidget
  1153. */
  1154. static void
  1155. TekInitialize(Widget request GCC_UNUSED,
  1156. Widget wnew GCC_UNUSED,
  1157. ArgList args GCC_UNUSED,
  1158. Cardinal *num_args GCC_UNUSED)
  1159. {
  1160. Widget tekparent = SHELL_OF(wnew);
  1161. TRACE(("TekInitialize\n"));
  1162. /* look for focus related events on the shell, because we need
  1163. * to care about the shell's border being part of our focus.
  1164. */
  1165. XtAddEventHandler(tekparent, EnterWindowMask, False,
  1166. HandleEnterWindow, (Opaque) 0);
  1167. XtAddEventHandler(tekparent, LeaveWindowMask, False,
  1168. HandleLeaveWindow, (Opaque) 0);
  1169. XtAddEventHandler(tekparent, FocusChangeMask, False,
  1170. HandleFocusChange, (Opaque) 0);
  1171. XtAddEventHandler((Widget) wnew, PropertyChangeMask, False,
  1172. HandleBellPropertyChange, (Opaque) 0);
  1173. }
  1174. static void
  1175. TekRealize(Widget gw GCC_UNUSED, /* same as tekWidget */
  1176. XtValueMask * valuemaskp,
  1177. XSetWindowAttributes * values)
  1178. {
  1179. TScreen *screen = &term->screen;
  1180. int i;
  1181. TekLink *tek;
  1182. double d;
  1183. int border = 2 * screen->border;
  1184. int pr;
  1185. XGCValues gcv;
  1186. int winX, winY, width, height;
  1187. XSizeHints sizehints;
  1188. char Tdefault[32];
  1189. unsigned TEKgcFontMask;
  1190. TRACE(("TekRealize\n"));
  1191. #ifndef NO_ACTIVE_ICON
  1192. term->screen.whichTwin = &term->screen.fullTwin;
  1193. #endif /* NO_ACTIVE_ICON */
  1194. BorderPixel(tekWidget) = BorderPixel(term);
  1195. for (i = 0; i < TEKNUMFONTS; i++) {
  1196. if (!tekWidget->tek.Tfont[i]) {
  1197. tekWidget->tek.Tfont[i] = XQueryFont(screen->display, DefaultGCID);
  1198. }
  1199. TRACE(("Tfont[%d] %dx%d\n",
  1200. i,
  1201. tekWidget->tek.Tfont[i]->ascent +
  1202. tekWidget->tek.Tfont[i]->descent,
  1203. tekWidget->tek.Tfont[i]->max_bounds.width));
  1204. tekWidget->tek.tobaseline[i] = tekWidget->tek.Tfont[i]->ascent;
  1205. }
  1206. if (!TekPtyData())
  1207. return;
  1208. if (term->misc.T_geometry == NULL) {
  1209. int defwidth, defheight;
  1210. if (term->misc.tekSmall) {
  1211. defwidth = TEKMINWIDTH;
  1212. defheight = TEKMINHEIGHT;
  1213. } else {
  1214. defwidth = TEKDEFWIDTH;
  1215. defheight = TEKDEFHEIGHT;
  1216. }
  1217. sprintf(Tdefault, "=%dx%d", defwidth + border, defheight + border);
  1218. term->misc.T_geometry = Tdefault;
  1219. }
  1220. winX = 1;
  1221. winY = 1;
  1222. width = TEKDEFWIDTH + border;
  1223. height = TEKDEFHEIGHT + border;
  1224. TRACE(("parsing T_geometry %s\n", NonNull(term->misc.T_geometry)));
  1225. pr = XParseGeometry(term->misc.T_geometry,
  1226. &winX,
  1227. &winY,
  1228. (unsigned int *) &width,
  1229. (unsigned int *) &height);
  1230. TRACE(("... position %d,%d size %dx%d\n", winY, winX, height, width));
  1231. if ((pr & XValue) && (pr & XNegative))
  1232. winX += DisplayWidth(screen->display, DefaultScreen(screen->display))
  1233. - width - (BorderWidth(SHELL_OF(term)) * 2);
  1234. if ((pr & YValue) && (pr & YNegative))
  1235. winY += DisplayHeight(screen->display, DefaultScreen(screen->display))
  1236. - height - (BorderWidth(SHELL_OF(term)) * 2);
  1237. /* set up size hints */
  1238. sizehints.min_width = TEKMINWIDTH + border;
  1239. sizehints.min_height = TEKMINHEIGHT + border;
  1240. sizehints.width_inc = 1;
  1241. sizehints.height_inc = 1;
  1242. sizehints.flags = PMinSize | PResizeInc;
  1243. sizehints.x = winX;
  1244. sizehints.y = winY;
  1245. if ((XValue & pr) || (YValue & pr)) {
  1246. sizehints.flags |= USSize | USPosition;
  1247. sizehints.flags |= PWinGravity;
  1248. switch (pr & (XNegative | YNegative)) {
  1249. case 0:
  1250. sizehints.win_gravity = NorthWestGravity;
  1251. break;
  1252. case XNegative:
  1253. sizehints.win_gravity = NorthEastGravity;
  1254. break;
  1255. case YNegative:
  1256. sizehints.win_gravity = SouthWestGravity;
  1257. break;
  1258. default:
  1259. sizehints.win_gravity = SouthEastGravity;
  1260. break;
  1261. }
  1262. } else {
  1263. /* set a default size, but do *not* set position */
  1264. sizehints.flags |= PSize;
  1265. }
  1266. sizehints.width = width;
  1267. sizehints.height = height;
  1268. if ((WidthValue & pr) || (HeightValue & pr))
  1269. sizehints.flags |= USSize;
  1270. else
  1271. sizehints.flags |= PSize;
  1272. TRACE(("make resize request %dx%d\n", height, width));
  1273. (void) XtMakeResizeRequest((Widget) tekWidget,
  1274. width, height,
  1275. &tekWidget->core.width, &tekWidget->core.height);
  1276. TRACE(("...made resize request %dx%d\n", tekWidget->core.height, tekWidget->core.width));
  1277. /* XXX This is bogus. We are parsing geometries too late. This
  1278. * is information that the shell widget ought to have before we get
  1279. * realized, so that it can do the right thing.
  1280. */
  1281. if (sizehints.flags & USPosition)
  1282. XMoveWindow(XtDisplay(tekWidget), TShellWindow, sizehints.x, sizehints.y);
  1283. XSetWMNormalHints(XtDisplay(tekWidget), TShellWindow, &sizehints);
  1284. XFlush(XtDisplay(tekWidget)); /* get it out to window manager */
  1285. values->win_gravity = NorthWestGravity;
  1286. values->background_pixel = T_COLOR(screen, TEK_BG);
  1287. XtWindow(tekWidget) = TWindow(screen) =
  1288. XCreateWindow(screen->display,
  1289. XtWindow(SHELL_OF(tekWidget)),
  1290. tekWidget->core.x, tekWidget->core.y,
  1291. tekWidget->core.width, tekWidget->core.height, BorderWidth(tekWidget),
  1292. (int) tekWidget->core.depth,
  1293. InputOutput, CopyFromParent,
  1294. ((*valuemaskp) | CWBackPixel | CWWinGravity),
  1295. values);
  1296. TFullWidth(screen) = width;
  1297. TFullHeight(screen) = height;
  1298. TWidth(screen) = width - border;
  1299. THeight(screen) = height - border;
  1300. TekScale(screen) = (double) TWidth(screen) / TEKWIDTH;
  1301. if ((d = (double) THeight(screen) / (TEKHEIGHT + TEKTOPPAD +
  1302. TEKBOTTOMPAD)) < TekScale(screen))
  1303. TekScale(screen) = d;
  1304. screen->cur.fontsize = TEK_FONT_LARGE;
  1305. if (tekWidget->tek.initial_font) {
  1306. char *s = tekWidget->tek.initial_font;
  1307. if (XmuCompareISOLatin1(s, "large") == 0)
  1308. screen->cur.fontsize = TEK_FONT_LARGE;
  1309. else if (XmuCompareISOLatin1(s, "2") == 0 ||
  1310. XmuCompareISOLatin1(s, "two") == 0)
  1311. screen->cur.fontsize = TEK_FONT_2;
  1312. else if (XmuCompareISOLatin1(s, "3") == 0 ||
  1313. XmuCompareISOLatin1(s, "three") == 0)
  1314. screen->cur.fontsize = TEK_FONT_3;
  1315. else if (XmuCompareISOLatin1(s, "small") == 0)
  1316. screen->cur.fontsize = TEK_FONT_SMALL;
  1317. }
  1318. #define TestGIN(s) XmuCompareISOLatin1(tekWidget->tek.gin_terminator_str, s)
  1319. if (TestGIN(GIN_TERM_NONE_STR) == 0)
  1320. screen->gin_terminator = GIN_TERM_NONE;
  1321. else if (TestGIN(GIN_TERM_CR_STR) == 0)
  1322. screen->gin_terminator = GIN_TERM_CR;
  1323. else if (TestGIN(GIN_TERM_EOT_STR) == 0)
  1324. screen->gin_terminator = GIN_TERM_EOT;
  1325. else
  1326. fprintf(stderr, "%s: illegal GIN terminator setting \"%s\"\n",
  1327. xterm_name, tekWidget->tek.gin_terminator_str);
  1328. gcv.graphics_exposures = True; /* default */
  1329. gcv.font = tekWidget->tek.Tfont[screen->cur.fontsize]->fid;
  1330. gcv.foreground = T_COLOR(screen, TEK_FG);
  1331. gcv.background = T_COLOR(screen, TEK_BG);
  1332. /* if font wasn't successfully opened, then gcv.font will contain
  1333. the Default GC's ID, meaning that we must use the server default font.
  1334. */
  1335. TEKgcFontMask = (gcv.font == DefaultGCID) ? 0 : GCFont;
  1336. screen->TnormalGC = XCreateGC(screen->display, TWindow(screen),
  1337. (TEKgcFontMask | GCGraphicsExposures |
  1338. GCForeground | GCBackground),
  1339. &gcv);
  1340. gcv.function = GXinvert;
  1341. gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^
  1342. T_COLOR(screen, TEK_CURSOR));
  1343. gcv.join_style = JoinMiter; /* default */
  1344. gcv.line_width = 1;
  1345. screen->TcursorGC = XCreateGC(screen->display, TWindow(screen),
  1346. (GCFunction | GCPlaneMask), &gcv);
  1347. gcv.foreground = T_COLOR(screen, TEK_FG);
  1348. gcv.line_style = LineOnOffDash;
  1349. gcv.line_width = 0;
  1350. for (i = 0; i < TEKNUMLINES; i++) {
  1351. screen->linepat[i] = XCreateGC(screen->display, TWindow(screen),
  1352. (GCForeground | GCLineStyle), &gcv);
  1353. XSetDashes(screen->display, screen->linepat[i], 0,
  1354. (char *) dashes[i], dash_length[i]);
  1355. }
  1356. TekBackground(screen);
  1357. screen->margin = MARGIN1; /* Margin 1 */
  1358. screen->TekGIN = False; /* GIN off */
  1359. XDefineCursor(screen->display, TWindow(screen), screen->pointer_cursor);
  1360. { /* there's gotta be a better way... */
  1361. static Arg args[] =
  1362. {
  1363. {XtNtitle, (XtArgVal) NULL},
  1364. {XtNiconName, (XtArgVal) NULL},
  1365. };
  1366. char *icon_name, *title, *tek_icon_name, *tek_title;
  1367. args[0].value = (XtArgVal) & icon_name;
  1368. args[1].value = (XtArgVal) & title;
  1369. XtGetValues(SHELL_OF(tekWidget), args, 2);
  1370. tek_icon_name = XtMalloc(strlen(icon_name) + 7);
  1371. strcpy(tek_icon_name, icon_name);
  1372. strcat(tek_icon_name, "(Tek)");
  1373. tek_title = XtMalloc(strlen(title) + 7);
  1374. strcpy(tek_title, title);
  1375. strcat(tek_title, "(Tek)");
  1376. args[0].value = (XtArgVal) tek_icon_name;
  1377. args[1].value = (XtArgVal) tek_title;
  1378. XtSetValues(SHELL_OF(tekWidget), args, 2);
  1379. XtFree(tek_icon_name);
  1380. XtFree(tek_title);
  1381. }
  1382. tek = TekRecord = &Tek0;
  1383. tek->next = (TekLink *) 0;
  1384. tek->fontsize = screen->cur.fontsize;
  1385. tek->count = 0;
  1386. tek->ptr = tek->data;
  1387. Tpushback = Tpushb;
  1388. screen->cur_X = 0;
  1389. screen->cur_Y = TEKHOME;
  1390. line_pt = Tline;
  1391. Ttoggled = True;
  1392. screen->page = screen->cur;
  1393. return;
  1394. }
  1395. void
  1396. TekSetFontSize(int newitem)
  1397. {
  1398. TScreen *screen = &term->screen;
  1399. int oldsize = screen->cur.fontsize;
  1400. int newsize = MI2FS(newitem);
  1401. Font fid;
  1402. TRACE(("TekSetFontSize(%d)\n", newitem));
  1403. if (!tekWidget || oldsize == newsize)
  1404. return;
  1405. if (!Ttoggled)
  1406. TCursorToggle(TOGGLE);
  1407. set_tekfont_menu_item(oldsize, False);
  1408. fid = tekWidget->tek.Tfont[newsize]->fid;
  1409. if (fid == DefaultGCID)
  1410. /* we didn't succeed in opening a real font
  1411. for this size. Instead, use server default. */
  1412. XCopyGC(screen->display,
  1413. DefaultGC(screen->display, DefaultScreen(screen->display)),
  1414. GCFont, screen->TnormalGC);
  1415. else
  1416. XSetFont(screen->display, screen->TnormalGC, fid);
  1417. screen->cur.fontsize = newsize;
  1418. set_tekfont_menu_item(newsize, True);
  1419. if (!Ttoggled)
  1420. TCursorToggle(TOGGLE);
  1421. }
  1422. void
  1423. ChangeTekColors(TScreen * screen, ScrnColors * pNew)
  1424. {
  1425. int i;
  1426. XGCValues gcv;
  1427. if (COLOR_DEFINED(pNew, TEK_FG)) {
  1428. T_COLOR(screen, TEK_FG) = COLOR_VALUE(pNew, TEK_FG);
  1429. TRACE(("... TEK_FG: %#lx\n", T_COLOR(screen, TEK_FG)));
  1430. }
  1431. if (COLOR_DEFINED(pNew, TEK_BG)) {
  1432. T_COLOR(screen, TEK_BG) = COLOR_VALUE(pNew, TEK_BG);
  1433. TRACE(("... TEK_BG: %#lx\n", T_COLOR(screen, TEK_BG)));
  1434. }
  1435. if (COLOR_DEFINED(pNew, TEK_CURSOR)) {
  1436. T_COLOR(screen, TEK_CURSOR) = COLOR_VALUE(pNew, TEK_CURSOR);
  1437. TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR)));
  1438. } else {
  1439. T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG);
  1440. TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR)));
  1441. }
  1442. if (tekWidget) {
  1443. XSetForeground(screen->display, screen->TnormalGC,
  1444. T_COLOR(screen, TEK_FG));
  1445. XSetBackground(screen->display, screen->TnormalGC,
  1446. T_COLOR(screen, TEK_BG));
  1447. if (BorderPixel(tekWidget) == T_COLOR(screen, TEK_BG)) {
  1448. BorderPixel(tekWidget) = T_COLOR(screen, TEK_FG);
  1449. BorderPixel(XtParent(tekWidget)) = T_COLOR(screen, TEK_FG);
  1450. if (XtWindow(XtParent(tekWidget)))
  1451. XSetWindowBorder(screen->display,
  1452. XtWindow(XtParent(tekWidget)),
  1453. BorderPixel(tekWidget));
  1454. }
  1455. for (i = 0; i < TEKNUMLINES; i++) {
  1456. XSetForeground(screen->display, screen->linepat[i],
  1457. T_COLOR(screen, TEK_FG));
  1458. }
  1459. gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^
  1460. T_COLOR(screen, TEK_CURSOR));
  1461. XChangeGC(screen->display, screen->TcursorGC, GCPlaneMask, &gcv);
  1462. TekBackground(screen);
  1463. }
  1464. return;
  1465. }
  1466. void
  1467. TekReverseVideo(TScreen * screen)
  1468. {
  1469. int i;
  1470. XGCValues gcv;
  1471. EXCHANGE(T_COLOR(screen, TEK_FG), T_COLOR(screen, TEK_BG), i);
  1472. T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG);
  1473. if (tekWidget) {
  1474. XSetForeground(screen->display, screen->TnormalGC, T_COLOR(screen, TEK_FG));
  1475. XSetBackground(screen->display, screen->TnormalGC, T_COLOR(screen, TEK_BG));
  1476. if (BorderPixel(tekWidget) == T_COLOR(screen, TEK_BG)) {
  1477. BorderPixel(tekWidget) = T_COLOR(screen, TEK_FG);
  1478. BorderPixel(XtParent(tekWidget)) = T_COLOR(screen, TEK_FG);
  1479. if (XtWindow(XtParent(tekWidget)))
  1480. XSetWindowBorder(screen->display,
  1481. XtWindow(XtParent(tekWidget)),
  1482. BorderPixel(tekWidget));
  1483. }
  1484. for (i = 0; i < TEKNUMLINES; i++) {
  1485. XSetForeground(screen->display, screen->linepat[i],
  1486. T_COLOR(screen, TEK_FG));
  1487. }
  1488. gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^
  1489. T_COLOR(screen, TEK_CURSOR));
  1490. XChangeGC(screen->display, screen->TcursorGC, GCPlaneMask, &gcv);
  1491. TekBackground(screen);
  1492. }
  1493. }
  1494. static void
  1495. TekBackground(TScreen * screen)
  1496. {
  1497. if (TWindow(screen))
  1498. XSetWindowBackground(screen->display, TWindow(screen),
  1499. T_COLOR(screen, TEK_BG));
  1500. }
  1501. /*
  1502. * Toggles cursor on or off at cursor position in screen.
  1503. */
  1504. void
  1505. TCursorToggle(int toggle) /* TOGGLE or CLEAR */
  1506. {
  1507. TScreen *screen = &term->screen;
  1508. int c, x, y;
  1509. unsigned int cellwidth, cellheight;
  1510. if (!screen->Tshow)
  1511. return;
  1512. c = screen->cur.fontsize;
  1513. cellwidth = (unsigned) tekWidget->tek.Tfont[c]->max_bounds.width;
  1514. cellheight = (unsigned) (tekWidget->tek.Tfont[c]->ascent +
  1515. tekWidget->tek.Tfont[c]->descent);
  1516. x = (int) ((screen->cur_X * TekScale(screen)) + screen->border);
  1517. y = (int) (((TEKHEIGHT + TEKTOPPAD - screen->cur_Y) * TekScale(screen))
  1518. + screen->border - tekWidget->tek.tobaseline[c]);
  1519. if (toggle == TOGGLE) {
  1520. if (screen->select || screen->always_highlight)
  1521. XFillRectangle(screen->display, TWindow(screen),
  1522. screen->TcursorGC, x, y,
  1523. cellwidth, cellheight);
  1524. else { /* fix to use different GC! */
  1525. XDrawRectangle(screen->display, TWindow(screen),
  1526. screen->TcursorGC, x, y,
  1527. cellwidth - 1, cellheight - 1);
  1528. }
  1529. } else {
  1530. /* Clear the entire rectangle, even though we may only
  1531. * have drawn an outline. This fits with our refresh
  1532. * scheme of redrawing the entire window on any expose
  1533. * event and is easier than trying to figure out exactly
  1534. * which part of the cursor needs to be erased.
  1535. */
  1536. XClearArea(screen->display, TWindow(screen), x, y,
  1537. cellwidth, cellheight, False);
  1538. }
  1539. }
  1540. void
  1541. TekSimulatePageButton(Bool reset)
  1542. {
  1543. TScreen *screen = &term->screen;
  1544. if (!tekWidget)
  1545. return;
  1546. if (reset) {
  1547. bzero((char *) &screen->cur, sizeof screen->cur);
  1548. }
  1549. TekRefresh = (TekLink *) 0;
  1550. TekPage();
  1551. screen->cur_X = 0;
  1552. screen->cur_Y = TEKHOME;
  1553. }
  1554. /* write copy of screen to a file */
  1555. void
  1556. TekCopy(void)
  1557. {
  1558. TScreen *screen = &term->screen;
  1559. TekLink *Tp;
  1560. char buf[32];
  1561. char initbuf[5];
  1562. int tekcopyfd;
  1563. timestamp_filename(buf, "COPY");
  1564. if (access(buf, F_OK) >= 0
  1565. && access(buf, W_OK) < 0) {
  1566. Bell(XkbBI_MinorError, 0);
  1567. return;
  1568. }
  1569. #ifndef VMS
  1570. if (access(".", W_OK) < 0) { /* can't write in directory */
  1571. Bell(XkbBI_MinorError, 0);
  1572. return;
  1573. }
  1574. #endif
  1575. if ((tekcopyfd = open_userfile(screen->uid, screen->gid, buf, False)) >= 0) {
  1576. sprintf(initbuf, "%c%c%c%c",
  1577. ESC, (char) (screen->page.fontsize + '8'),
  1578. ESC, (char) (screen->page.linetype + '`'));
  1579. write(tekcopyfd, initbuf, 4);
  1580. Tp = &Tek0;
  1581. do {
  1582. write(tekcopyfd, Tp->data, Tp->count);
  1583. Tp = Tp->next;
  1584. } while (Tp);
  1585. close(tekcopyfd);
  1586. }
  1587. }