2
/* This file holds the functions for manipulating video memory */
9
/* This function returns a pointer to a video memory area of ints.
10
Integers are used to encode both the characters and the flags.
11
If this function fails, it should be a fatal error. Allocated
12
memory is not freed if the function fails.
15
int **alloc_video(rows, cols)
22
/* Allocate row pointers */
23
if ( (videomem=(int **)malloc(rows*sizeof(int *))) == NULL )
26
/* Allocate the columns for each row */
27
for ( i=0; i<rows; ++i ) {
28
if ( (videomem[i]=(int *)malloc(cols*sizeof(int))) == NULL )
30
for ( j=0; j<cols; ++j )
36
/* This function copies an existing window to a new buffer,
37
truncating lines if necessary, and translates the cursor position */
38
void copy_video(win, newarea, rows, cols, newcursor)
47
/* Copy from the bottom up... */
49
for ( i=win->rows, ni=rows; i && ni; --i, --ni ) {
50
if ( win->cursor.x == i ) {
51
if ( (newcursor->x=(i+rows-win->rows)) < 1 )
54
for ( j=0, nj=0; (j<win->cols) && (nj<cols); ++j, ++nj )
55
newarea[ni-1][nj]=win->videomem[i-1][j];
57
if ( ! newcursor->x ) /* We never reached the old cursor */
59
newcursor->y=(win->cursor.y > cols ? cols : win->cursor.y);
62
/* This function adds a character to the video memory at the cursor position */
63
void add_video(win, c)
67
win->videomem[win->cursor.x - 1][win->cursor.y - 1] = (int)c;
68
win->videomem[win->cursor.x - 1][win->cursor.y - 1] |=
69
(((int)win->textattr)<<8);
72
/* This function returns a character from video at a specific position */
73
int get_video(win, x, y)
77
return(win->videomem[x-1][y-1]);
80
/* This function sets a character position in video memory */
81
void put_video(c, win, x, y)
86
win->videomem[x-1][y-1]=c;
89
/* This function returns the array index of the end of the specified line
90
in the specified window. lineno should start as 1 for the first line.
92
static int video_eol(win, lineno)
98
for ( j=0; j<win->cols; ++j ) {
99
if ( (win->videomem[lineno-1][j]&0xFF) != 0 )
106
/* This function copies a specified section of video memory to a buffer */
107
/* x1 is the first line, x2 is the second line, y1 is the y on the first
108
line, and y2 is the y on the last line.
110
void getsel_video(win, buf, maxlen, x1, x2, y1, y2)
117
int l=0, i, j, eol, eos;
119
--maxlen; /* Account for trailing null */
120
for ( i=(x1-1); (i<x2 && l<maxlen); ++i ) {
121
eol=video_eol(win, i+1);
128
eos=((y2-1) < eol ? (y2-1) : eol);
129
for ( ; j<eos; ++j ) {
130
if ( (win->videomem[i][j]&0xFF) == '\0' )
133
*(buf++) = (win->videomem[i][j]&0xFF);
136
if ( l<maxlen && j >= eol ) {
145
/* This function clears the SELECTED bit in a whole window */
146
void clrsel_video(win)
151
for ( i=0; i<win->rows; ++i ) {
152
for ( j=0; j<win->cols; ++j ) {
153
if ( ((win->videomem[i][j]>>8)&SELECTED) == SELECTED )
154
win->videomem[i][j] &= ~(SELECTED<<8);
159
/* This function erases a specified section of video memory */
160
void erase_video(win, x1, x2, y1, y2)
167
for ( i=(x1-1); i<x2; ++i ) {
168
for ( j=(y1-1); j<y2; ++j )
169
win->videomem[i][j] = 0;
174
/* This function "scrolls" video memory forward */
175
void scroll_video(win, numlines)
181
/* Don't scroll memory if cursor is outside of scroll region */
182
if ( win->cursor.x > win->scr_lower )
185
/* Otherwise, scroll away! */
186
for ( i=0; i<numlines; ++i ) {
187
/* Clear out the line that has been scrolled off the edge */
188
tmp=win->videomem[win->scr_upper-1];
189
for ( n=0; n<win->cols; ++n )
192
/* Now perform the scroll */
193
for ( n=(win->scr_upper-1); n<(win->scr_lower-1); ++n )
194
win->videomem[n]=win->videomem[n+1];
195
win->videomem[n]=tmp;
201
/* This function "scrolls" video memory backward */
202
void revscroll_video(win, numlines)
208
/* Don't scroll memory if cursor is outside of scroll region */
209
if ( win->cursor.x < win->scr_upper )
212
/* Otherwise, scroll away! */
213
for ( i=0; i<numlines; ++i ) {
214
/* Clear out the line that has been scrolled off the edge */
215
tmp=win->videomem[win->scr_lower-1];
216
for ( n=0; n<win->cols; ++n )
219
/* Now perform the scroll */
220
for ( n=(win->scr_lower-1); n>(win->scr_upper-1); --n )
221
win->videomem[n]=win->videomem[n-1];
222
win->videomem[n]=tmp;
228
/* This function inserts nulls in a line, shifting everything right */
229
void rshift_video(win, numcols)
235
for ( i=(win->cols-1); i > (win->cursor.y-1); --i ) {
236
if ( (i-numcols) >= 0 )
237
win->videomem[win->cursor.x-1][i] =
238
win->videomem[win->cursor.x-1][i-numcols];
240
win->videomem[win->cursor.x-1][i] = 0;
244
int check_attr(pixel, lastattr, currattr)
247
unsigned char *currattr;
249
unsigned char simplepixel, lastpixel;
250
unsigned char change;
251
unsigned char selected, reversed;
253
/* Set the simplepixel REVERSE bit if SELECTED ^ REVERSE */
254
simplepixel = ((pixel>>8)&(~SELECTED)&(~REVERSE));
255
selected = ( ((pixel>>8)&(~SELECTED)) ? 1 : 0 );
256
reversed = ( ((pixel>>8)&(~REVERSE)) ? 1 : 0 );
257
if ( selected ^ reversed )
258
simplepixel |= REVERSE;
260
/* Set the lastpixel REVERSE bit if SELECTED ^ REVERSE */
261
lastpixel = ((lastattr>>8)&(~SELECTED)&(~REVERSE));
262
selected = ( ((lastattr>>8)&(~SELECTED)) ? 1 : 0 );
263
reversed = ( ((lastattr>>8)&(~REVERSE)) ? 1 : 0 );
264
if ( selected ^ reversed )
265
lastpixel |= REVERSE;
267
/* Thanks to Dan Dorough for the XOR code */
269
change = (lastpixel ^ simplepixel);
271
if ( change&REVERSE ) {
272
if ( (*currattr)&REVERSE ) {
273
#define GOTO_HACK /* vt_reverse(0) doesn't work on xterms :-( */
274
#ifdef GOTO_HACK /* This goto hack resets all current attributes */
276
*currattr &= ~REVERSE;
278
lastpixel &= (~REVERSE);
280
#else /* ideal code */
282
*currattr &= ~REVERSE;
286
*currattr |= REVERSE;
290
if ( (*currattr)&BOLD ) {
298
if ( change&UNDERLINE ) {
299
if ( (*currattr)&UNDERLINE ) {
301
*currattr &= ~UNDERLINE;
304
*currattr |= UNDERLINE;
307
if ( change&BLINK ) {
308
if ( (*currattr)&BLINK ) {
320
void paint_video(win)
323
unsigned char change, on=NORMAL;
328
vt_goto(1+win->row_offset, 1);
329
for ( i=0; i<win->rows; ++i ) {
330
for ( j=0; j<win->cols; ++j ) {
331
if ( win->videomem[i][j]&0xFF ) {
332
oldattr=check_attr(win->videomem[i][j],
334
printf("%c", (win->videomem[i][j]&0xFF));
337
if ( on != NORMAL ) {
345
vt_down(1); /* This shouldn't cause scroll */
347
vt_setscroll(win->scr_upper+win->row_offset,
348
win->scr_lower+win->row_offset);
349
vt_goto(win->cursor.x+win->row_offset, win->cursor.y);