1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: /* screen.c */ 6: 7: #ifndef lint 8: static char *rcsid_screen_c = "$Header: screen.c,v 10.13 86/02/01 16:07:00 tony Rel $"; 9: #endif lint 10: 11: #include <X/Xlib.h> 12: #include <stdio.h> 13: #include <sys/ioctl.h> 14: #include "ptyx.h" 15: 16: ScrnBuf Allocate (nrow, ncol) 17: /* 18: allocates memory for a 2-dimensional array of shorts and returns a pointer thereto 19: */ 20: register int nrow, ncol; 21: { 22: register ScrnBuf base; 23: 24: if ((base = (ScrnBuf) calloc (nrow, sizeof (short *))) == 0) Error (); 25: 26: for (nrow--; nrow >= 0; nrow--) 27: if ((base [nrow] = (short *) calloc (ncol, sizeof (short))) == 0) Error (); 28: 29: return (base); 30: } 31: 32: ScreenWrite (screen, str, flags, length) 33: /* 34: Writes str into buf at row row and column col. Characters are set to match flags. 35: */ 36: Screen *screen; 37: register char *str; 38: unsigned flags; 39: register int length; /* length of string */ 40: { 41: register short mask = 0; 42: register short *row = screen->buf [screen->cur_row]; 43: register short *col = row + screen->cur_col; 44: register int avail = screen->max_col - screen->cur_col + 1; 45: if (length > avail) 46: length = avail; 47: if (length <= 0) return; 48: 49: if (flags & INVERSE) mask |= INVERSEbit; 50: if (flags & BOLD) mask |= BOLDbit; 51: 52: if (mask) 53: do { *col++ = *str++ | mask; } while (--length > 0); 54: else 55: do { *col++ = *str++; } while (--length > 0); 56: } 57: 58: char *ScrnGetChars (sb, row, col, max, ptr, flags) 59: /* 60: Stores characters from sb at row, col into *ptr. At most max 61: characters are stored; will stop if the characters in sb do not match 62: the characteristics of flags. Returns the number of characters actually 63: stored + ptr. 64: 65: Requires max + col - 1 <= the maximum size of a row in sb. 66: max >= 0 67: */ 68: ScrnBuf sb; 69: int row, col; 70: register int max; 71: register char *ptr; 72: unsigned int flags; 73: { 74: register short mask = 0; 75: register short *fetch = sb [row] + col; 76: 77: if (flags & INVERSE) mask |= INVERSEbit; 78: if (flags & BOLD) mask |= BOLDbit; 79: 80: while (((*fetch & (short) 0xff00) == mask) && (max-- > 0)) 81: { 82: if (*fetch == 0) *fetch = (short) ' '; 83: *(ptr++) = (char) (*(fetch++) & (short) 0xff); 84: } 85: 86: return (ptr); 87: } 88: 89: ScrnInsertLine (sb, last, where, n, size) 90: /* 91: Inserts n blank lines at sb + where, treating last as a bottom margin. 92: Size is the size of each entry in sb. 93: Requires: 0 <= where < where + n <= last 94: n <= MAX_ROWS 95: */ 96: register ScrnBuf sb; 97: int last; 98: register int where, n, size; 99: { 100: register int i; 101: register short *save [MAX_ROWS]; 102: int length = size * sizeof (short); 103: 104: /* save n lines at bottom */ 105: bcopy ((char *) &sb [last - n + 1], (char *) save, 106: n * sizeof (short *)); 107: 108: /* clear contents of old rows */ 109: for (i = 0; i < n; i++) 110: bzero ((char *) save [i], length); 111: 112: /* move down lines */ 113: bcopy ((char *) &sb [where], (char *) &sb [where + n], 114: (last - where - n + 1) * sizeof (short *)); 115: 116: /* reuse storage for new lines at where */ 117: bcopy ((char *) save, (char *) &sb [where], n * sizeof (short *)); 118: } 119: 120: 121: ScrnDeleteLine (sb, last, where, n, size) 122: /* 123: Deletes n lines at sb + where, treating last as a bottom margin. 124: Size is the size of each entry in sb. 125: Requires 0 <= where < where + n < = last 126: n <= MAX_ROWS 127: */ 128: register ScrnBuf sb; 129: register int n, last, size; 130: int where; 131: { 132: register int i; 133: register short *save [MAX_ROWS]; 134: int length = size * sizeof (short); 135: 136: /* save n lines at where */ 137: bcopy ((char *) &sb [where], (char *) save, n * sizeof (short *)); 138: 139: /* clear contents of old rows */ 140: for (i = 0; i < n; i++) 141: bzero ((char *) save [i], length); 142: 143: /* move up lines */ 144: bcopy ((char *) &sb [where + n], (char *) &sb [where], 145: (last - where - n + 1) * sizeof (short *)); 146: 147: /* reuse storage for new bottom lines */ 148: bcopy ((char *) save, (char *) &sb [last - n + 1], 149: n * sizeof (short *)); 150: } 151: 152: 153: ScrnInsertChar (sb, row, col, n, size) 154: /* 155: Inserts n blanks in sb at row, col. Size is the size of each row. 156: */ 157: ScrnBuf sb; 158: int row, size; 159: register int col, n; 160: { 161: register short *ptr = sb [row]; 162: register int i; 163: 164: for (i = size - 1; i >= col + n; i--) 165: ptr [i] = ptr [i - n]; 166: 167: bzero (ptr + col, n * sizeof (short)); 168: } 169: 170: 171: ScrnDeleteChar (sb, row, col, n, size) 172: /* 173: Deletes n characters in sb at row, col. Size is the size of each row. 174: */ 175: ScrnBuf sb; 176: register int row, size; 177: register int n, col; 178: { 179: register short *ptr = sb [row]; 180: register nbytes; 181: nbytes = (size - n - col) * sizeof (short); 182: 183: bcopy (ptr + col + n, ptr + col, nbytes); 184: bzero (ptr + size - n, n * sizeof (short)); 185: } 186: 187: 188: ScrnRefresh (screen, toprow, leftcol, nrows, ncols) 189: /* 190: Repaints the area enclosed by the parameters. 191: Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are 192: coordinates of characters in screen; 193: nrows and ncols positive. 194: */ 195: register Screen *screen; 196: int toprow, leftcol, nrows, ncols; 197: { 198: char str [MAX_COLS]; 199: int y = toprow * screen->f_height + screen->border; 200: register int row; 201: int maxrow = toprow + nrows - 1; 202: 203: for (row = toprow; row <= maxrow; y += screen->f_height, row++) 204: { 205: register short *chars = screen->buf [row]; 206: register int col = leftcol; 207: int maxcol = leftcol + ncols - 1; 208: int lastind, curind; 209: unsigned short flags; 210: int gxfunction; 211: Font fnt; 212: int x; 213: short s; 214: #ifdef JUMPSCROLL 215: curind = row - screen->scroll_amt; 216: if (curind < 0 || curind > screen->max_row) 217: continue; 218: chars = screen->buf [curind]; 219: #else 220: chars = screen->buf [row]; 221: #endif JUMPSCROLL 222: 223: while (col <= maxcol && ((s = (chars[col] & ~BOLDbit)) == 0 || 224: s == ' ')) 225: col++; 226: 227: while (col <= maxcol && ((s = (chars[maxcol] & ~BOLDbit)) == 0 || 228: s == ' ')) 229: maxcol--; 230: 231: if (col > maxcol) continue; 232: 233: flags = (chars [col] & ~CHAR); 234: 235: if (flags & BOLDbit) fnt = screen->fnt_bold; 236: else fnt = screen->fnt_norm; 237: 238: x = col * screen->f_width + screen->border; 239: lastind = curind = 0; 240: 241: for (; col <= maxcol; col++, curind++) 242: { 243: s = chars [col]; 244: 245: if ((s & ~CHAR) != flags) 246: { 247: if (flags & INVERSEbit) 248: XText (screen->window, x, y, &str[lastind], 249: curind-lastind, fnt, 250: screen->background, screen->foreground); 251: else 252: XText (screen->window, x, y, &str[lastind], 253: curind-lastind, fnt, 254: screen->foreground, screen->background); 255: 256: x += (curind - lastind) * screen->f_width; 257: 258: lastind = curind; 259: 260: flags = (s & ~CHAR); 261: 262: if (flags & BOLDbit) fnt = screen->fnt_bold; 263: else fnt = screen->fnt_norm; 264: } 265: 266: if ((str[curind] = (char) (s & CHAR)) == 0) str[curind] = ' '; 267: } 268: 269: if (flags & INVERSEbit) 270: XText (screen->window, x, y, &str[lastind], curind - lastind, 271: fnt, screen->background, screen->foreground); 272: else 273: XText (screen->window, x, y, &str[lastind], curind - lastind, 274: fnt, screen->foreground, screen->background); 275: } 276: } 277: 278: ClearBufRows (screen, first, last) 279: /* 280: Sets the rows first though last of the buffer of screen to spaces. 281: Requires first <= last; first, last are rows of screen->buf. 282: */ 283: register Screen *screen; 284: register int first, last; 285: { 286: while (first <= last) 287: bzero (screen->buf [first++], sizeof (short) * 288: (screen->max_col + 1)); 289: } 290: 291: ScreenResize (screen, width, height, flags) 292: /* 293: Resizes screen: 294: 1. If new window would have fractional characters, sets window size so as to discard fractional characters and returns -1. 295: Minimum screen size is 1 X 1. 296: Note that this causes another ExposeWindow event. 297: 2. Enlarges screen->buf if necessary. New space is appended to the bottom and to the right 298: 3. Reduces screen->buf if necessary. Old space is removed from the bottom and from the right 299: 4. Cursor is positioned as closely to its former position as possible 300: 5. Sets screen->max_row and screen->max_col to reflect new size 301: 6. Maintains the inner border. 302: 7. Clears origin mode and sets scrolling region to be entire screen. 303: 8. Returns 0 304: */ 305: register Screen *screen; 306: int width, height; 307: unsigned *flags; 308: { 309: register int rows, cols; 310: register int index; 311: register ScrnBuf sb = screen->buf; 312: double scale_x, scale_y; 313: #ifdef TIOCSWINSZ 314: struct winsize ws; 315: #endif 316: 317: /* round so that it is unlikely the screen will change size on */ 318: /* small mouse movements. */ 319: rows = (height + screen->f_height / 2 - 2 * screen->border) / 320: screen->f_height; 321: cols = (width + screen->f_width / 2 - 2 * screen->border) / 322: screen->f_width; 323: if (rows < 1) rows = 1; 324: if (cols < 1) cols = 1; 325: 326: if ((width - screen->border * 2) % screen->f_width != 0 || 327: (height - screen->border * 2) % screen->f_height != 0) { 328: int nwidth = cols * screen->f_width + screen->border * 2; 329: int nheight = rows * screen->f_height + screen->border * 2; 330: 331: XChangeWindow (screen->window, nwidth, nheight); 332: return (-1); 333: } 334: 335: /* don't change anything if the screen has not changed size */ 336: if (screen->max_row == rows - 1 && screen->max_col == cols - 1) 337: return (0); 338: 339: /* resize current lines */ 340: if (sb) for (index = 0; index <= screen->max_row; index++) { 341: if ((sb [index] = (short *) realloc ((char *) sb [index], 342: cols * sizeof (short))) == NULL) Error (); 343: if (cols > (screen->max_col + 1)) 344: bzero (sb [index] + screen->max_col + 1, 345: sizeof(short) *(cols - (screen->max_col + 1))); 346: } 347: 348: /* discard excess bottom rows */ 349: for (index = rows; index <= screen->max_row; index++) 350: free (sb [index]); 351: 352: /* resize sb */ 353: if (sb == NULL) 354: sb = (ScrnBuf) malloc (rows * sizeof (short *)); 355: else 356: sb = (ScrnBuf) realloc (sb, rows * sizeof (short *)); 357: if (sb == NULL) 358: Error (); 359: screen->buf = sb; 360: 361: /* create additional bottom rows as required */ 362: for (index = screen->max_row + 1; index < rows; index++) 363: if ((sb [index] = (short *) calloc (cols, sizeof (short))) == NULL) 364: Error (); 365: 366: screen->max_row = rows - 1; 367: screen->max_col = cols - 1; 368: 369: /* adjust scrolling region */ 370: screen->top_marg = 0; 371: screen->bot_marg = screen->max_row; 372: *flags &= ~ORIGIN; 373: 374: if (screen->cur_row > screen->max_row) 375: screen->cur_row = screen->max_row; 376: if (screen->cur_col > screen->max_col) 377: screen->cur_col = screen->max_col; 378: 379: screen->height = height - 2 * screen->border; 380: screen->width = width - 2 * screen->border; 381: 382: /* Set Tektronix scale factor */ 383: scale_x = screen->width / 4096.0; 384: scale_y = screen->height / 3128.0; 385: screen->TekScale = (scale_x < scale_y) ? scale_x : scale_y; 386: 387: #ifdef TIOCSWINSZ 388: /* Set tty's idea of window size */ 389: ws.ws_row = rows; 390: ws.ws_col = cols; 391: ws.ws_xpixel = width; 392: ws.ws_ypixel = height; 393: ioctl (screen->respond, TIOCSWINSZ, &ws); 394: #endif 395: return (0); 396: }