|
|
1.1 ! root 1: /* ! 2: * $Source: /u1/X/xterm/RCS/screen.c,v $ ! 3: * $Header: screen.c,v 10.100 86/12/01 14:45:17 jg Rel $ ! 4: */ ! 5: ! 6: #include <X/mit-copyright.h> ! 7: ! 8: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ ! 9: ! 10: /* screen.c */ ! 11: ! 12: #ifndef lint ! 13: static char csrg_id[] = "@(#)screen.c 1.6\t(Berkeley/CSRG)\t9/21/87"; ! 14: static char sccs_id[] = "@(#)screen.c\tX10/6.6B\t12/26/86"; ! 15: #endif lint ! 16: ! 17: #include <X/Xlib.h> ! 18: #include <stdio.h> ! 19: #include <sys/ioctl.h> ! 20: #include <signal.h> ! 21: #include "scrollbar.h" ! 22: #include "ptyx.h" ! 23: #include "error.h" ! 24: ! 25: extern char *calloc(); ! 26: extern char *malloc(); ! 27: extern char *realloc(); ! 28: ! 29: ScrnBuf Allocate (nrow, ncol) ! 30: /* ! 31: allocates memory for a 2-dimensional array of chars and returns a pointer ! 32: thereto ! 33: each line is formed from a pair of char arrays. The first (even) one is ! 34: the actual character array and the second (odd) one is the attributes. ! 35: */ ! 36: register int nrow, ncol; ! 37: { ! 38: register ScrnBuf base; ! 39: ! 40: if ((base = (ScrnBuf) calloc ((nrow *= 2), sizeof (char *))) == 0) ! 41: SysError (ERROR_SCALLOC); ! 42: ! 43: for (nrow--; nrow >= 0; nrow--) ! 44: if ((base [nrow] = calloc (ncol, sizeof(char))) == 0) ! 45: SysError (ERROR_SCALLOC2); ! 46: ! 47: return (base); ! 48: } ! 49: ! 50: ScreenWrite (screen, str, flags, length) ! 51: /* ! 52: Writes str into buf at row row and column col. Characters are set to match ! 53: flags. ! 54: */ ! 55: Screen *screen; ! 56: char *str; ! 57: register unsigned flags; ! 58: register int length; /* length of string */ ! 59: { ! 60: register char *att; ! 61: register int avail = screen->max_col - screen->cur_col + 1; ! 62: register char *col; ! 63: ! 64: if (length > avail) ! 65: length = avail; ! 66: if (length <= 0) ! 67: return; ! 68: ! 69: col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col; ! 70: att = screen->buf[avail + 1] + screen->cur_col; ! 71: flags &= ATTRIBUTES; ! 72: bcopy(str, col, length); ! 73: while(length-- > 0) ! 74: *att++ = flags; ! 75: } ! 76: ! 77: ScrnInsertLine (sb, last, where, n, size) ! 78: /* ! 79: Inserts n blank lines at sb + where, treating last as a bottom margin. ! 80: Size is the size of each entry in sb. ! 81: Requires: 0 <= where < where + n <= last ! 82: n <= MAX_ROWS ! 83: */ ! 84: register ScrnBuf sb; ! 85: int last; ! 86: register int where, n, size; ! 87: { ! 88: register int i; ! 89: char *save [2 * MAX_ROWS]; ! 90: ! 91: /* save n lines at bottom */ ! 92: bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save, ! 93: 2 * sizeof (char *) * n); ! 94: ! 95: /* clear contents of old rows */ ! 96: for (i = 2 * n - 1; i >= 0; i--) ! 97: bzero ((char *) save [i], size); ! 98: ! 99: /* move down lines */ ! 100: bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)], ! 101: 2 * sizeof (char *) * (last - where)); ! 102: ! 103: /* reuse storage for new lines at where */ ! 104: bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n); ! 105: } ! 106: ! 107: ! 108: ScrnDeleteLine (sb, last, where, n, size) ! 109: /* ! 110: Deletes n lines at sb + where, treating last as a bottom margin. ! 111: Size is the size of each entry in sb. ! 112: Requires 0 <= where < where + n < = last ! 113: n <= MAX_ROWS ! 114: */ ! 115: register ScrnBuf sb; ! 116: register int n, last, size; ! 117: int where; ! 118: { ! 119: register int i; ! 120: char *save [2 * MAX_ROWS]; ! 121: ! 122: /* save n lines at where */ ! 123: bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n); ! 124: ! 125: /* clear contents of old rows */ ! 126: for (i = 2 * n - 1 ; i >= 0 ; i--) ! 127: bzero ((char *) save [i], size); ! 128: ! 129: /* move up lines */ ! 130: bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where], ! 131: 2 * sizeof (char *) * ((last -= n - 1) - where)); ! 132: ! 133: /* reuse storage for new bottom lines */ ! 134: bcopy ((char *)save, (char *) &sb[2 * last], ! 135: 2 * sizeof(char *) * n); ! 136: } ! 137: ! 138: ! 139: ScrnInsertChar (sb, row, col, n, size) ! 140: /* ! 141: Inserts n blanks in sb at row, col. Size is the size of each row. ! 142: */ ! 143: ScrnBuf sb; ! 144: int row, size; ! 145: register int col, n; ! 146: { ! 147: register int i, j; ! 148: register char *ptr = sb [2 * row]; ! 149: register char *att = sb [2 * row + 1]; ! 150: ! 151: for (i = size - 1; i >= col + n; i--) { ! 152: ptr[i] = ptr[j = i - n]; ! 153: att[i] = att[j]; ! 154: } ! 155: ! 156: bzero (ptr + col, n); ! 157: bzero (att + col, n); ! 158: } ! 159: ! 160: ! 161: ScrnDeleteChar (sb, row, col, n, size) ! 162: /* ! 163: Deletes n characters in sb at row, col. Size is the size of each row. ! 164: */ ! 165: ScrnBuf sb; ! 166: register int row, size; ! 167: register int n, col; ! 168: { ! 169: register char *ptr = sb[2 * row]; ! 170: register char *att = sb[2 * row + 1]; ! 171: register nbytes = (size - n - col); ! 172: ! 173: bcopy (ptr + col + n, ptr + col, nbytes); ! 174: bcopy (att + col + n, att + col, nbytes); ! 175: bzero (ptr + size - n, n); ! 176: bzero (att + size - n, n); ! 177: } ! 178: ! 179: ! 180: ScrnRefresh (screen, toprow, leftcol, nrows, ncols) ! 181: /* ! 182: Repaints the area enclosed by the parameters. ! 183: Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are ! 184: coordinates of characters in screen; ! 185: nrows and ncols positive. ! 186: */ ! 187: register Screen *screen; ! 188: int toprow, leftcol, nrows, ncols; ! 189: { ! 190: int y = toprow * FontHeight(screen) + screen->border + Titlebar(screen); ! 191: register int row; ! 192: register int topline = screen->topline; ! 193: int maxrow = toprow + nrows - 1; ! 194: int scrollamt = screen->scroll_amt; ! 195: int max = screen->max_row; ! 196: int dostatus = 0, left, width; ! 197: ! 198: ! 199: if(screen->statusline && maxrow == screen->max_row + 1) { ! 200: dostatus++; ! 201: maxrow--; ! 202: } ! 203: if(screen->cursor_col >= leftcol && screen->cursor_col <= ! 204: (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline && ! 205: screen->cursor_row <= maxrow + topline) ! 206: screen->cursor_state = OFF; ! 207: for( ; ; ) { ! 208: for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) ! 209: { ! 210: register char *chars; ! 211: register char *att; ! 212: register int col = leftcol; ! 213: int maxcol = leftcol + ncols - 1; ! 214: int lastind; ! 215: int flags; ! 216: int gxfunction; ! 217: Font fnt; ! 218: int x, yb, pix, n; ! 219: ! 220: lastind = row - scrollamt; ! 221: if (lastind < 0 || lastind > max) ! 222: continue; ! 223: chars = screen->buf [2 * (lastind + topline)]; ! 224: att = screen->buf [2 * (lastind + topline) + 1]; ! 225: ! 226: while (col <= maxcol && (att[col] & ~BOLD) == 0 && ! 227: (chars[col] & ~040) == 0) ! 228: col++; ! 229: ! 230: while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 && ! 231: (chars[maxcol] & ~040) == 0) ! 232: maxcol--; ! 233: ! 234: if (col > maxcol) continue; ! 235: ! 236: flags = att[col]; ! 237: ! 238: fnt = ActiveIcon(screen) ! 239: ? screen->fnt_icon ! 240: : (flags & BOLD) ! 241: ? screen->fnt_bold ! 242: : screen->fnt_norm; ! 243: ! 244: x = col * FontWidth(screen) + screen->border; ! 245: lastind = col; ! 246: ! 247: for (; col <= maxcol; col++) { ! 248: if (att[col] != flags) { ! 249: if (((flags & INVERSE) != 0) ^ (dostatus < 0 && ! 250: screen->reversestatus)) ! 251: XText (VWindow(screen), x, y, &chars[lastind], ! 252: n = col - lastind, fnt, ! 253: pix = screen->background, screen->foreground); ! 254: else ! 255: XText (VWindow(screen), x, y, &chars[lastind], ! 256: n = col - lastind, fnt, ! 257: pix = screen->foreground, screen->background); ! 258: if((flags & BOLD) && screen->enbolden) ! 259: XTextMask (VWindow(screen), x + 1, y, &chars[lastind], ! 260: n, fnt, pix); ! 261: if(flags & UNDERLINE) { ! 262: yb = y + FontHeight(screen) - 2; ! 263: XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), ! 264: yb, 1, 1, pix, GXcopy, AllPlanes); ! 265: } ! 266: ! 267: x += (col - lastind) * FontWidth(screen); ! 268: ! 269: lastind = col; ! 270: ! 271: flags = att[col]; ! 272: ! 273: fnt = ActiveIcon(screen) ! 274: ? screen->fnt_icon ! 275: : (flags & BOLD) ! 276: ? screen->fnt_bold ! 277: : screen->fnt_norm; ! 278: } ! 279: ! 280: if(chars[col] == 0) ! 281: chars[col] = ' '; ! 282: } ! 283: ! 284: if (((flags & INVERSE) != 0) ^ (dostatus < 0 && ! 285: screen->reversestatus)) ! 286: XText (VWindow(screen), x, y, &chars[lastind], ! 287: n = col - lastind, fnt, pix = screen->background, ! 288: screen->foreground); ! 289: else ! 290: XText (VWindow(screen), x, y, &chars[lastind], ! 291: n = col - lastind, fnt, pix = screen->foreground, ! 292: screen->background); ! 293: if((flags & BOLD) && screen->enbolden) ! 294: XTextMask (VWindow(screen), x + 1, y, &chars[lastind], ! 295: n, fnt, pix); ! 296: if(flags & UNDERLINE) { ! 297: yb = y + FontHeight(screen) - 2; ! 298: XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1, ! 299: pix, GXcopy, AllPlanes); ! 300: } ! 301: } ! 302: if(dostatus <= 0) ! 303: break; ! 304: dostatus = -1; ! 305: topline = 0; ! 306: scrollamt = 0; ! 307: toprow = maxrow = max = screen->max_row + 1; ! 308: left = leftcol * FontWidth(screen) + screen->border; ! 309: width = ncols * FontWidth(screen); ! 310: if(leftcol == 0) { ! 311: left--; ! 312: width++; ! 313: } ! 314: if(leftcol + ncols - 1 >= screen->max_col) ! 315: width++; ! 316: XPixSet(VWindow(screen), left, y, width, screen->statusheight, ! 317: screen->reversestatus ? screen->foreground : screen->background); ! 318: if(!screen->reversestatus) ! 319: StatusBox(screen); ! 320: y++; ! 321: } ! 322: } ! 323: ! 324: ClearBufRows (screen, first, last) ! 325: /* ! 326: Sets the rows first though last of the buffer of screen to spaces. ! 327: Requires first <= last; first, last are rows of screen->buf. ! 328: */ ! 329: register Screen *screen; ! 330: register int first, last; ! 331: { ! 332: first *= 2; ! 333: last = 2 * last + 1; ! 334: while (first <= last) ! 335: bzero (screen->buf [first++], (screen->max_col + 1)); ! 336: } ! 337: ! 338: ScreenResize (screen, width, height, flags) ! 339: /* ! 340: Resizes screen: ! 341: 1. If new window would have fractional characters, sets window size so as to ! 342: discard fractional characters and returns -1. ! 343: Minimum screen size is 1 X 1. ! 344: Note that this causes another ExposeWindow event. ! 345: 2. Enlarges screen->buf if necessary. New space is appended to the bottom ! 346: and to the right ! 347: 3. Reduces screen->buf if necessary. Old space is removed from the bottom ! 348: and from the right ! 349: 4. Cursor is positioned as closely to its former position as possible ! 350: 5. Sets screen->max_row and screen->max_col to reflect new size ! 351: 6. Maintains the inner border. ! 352: 7. Clears origin mode and sets scrolling region to be entire screen. ! 353: 8. Returns 0 ! 354: */ ! 355: register Screen *screen; ! 356: int width, height; ! 357: unsigned *flags; ! 358: { ! 359: register int rows, cols; ! 360: register int index; ! 361: register int savelines; ! 362: register ScrnBuf sb = screen->allbuf; ! 363: register ScrnBuf ab = screen->altbuf; ! 364: register int x; ! 365: register int border = 2 * screen->border; ! 366: register int extra, i, j, k; ! 367: register char *sl0, *sl1; /* keep status line */ ! 368: double scale_x, scale_y; ! 369: #ifdef TIOCSWINSZ ! 370: struct winsize ws; ! 371: #endif TIOCSWINSZ ! 372: ! 373: ! 374: /* don't resize on icon exposure */ ! 375: if (ActiveIcon(screen)) ! 376: return( 0 ); ! 377: ! 378: extra = Titlebar(screen) + screen->statusheight; ! 379: /* round so that it is unlikely the screen will change size on */ ! 380: /* small mouse movements. */ ! 381: rows = (height + FontHeight(screen) / 2 - border - extra) / ! 382: FontHeight(screen); ! 383: cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) / ! 384: FontWidth(screen); ! 385: if (rows < 1) rows = 1; ! 386: if (cols < 1) cols = 1; ! 387: ! 388: if ((width - border - screen->scrollbar) % FontWidth(screen) ! 389: != 0 || (height - border - extra) % FontHeight(screen) != 0 || ! 390: rows < screen->minrows) { ! 391: XChangeWindow (VWindow(screen), ! 392: cols * FontWidth(screen) + border + screen->scrollbar, ! 393: (rows < screen->minrows ? screen->minrows : rows) * ! 394: FontHeight(screen) + border + extra); ! 395: return (-1); ! 396: } ! 397: ! 398: /* change buffers if the screen has changed size */ ! 399: if (screen->max_row != rows - 1 || screen->max_col != cols - 1) { ! 400: if(screen->cursor_state) ! 401: HideCursor(); ! 402: savelines = screen->sb ? screen->savelines : 0; ! 403: j = screen->max_col + 1; ! 404: i = cols - j; ! 405: k = screen->max_row; ! 406: if(ab) { ! 407: /* resize current lines in alternate buf */ ! 408: for (index = x = 0; index <= k; x += 2, index++) { ! 409: if ((ab[x] = realloc(ab[x], cols)) == NULL) ! 410: SysError(ERROR_SREALLOC); ! 411: if((ab[x + 1] = realloc(ab[x + 1], cols)) == ! 412: NULL) ! 413: SysError (ERROR_SREALLOC2); ! 414: if (cols > j) { ! 415: bzero (ab [x] + j, i); ! 416: bzero (ab [x + 1] + j, i); ! 417: } ! 418: } ! 419: } ! 420: /* resize current lines */ ! 421: k += savelines + 1; /* includes status line */ ! 422: for (index = x = 0; index <= k; x += 2, index++) { ! 423: if ((sb[x] = realloc(sb[x], cols)) == NULL) ! 424: SysError(ERROR_SREALLOC3); ! 425: if((sb[x + 1] = realloc(sb[x + 1], cols)) == NULL) ! 426: SysError (ERROR_SREALLOC4); ! 427: if (cols > j) { ! 428: bzero (sb [x] + j, i); ! 429: bzero (sb [x + 1] + j, i); ! 430: } ! 431: } ! 432: ! 433: /* ! 434: * Adjust the number of lines, either discarding the ! 435: * oldest (if we're getting shorter) or padding at ! 436: * the "old" end with blanks (if we're getting taller. ! 437: * ! 438: * Throughout this section, i is the number of lines ! 439: * we need, j is the number we currently have & index ! 440: * is the difference. ! 441: */ ! 442: i = rows + savelines + 1; ! 443: j = screen->max_row + savelines + 2; ! 444: index = j - i; ! 445: if (index > 0) { ! 446: /* we're getting shorter - free the oldest lines */ ! 447: for (x = 0; x < 2*index; ) { ! 448: free (sb[x++]); ! 449: } ! 450: /* move the newer stuff into the right place */ ! 451: k = i * 2 * sizeof(*sb); ! 452: bcopy (&sb[2*index], sb, k); ! 453: sb = (ScrnBuf) realloc (sb, k); ! 454: if (! sb) ! 455: SysError (ERROR_RESIZE2); ! 456: ! 457: /* do the same thing for the alternate buf */ ! 458: if (ab) { ! 459: for (x = 0; x < 2*index;) { ! 460: free (ab[x++]); ! 461: } ! 462: k = (screen->max_row + 1)* sizeof(*sb); ! 463: bcopy (&ab[2*index], ab, k); ! 464: ab = (ScrnBuf) realloc (ab, k); ! 465: if (! ab) ! 466: SysError (ERROR_RESIZE); ! 467: } ! 468: } ! 469: else if (index < 0) { ! 470: /* we're getting taller - add 'index' lines */ ! 471: /* at the "old" end of the saved lines */ ! 472: sb = (ScrnBuf) realloc (sb, i * 2 * sizeof(*sb)); ! 473: if (! sb) ! 474: SysError (ERROR_RESIZE2); ! 475: ! 476: /* move up the stuff we want at the new end */ ! 477: /* of the buffer and fill the hole with blanks */ ! 478: k = -2 * index; ! 479: bcopy (sb, &sb[k], j * 2 * sizeof(*sb)); ! 480: ! 481: for (x = 0; x < k; ) { ! 482: if (! (sb[x++] = calloc (cols, sizeof(**sb)))) ! 483: SysError(ERROR_RESIZROW3); ! 484: } ! 485: ! 486: /* do the same thing with the alternate buffer */ ! 487: if (ab) { ! 488: ab = (ScrnBuf) realloc (ab, rows*2*sizeof(*ab)); ! 489: if (! ab) ! 490: SysError (ERROR_RESIZE); ! 491: ! 492: bcopy (ab, &ab[k], (screen->max_row + 1) * ! 493: 2 * sizeof(*ab)); ! 494: for (x = 0; x < k; ) { ! 495: if (! (ab[x++] = calloc (cols, ! 496: sizeof(**ab)))) ! 497: SysError(ERROR_RESIZROW4); ! 498: } ! 499: } ! 500: } ! 501: screen->allbuf = sb; ! 502: screen->buf = &sb[2 * savelines]; ! 503: screen->altbuf = ab; ! 504: ! 505: /* add the new lines to the old screen size & pos */ ! 506: screen->max_row -= index; ! 507: if (! screen->instatus) ! 508: screen->cur_row -= index; ! 509: else ! 510: screen->cur_row = screen->max_row + 1; ! 511: ! 512: screen->max_row = rows - 1; ! 513: screen->max_col = cols - 1; ! 514: ! 515: /* adjust scrolling region */ ! 516: screen->top_marg = 0; ! 517: screen->bot_marg = screen->max_row; ! 518: *flags &= ~ORIGIN; ! 519: ! 520: if (screen->cur_row > screen->max_row) ! 521: screen->cur_row = screen->max_row; ! 522: else if (screen->cur_row < 0) ! 523: screen->cur_row = 0; ! 524: if (screen->cur_col > screen->max_col) ! 525: screen->cur_col = screen->max_col; ! 526: else if (screen->cur_col < 0) ! 527: screen->cur_col = 0; ! 528: ! 529: screen->fullVwin.height = height - extra; ! 530: screen->fullVwin.width = width; ! 531: ! 532: if (screen->active_icon) ! 533: SetIconSize( screen ); ! 534: ! 535: } ! 536: else if(FullHeight(screen) == height && FullWidth(screen) == width) ! 537: return(0); /* nothing has changed at all */ ! 538: ! 539: if(screen->sb) ! 540: ResizeScrollBar(screen->sb, width - SCROLLBARWIDTH, ! 541: Titlebar(screen) - 1, height - Titlebar(screen), rows); ! 542: if(screen->title.tbar && FullWidth(screen) != width) ! 543: VTTitleResize(width); ! 544: ! 545: screen->fullVwin.fullheight = height; ! 546: screen->fullVwin.fullwidth = width; ! 547: #ifdef TIOCSWINSZ ! 548: /* Set tty's idea of window size */ ! 549: ws.ws_row = rows; ! 550: ws.ws_col = cols; ! 551: ws.ws_xpixel = width; ! 552: ws.ws_ypixel = height; ! 553: ioctl (screen->respond, TIOCSWINSZ, &ws); ! 554: #ifdef SIGWINCH ! 555: if(screen->pid > 1) ! 556: killpg(getpgrp(screen->pid), SIGWINCH); ! 557: #endif SIGWINCH ! 558: #endif TIOCSWINSZ ! 559: return (0); ! 560: } ! 561: ! 562: ! 563: SetIconSize( screen ) ! 564: Screen *screen; ! 565: { ! 566: if (screen->active_icon) { ! 567: screen->iconVwin.width = (screen->max_col + 1) ! 568: * screen->iconVwin.f_width ! 569: + screen->border * 2; ! 570: screen->iconVwin.height = (screen->max_row + 1) ! 571: * screen->iconVwin.f_height ! 572: + screen->border * 2; ! 573: XChangeWindow( screen->iconVwin.window, ! 574: screen->iconVwin.width, ! 575: screen->iconVwin.height ); ! 576: } else { ! 577: IconRecalc( screen ); ! 578: } ! 579: ! 580: screen->iconVwin.fullwidth = screen->iconVwin.width; ! 581: screen->iconVwin.fullheight = screen->iconVwin.height; ! 582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.