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