1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: /* util.c */ 6: 7: #ifndef lint 8: static char *rcsid_util_c = "$Header: util.c,v 10.11 86/04/28 15:05:29 jg Exp $"; 9: #endif lint 10: 11: #include <stdio.h> 12: #include <X/Xlib.h> 13: #include <errno.h> 14: #include <signal.h> 15: 16: #include "ptyx.h" 17: 18: extern errno; 19: extern debug; 20: #ifdef JUMPSCROLL 21: /* 22: * These routines are used for the jump scroll feature 23: */ 24: FlushScroll(screen) 25: register Screen *screen; 26: { 27: register int height = screen->bot_marg - screen->top_marg + 1; 28: register int samount = screen->scroll_amt; 29: register int ramount = screen->refresh_amt; 30: register int scrolled = samount * screen->f_height; 31: register int refreshed = ramount * screen->f_height; 32: register int top = screen->top_marg * screen->f_height + screen->border; 33: int rtop; 34: 35: if(samount > 0) { 36: rtop = screen->bot_marg - ramount + 1; 37: } else { 38: rtop = screen->top_marg; 39: top -= scrolled; 40: ramount = -ramount; 41: refreshed = -refreshed; 42: } 43: 44: if (ramount != height) { 45: 46: if (screen->multiscroll && samount == 1 && 47: screen->top_marg == 0 && screen->bot_marg == screen->max_row) { 48: if (screen->incopy < 0 && screen->scrolls == 0) 49: CopyWait (screen); 50: screen->scrolls++; 51: } else { 52: if (screen->incopy) 53: CopyWait (screen); 54: screen->incopy = -1; 55: } 56: 57: XMoveArea (screen->window, 58: screen->border, top + scrolled, screen->border, top, 59: screen->width, height * screen->f_height - refreshed); 60: } 61: screen->scroll_amt = 0; 62: screen->refresh_amt = 0; 63: XTileSet (screen->window, screen->border, 64: rtop * screen->f_height + screen->border, 65: screen->width, refreshed, screen->bgndtile); 66: ScrnRefresh(screen, rtop, 0, ramount, screen->max_col + 1); 67: } 68: 69: AddToRefresh(screen) 70: register Screen *screen; 71: { 72: register int amount = screen->refresh_amt; 73: register int row = screen->cur_row; 74: 75: if(amount == 0) 76: return(0); 77: if(amount > 0) { 78: register int bottom; 79: 80: if(row == (bottom = screen->bot_marg) - amount) { 81: screen->refresh_amt++; 82: return(1); 83: } 84: return(row >= bottom - amount + 1 && row <= bottom); 85: } else { 86: register int top; 87: 88: amount = -amount; 89: if(row == (top = screen->top_marg) + amount) { 90: screen->refresh_amt--; 91: return(1); 92: } 93: return(row <= top + amount - 1 && row >= top); 94: } 95: } 96: #endif JUMPSCROLL 97: 98: /* 99: * scrolls the screen by amount lines, erases bottom, doesn't alter 100: * cursor position (i.e. cursor moves down amount relative to text). 101: * All done within the scrolling region, of course. 102: * requires: amount > 0 103: */ 104: Scroll (screen, amount) 105: register Screen *screen; 106: register int amount; 107: { 108: register int height = screen->bot_marg - screen->top_marg + 1; 109: register int covered; 110: register int border = screen->border; 111: register int top = screen->top_marg * screen->f_height + border; 112: 113: if (amount > height) 114: amount = height; 115: #ifdef JUMPSCROLL 116: if(screen->jumpscroll) { 117: if(screen->scroll_amt > 0) { 118: if(screen->refresh_amt + amount > height) 119: FlushScroll(screen); 120: screen->scroll_amt += amount; 121: screen->refresh_amt += amount; 122: } else { 123: if(screen->scroll_amt < 0) 124: FlushScroll(screen); 125: screen->scroll_amt = amount; 126: screen->refresh_amt = amount; 127: } 128: } else { 129: #endif JUMPSCROLL 130: 131: if (amount == height) { 132: ClearScreen(screen); 133: return; 134: } 135: 136: covered = amount * screen->f_height; 137: 138: if (screen->multiscroll 139: && amount==1 140: && screen->top_marg==0 141: && screen->bot_marg==screen->max_row) { 142: if (screen->incopy<0 && screen->scrolls==0) 143: CopyWait(screen); 144: screen->scrolls++; 145: } else { 146: if (screen->incopy) 147: CopyWait(screen); 148: screen->incopy = -1; 149: } 150: 151: XMoveArea(screen->window, border, top + covered, border, top, 152: screen->width, height * screen->f_height - covered); 153: XTileSet(screen->window, border, 154: (screen->bot_marg - amount + 1) * screen->f_height + border, 155: screen->width, covered, screen->bgndtile); 156: #ifdef JUMPSCROLL 157: } 158: #endif JUMPSCROLL 159: 160: ScrnDeleteLine(screen->buf, screen->bot_marg, screen->top_marg, 161: amount, screen->max_col + 1); 162: } 163: 164: 165: /* 166: * Reverse scrolls the screen by amount lines, erases top, doesn't alter 167: * cursor position (i.e. cursor moves up amount relative to text). 168: * All done within the scrolling region, of course. 169: * Requires: amount > 0 170: */ 171: RevScroll(screen, amount) 172: register Screen *screen; 173: register int amount; 174: { 175: register int height = screen->bot_marg - screen->top_marg + 1; 176: register int border = screen->border; 177: register int top = screen->top_marg * screen->f_height + border; 178: register int covered; 179: 180: amount = (amount < height) ? amount : height; 181: #ifdef JUMPSCROLL 182: if(screen->jumpscroll) { 183: if(screen->scroll_amt < 0) { 184: if(-screen->refresh_amt + amount > height) 185: FlushScroll(screen); 186: screen->scroll_amt -= amount; 187: screen->refresh_amt -= amount; 188: } else { 189: if(screen->scroll_amt > 0) 190: FlushScroll(screen); 191: screen->scroll_amt = -amount; 192: screen->refresh_amt = -amount; 193: } 194: } else { 195: #endif JUMPSCROLL 196: covered = amount * screen->f_height; 197: 198: if (screen->incopy) 199: CopyWait (screen); 200: screen->incopy = -1; 201: 202: XMoveArea (screen->window, 203: border, top, 204: border, top + covered, 205: screen->width, height * screen->f_height - covered); 206: XTileSet (screen->window, 207: border, top, 208: screen->width, covered, 209: screen->bgndtile); 210: 211: #ifdef JUMPSCROLL 212: } 213: #endif JUMPSCROLL 214: ScrnInsertLine (screen->buf, screen->bot_marg, screen->top_marg, 215: amount, screen->max_col + 1); 216: } 217: 218: /* 219: * If cursor not in scrolling region, returns. Else, 220: * inserts n blank lines at the cursor's position. Lines above the 221: * bottom margin are lost. 222: */ 223: InsertLine (screen, n) 224: register Screen *screen; 225: register int n; 226: { 227: register int height; 228: register int bottom = screen->bot_marg; 229: 230: if (screen->cur_row < screen->top_marg || 231: screen->cur_row > screen->bot_marg) return; 232: 233: if (screen->cur_row + n - 1 > bottom) n = bottom - screen->cur_row + 1; 234: #ifdef JUMPSCROLL 235: if(screen->jumpscroll) { 236: if(screen->scroll_amt <= 0&&screen->cur_row <= -screen->refresh_amt) { 237: if(-screen->refresh_amt + n > height) 238: FlushScroll(screen); 239: screen->scroll_amt -= n; 240: screen->refresh_amt -= n; 241: } else if(screen->scroll_amt) 242: FlushScroll(screen); 243: } 244: if(!screen->scroll_amt) { 245: #endif JUMPSCROLL 246: 247: 248: height = n * screen->f_height; 249: 250: screen->do_wrap = 0; 251: 252: if (screen->incopy) 253: CopyWait (screen); 254: screen->incopy = -1; 255: 256: /* 257: * move stuff down. 258: * clear hole. 259: */ 260: XMoveArea(screen->window, 261: screen->border, CursorY (screen), 262: screen->border, CursorY (screen) + height, 263: screen->width, 264: (bottom + 1 - screen->cur_row - n) * screen->f_height); 265: XTileSet(screen->window, 266: screen->border, CursorY (screen), 267: screen->width, height, screen->bgndtile); 268: 269: #ifdef JUMPSCROLL 270: } 271: #endif JUMPSCROLL 272: /* adjust screen->buf */ 273: ScrnInsertLine(screen->buf, bottom, screen->cur_row, n, 274: screen->max_col + 1); 275: } 276: 277: /* 278: * If cursor not in scrolling region, returns. Else, deletes n lines 279: * at the cursor's position, lines added at bottom margin are blank. 280: */ 281: DeleteLine(screen, n) 282: register Screen *screen; 283: register int n; 284: { 285: register int height; 286: register int bottom = screen->bot_marg; 287: 288: if (screen->cur_row < screen->top_marg 289: || screen->cur_row > screen->bot_marg) 290: return; 291: 292: if (screen->cur_row + n - 1 > bottom) 293: n = bottom - screen->cur_row + 1; 294: #ifdef JUMPSCROLL 295: if(screen->jumpscroll) { 296: if(screen->scroll_amt >= 0 && screen->cur_row == screen->top_marg) { 297: if(screen->refresh_amt + n > height) 298: FlushScroll(screen); 299: screen->scroll_amt += n; 300: screen->refresh_amt += n; 301: } else if(screen->scroll_amt) 302: FlushScroll(screen); 303: } 304: if(!screen->scroll_amt) { 305: #endif JUMPSCROLL 306: 307: height = n * screen->f_height; 308: screen->do_wrap = 0; 309: 310: if (screen->incopy) 311: CopyWait(screen); 312: screen->incopy = -1; 313: 314: /* 315: * move stuff up. 316: * clear bottom. 317: */ 318: XMoveArea(screen->window, 319: screen->border, CursorY (screen) + height, 320: screen->border, CursorY (screen), 321: screen->width, 322: (bottom + 1 - screen->cur_row - n) * screen->f_height); 323: XTileSet(screen->window, 324: screen->border, 325: (bottom + 1 - n) * screen->f_height + screen->border, 326: screen->width, height, screen->bgndtile); 327: 328: #ifdef JUMPSCROLL 329: } 330: #endif JUMPSCROLL 331: /* adjust screen->buf */ 332: ScrnDeleteLine(screen->buf, bottom, screen->cur_row, n, 333: screen->max_col + 1); 334: } 335: 336: /* 337: * Insert n blanks at the cursor's position, no wraparound. 338: */ 339: InsertChar (screen, n) 340: register Screen *screen; 341: register int n; 342: { 343: register int width = n * screen->f_width; 344: 345: #ifdef JUMPSCROLL 346: if(!AddToRefresh(screen)) { 347: if(screen->scroll_amt) 348: FlushScroll(screen); 349: #endif JUMPSCROLL 350: 351: screen->do_wrap = 0; 352: 353: if (screen->incopy) 354: CopyWait (screen); 355: screen->incopy = -1; 356: 357: XMoveArea(screen->window, 358: CursorX (screen), CursorY (screen), 359: CursorX (screen) + width, CursorY (screen), 360: screen->width - (screen->cur_col + n) * screen->f_width, 361: screen->f_height); 362: XTileSet(screen->window, 363: CursorX (screen), CursorY (screen), 364: width, screen->f_height, screen->bgndtile); 365: 366: #ifdef JUMPSCROLL 367: } 368: #endif JUMPSCROLL 369: /* adjust screen->buf */ 370: ScrnInsertChar(screen->buf, screen->cur_row, screen->cur_col, n, 371: screen->max_col + 1); 372: } 373: 374: /* 375: * Deletes n chars at the cursor's position, no wraparound. 376: */ 377: DeleteChar (screen, n) 378: register Screen *screen; 379: register int n; 380: { 381: register int width; 382: 383: if (screen->cur_col + n > screen->max_col + 1) 384: n = screen->max_col + 1 - screen->cur_col; 385: 386: #ifdef JUMPSCROLL 387: if(!AddToRefresh(screen)) { 388: if(screen->scroll_amt) 389: FlushScroll(screen); 390: #endif JUMPSCROLL 391: 392: width = n * screen->f_width; 393: 394: screen->do_wrap = 0; 395: 396: if (screen->incopy) 397: CopyWait (screen); 398: screen->incopy = -1; 399: 400: XMoveArea(screen->window, 401: CursorX (screen) + width, CursorY (screen), 402: CursorX (screen), CursorY (screen), 403: screen->width - (screen->cur_col + n) * screen->f_width, 404: screen->f_height); 405: XTileSet (screen->window, 406: screen->border + screen->width - width, CursorY (screen), 407: width, screen->f_height, screen->bgndtile); 408: 409: #ifdef JUMPSCROLL 410: } 411: #endif JUMPSCROLL 412: /* adjust screen->buf */ 413: ScrnDeleteChar (screen->buf, screen->cur_row, screen->cur_col, n, 414: screen->max_col + 1); 415: 416: } 417: 418: /* 419: * Clear from cursor position to beginning of display, inclusive. 420: */ 421: ClearAbove (screen) 422: register Screen *screen; 423: { 424: #ifdef JUMPSCROLL 425: if(screen->scroll_amt) 426: FlushScroll(screen); 427: #endif JUMPSCROLL 428: ClearLeft(screen); 429: 430: XTileSet(screen->window, screen->border, 0, 431: screen->width, CursorY (screen), screen->bgndtile); 432: ClearBufRows(screen, 0, screen->cur_row - 1); 433: } 434: 435: /* 436: * Clear from cursor position to end of display, inclusive. 437: */ 438: ClearBelow (screen) 439: register Screen *screen; 440: { 441: register int sy = CursorY (screen) + screen->f_height; 442: 443: #ifdef JUMPSCROLL 444: if(screen->scroll_amt) 445: FlushScroll(screen); 446: #endif JUMPSCROLL 447: ClearRight(screen); 448: XTileSet(screen->window, screen->border, sy, 449: screen->width, screen->height - sy + screen->border, 450: screen->bgndtile); 451: ClearBufRows(screen, screen->cur_row + 1, screen->max_row); 452: } 453: 454: /* 455: * Clear last part of cursor's line, inclusive. 456: */ 457: ClearRight (screen) 458: register Screen *screen; 459: { 460: screen->do_wrap = 0; 461: 462: #ifdef JUMPSCROLL 463: if(!AddToRefresh(screen)) { 464: if(screen->scroll_amt) 465: FlushScroll(screen); 466: #endif JUMPSCROLL 467: XTileSet(screen->window, 468: CursorX (screen), CursorY (screen), 469: screen->width-screen->cur_col * screen->f_width,screen->f_height, 470: screen->bgndtile); 471: #ifdef JUMPSCROLL 472: } 473: #endif JUMPSCROLL 474: bzero((char *)(screen->buf [screen->cur_row] + screen->cur_col), 475: sizeof (short) * (screen->max_col - screen->cur_col + 1)); 476: } 477: 478: /* 479: * Clear first part of cursor's line, inclusive. 480: */ 481: ClearLeft (screen) 482: register Screen *screen; 483: { 484: screen->do_wrap = 0; 485: 486: #ifdef JUMPSCROLL 487: if(!AddToRefresh(screen)) { 488: if(screen->scroll_amt) 489: FlushScroll(screen); 490: #endif JUMPSCROLL 491: 492: XTileSet (screen->window, 493: screen->border, CursorY (screen), 494: (screen->cur_col + 1) * screen->f_width, 495: screen->f_height, screen->bgndtile); 496: #ifdef JUMPSCROLL 497: } 498: #endif JUMPSCROLL 499: bzero ((char *)screen->buf [screen->cur_row], 500: sizeof (short) * (screen->cur_col + 1)); 501: } 502: 503: /* 504: * Erase the cursor's line. 505: */ 506: ClearLine(screen) 507: register Screen *screen; 508: { 509: screen->do_wrap = 0; 510: 511: #ifdef JUMPSCROLL 512: if(!AddToRefresh(screen)) { 513: if(screen->scroll_amt) 514: FlushScroll(screen); 515: #endif JUMPSCROLL 516: XTileSet (screen->window, 517: screen->border, CursorY (screen), 518: screen->width, screen->f_height, screen->bgndtile); 519: #ifdef JUMPSCROLL 520: } 521: #endif JUMPSCROLL 522: bzero ((char *)screen->buf [screen->cur_row], 523: sizeof (short) * (screen->max_col + 1)); 524: } 525: 526: ClearScreen(screen) 527: register Screen *screen; 528: { 529: screen->do_wrap = 0; 530: 531: #ifdef JUMPSCROLL 532: if(screen->scroll_amt) 533: FlushScroll(screen); 534: #endif JUMPSCROLL 535: XClear(screen->window); 536: ClearBufRows (screen, 0, screen->max_row); 537: } 538: 539: CopyWait(screen) 540: register Screen *screen; 541: { 542: XEvent reply; 543: XEvent *rep = &reply; 544: 545: while (1) { 546: XWindowEvent (screen->window, ExposeRegion|ExposeCopy, &reply); 547: switch (reply.type) { 548: case ExposeRegion: 549: if (((XExposeEvent *)rep)->detail == ExposeCopy && 550: screen->incopy <= 0) { 551: screen->incopy = 1; 552: if (screen->scrolls > 0) 553: screen->scrolls--; 554: } 555: HandleExposure (screen, &reply); 556: break; 557: case ExposeCopy: 558: if (screen->incopy <= 0 && screen->scrolls > 0) 559: screen->scrolls--; 560: if (screen->scrolls == 0) { 561: screen->incopy = 0; 562: return; 563: } 564: screen->incopy = -1; 565: break; 566: } 567: } 568: } 569: /* 570: * This routine handles exposure events 571: */ 572: HandleExposure (screen, reply) 573: register Screen *screen; 574: register XExposeEvent *reply; 575: { 576: int toprow, leftcol, nrows, ncols; 577: extern Terminal term; /* kludge */ 578: XExposeRegionEvent event; 579: 580: toprow = (reply->y - screen->border) / screen->f_height; 581: leftcol = (reply->x - screen->border) / screen->f_width; 582: nrows = (reply->y + reply->height - 1 - screen->border) / 583: screen->f_height - toprow + 1; 584: ncols = (reply->x + reply->width - 1 - screen->border) / 585: screen->f_width - leftcol + 1; 586: toprow -= screen->scrolls; 587: if (toprow < 0) { 588: nrows += toprow; 589: toprow = 0; 590: } 591: if (toprow + nrows - 1 > screen->max_row) 592: nrows = screen->max_row - toprow + 1; 593: if (leftcol + ncols - 1 > screen->max_col) 594: ncols = screen->max_col - leftcol + 1; 595: 596: if (nrows > 0 && ncols > 0) { 597: if (screen->TekEmu && reply->detail != ExposeCopy) 598: /* Clear to avoid possible dangling cursor */ 599: XTileSet (screen->window, 600: leftcol * screen->f_width + screen->border, 601: toprow * screen->f_height + screen->border, 602: ncols * screen->f_width, 603: nrows * screen->f_height, 604: screen->bgndtile); 605: ScrnRefresh (screen, toprow, leftcol, nrows, ncols); 606: /* only do the tek refresh on the last refresh event */ 607: if (screen->TekEmu) { 608: XSync(0); /* make sure they are all here */ 609: if (XPending() != 0) { 610: XPeekEvent(&event); 611: if (event.type != ExposeRegion) { 612: if (reply->detail != ExposeCopy) 613: TekRefresh(&term); 614: } 615: } 616: else { 617: if (reply->detail != ExposeCopy) 618: TekRefresh (&term); 619: } 620: } 621: if (screen->cur_row >= toprow && 622: screen->cur_row < toprow + nrows && 623: screen->cur_col >= leftcol && 624: screen->cur_col < leftcol + ncols) 625: return (1); 626: } 627: return (0); 628: } 629: 630: Panic(s, a) 631: char *s; 632: { 633: fprintf(stderr, "PANIC! "); 634: fprintf(stderr, s, a); 635: fprintf(stderr, "\r\n"); 636: fflush(stderr); 637: } 638: 639: Error () 640: { 641: fprintf (stderr, "Error %d: ", errno); 642: perror (""); 643: Cleanup(66); 644: } 645: 646: /* 647: * cleanup by sending SIGHUP to client processes 648: */ 649: Cleanup (code) 650: int code; 651: { 652: extern Terminal term; 653: register Screen *screen; 654: register long pgrp; 655: screen = &term.screen; 656: if (screen->pid > 1) { 657: pgrp = getpgrp(screen->pid); 658: if (pgrp > 1) killpg(pgrp, SIGHUP); 659: } 660: exit(code); 661: } 662: 663: /* 664: * sets the value of var to be arg in the Unix 4.2 BSD environment env. 665: * Var should end with '=' (bindings are of the form "var=value"). 666: * This procedure assumes the memory for the first level of environ 667: * was allocated using malloc. 668: */ 669: Setenv (var, value) 670: register char *var, *value; 671: { 672: extern char **environ; 673: register int index = 0; 674: 675: while (environ [index] != NULL) { 676: if (strncmp (environ [index], var, strlen (var)) == 0) { 677: /* found it */ 678: environ [index] = (char *) malloc (strlen (var) + strlen (value)); 679: strcpy (environ [index], var); 680: strcat (environ [index], value); 681: return; 682: } 683: index ++; 684: } 685: 686: if (debug) printf ("expanding env\n"); 687: environ = (char **) realloc((char *)environ, sizeof(char *) * (index+2)); 688: if (environ == NULL) { 689: fprintf (stderr, "Setenv: malloc out of memory\n"); 690: exit (1); 691: } 692: 693: environ [index] = (char *) malloc (strlen (var) + strlen (value)); 694: strcpy (environ [index], var); 695: strcat (environ [index], value); 696: environ [++index] = NULL; 697: } 698: 699: /* 700: * returns a pointer to the first occurrence of s2 in s1, 701: * or NULL if there are none. 702: */ 703: char *strindex (s1, s2) 704: register char *s1, *s2; 705: { 706: register char *s3; 707: char *index(); 708: 709: while ((s3=index(s1, *s2)) != NULL) { 710: if (strncmp(s3, s2, strlen(s2)) == 0) 711: return (s3); 712: s1 = ++s3; 713: } 714: return (NULL); 715: }