|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 15361 (0x3c01) Types: TextFile Names: »screen.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─⟦this⟧ »./X.V10R4/xterm/screen.c«
/* * $Source: /u1/X/xterm/RCS/screen.c,v $ * $Header: screen.c,v 10.100 86/12/01 14:45:17 jg Rel $ */ #include <X/mit-copyright.h> /* Copyright Massachusetts Institute of Technology 1984, 1985 */ /* screen.c */ #ifndef lint static char sccs_id[] = "@(#)screen.c\tX10/6.6\t11/3/86"; #endif lint #include <X/Xlib.h> #include <stdio.h> #include <sys/ioctl.h> #include <signal.h> #include "scrollbar.h" #include "ptyx.h" #include "error.h" extern char *calloc(); extern char *malloc(); extern char *realloc(); ScrnBuf Allocate (nrow, ncol) /* allocates memory for a 2-dimensional array of chars and returns a pointer thereto each line is formed from a pair of char arrays. The first (even) one is the actual character array and the second (odd) one is the attributes. */ register int nrow, ncol; { register ScrnBuf base; if ((base = (ScrnBuf) calloc ((nrow *= 2), sizeof (char *))) == 0) SysError (ERROR_SCALLOC); for (nrow--; nrow >= 0; nrow--) if ((base [nrow] = calloc (ncol, sizeof(char))) == 0) SysError (ERROR_SCALLOC2); return (base); } ScreenWrite (screen, str, flags, length) /* Writes str into buf at row row and column col. Characters are set to match flags. */ Screen *screen; char *str; register unsigned flags; register int length; /* length of string */ { register char *att; register int avail = screen->max_col - screen->cur_col + 1; register char *col; if (length > avail) length = avail; if (length <= 0) return; col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col; att = screen->buf[avail + 1] + screen->cur_col; flags &= ATTRIBUTES; bcopy(str, col, length); while(length-- > 0) *att++ = flags; } ScrnInsertLine (sb, last, where, n, size) /* Inserts n blank lines at sb + where, treating last as a bottom margin. Size is the size of each entry in sb. Requires: 0 <= where < where + n <= last n <= MAX_ROWS */ register ScrnBuf sb; int last; register int where, n, size; { register int i; char *save [2 * MAX_ROWS]; /* save n lines at bottom */ bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save, 2 * sizeof (char *) * n); /* clear contents of old rows */ for (i = 2 * n - 1; i >= 0; i--) bzero ((char *) save [i], size); /* move down lines */ bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)], 2 * sizeof (char *) * (last - where)); /* reuse storage for new lines at where */ bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n); } ScrnDeleteLine (sb, last, where, n, size) /* Deletes n lines at sb + where, treating last as a bottom margin. Size is the size of each entry in sb. Requires 0 <= where < where + n < = last n <= MAX_ROWS */ register ScrnBuf sb; register int n, last, size; int where; { register int i; char *save [2 * MAX_ROWS]; /* save n lines at where */ bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n); /* clear contents of old rows */ for (i = 2 * n - 1 ; i >= 0 ; i--) bzero ((char *) save [i], size); /* move up lines */ bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where], 2 * sizeof (char *) * ((last -= n - 1) - where)); /* reuse storage for new bottom lines */ bcopy ((char *)save, (char *) &sb[2 * last], 2 * sizeof(char *) * n); } ScrnInsertChar (sb, row, col, n, size) /* Inserts n blanks in sb at row, col. Size is the size of each row. */ ScrnBuf sb; int row, size; register int col, n; { register int i, j; register char *ptr = sb [2 * row]; register char *att = sb [2 * row + 1]; for (i = size - 1; i >= col + n; i--) { ptr[i] = ptr[j = i - n]; att[i] = att[j]; } bzero (ptr + col, n); bzero (att + col, n); } ScrnDeleteChar (sb, row, col, n, size) /* Deletes n characters in sb at row, col. Size is the size of each row. */ ScrnBuf sb; register int row, size; register int n, col; { register char *ptr = sb[2 * row]; register char *att = sb[2 * row + 1]; register nbytes = (size - n - col); bcopy (ptr + col + n, ptr + col, nbytes); bcopy (att + col + n, att + col, nbytes); bzero (ptr + size - n, n); bzero (att + size - n, n); } ScrnRefresh (screen, toprow, leftcol, nrows, ncols) /* Repaints the area enclosed by the parameters. Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are coordinates of characters in screen; nrows and ncols positive. */ register Screen *screen; int toprow, leftcol, nrows, ncols; { int y = toprow * FontHeight(screen) + screen->border + Titlebar(screen); register int row; register int topline = screen->topline; int maxrow = toprow + nrows - 1; int scrollamt = screen->scroll_amt; int max = screen->max_row; int dostatus = 0, left, width; if(screen->statusline && maxrow == screen->max_row + 1) { dostatus++; maxrow--; } if(screen->cursor_col >= leftcol && screen->cursor_col <= (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline && screen->cursor_row <= maxrow + topline) screen->cursor_state = OFF; for( ; ; ) { for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) { register char *chars; register char *att; register int col = leftcol; int maxcol = leftcol + ncols - 1; int lastind; int flags; int gxfunction; Font fnt; int x, yb, pix, n; lastind = row - scrollamt; if (lastind < 0 || lastind > max) continue; chars = screen->buf [2 * (lastind + topline)]; att = screen->buf [2 * (lastind + topline) + 1]; while (col <= maxcol && (att[col] & ~BOLD) == 0 && (chars[col] & ~040) == 0) col++; while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 && (chars[maxcol] & ~040) == 0) maxcol--; if (col > maxcol) continue; flags = att[col]; fnt = ActiveIcon(screen) ? screen->fnt_icon : (flags & BOLD) ? screen->fnt_bold : screen->fnt_norm; x = col * FontWidth(screen) + screen->border; lastind = col; for (; col <= maxcol; col++) { if (att[col] != flags) { if (((flags & INVERSE) != 0) ^ (dostatus < 0 && screen->reversestatus)) XText (VWindow(screen), x, y, &chars[lastind], n = col - lastind, fnt, pix = screen->background, screen->foreground); else XText (VWindow(screen), x, y, &chars[lastind], n = col - lastind, fnt, pix = screen->foreground, screen->background); if((flags & BOLD) && screen->enbolden) XTextMask (VWindow(screen), x + 1, y, &chars[lastind], n, fnt, pix); if(flags & UNDERLINE) { yb = y + FontHeight(screen) - 2; XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1, pix, GXcopy, AllPlanes); } x += (col - lastind) * FontWidth(screen); lastind = col; flags = att[col]; fnt = ActiveIcon(screen) ? screen->fnt_icon : (flags & BOLD) ? screen->fnt_bold : screen->fnt_norm; } if(chars[col] == 0) chars[col] = ' '; } if (((flags & INVERSE) != 0) ^ (dostatus < 0 && screen->reversestatus)) XText (VWindow(screen), x, y, &chars[lastind], n = col - lastind, fnt, pix = screen->background, screen->foreground); else XText (VWindow(screen), x, y, &chars[lastind], n = col - lastind, fnt, pix = screen->foreground, screen->background); if((flags & BOLD) && screen->enbolden) XTextMask (VWindow(screen), x + 1, y, &chars[lastind], n, fnt, pix); if(flags & UNDERLINE) { yb = y + FontHeight(screen) - 2; XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1, pix, GXcopy, AllPlanes); } } if(dostatus <= 0) break; dostatus = -1; topline = 0; scrollamt = 0; toprow = maxrow = max = screen->max_row + 1; left = leftcol * FontWidth(screen) + screen->border; width = ncols * FontWidth(screen); if(leftcol == 0) { left--; width++; } if(leftcol + ncols - 1 >= screen->max_col) width++; XPixSet(VWindow(screen), left, y, width, screen->statusheight, screen->reversestatus ? screen->foreground : screen->background); if(!screen->reversestatus) StatusBox(screen); y++; } } ClearBufRows (screen, first, last) /* Sets the rows first though last of the buffer of screen to spaces. Requires first <= last; first, last are rows of screen->buf. */ register Screen *screen; register int first, last; { first *= 2; last = 2 * last + 1; while (first <= last) bzero (screen->buf [first++], (screen->max_col + 1)); } ScreenResize (screen, width, height, flags) /* Resizes screen: 1. If new window would have fractional characters, sets window size so as to discard fractional characters and returns -1. Minimum screen size is 1 X 1. Note that this causes another ExposeWindow event. 2. Enlarges screen->buf if necessary. New space is appended to the bottom and to the right 3. Reduces screen->buf if necessary. Old space is removed from the bottom and from the right 4. Cursor is positioned as closely to its former position as possible 5. Sets screen->max_row and screen->max_col to reflect new size 6. Maintains the inner border. 7. Clears origin mode and sets scrolling region to be entire screen. 8. Returns 0 */ register Screen *screen; int width, height; unsigned *flags; { register int rows, cols; register int index; register int savelines; register ScrnBuf sb = screen->allbuf; register ScrnBuf ab = screen->altbuf; register int x; register int border = 2 * screen->border; register int extra, i, j, k; register char *sl0, *sl1; /* keep status line */ double scale_x, scale_y; #ifdef sun #ifdef TIOCSSIZE struct ttysize ts; #endif TIOCSSIZE #else sun #ifdef TIOCSWINSZ struct winsize ws; #endif TIOCSWINSZ #endif sun if (ActiveIcon(screen)) return( 0 ); /* don't resize on icon exposure */ extra = Titlebar(screen) + screen->statusheight; /* round so that it is unlikely the screen will change size on */ /* small mouse movements. */ rows = (height + FontHeight(screen) / 2 - border - extra) / FontHeight(screen); cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) / FontWidth(screen); if (rows < 1) rows = 1; if (cols < 1) cols = 1; if ((width - border - screen->scrollbar) % FontWidth(screen) != 0 || (height - border - extra) % FontHeight(screen) != 0 || rows < screen->minrows) { XChangeWindow (VWindow(screen), cols * FontWidth(screen) + border + screen->scrollbar, (rows < screen->minrows ? screen->minrows : rows) * FontHeight(screen) + border + extra); return (-1); } /* change buffers if the screen has changed size */ if (screen->max_row != rows - 1 || screen->max_col != cols - 1) { if(screen->cursor_state) HideCursor(); savelines = screen->sb ? screen->savelines : 0; /* save status line */ sl0 = sb[i = 2 * (savelines + screen->max_row + 1)]; sl1 = sb[i + 1]; j = screen->max_col + 1; i = cols - j; k = screen->max_row; if(rows < k) k = rows; if(ab) { /* resize current lines in alternate buf */ for (index = x = 0; index <= k; x += 2, index++) { if ((ab[x] = realloc(ab[x], cols)) == NULL) SysError(ERROR_SREALLOC); if((ab[x + 1] = realloc(ab[x + 1], cols)) == NULL) SysError (ERROR_SREALLOC2); if (cols > j) { bzero (ab [x] + j, i); bzero (ab [x + 1] + j, i); } } /* discard excess bottom rows in alt buf */ for (index = rows, x = 2 * k ; index <= screen->max_row; x += 2, index++) { free (ab [x]); free (ab [x + 1]); } } /* resize current lines */ k += savelines + 1; /* includes status line */ for (index = x = 0; index <= k; x += 2, index++) { if ((sb[x] = realloc(sb[x], cols)) == NULL) SysError(ERROR_SREALLOC3); if((sb[x + 1] = realloc(sb[x + 1], cols)) == NULL) SysError (ERROR_SREALLOC4); if (cols > j) { bzero (sb [x] + j, i); bzero (sb [x + 1] + j, i); } } /* discard excess bottom rows, but not status line */ for (index = rows, x = 2 * (k - 1); index <= screen->max_row; x += 2, index++) { free (sb [x]); free (sb [x + 1]); } if(ab) { if((ab = (ScrnBuf)realloc(ab, 2 * sizeof(char *) * rows)) == NULL) SysError (ERROR_RESIZE); screen->altbuf = ab; } k = 2 * (rows + savelines + 1); /* includes status line */ /* resize sb */ if((sb = (ScrnBuf)realloc(sb, k * sizeof(char *))) == NULL) SysError (ERROR_RESIZE2); screen->allbuf = sb; screen->buf = &sb[2 * savelines]; if(ab) { /* create additional bottom rows as required in alt */ for (index = screen->max_row + 1, x = 2 * index ; index < rows; x += 2, index++) { if((ab[x] = calloc (cols, sizeof(char))) == NULL) SysError(ERROR_RESIZROW); if((ab[x + 1] = calloc (cols, sizeof(char))) == NULL) SysError(ERROR_RESIZROW2); } } /* create additional bottom rows as required */ for (index = screen->max_row + 1, x = 2 * (index + savelines) ; index < rows; x += 2, index++) { if((sb[x] = calloc (cols, sizeof(char))) == NULL) SysError(ERROR_RESIZROW3); if((sb[x + 1] = calloc (cols, sizeof(char))) == NULL) SysError(ERROR_RESIZROW4); } /* reinstall status line */ sb[x] = sl0; sb[x + 1] = sl1; screen->max_row = rows - 1; screen->max_col = cols - 1; /* adjust scrolling region */ screen->top_marg = 0; screen->bot_marg = screen->max_row; *flags &= ~ORIGIN; if (screen->instatus) screen->cur_row = screen->max_row + 1; else if (screen->cur_row > screen->max_row) screen->cur_row = screen->max_row; if (screen->cur_col > screen->max_col) screen->cur_col = screen->max_col; screen->fullVwin.height = height - border - extra; screen->fullVwin.width = width - border - screen->scrollbar; if (screen->active_icon) SetIconSize( screen ); } else if(FullHeight(screen) == height && FullWidth(screen) == width) return(0); /* nothing has changed at all */ if(screen->sb) ResizeScrollBar(screen->sb, width - SCROLLBARWIDTH, Titlebar(screen) - 1, height - Titlebar(screen), rows); if(screen->title.tbar && FullWidth(screen) != width) VTTitleResize(width); screen->fullVwin.fullheight = height; screen->fullVwin.fullwidth = width; #ifdef sun #ifdef TIOCSSIZE /* Set tty's idea of window size */ ts.ts_lines = rows; ts.ts_cols = cols; ioctl (screen->respond, TIOCSSIZE, &ts); #ifdef SIGWINCH if(screen->pid > 1) killpg(getpgrp(screen->pid), SIGWINCH); #endif SIGWINCH #endif TIOCSSIZE #else sun #ifdef TIOCSWINSZ /* Set tty's idea of window size */ ws.ws_row = rows; ws.ws_col = cols; ws.ws_xpixel = width; ws.ws_ypixel = height; ioctl (screen->respond, TIOCSWINSZ, &ws); #ifdef SIGWINCH if(screen->pid > 1) killpg(getpgrp(screen->pid), SIGWINCH); #endif SIGWINCH #endif TIOCSWINSZ #endif sun return (0); } SetIconSize( screen ) Screen *screen; { if (screen->active_icon) { screen->iconVwin.width = (screen->max_col + 1) * screen->iconVwin.f_width + screen->border * 2; screen->iconVwin.height = (screen->max_row + 1) * screen->iconVwin.f_height + screen->border * 2; XChangeWindow( screen->iconVwin.window, screen->iconVwin.width, screen->iconVwin.height ); } else { IconRecalc( screen ); } screen->iconVwin.fullwidth = screen->iconVwin.width; screen->iconVwin.fullheight = screen->iconVwin.height; }