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