|
|
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;
}