|
|
1.1 ! root 1: /* ! 2: * $Source: /orpheus/u1/X11/clients/xterm/RCS/screen.c,v $ ! 3: * $Header: screen.c,v 1.9 87/08/13 16:02:42 guarino Exp $ ! 4: */ ! 5: ! 6: #include <X11/copyright.h> ! 7: ! 8: /* ! 9: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. ! 10: * ! 11: * All Rights Reserved ! 12: * ! 13: * Permission to use, copy, modify, and distribute this software and its ! 14: * documentation for any purpose and without fee is hereby granted, ! 15: * provided that the above copyright notice appear in all copies and that ! 16: * both that copyright notice and this permission notice appear in ! 17: * supporting documentation, and that the name of Digital Equipment ! 18: * Corporation not be used in advertising or publicity pertaining to ! 19: * distribution of the software without specific, written prior permission. ! 20: * ! 21: * ! 22: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 23: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 24: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 25: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 26: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 27: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 28: * SOFTWARE. ! 29: */ ! 30: ! 31: /* screen.c */ ! 32: ! 33: #ifndef lint ! 34: static char rcs_id[] = "$Header: screen.c,v 1.9 87/08/13 16:02:42 guarino Exp $"; ! 35: #endif lint ! 36: ! 37: #include <X11/Xlib.h> ! 38: #include <stdio.h> ! 39: #include <sys/ioctl.h> ! 40: #include <signal.h> ! 41: #include "ptyx.h" ! 42: #include "error.h" ! 43: ! 44: extern char *calloc(); ! 45: extern char *malloc(); ! 46: extern char *realloc(); ! 47: extern void bcopy(); ! 48: extern void free(); ! 49: ! 50: ScrnBuf Allocate (nrow, ncol) ! 51: /* ! 52: allocates memory for a 2-dimensional array of chars and returns a pointer ! 53: thereto ! 54: each line is formed from a pair of char arrays. The first (even) one is ! 55: the actual character array and the second (odd) one is the attributes. ! 56: */ ! 57: register int nrow, ncol; ! 58: { ! 59: register ScrnBuf base; ! 60: ! 61: if ((base = (ScrnBuf) calloc ((unsigned)(nrow *= 2), sizeof (char *))) == 0) ! 62: SysError (ERROR_SCALLOC); ! 63: ! 64: for (nrow--; nrow >= 0; nrow--) ! 65: if ((base [nrow] = calloc ((unsigned)ncol, sizeof(char))) == 0) ! 66: SysError (ERROR_SCALLOC2); ! 67: ! 68: return (base); ! 69: } ! 70: ! 71: ScreenWrite (screen, str, flags, length) ! 72: /* ! 73: Writes str into buf at row row and column col. Characters are set to match ! 74: flags. ! 75: */ ! 76: TScreen *screen; ! 77: char *str; ! 78: register unsigned flags; ! 79: register int length; /* length of string */ ! 80: { ! 81: register char *att; ! 82: register int avail = screen->max_col - screen->cur_col + 1; ! 83: register char *col; ! 84: ! 85: if (length > avail) ! 86: length = avail; ! 87: if (length <= 0) ! 88: return; ! 89: ! 90: col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col; ! 91: att = screen->buf[avail + 1] + screen->cur_col; ! 92: flags &= ATTRIBUTES; ! 93: bcopy(str, col, length); ! 94: while(length-- > 0) ! 95: *att++ = flags; ! 96: } ! 97: ! 98: ScrnInsertLine (sb, last, where, n, size) ! 99: /* ! 100: Inserts n blank lines at sb + where, treating last as a bottom margin. ! 101: Size is the size of each entry in sb. ! 102: Requires: 0 <= where < where + n <= last ! 103: n <= MAX_ROWS ! 104: */ ! 105: register ScrnBuf sb; ! 106: int last; ! 107: register int where, n, size; ! 108: { ! 109: register int i; ! 110: char *save [2 * MAX_ROWS]; ! 111: ! 112: /* save n lines at bottom */ ! 113: bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save, ! 114: 2 * sizeof (char *) * n); ! 115: ! 116: /* clear contents of old rows */ ! 117: for (i = 2 * n - 1; i >= 0; i--) ! 118: bzero ((char *) save [i], size); ! 119: ! 120: /* move down lines */ ! 121: bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)], ! 122: 2 * sizeof (char *) * (last - where)); ! 123: ! 124: /* reuse storage for new lines at where */ ! 125: bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n); ! 126: } ! 127: ! 128: ! 129: ScrnDeleteLine (sb, last, where, n, size) ! 130: /* ! 131: Deletes n lines at sb + where, treating last as a bottom margin. ! 132: Size is the size of each entry in sb. ! 133: Requires 0 <= where < where + n < = last ! 134: n <= MAX_ROWS ! 135: */ ! 136: register ScrnBuf sb; ! 137: register int n, last, size; ! 138: int where; ! 139: { ! 140: register int i; ! 141: char *save [2 * MAX_ROWS]; ! 142: ! 143: /* save n lines at where */ ! 144: bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n); ! 145: ! 146: /* clear contents of old rows */ ! 147: for (i = 2 * n - 1 ; i >= 0 ; i--) ! 148: bzero ((char *) save [i], size); ! 149: ! 150: /* move up lines */ ! 151: bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where], ! 152: 2 * sizeof (char *) * ((last -= n - 1) - where)); ! 153: ! 154: /* reuse storage for new bottom lines */ ! 155: bcopy ((char *)save, (char *) &sb[2 * last], ! 156: 2 * sizeof(char *) * n); ! 157: } ! 158: ! 159: ! 160: ScrnInsertChar (sb, row, col, n, size) ! 161: /* ! 162: Inserts n blanks in sb at row, col. Size is the size of each row. ! 163: */ ! 164: ScrnBuf sb; ! 165: int row, size; ! 166: register int col, n; ! 167: { ! 168: register int i, j; ! 169: register char *ptr = sb [2 * row]; ! 170: register char *att = sb [2 * row + 1]; ! 171: ! 172: for (i = size - 1; i >= col + n; i--) { ! 173: ptr[i] = ptr[j = i - n]; ! 174: att[i] = att[j]; ! 175: } ! 176: ! 177: bzero (ptr + col, n); ! 178: bzero (att + col, n); ! 179: } ! 180: ! 181: ! 182: ScrnDeleteChar (sb, row, col, n, size) ! 183: /* ! 184: Deletes n characters in sb at row, col. Size is the size of each row. ! 185: */ ! 186: ScrnBuf sb; ! 187: register int row, size; ! 188: register int n, col; ! 189: { ! 190: register char *ptr = sb[2 * row]; ! 191: register char *att = sb[2 * row + 1]; ! 192: register nbytes = (size - n - col); ! 193: ! 194: bcopy (ptr + col + n, ptr + col, nbytes); ! 195: bcopy (att + col + n, att + col, nbytes); ! 196: bzero (ptr + size - n, n); ! 197: bzero (att + size - n, n); ! 198: } ! 199: ! 200: ! 201: ScrnRefresh (screen, toprow, leftcol, nrows, ncols) ! 202: /* ! 203: Repaints the area enclosed by the parameters. ! 204: Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are ! 205: coordinates of characters in screen; ! 206: nrows and ncols positive. ! 207: */ ! 208: register TScreen *screen; ! 209: int toprow, leftcol, nrows, ncols; ! 210: { ! 211: int y = toprow * FontHeight(screen) + screen->border + ! 212: screen->fnt_norm->max_bounds.ascent; ! 213: register int row; ! 214: register int topline = screen->topline; ! 215: int maxrow = toprow + nrows - 1; ! 216: int scrollamt = screen->scroll_amt; ! 217: int max = screen->max_row; ! 218: ! 219: ! 220: if(screen->cursor_col >= leftcol && screen->cursor_col <= ! 221: (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline && ! 222: screen->cursor_row <= maxrow + topline) ! 223: screen->cursor_state = OFF; ! 224: for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) { ! 225: register char *chars; ! 226: register char *att; ! 227: register int col = leftcol; ! 228: int maxcol = leftcol + ncols - 1; ! 229: int lastind; ! 230: int flags; ! 231: int x, n; ! 232: GC gc; ! 233: ! 234: lastind = row - scrollamt; ! 235: if (lastind < 0 || lastind > max) ! 236: continue; ! 237: chars = screen->buf [2 * (lastind + topline)]; ! 238: att = screen->buf [2 * (lastind + topline) + 1]; ! 239: ! 240: while (col <= maxcol && (att[col] & ~BOLD) == 0 && ! 241: (chars[col] & ~040) == 0) ! 242: col++; ! 243: ! 244: while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 && ! 245: (chars[maxcol] & ~040) == 0) ! 246: maxcol--; ! 247: ! 248: if (col > maxcol) continue; ! 249: ! 250: flags = att[col]; ! 251: ! 252: if ((flags & INVERSE) != 0) ! 253: if (flags & BOLD) gc = screen->reverseboldGC; ! 254: else gc = screen->reverseGC; ! 255: else ! 256: if (flags & BOLD) gc = screen->normalboldGC; ! 257: else gc = screen->normalGC; ! 258: ! 259: x = CursorX(screen, col); ! 260: lastind = col; ! 261: ! 262: for (; col <= maxcol; col++) { ! 263: if (att[col] != flags) { ! 264: XDrawImageString(screen->display, TextWindow(screen), ! 265: gc, x, y, &chars[lastind], n = col - lastind); ! 266: if((flags & BOLD) && screen->enbolden) ! 267: XDrawString(screen->display, TextWindow(screen), ! 268: gc, x + 1, y, &chars[lastind], n); ! 269: if(flags & UNDERLINE) ! 270: XDrawLine(screen->display, TextWindow(screen), ! 271: gc, x, y+1, x+n*FontWidth(screen), y+1); ! 272: ! 273: x += (col - lastind) * FontWidth(screen); ! 274: ! 275: lastind = col; ! 276: ! 277: flags = att[col]; ! 278: ! 279: if ((flags & INVERSE) != 0) ! 280: if (flags & BOLD) gc = screen->reverseboldGC; ! 281: else gc = screen->reverseGC; ! 282: else ! 283: if (flags & BOLD) gc = screen->normalboldGC; ! 284: else gc = screen->normalGC; ! 285: } ! 286: ! 287: if(chars[col] == 0) ! 288: chars[col] = ' '; ! 289: } ! 290: ! 291: ! 292: if ((flags & INVERSE) != 0) ! 293: if (flags & BOLD) gc = screen->reverseboldGC; ! 294: else gc = screen->reverseGC; ! 295: else ! 296: if (flags & BOLD) gc = screen->normalboldGC; ! 297: else gc = screen->normalGC; ! 298: XDrawImageString(screen->display, TextWindow(screen), gc, ! 299: x, y, &chars[lastind], n = col - lastind); ! 300: if((flags & BOLD) && screen->enbolden) ! 301: XDrawString(screen->display, TextWindow(screen), gc, ! 302: x + 1, y, &chars[lastind], n); ! 303: if(flags & UNDERLINE) ! 304: XDrawLine(screen->display, TextWindow(screen), gc, ! 305: x, y+1, x + n * FontWidth(screen), y+1); ! 306: } ! 307: } ! 308: ! 309: ClearBufRows (screen, first, last) ! 310: /* ! 311: Sets the rows first though last of the buffer of screen to spaces. ! 312: Requires first <= last; first, last are rows of screen->buf. ! 313: */ ! 314: register TScreen *screen; ! 315: register int first, last; ! 316: { ! 317: first *= 2; ! 318: last = 2 * last + 1; ! 319: while (first <= last) ! 320: bzero (screen->buf [first++], (screen->max_col + 1)); ! 321: } ! 322: ! 323: ScreenResize (screen, width, height, flags) ! 324: /* ! 325: Resizes screen: ! 326: 1. If new window would have fractional characters, sets window size so as to ! 327: discard fractional characters and returns -1. ! 328: Minimum screen size is 1 X 1. ! 329: Note that this causes another ExposeWindow event. ! 330: 2. Enlarges screen->buf if necessary. New space is appended to the bottom ! 331: and to the right ! 332: 3. Reduces screen->buf if necessary. Old space is removed from the bottom ! 333: and from the right ! 334: 4. Cursor is positioned as closely to its former position as possible ! 335: 5. Sets screen->max_row and screen->max_col to reflect new size ! 336: 6. Maintains the inner border. ! 337: 7. Clears origin mode and sets scrolling region to be entire screen. ! 338: 8. Returns 0 ! 339: */ ! 340: register TScreen *screen; ! 341: int width, height; ! 342: unsigned *flags; ! 343: { ! 344: register int rows, cols; ! 345: register int index; ! 346: register int savelines; ! 347: register ScrnBuf sb = screen->allbuf; ! 348: register ScrnBuf ab = screen->altbuf; ! 349: register int x; ! 350: register int border = 2 * screen->border; ! 351: register int i, j, k; ! 352: #ifdef sun ! 353: #ifdef TIOCSSIZE ! 354: struct ttysize ts; ! 355: #endif TIOCSSIZE ! 356: #else sun ! 357: #ifdef TIOCSWINSZ ! 358: struct winsize ws; ! 359: #endif TIOCSWINSZ ! 360: #endif sun ! 361: ! 362: /* round so that it is unlikely the screen will change size on */ ! 363: /* small mouse movements. */ ! 364: rows = (height + FontHeight(screen) / 2 - border) / ! 365: FontHeight(screen); ! 366: cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) / ! 367: FontWidth(screen); ! 368: if (rows < 1) rows = 1; ! 369: if (cols < 1) cols = 1; ! 370: ! 371: if ((width - border - screen->scrollbar) % FontWidth(screen) ! 372: != 0 || (height - border) % FontHeight(screen) != 0) { ! 373: XResizeWindow( ! 374: screen->display, ! 375: TextWindow(screen), ! 376: (unsigned) cols * FontWidth(screen) + border ! 377: + screen->scrollbar, ! 378: (unsigned) rows * FontHeight(screen) + border); ! 379: return (-1); ! 380: } ! 381: ! 382: /* change buffers if the screen has changed size */ ! 383: if (screen->max_row != rows - 1 || screen->max_col != cols - 1) { ! 384: if(screen->cursor_state) ! 385: HideCursor(); ! 386: savelines = screen->scrollWindow ? screen->savelines : 0; ! 387: j = screen->max_col + 1; ! 388: i = cols - j; ! 389: k = screen->max_row; ! 390: if(rows < k) ! 391: k = rows; ! 392: if(ab) { ! 393: /* resize current lines in alternate buf */ ! 394: for (index = x = 0; index <= k; x += 2, index++) { ! 395: if ((ab[x] = realloc(ab[x], (unsigned) cols)) == NULL) ! 396: SysError(ERROR_SREALLOC); ! 397: if((ab[x + 1] = realloc(ab[x + 1], (unsigned) cols)) == ! 398: NULL) ! 399: SysError (ERROR_SREALLOC2); ! 400: if (cols > j) { ! 401: bzero (ab [x] + j, i); ! 402: bzero (ab [x + 1] + j, i); ! 403: } ! 404: } ! 405: /* discard excess bottom rows in alt buf */ ! 406: for (index = rows, x = 2 * k ; index <= ! 407: screen->max_row; x += 2, index++) { ! 408: free (ab [x]); ! 409: free (ab [x + 1]); ! 410: } ! 411: } ! 412: /* resize current lines */ ! 413: k += savelines; ! 414: for (index = x = 0; index <= k; x += 2, index++) { ! 415: if ((sb[x] = realloc(sb[x], (unsigned) cols)) == NULL) ! 416: SysError(ERROR_SREALLOC3); ! 417: if((sb[x + 1] = realloc(sb[x + 1], (unsigned) cols)) == NULL) ! 418: SysError (ERROR_SREALLOC4); ! 419: if (cols > j) { ! 420: bzero (sb [x] + j, i); ! 421: bzero (sb [x + 1] + j, i); ! 422: } ! 423: } ! 424: /* discard excess bottom rows */ ! 425: for (index = rows, x = 2 * k; index <= screen->max_row; ! 426: x += 2, index++) { ! 427: free (sb [x]); ! 428: free (sb [x + 1]); ! 429: } ! 430: if(ab) { ! 431: if((ab = (ScrnBuf)realloc((char *)ab, ! 432: (unsigned) 2 * sizeof(char *) * rows)) == NULL) ! 433: SysError (ERROR_RESIZE); ! 434: screen->altbuf = ab; ! 435: } ! 436: k = 2 * (rows + savelines); ! 437: /* resize sb */ ! 438: if((sb = (ScrnBuf)realloc((char *) sb, (unsigned) k * sizeof(char *))) ! 439: == NULL) ! 440: SysError (ERROR_RESIZE2); ! 441: screen->allbuf = sb; ! 442: screen->buf = &sb[2 * savelines]; ! 443: ! 444: if(ab) { ! 445: /* create additional bottom rows as required in alt */ ! 446: for (index = screen->max_row + 1, x = 2 * index ; ! 447: index < rows; x += 2, index++) { ! 448: if((ab[x] = calloc ((unsigned) cols, sizeof(char))) == NULL) ! 449: SysError(ERROR_RESIZROW); ! 450: if((ab[x + 1] = calloc ((unsigned) cols, sizeof(char))) == NULL) ! 451: SysError(ERROR_RESIZROW2); ! 452: } ! 453: } ! 454: /* create additional bottom rows as required */ ! 455: for (index = screen->max_row + 1, x = 2 * (index + savelines) ; ! 456: index < rows; x += 2, index++) { ! 457: if((sb[x] = calloc ((unsigned) cols, sizeof(char))) == NULL) ! 458: SysError(ERROR_RESIZROW3); ! 459: if((sb[x + 1] = calloc ((unsigned) cols, sizeof(char))) == NULL) ! 460: SysError(ERROR_RESIZROW4); ! 461: } ! 462: ! 463: screen->max_row = rows - 1; ! 464: screen->max_col = cols - 1; ! 465: ! 466: /* adjust scrolling region */ ! 467: screen->top_marg = 0; ! 468: screen->bot_marg = screen->max_row; ! 469: *flags &= ~ORIGIN; ! 470: ! 471: if (screen->cur_row > screen->max_row) ! 472: screen->cur_row = screen->max_row; ! 473: if (screen->cur_col > screen->max_col) ! 474: screen->cur_col = screen->max_col; ! 475: ! 476: screen->fullVwin.height = height - border; ! 477: screen->fullVwin.width = width - border - screen->scrollbar; ! 478: ! 479: } else if(FullHeight(screen) == height && FullWidth(screen) == width) ! 480: return(0); /* nothing has changed at all */ ! 481: ! 482: if(screen->scrollWindow) ! 483: ResizeScrollBar(screen->scrollWindow, -1, -1, height); ! 484: ! 485: screen->fullVwin.fullheight = height; ! 486: screen->fullVwin.fullwidth = width; ! 487: #ifdef sun ! 488: #ifdef TIOCSSIZE ! 489: /* Set tty's idea of window size */ ! 490: ts.ts_lines = rows; ! 491: ts.ts_cols = cols; ! 492: ioctl (screen->respond, TIOCSSIZE, &ts); ! 493: #ifdef SIGWINCH ! 494: if(screen->pid > 1) ! 495: killpg(getpgrp(screen->pid), SIGWINCH); ! 496: #endif SIGWINCH ! 497: #endif TIOCSSIZE ! 498: #else sun ! 499: #ifdef TIOCSWINSZ ! 500: /* Set tty's idea of window size */ ! 501: ws.ws_row = rows; ! 502: ws.ws_col = cols; ! 503: ws.ws_xpixel = width; ! 504: ws.ws_ypixel = height; ! 505: ioctl (screen->respond, TIOCSWINSZ, (char *)&ws); ! 506: #ifdef SIGWINCH ! 507: if(screen->pid > 1) ! 508: killpg(getpgrp((int)screen->pid), SIGWINCH); ! 509: #endif SIGWINCH ! 510: #endif TIOCSWINSZ ! 511: #endif sun ! 512: return (0); ! 513: } ! 514: ! 515:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.