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