home *** CD-ROM | disk | FTP | other *** search
- /*
- * $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.6B\t12/26/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;
- 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;
- }
- /* save status line */
- sl0 = sb[i = 2 * (savelines + screen->max_row + 1)];
- sl1 = sb[i + 1];
- 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 = 2 * (rows + savelines)] = 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;
- }
-