1: #include <X/mit-copyright.h> 2: 3: /* Copyright 1984, 1985 Massachusetts Institute of Technology */ 4: /* Tplot.c */ 5: 6: #ifndef lint 7: static char *rcsid_Tplot_c = "$Header: Tplot.c,v 10.8 86/02/01 16:05:23 tony Rel $"; 8: #endif lint 9: 10: #include <X/Xlib.h> 11: #include "ptyx.h" 12: #undef CTRL 13: #include <stdio.h> 14: #include <sys/file.h> 15: #include <sgtty.h> 16: #include <pwd.h> 17: #undef CTRL 18: 19: extern debug; 20: 21: static int bplot[5]; 22: static int nplot; 23: static int ipchr; 24: static int refresh; 25: static int LoYSet; 26: 27: #define MAX_PTS 150 28: #define MAX_VTX 300 29: static Vertex Tline[MAX_VTX]; 30: static Vertex *line_pt; 31: 32: static FILE *rfile, *wfile; 33: 34: static TekLink *TekBuf = NULL; 35: TekLink *tb_end_link = NULL; /* world accessible for TekBufPut */ 36: int tb_end = TEK_LINK_BLOCK_SIZE; /* world accessible for TekBufPut */ 37: static TekLink *tb_pt_link = NULL; 38: static int tb_pt = TEK_LINK_BLOCK_SIZE; 39: 40: #include "../cursors/tcross.cursor" 41: #include "../cursors/tcross_mask.cursor" 42: 43: TekErase (term) 44: 45: /* Reset buffer pointer for display list to start of buffer */ 46: 47: Terminal *term; 48: { 49: register Screen *screen = &term->screen; 50: register struct _TekLink *pnt; 51: register struct _TekLink *next; 52: 53: pnt = (struct _TekLink *) TekBuf; 54: 55: /* free stored list */ 56: while (pnt) 57: { 58: next = pnt->next; 59: free (pnt); 60: pnt = next; 61: } 62: 63: /* reset pointers */ 64: TekBuf = tb_end_link = tb_pt_link = NULL; 65: tb_end = tb_pt = TEK_LINK_BLOCK_SIZE; 66: 67: refresh = 0; 68: screen->cur_x = 0; 69: screen->cur_y = 0; 70: screen->TekGMode = 0; 71: screen->TekAMode = 0; 72: LoYSet = 0; 73: 74: if (debug) wfile = fopen ("testbufw","w"); 75: 76: return; 77: } 78: 79: 80: TekRefresh (term) 81: 82: /* Redisplay graphics screen, including positioned alpha strings */ 83: 84: register Terminal *term; 85: { 86: register Screen *screen = &term->screen; 87: Window window = screen->window; 88: Font fnt = screen->fnt_norm; 89: int chr, nstr; 90: register int ch; 91: unsigned char str[257]; 92: int modeG = screen->TekGMode, modeA = screen->TekAMode, 93: modeI = screen->TekIMode, modeP = screen->TekPMode; 94: 95: TekBufResetPt (); 96: 97: if (TekBufEmpty ()) return; 98: 99: if (debug) rfile = fopen ("testbufr","w"); 100: 101: refresh = 1; 102: TekAlph (term,0); 103: screen->cur_x = screen->cur_y = 0; 104: 105: while (TekBufGet (&chr) != -1) 106: { 107: ch = chr; /* lets get the char into a register */ 108: if (screen->TekGMode) 109: { 110: if (ch > 31) 111: { 112: if (screen->TekIMode) TekPoint (term,ch); 113: else TekPlot (term,ch); 114: } 115: else if (ch > 27 && ch < 31) TekInit (term,ch); 116: else if (ch == 31 || ch < 28) TekAlph (term,0); 117: continue; 118: } 119: 120: if (ch > 27 && ch < 31) 121: { 122: TekInit (term, ch); 123: continue; 124: } 125: 126: if (ch > (unsigned) 128) 127: { 128: nstr = ch - (unsigned) 128; 129: 130: if (debug) 131: { 132: fprintf (rfile,"alpha mode %d chars\n",nstr); 133: fflush (rfile); 134: } 135: 136: if (nstr > 256) exit (77); 137: TekBufGetString (str, nstr); 138: *(str + nstr) = NULL; 139: 140: XTextMask ( window, 141: TCursorX(screen), TCursorY(screen), 142: str, nstr, fnt, screen->foreground); 143: 144: screen->cur_X += (nstr * screen->f_width); 145: screen->cur_x += 146: (nstr * screen->f_width / screen->TekScale); 147: } 148: } 149: 150: if (nplot > 0) TekFlush (term); 151: refresh = 0; 152: 153: screen->TekGMode = modeG; 154: screen->TekAMode = modeA; 155: screen->TekIMode = modeI; 156: screen->TekPMode = modeP; 157: } 158: 159: 160: TekString (term, str, nchr) 161: 162: /* Display positioned alphanumeric string, saving it in display list */ 163: 164: register Terminal *term; 165: unsigned char *str; 166: int nchr; 167: { 168: register Screen *screen = &term->screen; 169: Window window = screen->window; 170: Font fnt = screen->fnt_norm; 171: 172: TekBufPut (128 + nchr); 173: if (debug) 174: { 175: fprintf (wfile,"alpha mode %d character string\n",nchr); 176: fflush (wfile); 177: } 178: 179: TekBufPutString (str, nchr); 180: 181: XTextMask (window, 182: TCursorX(screen), TCursorY(screen), 183: str, nchr, fnt, screen->foreground); 184: 185: screen->cur_X = screen->cur_X + (nchr * screen->f_width); 186: screen->cur_x = screen->cur_x + 187: (nchr * screen->f_width / screen->TekScale); 188: } 189: 190: TekBufResetPt () 191: /* set pt to point to beginning of buffer */ 192: { 193: tb_pt_link = TekBuf; 194: tb_pt = 0; 195: } 196: 197: TekBufEmpty () 198: /* return nonzero iff TekBuf is empty */ 199: { 200: return (((tb_end & ~TEK_LINK_BLOCK_SIZE) == 0) 201: && (tb_end_link == TekBuf)); 202: } 203: 204: 205: /* Extend display buffer */ 206: TekBufExtend () 207: { 208: 209: /* if TekBuf is NULL then must initialize */ 210: if (!TekBuf) 211: { 212: TekBuf = (TekLink *) malloc (sizeof (TekLink)); 213: TekBuf->next = NULL; 214: tb_end_link = TekBuf; 215: tb_end = 0; 216: } 217: else 218: { 219: tb_end_link->next = 220: (struct _TekLink *) malloc (sizeof (TekLink)); 221: tb_end_link = (TekLink *) tb_end_link->next; 222: tb_end_link->next = NULL; 223: tb_end = 0; 224: } 225: } 226: 227: /* 228: effect: puts len bytes at str into display buffer 229: */ 230: TekBufPutString (str, len) 231: register unsigned char *str; 232: register int len; 233: { 234: register int amount; 235: 236: while (len) 237: { 238: if (tb_end & TEK_LINK_BLOCK_SIZE) TekBufExtend (); 239: 240: amount = TEK_LINK_BLOCK_SIZE - tb_end; 241: if (amount > len) amount = len; 242: 243: bcopy (str, tb_end_link->data + tb_end, amount); 244: str += amount; 245: len -= amount; 246: tb_end += amount; 247: } 248: } 249: 250: 251: /* Read character from display list */ 252: 253: int TekBufGet (chr) 254: register unsigned int *chr; 255: { 256: if (tb_pt & TEK_LINK_BLOCK_SIZE) 257: 258: /* if tb_pt_link is NULL then check for a TekBuf */ 259: if (!tb_pt_link) 260: { 261: if (!TekBuf) return (-1); 262: tb_pt_link = TekBuf; 263: tb_pt = 0; 264: } 265: else 266: if (tb_pt_link->next == NULL) return (-1); 267: else 268: { 269: tb_pt_link = (TekLink *) tb_pt_link->next; 270: tb_pt = 0; 271: } 272: 273: if ((tb_pt_link == tb_end_link) && (tb_pt >= tb_end)) return (-1); 274: 275: *chr = tb_pt_link->data [tb_pt++]; 276: return (0); 277: } 278: 279: /* store next len characters of TekBuf in str, advancing tb_pt */ 280: TekBufGetString (str, len) 281: register char *str; 282: register int len; 283: { 284: register int n; 285: 286: while (len) 287: { 288: n = TEK_LINK_BLOCK_SIZE - tb_pt; 289: n = (n < len) ? n : len; 290: 291: bcopy (tb_pt_link->data + tb_pt, str, n); 292: tb_pt += n; 293: len -= n; 294: str += n; 295: 296: if (tb_pt == TEK_LINK_BLOCK_SIZE) 297: { 298: if (tb_pt_link->next == NULL) return; 299: tb_pt_link = (TekLink *) tb_pt_link->next; 300: tb_pt = 0; 301: } 302: } 303: } 304: 305: /* Switch to graphics mode and initialize byte and point counters */ 306: 307: TekInit (term,chr) 308: Terminal *term; 309: register int chr; 310: { 311: register Screen *screen = &term->screen; 312: 313: if (debug) 314: if (!refresh) 315: { 316: fprintf (wfile,"switching to graphics mode %d\n",chr); 317: fflush (wfile); 318: } 319: else 320: { 321: fprintf (rfile,"switching to graphics mode %d\n",chr); 322: fflush (rfile); 323: } 324: 325: if (!screen->TekGMode && nplot > 0) TekFlush (term); 326: 327: screen->pen = 0; 328: ipchr = 0; 329: screen->TekPMode = 0; 330: screen->TekIMode = 0; 331: if (chr == 28) screen->TekPMode = 1; 332: if (chr == 30) screen->TekIMode = 1; 333: 334: if (!refresh) TekBufPut (chr); 335: if (screen->TekGMode) return; 336: 337: nplot = 0; 338: screen->TekGMode = 1; 339: screen->TekAMode = 1; 340: /* 341: * screen->cur_row = 0; 342: * screen->cur_col = 0; 343: */ 344: line_pt = Tline; 345: } 346: 347: TekAlph (term,chr) 348: 349: /* Switch back to alphanumeric mode from graphics mode */ 350: 351: Terminal *term; 352: int chr; 353: { 354: register Screen *screen = &term->screen; 355: 356: if (!screen->TekGMode) return; 357: 358: if (debug) 359: if (!refresh) 360: { 361: fprintf (wfile,"switching to alpha mode %d\n",chr); 362: fflush (wfile); 363: } 364: else 365: { 366: fprintf (rfile,"switching to alpha mode %d\n",chr); 367: fflush (rfile); 368: } 369: 370: if (!refresh) TekBufPut (chr); 371: if (nplot > 0) TekFlush (term); 372: 373: screen->TekGMode = 0; 374: screen->TekPMode = 0; 375: screen->TekIMode = 0; 376: if (chr>0 && chr != 31) TekReset(term); 377: return; 378: } 379: 380: 381: TekReset (term) 382: 383: /* Switch back to vt100 alphanumeric mode from Tektronix alphanumeric mode 384: * This allows alphanumeric strings to be positioned by graphics commands, 385: * but reenables scrolling after CR or LF. */ 386: 387: Terminal *term; 388: { 389: register Screen *screen = &term->screen; 390: int fh = screen->f_height; 391: int fw = screen->f_width; 392: 393: screen->TekAMode = 0; 394: 395: if (debug) 396: if (!refresh) 397: { 398: fprintf (wfile,"resetting to alpha mode\n"); 399: fflush (wfile); 400: } 401: else 402: { 403: fprintf (rfile,"resetting to alpha mode\n"); 404: fflush (rfile); 405: } 406: 407: if (screen->cur_Y > 0) 408: { 409: screen->cur_row = (screen->cur_Y - (fh >> 1)) / fh; 410: if (screen->cur_row > screen->max_row) 411: screen->cur_row = screen->max_row; 412: screen->cur_Y = 0; 413: } 414: if (screen->cur_X > 0) 415: { 416: screen->cur_col = (screen->cur_X + (fw >> 1)) / fw; 417: if (screen->cur_col > screen->max_col) 418: screen->cur_col = screen->max_col; 419: screen->cur_X = 0; 420: } 421: screen->cur_x = 0; 422: screen->cur_y = 0; 423: 424: return; 425: } 426: 427: 428: TekCursor (term) 429: 430: /* Reads position of mouse cursor when a character is typed and returns 431: * it in Tektronix-format coordinates */ 432: 433: Terminal *term; 434: { 435: register Screen *screen = &term->screen; 436: Keyboard *keyboard = &term->keyboard; 437: register Window window = screen->window; 438: int MouseX, MouseY; 439: XEvent reply; 440: XEvent *rep = &reply; 441: Window subw; 442: int pty = screen->respond; 443: int keycode, event, shifts; 444: short c; 445: char cplot [5]; 446: extern int wflush (); 447: int x, y; 448: Cursor cursor; 449: char *string = " "; 450: int nbytes; 451: 452: TekAlph (term, 0); 453: TekReset (term); 454: 455: /* Set cross-hair cursor raster array */ 456: cursor = XCreateCursor(tcross_width, tcross_height, 457: tcross_bits, tcross_bits, 7, 7, 458: screen->foreground, screen->background, GXxor); 459: 460: /* Display cross-hair cursor */ 461: XDefineCursor(window, cursor); 462: 463: /* reselect input. Must be careful not to leave stray button 464: * events upon return since handle buttons would be invoked */ 465: 466: XSelectInput (window, ButtonReleased | KeyPressed); 467: 468: /* Wait for keyboard entry */ 469: XWindowEvent (window, KeyPressed | ButtonReleased, &reply); 470: 471: keycode = ((XKeyOrButtonEvent *)rep)->detail; 472: event = reply.type; 473: 474: /* Get current mouse position and translate to screen coordinates */ 475: XUpdateMouse (window, &MouseX, &MouseY, &subw); 476: 477: x = ((MouseX - screen->border) << 1); 478: y = 782 - ((MouseY - screen->border) << 1); 479: screen->cur_X = MouseX; 480: screen->cur_Y = MouseY; 481: 482: /* Translate x and y to Tektronix code */ 483: cplot[1] = 32 + (x >> 5); 484: cplot[2] = 32 + (x & 31); 485: cplot[3] = 32 + (y >> 5); 486: cplot[4] = 32 + (y & 31); 487: 488: /* Translate keyboard entry and return one byte from terminal */ 489: if (event == KeyPressed) 490: { 491: string = XLookupMapping ((XKeyPressedEvent *)& reply, &nbytes); 492: c = *string; 493: } 494: else c = keycode + 48; 495: 496: cplot[0] = c; 497: 498: /* Return encode screen coordinates */ 499: write (pty, cplot, 5 * sizeof (char)); 500: 501: /* Reset cursor and return */ 502: 503: XFreeCursor(cursor); 504: XDefineCursor(window, 505: (term->flags & INVERSE) ? screen->rcurs : screen->curs); 506: 507: 508: TekInit (term,0); 509: 510: XSelectInput (window, KeyPressed | ExposeWindow | ExposeRegion | 511: ExposeCopy | ButtonPressed | ButtonReleased); 512: } 513: 514: 515: TekPlot (term,chr) 516: 517: /* Translates Tektronix byte-encoded screen coordinates to integer screen 518: * coordinates each time the final byte of a coordinate set is encountered. */ 519: 520: Terminal *term; 521: register int chr; 522: { 523: register Screen *screen = &term->screen; 524: register int *bp = bplot; 525: register int x, y; 526: 527: ipchr++; 528: if (ipchr > 5) 529: { 530: TekAlph (term,chr); 531: return; 532: } 533: 534: /* decode Tektronix byte position codes */ 535: 536: if (chr < 64) 537: { 538: if (LoYSet) /* 4st byte */ 539: { 540: bp[3] = chr & ~32; 541: } 542: else /* 1st byte */ 543: { 544: bp[0] = chr & ~32; 545: bp[1] = 0; 546: } 547: } 548: else if (chr > 95) 549: { 550: if (LoYSet) /* 2nd byte */ 551: { /* 3rd if 2nd present */ 552: bp[1] = bp[2]; 553: bp[2] = chr & ~96; 554: } 555: else /* 3rd byte */ 556: { 557: bp[2] = chr & ~96; 558: bp[1] = 0; 559: LoYSet = 1; 560: } 561: } 562: else /* 5th byte */ 563: { 564: bp[4] = chr & ~64; 565: ipchr = 0; 566: LoYSet = 0; 567: 568: /* compute screen x and y coordinates ignoring extended 569: * precision byte */ 570: 571: y = (bp[0] << 7) + (bp[2] << 2); 572: x = (bp[3] << 7) + (bp[4] << 2); 573: 574: /* add in 4014 extended precision byte */ 575: if (bp[1] > 0) 576: { 577: x += (bp [1] & 3); 578: y += ((bp [1] & 12) >> 2); 579: } 580: 581: /* Check to make sure screen limits are not exceeded */ 582: if (y > 3127) y = 3127; 583: 584: /* transfer this point to vertex array */ 585: if (screen->TekPMode) 586: { 587: TekDraw (0, x, y, term); 588: TekDraw (1, x, y, term); 589: } 590: else 591: { 592: TekDraw (screen->pen, x, y, term); 593: screen->pen = 1; 594: } 595: } 596: } 597: 598: 599: TekPoint (term,chr) 600: 601: /* Translates Tektronix byte-encoded incremental plot commands to screen 602: * coordinates and writes them to the vector buffer */ 603: 604: register Terminal *term; 605: register int chr; 606: { 607: Screen *screen = &term->screen; 608: register int pen,x,y; 609: 610: x = screen->cur_x; 611: y = screen->cur_y; 612: pen = screen->pen; 613: 614: if (nplot == 0) TekDraw (0,x,y,term); 615: 616: switch (chr) 617: { 618: case ' ': screen->pen = 0; 619: break; 620: 621: case 'P': screen->pen = 1; 622: break; 623: 624: case 'D': TekDraw (pen, x, ++y, term); 625: break; 626: 627: case 'E': TekDraw (pen, ++x, ++y, term); 628: break; 629: 630: case 'A': TekDraw (pen, ++x, y, term); 631: break; 632: 633: case 'I': TekDraw (pen, ++x, --y, term); 634: break; 635: 636: case 'H': TekDraw (pen, x, --y, term); 637: break; 638: 639: case 'J': TekDraw (pen, --x, --y, term); 640: break; 641: 642: case 'B': TekDraw (pen, --x, y, term); 643: break; 644: 645: case 'F': TekDraw (pen, --x, ++y, term); 646: break; 647: 648: } 649: } 650: 651: 652: TekDraw (pen, x, y, term) 653: 654: /* Translates Tektronix screen coordinates to vs100 screen 655: * coordinates, drawing them to the screen when a buffer is filled */ 656: 657: int x,y,pen; 658: Terminal *term; 659: { 660: register Screen *screen = &term->screen; 661: register Vertex *lp = line_pt; 662: 663: screen->cur_x = x; 664: screen->cur_y = y; 665: 666: /* convert to vs100 window coordinates */ 667: screen->cur_X = (x + 1) * screen->TekScale + screen->border; 668: screen->cur_Y = (3128 - y) * screen->TekScale + screen->border; 669: 670: /* write to plot buffer */ 671: lp->x = screen->cur_X; 672: lp->y = screen->cur_Y; 673: 674: if (pen) lp->flags = VertexDrawLastPoint; 675: else lp->flags = VertexDontDraw; 676: 677: lp = ++line_pt; 678: nplot++; 679: 680: if (debug) 681: if (refresh) fprintf (rfile,"%d: %d %d,%d -> %d,%d\n", 682: nplot,pen,x,y,screen->cur_X,screen->cur_Y); 683: else fprintf (wfile,"%d: %d %d,%d -> %d,%d\n", 684: nplot,pen,x,y,screen->cur_X,screen->cur_Y); 685: if (debug) 686: if (refresh) fflush (rfile); 687: else fflush (wfile); 688: 689: /* draw line if buffer limit has been reached */ 690: if (nplot >= MAX_PTS) 691: { 692: TekFlush (term); 693: lp = line_pt; 694: lp->x = screen->cur_X; 695: lp->y = screen->cur_Y; 696: lp->flags = VertexDontDraw; 697: line_pt++; 698: nplot++; 699: } 700: } 701: 702: 703: TekFlush (term) 704: 705: register Terminal *term; 706: { 707: Window window = term->screen.window; 708: 709: XDraw (window, Tline, nplot, 1, 1, term->screen.foreground, GXcopy, 710: AllPlanes); 711: nplot = 0; 712: 713: line_pt = Tline; 714: } 715: 716: TekInq (term) 717: /* Reports position of cursor in Tektronix-format coordinates */ 718: Terminal *term; 719: { 720: register Screen *screen = &term->screen; 721: int pty = screen->respond; 722: char cplot [5]; 723: int x, y; 724: x = ((screen->cur_X - screen->border) << 1); 725: y = 782 - ((screen->cur_Y - screen->border) << 1); 726: /* Translate x and y to Tektronix code */ 727: cplot[1] = 32 + (x >> 5); 728: cplot[2] = 32 + (x & 31); 729: cplot[3] = 32 + (y >> 5); 730: cplot[4] = 32 + (y & 31); 731: cplot[0] = '%'; /* standard hardware config */ 732: /* Return encoded screen coordinates */ 733: write (pty, cplot, 5 * sizeof (char)); 734: } 735: 736: #ifdef ENABLE_PRINT 737: 738: #include <signal.h> 739: 740: TekPrint () 741: 742: /* Dump graphics screen, including positioned alpha strings */ 743: 744: { 745: int chr, pid, uid, i; 746: char c; 747: FILE *tekfile; 748: char *uname, tekfile_name[40]; 749: struct passwd *upasswd; 750: int temp_tb_pt = tb_pt; 751: TekLink *temp_tb_pt_link = tb_pt_link; 752: 753: TekBufResetPt (); 754: if (TekBufEmpty ()) return; 755: 756: pid = getpid (); 757: uid = getuid (); 758: upasswd = getpwuid (uid); 759: sprintf (tekfile_name,"/tmp/vst%d\.%s\0",pid,upasswd->pw_name); 760: 761: tekfile = fopen (tekfile_name,"w"); 762: 763: while (TekBufGet (&chr) != -1) 764: { 765: c = chr; 766: if (chr < 128) putc (c,tekfile); 767: } 768: 769: tb_pt = temp_tb_pt; 770: tb_pt_link = temp_tb_pt_link; 771: 772: fclose (tekfile); 773: 774: if (debug) printf ("attempting fork\n"); 775: 776: switch (fork ()) 777: { 778: case -1: Error (); 779: break; 780: 781: case 0: for (i= 0; i < _NFILE; i++) close (i); 782: signal(SIGCHLD, SIG_DFL); 783: signal(SIGTERM, SIG_DFL); 784: signal(SIGHUP, SIG_IGN); 785: execlp("imtek", "imtek", "-x",tekfile_name, 0); 786: exit (1); 787: break; 788: 789: default: 790: break; 791: } 792: } 793: 794: #endif