Tekproc.c revision f2e35a3a
1/* $XTermId: Tekproc.c,v 1.241 2021/02/02 00:19:32 tom Exp $ */ 2 3/* 4 * Copyright 2001-2020,2021 by Thomas E. Dickey 5 * 6 * All Rights Reserved 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sublicense, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 * Except as contained in this notice, the name(s) of the above copyright 28 * holders shall not be used in advertising or otherwise to promote the 29 * sale, use or other dealings in this Software without prior written 30 * authorization. 31 * 32 * Copyright 1988 X Consortium 33 * 34 * Permission to use, copy, modify, distribute, and sell this software and its 35 * documentation for any purpose is hereby granted without fee, provided that 36 * the above copyright notice appear in all copies and that both that 37 * copyright notice and this permission notice appear in supporting 38 * documentation. 39 * 40 * The above copyright notice and this permission notice shall be included in 41 * all copies or substantial portions of the Software. 42 * 43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 47 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 48 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 49 * 50 * Except as contained in this notice, the name of the X Consortium shall not be 51 * used in advertising or otherwise to promote the sale, use or other dealings 52 * in this Software without prior written authorization from the X Consortium. 53 * 54 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 55 * 56 * All Rights Reserved 57 * 58 * Permission to use, copy, modify, and distribute this software and its 59 * documentation for any purpose and without fee is hereby granted, 60 * provided that the above copyright notice appear in all copies and that 61 * both that copyright notice and this permission notice appear in 62 * supporting documentation, and that the name of Digital Equipment 63 * Corporation not be used in advertising or publicity pertaining to 64 * distribution of the software without specific, written prior permission. 65 * 66 * 67 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 68 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 69 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 70 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 71 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 72 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 73 * SOFTWARE. 74 */ 75 76/* Tekproc.c */ 77 78#define RES_OFFSET(field) XtOffsetOf(TekWidgetRec, field) 79 80#include <xterm.h> 81 82#include <X11/Xatom.h> 83#include <X11/Xutil.h> 84#include <X11/cursorfont.h> 85#include <X11/Xmu/CharSet.h> 86 87#if OPT_TOOLBAR 88 89#if defined(HAVE_LIB_XAW) 90#include <X11/Xaw/Form.h> 91#elif defined(HAVE_LIB_XAW3D) 92#include <X11/Xaw3d/Form.h> 93#elif defined(HAVE_LIB_XAW3DXFT) 94#include <X11/Xaw3dxft/Form.h> 95#elif defined(HAVE_LIB_NEXTAW) 96#include <X11/neXtaw/Form.h> 97#elif defined(HAVE_LIB_XAWPLUS) 98#include <X11/XawPlus/Form.h> 99#endif 100 101#endif /* OPT_TOOLBAR */ 102 103#include <assert.h> 104#include <stdio.h> 105#include <ctype.h> 106#include <signal.h> 107 108#include <Tekparse.h> 109#include <data.h> 110#include <error.h> 111#include <menu.h> 112#include <xstrings.h> 113 114#define DefaultGCID(tw) \ 115 XGContextFromGC(DefaultGC(XtDisplay(tw), \ 116 DefaultScreen(XtDisplay(tw)))) 117 118/* Tek defines */ 119 120#define MY_CLASS "Tek4014" 121#define MY_NAME "tek4014" 122 123#define SOLIDLINE 0 124#define DOTTEDLINE 1 125#define DOTDASHEDLINE 2 126#define SHORTDASHEDLINE 3 127#define LONGDASHEDLINE 4 128 129#define EAST 001 130#define WEST 002 131#define NORTH 004 132#define SOUTH 010 133 134#define LINEMASK 07 135#define MARGIN1 0 136#define MARGIN2 1 137#define MAX_PTS 150 138#define MAX_VTX 300 139#define PENDOWN 1 140#define PENUP 0 141#define TEKBOTTOMPAD 23 142#define TEKDEFHEIGHT 565 143#define TEKDEFWIDTH 750 144#define TEKHEIGHT 3072 145#define TEKHOME ( (TekChar[tekscr->page.fontsize].nlines - 1) \ 146 * TekChar[tekscr->page.fontsize].vsize) 147#define TEKMINHEIGHT 452 148#define TEKMINWIDTH 600 149#define TEKTOPPAD 34 150#define TEKWIDTH 4096 151 152#define FULL_HEIGHT (TEKHEIGHT + TEKTOPPAD + TEKBOTTOMPAD) 153 154#define BottomY(y) (TEKHEIGHT + TEKTOPPAD - (y)) 155#define BorderOf(tw) (TScreenOf((tw)->vt)->border) 156#define ScaleOf(tw) TekScale(TekScreenOf(tw)) 157#define ScaledX(tw,x) (((x) * ScaleOf(tw)) + BorderOf(tw)) 158#define ScaledY(tw,y) ((BottomY(y) * ScaleOf(tw)) + BorderOf(tw)) 159 160#define TekMove(tw,x,y) do { tekscr->cur_X = x; tekscr->cur_Y = y; } while (0) 161#define input() Tinput(tw) 162#define unput(c) *Tpushback++ = (Char) c 163/* *INDENT-OFF* */ 164static const struct Tek_Char { 165 int hsize; /* in Tek units */ 166 int vsize; /* in Tek units */ 167 int charsperline; 168 int nlines; 169} TekChar[TEKNUMFONTS] = { 170 {56, 88, 74, 35}, /* large */ 171 {51, 82, 81, 38}, /* #2 */ 172 {34, 53, 121, 58}, /* #3 */ 173 {31, 48, 133, 64}, /* small */ 174}; 175/* *INDENT-ON* */ 176 177static Cursor GINcursor; 178static XSegment *line_pt; 179static int nplot; 180static TekLink Tek0; 181static jmp_buf Tekjump; 182static TekLink *TekRecord; 183static XSegment *Tline; 184 185static Const int *curstate = Talptable; 186static Const int *Tparsestate = Talptable; 187 188static char defaultTranslations[] = "\ 189 ~Meta<KeyPress>: insert-seven-bit() \n\ 190 Meta<KeyPress>: insert-eight-bit() \n\ 191 !Ctrl <Btn1Down>: popup-menu(mainMenu) \n\ 192 !Lock Ctrl <Btn1Down>: popup-menu(mainMenu) \n\ 193!Lock Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\ 194 !Ctrl @Num_Lock <Btn1Down>: popup-menu(mainMenu) \n\ 195 !Ctrl <Btn2Down>: popup-menu(tekMenu) \n\ 196 !Lock Ctrl <Btn2Down>: popup-menu(tekMenu) \n\ 197!Lock Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\ 198 !Ctrl @Num_Lock <Btn2Down>: popup-menu(tekMenu) \n\ 199 Shift ~Meta<Btn1Down>: gin-press(L) \n\ 200 ~Meta<Btn1Down>: gin-press(l) \n\ 201 Shift ~Meta<Btn2Down>: gin-press(M) \n\ 202 ~Meta<Btn2Down>: gin-press(m) \n\ 203 Shift ~Meta<Btn3Down>: gin-press(R) \n\ 204 ~Meta<Btn3Down>: gin-press(r)"; 205/* *INDENT-OFF* */ 206static XtActionsRec actionsList[] = { 207 { "string", HandleStringEvent }, 208 { "insert", HandleKeyPressed }, /* alias for insert-seven-bit */ 209 { "insert-seven-bit", HandleKeyPressed }, 210 { "insert-eight-bit", HandleEightBitKeyPressed }, 211 { "gin-press", HandleGINInput }, 212 { "secure", HandleSecure }, 213 { "create-menu", HandleCreateMenu }, 214 { "popup-menu", HandlePopupMenu }, 215 /* menu actions */ 216 { "allow-send-events", HandleAllowSends }, 217 { "set-visual-bell", HandleSetVisualBell }, 218#ifdef ALLOWLOGGING 219 { "set-logging", HandleLogging }, 220#endif 221 { "redraw", HandleRedraw }, 222 { "send-signal", HandleSendSignal }, 223 { "quit", HandleQuit }, 224 { "set-scrollbar", HandleScrollbar }, 225 { "set-jumpscroll", HandleJumpscroll }, 226 { "set-reverse-video", HandleReverseVideo }, 227 { "set-autowrap", HandleAutoWrap }, 228 { "set-reversewrap", HandleReverseWrap }, 229 { "set-autolinefeed", HandleAutoLineFeed }, 230 { "set-appcursor", HandleAppCursor }, 231 { "set-appkeypad", HandleAppKeypad }, 232 { "set-scroll-on-key", HandleScrollKey }, 233 { "set-scroll-on-tty-output", HandleScrollTtyOutput }, 234 { "set-allow132", HandleAllow132 }, 235 { "set-cursesemul", HandleCursesEmul }, 236 { "set-marginbell", HandleMarginBell }, 237 { "set-altscreen", HandleAltScreen }, 238 { "soft-reset", HandleSoftReset }, 239 { "hard-reset", HandleHardReset }, 240 { "set-terminal-type", HandleSetTerminalType }, 241 { "set-visibility", HandleVisibility }, 242 { "set-tek-text", HandleSetTekText }, 243 { "tek-page", HandleTekPage }, 244 { "tek-reset", HandleTekReset }, 245 { "tek-copy", HandleTekCopy }, 246#if OPT_TOOLBAR 247 { "set-toolbar", HandleToolbar }, 248#endif 249}; 250/* *INDENT-ON* */ 251 252static Dimension defOne = 1; 253 254#define GIN_TERM_NONE_STR "none" 255#define GIN_TERM_CR_STR "CRonly" 256#define GIN_TERM_EOT_STR "CR&EOT" 257 258#define GIN_TERM_NONE 0 259#define GIN_TERM_CR 1 260#define GIN_TERM_EOT 2 261 262#ifdef VMS 263#define DFT_FONT_SMALL "FIXED" 264#else 265#define DFT_FONT_SMALL "6x10" 266#endif 267 268static XtResource resources[] = 269{ 270 {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), 271 XtOffsetOf(CoreRec, core.width), XtRDimension, (caddr_t) & defOne}, 272 {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), 273 XtOffsetOf(CoreRec, core.height), XtRDimension, (caddr_t) & defOne}, 274 Fres("fontLarge", XtCFont, tek.Tfont[TEK_FONT_LARGE], "9x15"), 275 Fres("font2", XtCFont, tek.Tfont[TEK_FONT_2], "6x13"), 276 Fres("font3", XtCFont, tek.Tfont[TEK_FONT_3], "8x13"), 277 Fres("fontSmall", XtCFont, tek.Tfont[TEK_FONT_SMALL], DFT_FONT_SMALL), 278 Sres(XtNinitialFont, XtCInitialFont, tek.initial_font, "large"), 279 Sres("ginTerminator", "GinTerminator", tek.gin_terminator_str, GIN_TERM_NONE_STR), 280#if OPT_TOOLBAR 281 Wres(XtNmenuBar, XtCMenuBar, tek.tb_info.menu_bar, 0), 282 Ires(XtNmenuHeight, XtCMenuHeight, tek.tb_info.menu_height, 25), 283#endif 284}; 285 286static IChar Tinput(TekWidget /* tw */ ); 287static int getpoint(TekWidget /* tw */ ); 288static void TCursorBack(TekWidget /* tw */ ); 289static void TCursorDown(TekWidget /* tw */ ); 290static void TCursorForward(TekWidget /* tw */ ); 291static void TCursorUp(TekWidget /* tw */ ); 292static void TekBackground(TekWidget /* tw */ , 293 TScreen * /* screen */ ); 294static void TekResize(Widget /* w */ ); 295static void TekDraw(TekWidget /* tw */ , 296 int /* x */ , 297 int /* y */ ); 298static void TekEnq(TekWidget /* tw */ , 299 unsigned /* status */ , 300 int /* x */ , 301 int /* y */ ); 302static void TekFlush(TekWidget /* tw */ ); 303static void TekInitialize(Widget /* request */ , 304 Widget /* wnew */ , 305 ArgList /* args */ , 306 Cardinal * /* num_args */ ); 307static void TekPage(TekWidget /* tw */ ); 308static void TekRealize(Widget /* gw */ , 309 XtValueMask * /* valuemaskp */ , 310 XSetWindowAttributes * /* values */ ); 311 312static WidgetClassRec tekClassRec = 313{ 314 { 315/* core_class fields */ 316 (WidgetClass) & widgetClassRec, /* superclass */ 317 MY_CLASS, /* class_name */ 318 sizeof(TekWidgetRec), /* widget_size */ 319 NULL, /* class_initialize */ 320 NULL, /* class_part_initialize */ 321 False, /* class_inited */ 322 TekInitialize, /* initialize */ 323 NULL, /* initialize_hook */ 324 TekRealize, /* realize */ 325 actionsList, /* actions */ 326 XtNumber(actionsList), /* num_actions */ 327 resources, /* resources */ 328 XtNumber(resources), /* num_resources */ 329 NULLQUARK, /* xrm_class */ 330 True, /* compress_motion */ 331 True, /* compress_exposure */ 332 True, /* compress_enterleave */ 333 False, /* visible_interest */ 334 NULL, /* destroy */ 335 TekResize, /* resize */ 336 TekExpose, /* expose */ 337 NULL, /* set_values */ 338 NULL, /* set_values_hook */ 339 XtInheritSetValuesAlmost, /* set_values_almost */ 340 NULL, /* get_values_hook */ 341 NULL, /* accept_focus */ 342 XtVersion, /* version */ 343 NULL, /* callback_offsets */ 344 defaultTranslations, /* tm_table */ 345 XtInheritQueryGeometry, /* query_geometry */ 346 XtInheritDisplayAccelerator, /* display_accelerator */ 347 NULL /* extension */ 348 } 349}; 350WidgetClass tekWidgetClass = (WidgetClass) & tekClassRec; 351 352static Bool Tfailed = False; 353 354/* 355 * TekInit/TekRun are called after the VT100 widget has been initialized, but 356 * may be before VT100 is realized, depending upon whether Tek4014 is the 357 * first window to be shown. 358 */ 359int 360TekInit(void) 361{ 362 Widget form_top, menu_top; 363 Dimension menu_high; 364 365 if (!Tfailed 366 && tekWidget == 0) { 367 Cardinal nargs = 0; 368 Arg myArgs[3]; 369 Boolean iconic = 0; 370 371 TRACE(("TekInit\n")); 372 XtSetArg(myArgs[nargs], XtNiconic, &iconic); 373 ++nargs; 374 XtGetValues(toplevel, myArgs, nargs); 375 376 nargs = 0; 377 XtSetArg(myArgs[nargs], XtNiconic, iconic); 378 ++nargs; 379 XtSetArg(myArgs[nargs], XtNallowShellResize, True); 380 ++nargs; 381 XtSetArg(myArgs[nargs], XtNinput, True); 382 ++nargs; 383 384 /* this causes the Initialize method to be called */ 385 tekshellwidget = 386 XtCreatePopupShell("tektronix", topLevelShellWidgetClass, 387 toplevel, myArgs, nargs); 388 389 SetupMenus(tekshellwidget, &form_top, &menu_top, &menu_high); 390 391 /* this causes the Realize method to be called */ 392 tekWidget = (TekWidget) 393 XtVaCreateManagedWidget(MY_NAME, 394 tekWidgetClass, form_top, 395#if OPT_TOOLBAR 396 XtNmenuBar, menu_top, 397 XtNresizable, True, 398 XtNfromVert, menu_top, 399 XtNtop, XawChainTop, 400 XtNleft, XawChainLeft, 401 XtNright, XawChainRight, 402 XtNbottom, XawChainBottom, 403 XtNmenuHeight, menu_high, 404#endif 405 (XtPointer) 0); 406#if OPT_TOOLBAR 407 ShowToolbar(resource.toolBar); 408#endif 409 } 410 return (!Tfailed); 411} 412 413/* 414 * If we haven't allocated the PtyData struct, do so. 415 */ 416static int 417TekPtyData(void) 418{ 419 if (Tpushb == 0 && !Tfailed) { 420 if ((Tpushb = TypeMallocN(Char, 10)) == NULL 421 || (Tline = TypeMallocN(XSegment, MAX_VTX)) == NULL) { 422 xtermWarning("Not enough core for Tek mode\n"); 423 free(Tpushb); 424 Tfailed = True; 425 } 426 } 427 return (Tfailed ? 0 : 1); 428} 429 430static void 431Tekparse(TekWidget tw) 432{ 433 TekScreen *tekscr = TekScreenOf(tw); 434 TScreen *screen = TScreenOf(tw->vt); 435 int x, y; 436 IChar ch; 437 int nextstate; 438 439 for (;;) { 440 IChar c = input(); 441 /* 442 * The parsing tables all have 256 entries. If we're supporting 443 * wide characters, we handle them by treating them the same as 444 * printing characters. 445 */ 446#if OPT_WIDE_CHARS 447 if (c > 255) { 448 nextstate = (Tparsestate == Talptable) 449 ? CASE_PRINT 450 : CASE_IGNORE; 451 } else 452#endif 453 nextstate = Tparsestate[c]; 454 TRACE(("Tekparse %04X -> %d\n", c, nextstate)); 455 456 switch (nextstate) { 457 case CASE_REPORT: 458 TRACE(("case: report address\n")); 459 if (tekscr->TekGIN) { 460 TekGINoff(tw); 461 TekEnqMouse(tw, 0); 462 } else { 463 c = 064; /* has hard copy unit */ 464 if (tekscr->margin == MARGIN2) 465 c |= 02; 466 TekEnq(tw, c, tekscr->cur_X, tekscr->cur_Y); 467 } 468 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */ 469 Tparsestate = curstate; 470 break; 471 472 case CASE_VT_MODE: 473 TRACE(("case: special return to vt102 mode\n")); 474 Tparsestate = curstate; 475 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */ 476 FlushLog(tw->vt); 477 return; 478 479 case CASE_SPT_STATE: 480 TRACE(("case: Enter Special Point Plot mode\n")); 481 if (tekscr->TekGIN) 482 TekGINoff(tw); 483 Tparsestate = curstate = Tspttable; 484 break; 485 486 case CASE_GIN: 487 TRACE(("case: Do Tek GIN mode\n")); 488 tekscr->TekGIN = &TekRecord->ptr[-1]; 489 /* Set cross-hair cursor raster array */ 490 if ((GINcursor = 491 make_colored_cursor(XC_tcross, 492 T_COLOR(screen, MOUSE_FG), 493 T_COLOR(screen, MOUSE_BG))) != 0) { 494 XDefineCursor(XtDisplay(tw), TWindow(tekscr), 495 GINcursor); 496 } 497 Tparsestate = Tbyptable; /* Bypass mode */ 498 break; 499 500 case CASE_BEL: 501 TRACE(("case: BEL\n")); 502 if (tekscr->TekGIN) 503 TekGINoff(tw); 504 if (!tekRefreshList) 505 Bell(tw->vt, XkbBI_TerminalBell, 0); 506 Tparsestate = curstate; /* clear bypass condition */ 507 break; 508 509 case CASE_BS: 510 TRACE(("case: BS\n")); 511 if (tekscr->TekGIN) 512 TekGINoff(tw); 513 Tparsestate = curstate; /* clear bypass condition */ 514 TCursorBack(tw); 515 break; 516 517 case CASE_PT_STATE: 518 TRACE(("case: Enter Tek Point Plot mode\n")); 519 if (tekscr->TekGIN) 520 TekGINoff(tw); 521 Tparsestate = curstate = Tpttable; 522 break; 523 524 case CASE_PLT_STATE: 525 TRACE(("case: Enter Tek Plot mode\n")); 526 if (tekscr->TekGIN) 527 TekGINoff(tw); 528 Tparsestate = curstate = Tplttable; 529 if ((c = input()) == ANSI_BEL) 530 tekscr->pen = PENDOWN; 531 else { 532 unput(c); 533 tekscr->pen = PENUP; 534 } 535 break; 536 537 case CASE_TAB: 538 TRACE(("case: HT\n")); 539 if (tekscr->TekGIN) 540 TekGINoff(tw); 541 Tparsestate = curstate; /* clear bypass condition */ 542 TCursorForward(tw); 543 break; 544 545 case CASE_IPL_STATE: 546 TRACE(("case: Enter Tek Incremental Plot mode\n")); 547 if (tekscr->TekGIN) 548 TekGINoff(tw); 549 Tparsestate = curstate = Tipltable; 550 break; 551 552 case CASE_ALP_STATE: 553 TRACE(("case: Enter Tek Alpha mode from any other mode\n")); 554 if (tekscr->TekGIN) 555 TekGINoff(tw); 556 /* if in one of graphics states, move alpha cursor */ 557 if (nplot > 0) /* flush line VTbuffer */ 558 TekFlush(tw); 559 Tparsestate = curstate = Talptable; 560 break; 561 562 case CASE_UP: 563 TRACE(("case: cursor up\n")); 564 if (tekscr->TekGIN) 565 TekGINoff(tw); 566 Tparsestate = curstate; /* clear bypass condition */ 567 TCursorUp(tw); 568 break; 569 570 case CASE_COPY: 571 TRACE(("case: make copy\n")); 572 if (tekscr->TekGIN) 573 TekGINoff(tw); 574 TekCopy(tw); 575 TekRecord->ptr[-1] = ANSI_NAK; /* remove from recording */ 576 Tparsestate = curstate; /* clear bypass condition */ 577 break; 578 579 case CASE_PAGE: 580 TRACE(("case: Page Function\n")); 581 if (tekscr->TekGIN) 582 TekGINoff(tw); 583 TekPage(tw); /* clear bypass condition */ 584 break; 585 586 case CASE_BES_STATE: 587 TRACE(("case: Byp: an escape char\n")); 588 Tparsestate = Tbestable; 589 break; 590 591 case CASE_BYP_STATE: 592 TRACE(("case: set bypass condition\n")); 593 Tparsestate = Tbyptable; 594 break; 595 596 case CASE_IGNORE: 597 TRACE(("case: Esc: totally ignore CR, ESC, LF, ~\n")); 598 break; 599 600 case CASE_ASCII: 601 TRACE(("case: Select ASCII char set\n")); 602 /* ignore for now */ 603 Tparsestate = curstate; 604 break; 605 606 case CASE_APL: 607 TRACE(("case: Select APL char set\n")); 608 /* ignore for now */ 609 Tparsestate = curstate; 610 break; 611 612 case CASE_CHAR_SIZE: 613 TRACE(("case: character size selector\n")); 614 TekSetFontSize(tw, False, (int) (c & 03)); 615 Tparsestate = curstate; 616 break; 617 618 case CASE_BEAM_VEC: 619 TRACE(("case: beam and vector selector\n")); 620 /* only line types */ 621 c = (IChar) (c & LINEMASK); 622 if (c != tekscr->cur.linetype) { 623 if (nplot > 0) 624 TekFlush(tw); 625 if (c <= TEKNUMLINES) 626 tekscr->cur.linetype = c; 627 } 628 Tparsestate = curstate; 629 break; 630 631 case CASE_CURSTATE: 632 Tparsestate = curstate; 633 break; 634 635 case CASE_PENUP: 636 TRACE(("case: Ipl: penup\n")); 637 tekscr->pen = PENUP; 638 break; 639 640 case CASE_PENDOWN: 641 TRACE(("case: Ipl: pendown\n")); 642 tekscr->pen = PENDOWN; 643 break; 644 645 case CASE_IPL_POINT: 646 TRACE(("case: Ipl: point\n")); 647 x = tekscr->cur_X; 648 y = tekscr->cur_Y; 649 if (c & NORTH) 650 y++; 651 else if (c & SOUTH) 652 y--; 653 if (c & EAST) 654 x++; 655 else if (c & WEST) 656 x--; 657 if (tekscr->pen == PENDOWN) { 658 TekDraw(tw, x, y); 659 } else { 660 TekMove(tw, x, y); 661 } 662 break; 663 664 case CASE_PLT_VEC: 665 TRACE(("case: Plt: vector\n")); 666 unput(c); 667 if (getpoint(tw)) { 668 if (tekscr->pen == PENDOWN) { 669 TekDraw(tw, tekscr->cur.x, tekscr->cur.y); 670 } else { 671 TekMove(tw, tekscr->cur.x, tekscr->cur.y); 672 } 673 tekscr->pen = PENDOWN; 674 } 675 break; 676 677 case CASE_PT_POINT: 678 TRACE(("case: Pt: point\n")); 679 unput(c); 680 if (getpoint(tw)) { 681 TekMove(tw, tekscr->cur.x, tekscr->cur.y); 682 TekDraw(tw, tekscr->cur.x, tekscr->cur.y); 683 } 684 break; 685 686 case CASE_SPT_POINT: 687 TRACE(("case: Spt: point\n")); 688 /* ignore intensity character in c */ 689 if (getpoint(tw)) { 690 TekMove(tw, tekscr->cur.x, tekscr->cur.y); 691 TekDraw(tw, tekscr->cur.x, tekscr->cur.y); 692 } 693 break; 694 695 case CASE_CR: 696 TRACE(("case: CR\n")); 697 if (tekscr->TekGIN) 698 TekGINoff(tw); 699 if (nplot > 0) /* flush line VTbuffer */ 700 TekFlush(tw); 701 tekscr->cur_X = tekscr->margin == MARGIN1 ? 0 : 702 TEKWIDTH / 2; 703 Tparsestate = curstate = Talptable; 704 break; 705 706 case CASE_ESC_STATE: 707 TRACE(("case: ESC\n")); 708 Tparsestate = Tesctable; 709 break; 710 711 case CASE_LF: 712 TRACE(("case: LF\n")); 713 if (tekscr->TekGIN) 714 TekGINoff(tw); 715 TCursorDown(tw); 716 if (!tekRefreshList) 717 do_xevents(tw->vt); 718 break; 719 720 case CASE_SP: 721 TRACE(("case: SP\n")); 722 TCursorForward(tw); 723 break; 724 725 case CASE_PRINT: 726 TRACE(("case: printable character\n")); 727 ch = c; 728 x = (int) ScaledX(tw, tekscr->cur_X); 729 y = (int) ScaledY(tw, tekscr->cur_Y); 730 731#if OPT_WIDE_CHARS 732 if (screen->wide_chars 733 && (ch > 255)) { 734 XChar2b sbuf; 735 sbuf.byte2 = LO_BYTE(ch); 736 sbuf.byte1 = HI_BYTE(ch); 737 XDrawImageString16(XtDisplay(tw), 738 TWindow(tekscr), 739 tekscr->TnormalGC, 740 x, 741 y, 742 &sbuf, 743 1); 744 } else 745#endif 746 { 747 char ch2 = (char) ch; 748 XDrawString(XtDisplay(tw), 749 TWindow(tekscr), 750 tekscr->TnormalGC, 751 x, 752 y, 753 &ch2, 754 1); 755 } 756 TCursorForward(tw); 757 break; 758 case CASE_OSC: 759 /* FIXME: someone should disentangle the input queues 760 * of this code so that it can be state-driven. 761 */ 762 TRACE(("case: do osc escape\n")); 763 { 764 /* 765 * do_osc() can call TekExpose(), which calls TekRefresh(), 766 * and sends us recurring here - don't do that... 767 */ 768 static int nested; 769 770 Char buf2[512]; 771 IChar c2; 772 size_t len = 0; 773 while ((c2 = input()) != ANSI_BEL) { 774 if (!isprint((int) (c2 & 0x7f)) 775 || len + 2 >= (int) sizeof(buf2)) 776 break; 777 buf2[len++] = (Char) c2; 778 } 779 buf2[len] = 0; 780 if (!nested++) { 781 if (c2 == ANSI_BEL) 782 do_osc(tw->vt, buf2, len, ANSI_BEL); 783 } 784 --nested; 785 } 786 Tparsestate = curstate; 787 break; 788 } 789 } 790} 791 792static int rcnt; 793static char *rptr; 794static PtySelect Tselect_mask; 795 796static IChar 797Tinput(TekWidget tw) 798{ 799 TekScreen *tekscr = TekScreenOf(tw); 800 TScreen *screen = TScreenOf(tw->vt); 801 TekLink *tek; 802 803 if (Tpushback > Tpushb) 804 return (*--Tpushback); 805 if (tekRefreshList) { 806 if (rcnt-- > 0) 807 return (IChar) (*rptr++); 808 if ((tek = tekRefreshList->next) != 0) { 809 tekRefreshList = tek; 810 rptr = tek->data; 811 rcnt = tek->count - 1; 812 TekSetFontSize(tw, False, tek->fontsize); 813 return (IChar) (*rptr++); 814 } 815 tekRefreshList = (TekLink *) 0; 816 longjmp(Tekjump, 1); 817 } 818 again: 819 if (VTbuffer->next >= VTbuffer->last) { 820 int update = VTbuffer->update; 821 822 if (nplot > 0) /* flush line */ 823 TekFlush(tw); 824#ifdef VMS 825 Tselect_mask = pty_mask; /* force a read */ 826#else /* VMS */ 827 XFD_COPYSET(&pty_mask, &Tselect_mask); 828#endif /* VMS */ 829 for (;;) { 830#ifdef CRAY 831 struct timeval crocktimeout; 832 crocktimeout.tv_sec = 0; 833 crocktimeout.tv_usec = 0; 834 (void) Select(max_plus1, 835 &Tselect_mask, NULL, NULL, 836 &crocktimeout); 837#endif 838 if (readPtyData(tw->vt, &Tselect_mask, VTbuffer)) { 839 break; 840 } 841 if (Ttoggled && curstate == Talptable) { 842 TCursorToggle(tw, TOGGLE); 843 Ttoggled = False; 844 } 845 if (xtermAppPending() & XtIMXEvent) { 846#ifdef VMS 847 Tselect_mask = X_mask; 848#else /* VMS */ 849 XFD_COPYSET(&X_mask, &Tselect_mask); 850#endif /* VMS */ 851 } else { 852 XFlush(XtDisplay(tw)); 853#ifdef VMS 854 Tselect_mask = Select_mask; 855 856#else /* VMS */ 857 XFD_COPYSET(&Select_mask, &Tselect_mask); 858 if (Select(max_plus1, &Tselect_mask, NULL, NULL, NULL) < 0) { 859 if (errno != EINTR) 860 SysError(ERROR_TSELECT); 861 continue; 862 } 863#endif /* VMS */ 864 } 865#ifdef VMS 866 if (Tselect_mask & X_mask) { 867 xevents(tw->vt); 868 if (VTbuffer->update != update) 869 goto again; 870 } 871#else /* VMS */ 872 if (FD_ISSET(ConnectionNumber(XtDisplay(tw)), &Tselect_mask)) { 873 xevents(tw->vt); 874 if (VTbuffer->update != update) 875 goto again; 876 } 877#endif /* VMS */ 878 } 879 if (!Ttoggled && curstate == Talptable) { 880 TCursorToggle(tw, TOGGLE); 881 Ttoggled = True; 882 } 883 } 884 tek = TekRecord; 885 if (tek->count >= TEK_LINK_BLOCK_SIZE 886 || tek->fontsize != tekscr->cur.fontsize) { 887 if ((TekRecord = tek->next = CastMalloc(TekLink)) == 0) { 888 Panic("Tinput: malloc error (%d)\n", errno); 889 } else { 890 tek = tek->next; 891 tek->next = (TekLink *) 0; 892 tek->fontsize = (unsigned short) tekscr->cur.fontsize; 893 tek->count = 0; 894 tek->ptr = tek->data; 895 } 896 } 897 tek->count++; 898 899 (void) morePtyData(screen, VTbuffer); 900 return (IChar) (*tek->ptr++ = (char) nextPtyData(screen, VTbuffer)); 901} 902 903static void 904TekClear(TekWidget tw) 905{ 906 TekScreen *tekscr = TekScreenOf(tw); 907 908 TRACE(("TekClear\n")); 909 nplot = 0; 910 line_pt = Tline; 911 if (TWindow(tekscr)) 912 XClearWindow(XtDisplay(tw), TWindow(tekscr)); 913} 914 915void 916TekSetWinSize(TekWidget tw) 917{ 918 if (TEK4014_ACTIVE(tw->vt)) { 919 TekScreen *tekscr = TekScreenOf(tw); 920 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize]; 921 int rows = THeight(tekscr) / (int) (ScaleOf(tw) * t->vsize); 922 int cols = TWidth(tekscr) / (int) (ScaleOf(tw) * t->hsize); 923 924 update_winsize(TScreenOf(tw->vt)->respond, 925 rows, cols, 926 TFullHeight(tekscr), 927 TFullWidth(tekscr)); 928 } 929} 930 931static void 932compute_sizes(TekWidget tw) 933{ 934 TekScreen *tekscr = TekScreenOf(tw); 935 int border = 2 * BorderOf(tw); 936 double d; 937#if OPT_TRACE 938 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize]; 939 const XFontStruct *fs = tw->tek.Tfont[tekscr->cur.fontsize]; 940#endif 941 942 /* *INDENT-EQLS* */ 943 TWidth(tekscr) = tw->core.width - border; 944 THeight(tekscr) = tw->core.height - border; 945 ScaleOf(tw) = (double) TWidth(tekscr) / TEKWIDTH; 946 947 if ((d = (double) THeight(tekscr) / FULL_HEIGHT) < ScaleOf(tw)) 948 ScaleOf(tw) = d; 949 950 TFullWidth(tekscr) = tw->core.width; 951 TFullHeight(tekscr) = tw->core.height; 952 953 TRACE(("%s size %dx%d full %dx%d scale %.2f\n", MY_NAME, 954 THeight(tekscr), TWidth(tekscr), 955 TFullHeight(tekscr), TFullWidth(tekscr), 956 ScaleOf(tw))); 957 958 /* The tek4014 fonts always look odd since their spacing is overridden to 959 * get the "same" size as a real Tektronix terminal. TrueType fonts for 960 * these small sizes would be no better... 961 */ 962 TRACE(("unscaled font %dx%d\n", t->vsize, t->hsize)); 963 TRACE(("scaled font %.1fx%.1f\n", d * t->vsize, d * t->hsize)); 964 TRACE(("actual font %dx%d\n", 965 fs->max_bounds.ascent + fs->max_bounds.descent, 966 fs->max_bounds.width)); 967 968 TekSetWinSize(tw); 969} 970 971static void 972TekResize(Widget w) 973{ 974 TekWidget tw = getTekWidget(w); 975 if (tw != 0) { 976 977 TRACE(("TekResize " TRACE_L "\n")); 978 TekClear(tw); 979 980 compute_sizes(tw); 981 982 TRACE((TRACE_R " TekResize\n")); 983 } 984} 985 986/*ARGSUSED*/ 987void 988TekExpose(Widget w, 989 XEvent *event GCC_UNUSED, 990 Region region GCC_UNUSED) 991{ 992 TekWidget tw = getTekWidget(w); 993 if (tw != 0) { 994 TekScreen *tekscr = TekScreenOf(tw); 995 996 TRACE(("TekExpose " TRACE_L "\n")); 997 998#ifdef lint 999 region = region; 1000#endif 1001 if (!Ttoggled) 1002 TCursorToggle(tw, CLEAR); 1003 Ttoggled = True; 1004 Tpushback = Tpushb; 1005 tekscr->cur_X = 0; 1006 tekscr->cur_Y = TEKHOME; 1007 tekscr->cur = tekscr->page; 1008 TekSetFontSize(tw, False, tekscr->cur.fontsize); 1009 tekscr->margin = MARGIN1; 1010 if (tekscr->TekGIN) { 1011 tekscr->TekGIN = NULL; 1012 TekGINoff(tw); 1013 } 1014 tekRefreshList = &Tek0; 1015 rptr = tekRefreshList->data; 1016 rcnt = tekRefreshList->count; 1017 Tparsestate = curstate = Talptable; 1018 TRACE(("TekExpose resets data to replay %d bytes\n", rcnt)); 1019 first_map_occurred(); 1020 if (!tekscr->waitrefresh) 1021 TekRefresh(tw); 1022 TRACE((TRACE_R " TekExpose\n")); 1023 } 1024} 1025 1026void 1027TekRefresh(TekWidget tw) 1028{ 1029 if (tw != 0) { 1030 TScreen *screen = TScreenOf(tw->vt); 1031 TekScreen *tekscr = TekScreenOf(tw); 1032 static Cursor wait_cursor = None; 1033 1034 if (wait_cursor == None) 1035 wait_cursor = make_colored_cursor(XC_watch, 1036 T_COLOR(screen, MOUSE_FG), 1037 T_COLOR(screen, MOUSE_BG)); 1038 XDefineCursor(XtDisplay(tw), TWindow(tekscr), wait_cursor); 1039 XFlush(XtDisplay(tw)); 1040 if (!setjmp(Tekjump)) 1041 Tekparse(tw); 1042 XDefineCursor(XtDisplay(tw), TWindow(tekscr), 1043 (tekscr->TekGIN && GINcursor) ? GINcursor : tekscr->arrow); 1044 } 1045} 1046 1047void 1048TekRepaint(TekWidget tw) 1049{ 1050 TRACE(("TekRepaint\n")); 1051 TekClear(tw); 1052 TekExpose((Widget) tw, (XEvent *) NULL, (Region) NULL); 1053} 1054 1055static void 1056TekPage(TekWidget tw) 1057{ 1058 TekScreen *tekscr = TekScreenOf(tw); 1059 TekLink *tek; 1060 1061 TRACE(("TekPage\n")); 1062 TekClear(tw); 1063 tekscr->cur_X = 0; 1064 tekscr->cur_Y = TEKHOME; 1065 tekscr->margin = MARGIN1; 1066 tekscr->page = tekscr->cur; 1067 if (tekscr->TekGIN) 1068 TekGINoff(tw); 1069 tek = TekRecord = &Tek0; 1070 tek->fontsize = (unsigned short) tekscr->cur.fontsize; 1071 tek->count = 0; 1072 tek->ptr = tek->data; 1073 tek = tek->next; 1074 if (tek) 1075 do { 1076 TekLink *tek2 = tek->next; 1077 1078 free(tek); 1079 tek = tek2; 1080 } while (tek); 1081 TekRecord->next = (TekLink *) 0; 1082 tekRefreshList = (TekLink *) 0; 1083 Ttoggled = True; 1084 Tparsestate = curstate = Talptable; /* Tek Alpha mode */ 1085} 1086 1087#define EXTRABITS 017 1088#define FIVEBITS 037 1089#define HIBITS (FIVEBITS << SHIFTHI) 1090#define LOBITS (FIVEBITS << SHIFTLO) 1091#define SHIFTHI 7 1092#define SHIFTLO 2 1093#define TWOBITS 03 1094 1095static int 1096getpoint(TekWidget tw) 1097{ 1098 int x, y, e, lo_y = 0; 1099 TekScreen *tekscr = TekScreenOf(tw); 1100 1101 x = tekscr->cur.x; 1102 y = tekscr->cur.y; 1103 1104 for (;;) { 1105 int c; 1106 1107 if ((c = (int) input()) < ' ') { /* control character */ 1108 unput(c); 1109 return (0); 1110 } 1111 if (c < '@') { /* Hi X or Hi Y */ 1112 if (lo_y) { /* seen a Lo Y, so this must be Hi X */ 1113 x &= ~HIBITS; 1114 x |= (c & FIVEBITS) << SHIFTHI; 1115 continue; 1116 } 1117 /* else Hi Y */ 1118 y &= ~HIBITS; 1119 y |= (c & FIVEBITS) << SHIFTHI; 1120 continue; 1121 } 1122 if (c < '`') { /* Lo X */ 1123 x &= ~LOBITS; 1124 x |= (c & FIVEBITS) << SHIFTLO; 1125 tekscr->cur.x = x; 1126 tekscr->cur.y = y; 1127 return (1); /* OK */ 1128 } 1129 /* else Lo Y */ 1130 if (lo_y) { /* seen a Lo Y, so other must be extra bits */ 1131 e = (y >> SHIFTLO) & EXTRABITS; 1132 x &= ~TWOBITS; 1133 x |= e & TWOBITS; 1134 y &= ~TWOBITS; 1135 y |= (e >> SHIFTLO) & TWOBITS; 1136 } 1137 y &= ~LOBITS; 1138 y |= (c & FIVEBITS) << SHIFTLO; 1139 lo_y++; 1140 } 1141} 1142 1143static void 1144TCursorBack(TekWidget tw) 1145{ 1146 TekScreen *tekscr = TekScreenOf(tw); 1147 const struct Tek_Char *t; 1148 int x = (tekscr->cur_X -= (t = &TekChar[tekscr->cur.fontsize])->hsize); 1149 1150 if (((tekscr->margin == MARGIN1) && (x < 0)) 1151 || ((tekscr->margin == MARGIN2) && (x < TEKWIDTH / 2))) { 1152 int l = ((tekscr->cur_Y + (t->vsize - 1)) / t->vsize + 1); 1153 if (l >= t->nlines) { 1154 tekscr->margin = !tekscr->margin; 1155 l = 0; 1156 } 1157 tekscr->cur_Y = l * t->vsize; 1158 tekscr->cur_X = (t->charsperline - 1) * t->hsize; 1159 } 1160} 1161 1162static void 1163TCursorForward(TekWidget tw) 1164{ 1165 TekScreen *tekscr = TekScreenOf(tw); 1166 const struct Tek_Char *t = &TekChar[tekscr->cur.fontsize]; 1167 1168 if ((tekscr->cur_X += t->hsize) > TEKWIDTH) { 1169 int l = (tekscr->cur_Y / t->vsize - 1); 1170 if (l < 0) { 1171 tekscr->margin = !tekscr->margin; 1172 l = t->nlines - 1; 1173 } 1174 tekscr->cur_Y = l * t->vsize; 1175 tekscr->cur_X = tekscr->margin == MARGIN1 ? 0 : TEKWIDTH / 2; 1176 } 1177} 1178 1179static void 1180TCursorUp(TekWidget tw) 1181{ 1182 TekScreen *tekscr = TekScreenOf(tw); 1183 const struct Tek_Char *t; 1184 int l; 1185 1186 t = &TekChar[tekscr->cur.fontsize]; 1187 1188 if ((l = (tekscr->cur_Y + (t->vsize - 1)) / t->vsize + 1) >= t->nlines) { 1189 l = 0; 1190 if ((tekscr->margin = !tekscr->margin) != MARGIN1) { 1191 if (tekscr->cur_X < TEKWIDTH / 2) 1192 tekscr->cur_X += TEKWIDTH / 2; 1193 } else if (tekscr->cur_X >= TEKWIDTH / 2) 1194 tekscr->cur_X -= TEKWIDTH / 2; 1195 } 1196 tekscr->cur_Y = l * t->vsize; 1197} 1198 1199static void 1200TCursorDown(TekWidget tw) 1201{ 1202 TekScreen *tekscr = TekScreenOf(tw); 1203 const struct Tek_Char *t; 1204 int l; 1205 1206 t = &TekChar[tekscr->cur.fontsize]; 1207 1208 if ((l = tekscr->cur_Y / t->vsize - 1) < 0) { 1209 l = t->nlines - 1; 1210 if ((tekscr->margin = !tekscr->margin) != MARGIN1) { 1211 if (tekscr->cur_X < TEKWIDTH / 2) 1212 tekscr->cur_X += TEKWIDTH / 2; 1213 } else if (tekscr->cur_X >= TEKWIDTH / 2) 1214 tekscr->cur_X -= TEKWIDTH / 2; 1215 } 1216 tekscr->cur_Y = l * t->vsize; 1217} 1218 1219static void 1220AddToDraw(TekWidget tw, int x1, int y1, int x2, int y2) 1221{ 1222 XSegment *lp; 1223 1224 TRACE(("AddToDraw (%d,%d) (%d,%d)\n", x1, y1, x2, y2)); 1225 if (nplot >= MAX_PTS) { 1226 TekFlush(tw); 1227 } 1228 lp = line_pt++; 1229 lp->x1 = (short) ScaledX(tw, x1); 1230 lp->y1 = (short) ScaledY(tw, y1); 1231 lp->x2 = (short) ScaledX(tw, x2); 1232 lp->y2 = (short) ScaledY(tw, y2); 1233 nplot++; 1234 TRACE(("...AddToDraw %d points\n", nplot)); 1235} 1236 1237static void 1238TekDraw(TekWidget tw, int x, int y) 1239{ 1240 TekScreen *tekscr = TekScreenOf(tw); 1241 1242 if (nplot == 0 || T_lastx != tekscr->cur_X || T_lasty != tekscr->cur_Y) { 1243 /* 1244 * We flush on each unconnected line segment if the line 1245 * type is not solid. This solves a bug in X when drawing 1246 * points while the line type is not solid. 1247 */ 1248 if (nplot > 0 && tekscr->cur.linetype != SOLIDLINE) 1249 TekFlush(tw); 1250 } 1251 AddToDraw(tw, tekscr->cur_X, tekscr->cur_Y, x, y); 1252 T_lastx = tekscr->cur_X = x; 1253 T_lasty = tekscr->cur_Y = y; 1254} 1255 1256static void 1257TekFlush(TekWidget tw) 1258{ 1259 TekScreen *tekscr = TekScreenOf(tw); 1260 1261 TRACE(("TekFlush\n")); 1262 XDrawSegments(XtDisplay(tw), TWindow(tekscr), 1263 ((tekscr->cur.linetype == SOLIDLINE) 1264 ? tekscr->TnormalGC 1265 : tekscr->linepat[tekscr->cur.linetype - 1]), 1266 Tline, nplot); 1267 nplot = 0; 1268 line_pt = Tline; 1269} 1270 1271void 1272TekGINoff(TekWidget tw) 1273{ 1274 TekScreen *tekscr = TekScreenOf(tw); 1275 1276 TRACE(("TekGINoff\n")); 1277 XDefineCursor(XtDisplay(tw), TWindow(tekscr), tekscr->arrow); 1278 if (GINcursor) 1279 XFreeCursor(XtDisplay(tw), GINcursor); 1280 if (tekscr->TekGIN) { 1281 *tekscr->TekGIN = ANSI_CAN; /* modify recording */ 1282 tekscr->TekGIN = NULL; 1283 } 1284} 1285 1286void 1287TekEnqMouse(TekWidget tw, int c) /* character pressed */ 1288{ 1289 TekScreen *tekscr = TekScreenOf(tw); 1290 int mousex, mousey, rootx, rooty; 1291 unsigned int mask; /* XQueryPointer */ 1292 Window root, subw; 1293 1294 TRACE(("TekEnqMouse\n")); 1295 XQueryPointer( 1296 XtDisplay(tw), TWindow(tekscr), 1297 &root, &subw, 1298 &rootx, &rooty, 1299 &mousex, &mousey, 1300 &mask); 1301 if ((mousex = (int) ((mousex - BorderOf(tw)) / ScaleOf(tw))) < 0) 1302 mousex = 0; 1303 else if (mousex >= TEKWIDTH) 1304 mousex = TEKWIDTH - 1; 1305 if ((mousey = (int) BottomY((mousey - BorderOf(tw)) / ScaleOf(tw))) < 0) 1306 mousey = 0; 1307 else if (mousey >= TEKHEIGHT) 1308 mousey = TEKHEIGHT - 1; 1309 TekEnq(tw, (unsigned) c, mousex, mousey); 1310} 1311 1312static void 1313TekEnq(TekWidget tw, 1314 unsigned status, 1315 int x, 1316 int y) 1317{ 1318 TScreen *screen = TScreenOf(tw->vt); 1319 TekScreen *tekscr = TekScreenOf(tw); 1320 Char cplot[7]; 1321 int len = 5; 1322 int adj = (status != 0) ? 0 : 1; 1323 1324 TRACE(("TekEnq\n")); 1325 cplot[0] = (Char) status; 1326 /* Translate x and y to Tektronix code */ 1327 cplot[1] = (Char) (040 | ((x >> SHIFTHI) & FIVEBITS)); 1328 cplot[2] = (Char) (040 | ((x >> SHIFTLO) & FIVEBITS)); 1329 cplot[3] = (Char) (040 | ((y >> SHIFTHI) & FIVEBITS)); 1330 cplot[4] = (Char) (040 | ((y >> SHIFTLO) & FIVEBITS)); 1331 1332 if (tekscr->gin_terminator != GIN_TERM_NONE) 1333 cplot[len++] = '\r'; 1334 if (tekscr->gin_terminator == GIN_TERM_EOT) 1335 cplot[len++] = '\004'; 1336#ifdef VMS 1337 tt_write(cplot + adj, len - adj); 1338#else /* VMS */ 1339 v_write(screen->respond, cplot + adj, (unsigned) (len - adj)); 1340#endif /* VMS */ 1341} 1342 1343void 1344TekRun(void) 1345{ 1346 XtermWidget xw = term; 1347 1348 assert(xw != 0); 1349 if (tekWidget == 0) { 1350 TekInit(); 1351 } 1352 if (tekWidget != 0) { 1353 TRACE(("TekRun ...\n")); 1354 1355 if (!TEK4014_SHOWN(xw)) { 1356 set_tek_visibility(True); 1357 } 1358 update_vttekmode(); 1359 update_vtshow(); 1360 update_tekshow(); 1361 set_tekhide_sensitivity(); 1362 1363 Tpushback = Tpushb; 1364 Ttoggled = True; 1365 if (!setjmp(Tekend)) 1366 Tekparse(tekWidget); 1367 if (!Ttoggled) { 1368 TCursorToggle(tekWidget, TOGGLE); 1369 Ttoggled = True; 1370 } 1371 TEK4014_ACTIVE(xw) = False; 1372 xtermSetWinSize(xw); 1373 } else { 1374 TEK4014_ACTIVE(xw) = False; 1375 if (VWindow(TScreenOf(xw)) == 0) { 1376 Exit(ERROR_TINIT); 1377 } 1378 } 1379} 1380 1381#define DOTTED_LENGTH 2 1382#define DOT_DASHED_LENGTH 4 1383#define SHORT_DASHED_LENGTH 2 1384#define LONG_DASHED_LENGTH 2 1385 1386static const int dash_length[TEKNUMLINES] = 1387{ 1388 DOTTED_LENGTH, 1389 DOT_DASHED_LENGTH, 1390 SHORT_DASHED_LENGTH, 1391 LONG_DASHED_LENGTH, 1392}; 1393 1394static _Xconst char dotted[DOTTED_LENGTH] = 1395{3, 1}; 1396static _Xconst char dot_dashed[DOT_DASHED_LENGTH] = 1397{3, 4, 3, 1}; 1398static _Xconst char short_dashed[SHORT_DASHED_LENGTH] = 1399{4, 4}; 1400static _Xconst char long_dashed[LONG_DASHED_LENGTH] = 1401{4, 7}; 1402 1403static _Xconst char *dashes[TEKNUMLINES] = 1404{ 1405 dotted, 1406 dot_dashed, 1407 short_dashed, 1408 long_dashed, 1409}; 1410 1411/* 1412 * The following functions are called to initialize and realize the tekWidget 1413 */ 1414static void 1415TekInitialize(Widget wrequest, 1416 Widget new_arg, 1417 ArgList args, 1418 Cardinal *num_args) 1419{ 1420 XtermWidget xw = term; 1421 TScreen *vtscr = TScreenOf(xw); 1422 1423 TekWidget request = (TekWidget) wrequest; 1424 TekWidget wnew = (TekWidget) new_arg; 1425 1426 Widget tekparent = SHELL_OF(wnew); 1427 TekScreen *tekscr = TekScreenOf((TekWidget) wnew); 1428 1429 int i; 1430 int border; 1431 int pr; 1432 int winX, winY; 1433 unsigned min_width, min_height; 1434 unsigned width, height; 1435 char Tdefault[32]; 1436 1437 (void) args; 1438 (void) num_args; 1439 1440 TRACE(("TekInitialize " TRACE_L "\n")); 1441 memset(tekscr, 0, sizeof(*tekscr)); 1442 1443 /* 1444 * Eliminate 'term' as global from other functions. 1445 */ 1446 wnew->vt = xw; 1447 border = 2 * BorderOf(wnew); 1448 TRACE(("... border*2: %d\n", border)); 1449 1450 /* look for focus related events on the shell, because we need 1451 * to care about the shell's border being part of our focus. 1452 */ 1453 XtAddEventHandler(tekparent, EnterWindowMask, False, 1454 HandleEnterWindow, (Opaque) 0); 1455 XtAddEventHandler(tekparent, LeaveWindowMask, False, 1456 HandleLeaveWindow, (Opaque) 0); 1457 XtAddEventHandler(tekparent, FocusChangeMask, False, 1458 HandleFocusChange, (Opaque) 0); 1459 XtAddEventHandler(new_arg, PropertyChangeMask, False, 1460 HandleBellPropertyChange, (Opaque) 0); 1461 1462#ifndef NO_ACTIVE_ICON 1463 tekscr->whichTwin = &(tekscr->fullTwin); 1464#endif /* NO_ACTIVE_ICON */ 1465 1466 init_Sres(tek.initial_font); 1467 init_Sres(tek.gin_terminator_str); 1468#if OPT_TOOLBAR 1469 init_Ires(tek.tb_info.menu_height); 1470 wnew->tek.tb_info.menu_bar = request->tek.tb_info.menu_bar; 1471#endif 1472 1473 BorderPixel(wnew) = BorderPixel(xw); 1474 1475 tekscr->arrow = make_colored_cursor(XC_left_ptr, 1476 T_COLOR(vtscr, MOUSE_FG), 1477 T_COLOR(vtscr, MOUSE_BG)); 1478 1479 for (i = 0; i < TEKNUMFONTS; i++) { 1480 if (!wnew->tek.Tfont[i]) { 1481 wnew->tek.Tfont[i] = XQueryFont(XtDisplay(wnew), DefaultGCID(wnew)); 1482 } 1483 if (wnew->tek.Tfont[i]) { 1484 TRACE(("Tfont[%d] %dx%d\n", 1485 i, 1486 wnew->tek.Tfont[i]->max_bounds.width, 1487 wnew->tek.Tfont[i]->ascent + 1488 wnew->tek.Tfont[i]->descent)); 1489 wnew->tek.tobaseline[i] = wnew->tek.Tfont[i]->ascent; 1490 } else { 1491 TRACE(("Tfont[%d] disabled\n", i)); 1492 SetItemSensitivity(tekMenuEntries[i].widget, False); 1493 } 1494 } 1495 1496 if (xw->misc.T_geometry == NULL) { 1497 int def_width, def_height; 1498 1499 if (xw->misc.tekSmall) { 1500 def_width = TEKMINWIDTH; 1501 def_height = TEKMINHEIGHT; 1502 } else { 1503 def_width = TEKDEFWIDTH; 1504 def_height = TEKDEFHEIGHT; 1505 } 1506 sprintf(Tdefault, "=%dx%d", def_width + border, def_height + border); 1507 xw->misc.T_geometry = Tdefault; 1508 } 1509 1510 winX = 1; 1511 winY = 1; 1512 width = (unsigned) (TEKDEFWIDTH + border); 1513 height = (unsigned) (TEKDEFHEIGHT + border); 1514 min_width = (unsigned) (TEKMINWIDTH + border); 1515 min_height = (unsigned) (TEKMINHEIGHT + border); 1516 1517 TRACE(("parsing T_geometry %s\n", NonNull(xw->misc.T_geometry))); 1518 pr = XParseGeometry(xw->misc.T_geometry, 1519 &winX, 1520 &winY, 1521 &width, 1522 &height); 1523 1524 /* window-manager hints will do this anyway... */ 1525 if (height < min_height) { 1526 TRACE(("... override height from %d to %d\n", height, min_height)); 1527 height = min_height; 1528 } 1529 if (width < min_width) { 1530 TRACE(("... override width from %d to %d\n", width, min_width)); 1531 width = min_width; 1532 } 1533 1534 TRACE(("... position %d,%d size %dx%d\n", winY, winX, height, width)); 1535 if ((pr & XValue) && (pr & XNegative)) { 1536 winX += DisplayWidth(XtDisplay(wnew), DefaultScreen(XtDisplay(wnew))) 1537 - (int) width - (BorderWidth(SHELL_OF(xw)) * 2); 1538 } 1539 if ((pr & YValue) && (pr & YNegative)) { 1540 winY += DisplayHeight(XtDisplay(wnew), DefaultScreen(XtDisplay(wnew))) 1541 - (int) height - (BorderWidth(SHELL_OF(xw)) * 2); 1542 } 1543 1544 /* set up size hints */ 1545 1546 /* *INDENT-EQLS* */ 1547 wnew->hints.min_width = (int) min_width; 1548 wnew->hints.min_height = (int) min_height; 1549 wnew->hints.width_inc = 1; 1550 wnew->hints.height_inc = 1; 1551 wnew->hints.flags = PMinSize | PResizeInc; 1552 wnew->hints.x = winX; 1553 wnew->hints.y = winY; 1554 1555 if ((XValue & pr) || (YValue & pr)) { 1556 wnew->hints.flags |= USSize | USPosition; 1557 wnew->hints.flags |= PWinGravity; 1558 switch (pr & (XNegative | YNegative)) { 1559 case 0: 1560 wnew->hints.win_gravity = NorthWestGravity; 1561 break; 1562 case XNegative: 1563 wnew->hints.win_gravity = NorthEastGravity; 1564 break; 1565 case YNegative: 1566 wnew->hints.win_gravity = SouthWestGravity; 1567 break; 1568 default: 1569 wnew->hints.win_gravity = SouthEastGravity; 1570 break; 1571 } 1572 } else { 1573 /* set a default size, but do *not* set position */ 1574 wnew->hints.flags |= PSize; 1575 } 1576 wnew->hints.width = (int) width; 1577 wnew->hints.height = (int) height; 1578 if ((WidthValue & pr) || (HeightValue & pr)) 1579 wnew->hints.flags |= USSize; 1580 else 1581 wnew->hints.flags |= PSize; 1582 1583 tekscr->cur.fontsize = TEK_FONT_LARGE; 1584 if (wnew->tek.initial_font) { 1585 int result = TekGetFontSize(wnew->tek.initial_font); 1586 if (result >= 0) 1587 tekscr->cur.fontsize = result; 1588 } 1589 TRACE(("Tek cur.fontsize=%d\n", tekscr->cur.fontsize)); 1590 1591#define TestGIN(s) XmuCompareISOLatin1(wnew->tek.gin_terminator_str, s) 1592 1593 if (TestGIN(GIN_TERM_NONE_STR) == 0) 1594 tekscr->gin_terminator = GIN_TERM_NONE; 1595 else if (TestGIN(GIN_TERM_CR_STR) == 0) 1596 tekscr->gin_terminator = GIN_TERM_CR; 1597 else if (TestGIN(GIN_TERM_EOT_STR) == 0) 1598 tekscr->gin_terminator = GIN_TERM_EOT; 1599 else 1600 xtermWarning("illegal GIN terminator setting \"%s\"\n", 1601 wnew->tek.gin_terminator_str); 1602 TRACE(("Tek gin_terminator=%d\n", tekscr->gin_terminator)); 1603 1604 TRACE((TRACE_R " TekInitialize\n")); 1605} 1606 1607static void 1608TekRealize(Widget gw, 1609 XtValueMask * valuemaskp, 1610 XSetWindowAttributes * values) 1611{ 1612 TekWidget tw = (TekWidget) gw; 1613 TekScreen *tekscr = TekScreenOf(tw); 1614 TScreen *vtscr = TScreenOf(tw->vt); 1615 1616 int i; 1617 TekLink *tek; 1618 XGCValues gcv; 1619 unsigned width, height; 1620 unsigned long TEKgcFontMask; 1621 1622 TRACE(("TekRealize " TRACE_L "\n")); 1623 1624 if (!TekPtyData()) 1625 return; 1626 1627 /* use values from TekInitialize... */ 1628 height = (unsigned) tw->hints.height; 1629 width = (unsigned) tw->hints.width; 1630 1631 (void) REQ_RESIZE((Widget) tw, 1632 (Dimension) width, (Dimension) height, 1633 &tw->core.width, &tw->core.height); 1634 1635 /* XXX This is bogus. We are parsing geometries too late. This 1636 * is information that the shell widget ought to have before we get 1637 * realized, so that it can do the right thing. 1638 */ 1639 if (tw->hints.flags & USPosition) 1640 XMoveWindow(XtDisplay(tw), TShellWindow, tw->hints.x, tw->hints.y); 1641 1642 XSetWMNormalHints(XtDisplay(tw), TShellWindow, &tw->hints); 1643 XFlush(XtDisplay(tw)); /* get it out to window manager */ 1644 1645 values->win_gravity = NorthWestGravity; 1646 values->background_pixel = T_COLOR(vtscr, TEK_BG); 1647 1648 XtWindow(tw) = TWindow(tekscr) = 1649 XCreateWindow(XtDisplay(tw), 1650 VShellWindow(tw), 1651 tw->core.x, tw->core.y, 1652 tw->core.width, tw->core.height, 1653 BorderWidth(tw), 1654 (int) tw->core.depth, 1655 InputOutput, CopyFromParent, 1656 ((*valuemaskp) | CWBackPixel | CWWinGravity), 1657 values); 1658 1659 compute_sizes(tw); 1660 1661 gcv.graphics_exposures = True; /* default */ 1662 gcv.font = tw->tek.Tfont[tekscr->cur.fontsize]->fid; 1663 gcv.foreground = T_COLOR(vtscr, TEK_FG); 1664 gcv.background = T_COLOR(vtscr, TEK_BG); 1665 1666 /* if font wasn't successfully opened, then gcv.font will contain 1667 the Default GC's ID, meaning that we must use the server default font. 1668 */ 1669 TEKgcFontMask = (unsigned long) ((gcv.font == DefaultGCID(tw)) 1670 ? 0 1671 : GCFont); 1672 tekscr->TnormalGC = XCreateGC(XtDisplay(tw), TWindow(tekscr), 1673 (TEKgcFontMask | GCGraphicsExposures | 1674 GCForeground | GCBackground), 1675 &gcv); 1676 1677 gcv.function = GXinvert; 1678 gcv.plane_mask = (T_COLOR(vtscr, TEK_BG) ^ 1679 T_COLOR(vtscr, TEK_CURSOR)); 1680 gcv.join_style = JoinMiter; /* default */ 1681 gcv.line_width = 1; 1682 tekscr->TcursorGC = XCreateGC(XtDisplay(tw), TWindow(tekscr), 1683 (GCFunction | GCPlaneMask), &gcv); 1684 1685 gcv.foreground = T_COLOR(vtscr, TEK_FG); 1686 gcv.line_style = LineOnOffDash; 1687 gcv.line_width = 0; 1688 for (i = 0; i < TEKNUMLINES; i++) { 1689 tekscr->linepat[i] = XCreateGC(XtDisplay(tw), TWindow(tekscr), 1690 (GCForeground | GCLineStyle), &gcv); 1691 XSetDashes(XtDisplay(tw), tekscr->linepat[i], 0, 1692 dashes[i], dash_length[i]); 1693 } 1694 1695 TekBackground(tw, vtscr); 1696 1697 tekscr->margin = MARGIN1; /* Margin 1 */ 1698 tekscr->TekGIN = False; /* GIN off */ 1699 1700 XDefineCursor(XtDisplay(tw), TWindow(tekscr), tekscr->arrow); 1701 1702 { /* there's gotta be a better way... */ 1703 static char empty_string[1]; 1704 static Arg args[] = 1705 { 1706 {XtNtitle, (XtArgVal) NULL}, 1707 {XtNiconName, (XtArgVal) NULL}, 1708 }; 1709 char *icon_name = NULL; 1710 char *title = NULL; 1711 char *tek_icon_name = NULL; 1712 char *tek_title = NULL; 1713 1714 args[0].value = (XtArgVal) & icon_name; 1715 args[1].value = (XtArgVal) & title; 1716 XtGetValues(SHELL_OF(tw), args, 2); 1717 1718 if (IsEmpty(title)) { 1719 title = empty_string; 1720 } 1721 1722 if (IsEmpty(icon_name)) { 1723 icon_name = empty_string; 1724 } 1725 1726 TRACE(("TekShell title='%s', iconName='%s'\n", title, icon_name)); 1727 tek_icon_name = XtMalloc((Cardinal) strlen(icon_name) + 7); 1728 strcpy(tek_icon_name, icon_name); 1729 strcat(tek_icon_name, "(Tek)"); 1730 tek_title = XtMalloc((Cardinal) strlen(title) + 7); 1731 strcpy(tek_title, title); 1732 strcat(tek_title, "(Tek)"); 1733 args[0].value = (XtArgVal) tek_icon_name; 1734 args[1].value = (XtArgVal) tek_title; 1735 TRACE(("Tek title='%s', iconName='%s'\n", tek_title, tek_icon_name)); 1736 XtSetValues(SHELL_OF(tw), args, 2); 1737 XtFree(tek_icon_name); 1738 XtFree(tek_title); 1739 } 1740 1741 /* *INDENT-EQLS* */ 1742 tek = TekRecord = &Tek0; 1743 tek->next = (TekLink *) 0; 1744 tek->fontsize = (unsigned short) tekscr->cur.fontsize; 1745 tek->count = 0; 1746 tek->ptr = tek->data; 1747 Tpushback = Tpushb; 1748 tekscr->cur_X = 0; 1749 tekscr->cur_Y = TEKHOME; 1750 line_pt = Tline; 1751 Ttoggled = True; 1752 tekscr->page = tekscr->cur; 1753 1754 TRACE((TRACE_R " TekRealize\n")); 1755} 1756 1757int 1758TekGetFontSize(const char *param) 1759{ 1760 int result; 1761 1762 if (XmuCompareISOLatin1(param, "l") == 0 || 1763 XmuCompareISOLatin1(param, "large") == 0) 1764 result = TEK_FONT_LARGE; 1765 else if (XmuCompareISOLatin1(param, "2") == 0 || 1766 XmuCompareISOLatin1(param, "two") == 0) 1767 result = TEK_FONT_2; 1768 else if (XmuCompareISOLatin1(param, "3") == 0 || 1769 XmuCompareISOLatin1(param, "three") == 0) 1770 result = TEK_FONT_3; 1771 else if (XmuCompareISOLatin1(param, "s") == 0 || 1772 XmuCompareISOLatin1(param, "small") == 0) 1773 result = TEK_FONT_SMALL; 1774 else 1775 result = -1; 1776 1777 return result; 1778} 1779 1780void 1781TekSetFontSize(TekWidget tw, Bool fromMenu, int newitem) 1782{ 1783 if (tw != 0) { 1784 TekScreen *tekscr = TekScreenOf(tw); 1785 int oldsize = tekscr->cur.fontsize; 1786 int newsize = MI2FS(newitem); 1787 Font fid; 1788 1789 TRACE(("TekSetFontSize(%d) size %d ->%d\n", newitem, oldsize, newsize)); 1790 if (newsize < 0 || newsize >= TEKNUMFONTS) { 1791 Bell(tw->vt, XkbBI_MinorError, 0); 1792 } else if (oldsize != newsize) { 1793 if (!Ttoggled) 1794 TCursorToggle(tw, TOGGLE); 1795 set_tekfont_menu_item(oldsize, False); 1796 1797 tekscr->cur.fontsize = newsize; 1798 TekSetWinSize(tw); 1799 if (fromMenu) 1800 tekscr->page.fontsize = newsize; 1801 1802 fid = tw->tek.Tfont[newsize]->fid; 1803 if (fid == DefaultGCID(tw)) { 1804 /* we didn't succeed in opening a real font 1805 for this size. Instead, use server default. */ 1806 XCopyGC(XtDisplay(tw), 1807 DefaultGC(XtDisplay(tw), DefaultScreen(XtDisplay(tw))), 1808 GCFont, tekscr->TnormalGC); 1809 } else { 1810 XSetFont(XtDisplay(tw), tekscr->TnormalGC, fid); 1811 } 1812 1813 set_tekfont_menu_item(newsize, True); 1814 if (!Ttoggled) 1815 TCursorToggle(tw, TOGGLE); 1816 1817 if (fromMenu) { 1818 /* we'll get an exposure event after changing fontsize, so we 1819 * have to clear the screen to avoid painting over the previous 1820 * text. 1821 */ 1822 TekClear(tw); 1823 } 1824 } 1825 } 1826} 1827 1828void 1829ChangeTekColors(TekWidget tw, TScreen *screen, ScrnColors * pNew) 1830{ 1831 if (tw && screen) { 1832 TekScreen *tekscr = TekScreenOf(tw); 1833 XGCValues gcv; 1834 int i; 1835 1836 if (COLOR_DEFINED(pNew, TEK_FG)) { 1837 T_COLOR(screen, TEK_FG) = COLOR_VALUE(pNew, TEK_FG); 1838 TRACE(("... TEK_FG: %#lx\n", T_COLOR(screen, TEK_FG))); 1839 } 1840 if (COLOR_DEFINED(pNew, TEK_BG)) { 1841 T_COLOR(screen, TEK_BG) = COLOR_VALUE(pNew, TEK_BG); 1842 TRACE(("... TEK_BG: %#lx\n", T_COLOR(screen, TEK_BG))); 1843 } 1844 if (COLOR_DEFINED(pNew, TEK_CURSOR)) { 1845 T_COLOR(screen, TEK_CURSOR) = COLOR_VALUE(pNew, TEK_CURSOR); 1846 TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR))); 1847 } else { 1848 T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG); 1849 TRACE(("... TEK_CURSOR: %#lx\n", T_COLOR(screen, TEK_CURSOR))); 1850 } 1851 1852 XSetForeground(XtDisplay(tw), tekscr->TnormalGC, 1853 T_COLOR(screen, TEK_FG)); 1854 XSetBackground(XtDisplay(tw), tekscr->TnormalGC, 1855 T_COLOR(screen, TEK_BG)); 1856 if (BorderPixel(tw) == T_COLOR(screen, TEK_BG)) { 1857 BorderPixel(tw) = T_COLOR(screen, TEK_FG); 1858 BorderPixel(XtParent(tw)) = T_COLOR(screen, TEK_FG); 1859 if (XtWindow(XtParent(tw))) 1860 XSetWindowBorder(XtDisplay(tw), 1861 XtWindow(XtParent(tw)), 1862 BorderPixel(tw)); 1863 } 1864 1865 for (i = 0; i < TEKNUMLINES; i++) { 1866 XSetForeground(XtDisplay(tw), tekscr->linepat[i], 1867 T_COLOR(screen, TEK_FG)); 1868 } 1869 1870 gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^ 1871 T_COLOR(screen, TEK_CURSOR)); 1872 XChangeGC(XtDisplay(tw), tekscr->TcursorGC, GCPlaneMask, &gcv); 1873 TekBackground(tw, screen); 1874 } 1875 return; 1876} 1877 1878void 1879TekReverseVideo(XtermWidget xw, TekWidget tw) 1880{ 1881 if (tw) { 1882 TScreen *screen = TScreenOf(xw); 1883 TekScreen *tekscr = TekScreenOf(tw); 1884 Pixel tmp; 1885 XGCValues gcv; 1886 int i; 1887 1888 EXCHANGE(T_COLOR(screen, TEK_FG), T_COLOR(screen, TEK_BG), tmp); 1889 1890 T_COLOR(screen, TEK_CURSOR) = T_COLOR(screen, TEK_FG); 1891 1892 XSetForeground(XtDisplay(tw), tekscr->TnormalGC, T_COLOR(screen, TEK_FG)); 1893 XSetBackground(XtDisplay(tw), tekscr->TnormalGC, T_COLOR(screen, TEK_BG)); 1894 1895 if (BorderPixel(tw) == T_COLOR(screen, TEK_BG)) { 1896 BorderPixel(tw) = T_COLOR(screen, TEK_FG); 1897 BorderPixel(XtParent(tw)) = T_COLOR(screen, TEK_FG); 1898 if (XtWindow(XtParent(tw))) 1899 XSetWindowBorder(XtDisplay(tw), 1900 XtWindow(XtParent(tw)), 1901 BorderPixel(tw)); 1902 } 1903 1904 for (i = 0; i < TEKNUMLINES; i++) { 1905 XSetForeground(XtDisplay(tw), tekscr->linepat[i], 1906 T_COLOR(screen, TEK_FG)); 1907 } 1908 1909 gcv.plane_mask = (T_COLOR(screen, TEK_BG) ^ 1910 T_COLOR(screen, TEK_CURSOR)); 1911 XChangeGC(XtDisplay(tw), tekscr->TcursorGC, GCPlaneMask, &gcv); 1912 TekBackground(tw, screen); 1913 } 1914} 1915 1916static void 1917TekBackground(TekWidget tw, TScreen *screen) 1918{ 1919 TekScreen *tekscr = TekScreenOf(tw); 1920 1921 if (TWindow(tekscr)) 1922 XSetWindowBackground(XtDisplay(tw), TWindow(tekscr), 1923 T_COLOR(screen, TEK_BG)); 1924} 1925 1926/* 1927 * Toggles cursor on or off at cursor position in screen. 1928 */ 1929void 1930TCursorToggle(TekWidget tw, int toggle) /* TOGGLE or CLEAR */ 1931{ 1932 TekScreen *tekscr; 1933 XtermWidget xw; 1934 int c, x, y; 1935 unsigned cellwidth, cellheight; 1936 1937 if (tw == 0) 1938 return; 1939 if ((tekscr = TekScreenOf(tw)) == 0) 1940 return; 1941 if ((xw = tw->vt) == 0) 1942 return; 1943 if (!TEK4014_SHOWN(xw)) 1944 return; 1945 1946 TRACE(("TCursorToggle %s\n", (toggle == TOGGLE) ? "toggle" : "clear")); 1947 c = tekscr->cur.fontsize; 1948 cellwidth = (unsigned) tw->tek.Tfont[c]->max_bounds.width; 1949 cellheight = (unsigned) (tw->tek.Tfont[c]->ascent + 1950 tw->tek.Tfont[c]->descent); 1951 1952 x = (int) ScaledX(tw, tekscr->cur_X); 1953 y = (int) ScaledY(tw, tekscr->cur_Y) - tw->tek.tobaseline[c]; 1954 1955 if (toggle == TOGGLE) { 1956 TScreen *screen = TScreenOf(xw); 1957 if (screen->select || screen->always_highlight) 1958 XFillRectangle(XtDisplay(tw), TWindow(tekscr), 1959 tekscr->TcursorGC, x, y, 1960 cellwidth, cellheight); 1961 else { /* fix to use different GC! */ 1962 XDrawRectangle(XtDisplay(tw), TWindow(tekscr), 1963 tekscr->TcursorGC, x, y, 1964 cellwidth - 1, cellheight - 1); 1965 } 1966 } else { 1967 /* Clear the entire rectangle, even though we may only 1968 * have drawn an outline. This fits with our refresh 1969 * scheme of redrawing the entire window on any expose 1970 * event and is easier than trying to figure out exactly 1971 * which part of the cursor needs to be erased. 1972 */ 1973 XClearArea(XtDisplay(tw), TWindow(tekscr), x, y, 1974 cellwidth, cellheight, False); 1975 } 1976} 1977 1978/* 1979 * The Tektronix manual describes the PAGE/RESET button. For PAGE: 1980 * Erases the display, resets to Alpha Mode and home position; 1981 * resets to Margin 1 and cancels Bypass condition. 1982 * For the RESET function: 1983 * Entered with SHIFT held down; creates a "home" function, 1984 * resetting the Terminal to initial status; does not erase. 1985 * 1986 * The reset done here is different, changing the modes (which changes 1987 * the line-type and font to default values) as well as erasing the screen 1988 * (like PAGE). 1989 */ 1990void 1991TekSimulatePageButton(TekWidget tw, Bool reset) 1992{ 1993 if (tw != 0) { 1994 TekScreen *tekscr = TekScreenOf(tw); 1995 1996 if (reset) { 1997 memset(&tekscr->cur, 0, sizeof tekscr->cur); 1998 } 1999 tekRefreshList = (TekLink *) 0; 2000 TekPage(tw); 2001 tekscr->cur_X = 0; 2002 tekscr->cur_Y = TEKHOME; 2003 } 2004} 2005 2006/* write copy of screen to a file */ 2007 2008void 2009TekCopy(TekWidget tw) 2010{ 2011 if (tw != 0) { 2012 TekScreen *tekscr = TekScreenOf(tw); 2013 TScreen *screen = TScreenOf(tw->vt); 2014 2015 TekLink *Tp; 2016 char buf[TIMESTAMP_LEN + 10]; 2017 int tekcopyfd; 2018 2019 timestamp_filename(buf, "COPY"); 2020 if (access(buf, F_OK) >= 0 2021 && access(buf, W_OK) < 0) { 2022 Bell(tw->vt, XkbBI_MinorError, 0); 2023 return; 2024 } 2025#ifndef VMS 2026 if (access(".", W_OK) < 0) { /* can't write in directory */ 2027 Bell(tw->vt, XkbBI_MinorError, 0); 2028 return; 2029 } 2030#endif 2031 2032 tekcopyfd = open_userfile(screen->uid, screen->gid, buf, False); 2033 if (tekcopyfd >= 0) { 2034 char initbuf[5]; 2035 2036 sprintf(initbuf, "%c%c%c%c", 2037 ANSI_ESC, (char) (tekscr->page.fontsize + '8'), 2038 ANSI_ESC, (char) (tekscr->page.linetype + '`')); 2039 IGNORE_RC(write(tekcopyfd, initbuf, (size_t) 4)); 2040 Tp = &Tek0; 2041 do { 2042 IGNORE_RC(write(tekcopyfd, Tp->data, (size_t) Tp->count)); 2043 Tp = Tp->next; 2044 } while (Tp); 2045 close(tekcopyfd); 2046 } 2047 } 2048} 2049 2050/*ARGSUSED*/ 2051void 2052HandleGINInput(Widget w, 2053 XEvent *event GCC_UNUSED, 2054 String *param_list, 2055 Cardinal *nparamsp) 2056{ 2057 TekWidget tw = getTekWidget(w); 2058 2059 if (tw != 0) { 2060 TekScreen *tekscr = TekScreenOf(tw); 2061 2062 if (tekscr->TekGIN && *nparamsp == 1) { 2063 int c = param_list[0][0]; 2064 switch (c) { 2065 case 'l': 2066 case 'm': 2067 case 'r': 2068 case 'L': 2069 case 'M': 2070 case 'R': 2071 break; 2072 default: 2073 Bell(tw->vt, XkbBI_MinorError, 0); /* let them know they goofed */ 2074 c = 'l'; /* provide a default */ 2075 } 2076 TekEnqMouse(tw, c | 0x80); 2077 TekGINoff(tw); 2078 } else { 2079 Bell(tw->vt, XkbBI_MinorError, 0); 2080 } 2081 } 2082} 2083 2084/* 2085 * Check if the current widget, or any parent, is the "tek4014" widget. 2086 */ 2087TekWidget 2088getTekWidget(Widget w) 2089{ 2090 TekWidget tw; 2091 2092 if (w == 0) { 2093 tw = (TekWidget) CURRENT_EMU(); 2094 if (!IsTekWidget(tw)) { 2095 tw = 0; 2096 } 2097 } else if (IsTekWidget(w)) { 2098 tw = (TekWidget) w; 2099 } else { 2100 tw = getTekWidget(XtParent(w)); 2101 } 2102 TRACE2(("getTekWidget %p -> %p\n", w, tw)); 2103 return tw; 2104} 2105