|
|
1.1 root 1: /*
2: * $Source: /orpheus/u1/X11/clients/xterm/RCS/screen.c,v $
3: * $Header: screen.c,v 1.9 87/08/13 16:02:42 guarino Exp $
4: */
5:
6: #include <X11/copyright.h>
7:
8: /*
9: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
10: *
11: * All Rights Reserved
12: *
13: * Permission to use, copy, modify, and distribute this software and its
14: * documentation for any purpose and without fee is hereby granted,
15: * provided that the above copyright notice appear in all copies and that
16: * both that copyright notice and this permission notice appear in
17: * supporting documentation, and that the name of Digital Equipment
18: * Corporation not be used in advertising or publicity pertaining to
19: * distribution of the software without specific, written prior permission.
20: *
21: *
22: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
23: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
24: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
25: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
26: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
27: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28: * SOFTWARE.
29: */
30:
31: /* screen.c */
32:
33: #ifndef lint
34: static char rcs_id[] = "$Header: screen.c,v 1.9 87/08/13 16:02:42 guarino Exp $";
35: #endif lint
36:
37: #include <X11/Xlib.h>
38: #include <stdio.h>
39: #include <sys/ioctl.h>
40: #include <signal.h>
41: #include "ptyx.h"
42: #include "error.h"
43:
44: extern char *calloc();
45: extern char *malloc();
46: extern char *realloc();
47: extern void bcopy();
48: extern void free();
49:
50: ScrnBuf Allocate (nrow, ncol)
51: /*
52: allocates memory for a 2-dimensional array of chars and returns a pointer
53: thereto
54: each line is formed from a pair of char arrays. The first (even) one is
55: the actual character array and the second (odd) one is the attributes.
56: */
57: register int nrow, ncol;
58: {
59: register ScrnBuf base;
60:
61: if ((base = (ScrnBuf) calloc ((unsigned)(nrow *= 2), sizeof (char *))) == 0)
62: SysError (ERROR_SCALLOC);
63:
64: for (nrow--; nrow >= 0; nrow--)
65: if ((base [nrow] = calloc ((unsigned)ncol, sizeof(char))) == 0)
66: SysError (ERROR_SCALLOC2);
67:
68: return (base);
69: }
70:
71: ScreenWrite (screen, str, flags, length)
72: /*
73: Writes str into buf at row row and column col. Characters are set to match
74: flags.
75: */
76: TScreen *screen;
77: char *str;
78: register unsigned flags;
79: register int length; /* length of string */
80: {
81: register char *att;
82: register int avail = screen->max_col - screen->cur_col + 1;
83: register char *col;
84:
85: if (length > avail)
86: length = avail;
87: if (length <= 0)
88: return;
89:
90: col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col;
91: att = screen->buf[avail + 1] + screen->cur_col;
92: flags &= ATTRIBUTES;
93: bcopy(str, col, length);
94: while(length-- > 0)
95: *att++ = flags;
96: }
97:
98: ScrnInsertLine (sb, last, where, n, size)
99: /*
100: Inserts n blank lines at sb + where, treating last as a bottom margin.
101: Size is the size of each entry in sb.
102: Requires: 0 <= where < where + n <= last
103: n <= MAX_ROWS
104: */
105: register ScrnBuf sb;
106: int last;
107: register int where, n, size;
108: {
109: register int i;
110: char *save [2 * MAX_ROWS];
111:
112: /* save n lines at bottom */
113: bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save,
114: 2 * sizeof (char *) * n);
115:
116: /* clear contents of old rows */
117: for (i = 2 * n - 1; i >= 0; i--)
118: bzero ((char *) save [i], size);
119:
120: /* move down lines */
121: bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)],
122: 2 * sizeof (char *) * (last - where));
123:
124: /* reuse storage for new lines at where */
125: bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n);
126: }
127:
128:
129: ScrnDeleteLine (sb, last, where, n, size)
130: /*
131: Deletes n lines at sb + where, treating last as a bottom margin.
132: Size is the size of each entry in sb.
133: Requires 0 <= where < where + n < = last
134: n <= MAX_ROWS
135: */
136: register ScrnBuf sb;
137: register int n, last, size;
138: int where;
139: {
140: register int i;
141: char *save [2 * MAX_ROWS];
142:
143: /* save n lines at where */
144: bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n);
145:
146: /* clear contents of old rows */
147: for (i = 2 * n - 1 ; i >= 0 ; i--)
148: bzero ((char *) save [i], size);
149:
150: /* move up lines */
151: bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where],
152: 2 * sizeof (char *) * ((last -= n - 1) - where));
153:
154: /* reuse storage for new bottom lines */
155: bcopy ((char *)save, (char *) &sb[2 * last],
156: 2 * sizeof(char *) * n);
157: }
158:
159:
160: ScrnInsertChar (sb, row, col, n, size)
161: /*
162: Inserts n blanks in sb at row, col. Size is the size of each row.
163: */
164: ScrnBuf sb;
165: int row, size;
166: register int col, n;
167: {
168: register int i, j;
169: register char *ptr = sb [2 * row];
170: register char *att = sb [2 * row + 1];
171:
172: for (i = size - 1; i >= col + n; i--) {
173: ptr[i] = ptr[j = i - n];
174: att[i] = att[j];
175: }
176:
177: bzero (ptr + col, n);
178: bzero (att + col, n);
179: }
180:
181:
182: ScrnDeleteChar (sb, row, col, n, size)
183: /*
184: Deletes n characters in sb at row, col. Size is the size of each row.
185: */
186: ScrnBuf sb;
187: register int row, size;
188: register int n, col;
189: {
190: register char *ptr = sb[2 * row];
191: register char *att = sb[2 * row + 1];
192: register nbytes = (size - n - col);
193:
194: bcopy (ptr + col + n, ptr + col, nbytes);
195: bcopy (att + col + n, att + col, nbytes);
196: bzero (ptr + size - n, n);
197: bzero (att + size - n, n);
198: }
199:
200:
201: ScrnRefresh (screen, toprow, leftcol, nrows, ncols)
202: /*
203: Repaints the area enclosed by the parameters.
204: Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are
205: coordinates of characters in screen;
206: nrows and ncols positive.
207: */
208: register TScreen *screen;
209: int toprow, leftcol, nrows, ncols;
210: {
211: int y = toprow * FontHeight(screen) + screen->border +
212: screen->fnt_norm->max_bounds.ascent;
213: register int row;
214: register int topline = screen->topline;
215: int maxrow = toprow + nrows - 1;
216: int scrollamt = screen->scroll_amt;
217: int max = screen->max_row;
218:
219:
220: if(screen->cursor_col >= leftcol && screen->cursor_col <=
221: (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline &&
222: screen->cursor_row <= maxrow + topline)
223: screen->cursor_state = OFF;
224: for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) {
225: register char *chars;
226: register char *att;
227: register int col = leftcol;
228: int maxcol = leftcol + ncols - 1;
229: int lastind;
230: int flags;
231: int x, n;
232: GC gc;
233:
234: lastind = row - scrollamt;
235: if (lastind < 0 || lastind > max)
236: continue;
237: chars = screen->buf [2 * (lastind + topline)];
238: att = screen->buf [2 * (lastind + topline) + 1];
239:
240: while (col <= maxcol && (att[col] & ~BOLD) == 0 &&
241: (chars[col] & ~040) == 0)
242: col++;
243:
244: while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 &&
245: (chars[maxcol] & ~040) == 0)
246: maxcol--;
247:
248: if (col > maxcol) continue;
249:
250: flags = att[col];
251:
252: if ((flags & INVERSE) != 0)
253: if (flags & BOLD) gc = screen->reverseboldGC;
254: else gc = screen->reverseGC;
255: else
256: if (flags & BOLD) gc = screen->normalboldGC;
257: else gc = screen->normalGC;
258:
259: x = CursorX(screen, col);
260: lastind = col;
261:
262: for (; col <= maxcol; col++) {
263: if (att[col] != flags) {
264: XDrawImageString(screen->display, TextWindow(screen),
265: gc, x, y, &chars[lastind], n = col - lastind);
266: if((flags & BOLD) && screen->enbolden)
267: XDrawString(screen->display, TextWindow(screen),
268: gc, x + 1, y, &chars[lastind], n);
269: if(flags & UNDERLINE)
270: XDrawLine(screen->display, TextWindow(screen),
271: gc, x, y+1, x+n*FontWidth(screen), y+1);
272:
273: x += (col - lastind) * FontWidth(screen);
274:
275: lastind = col;
276:
277: flags = att[col];
278:
279: if ((flags & INVERSE) != 0)
280: if (flags & BOLD) gc = screen->reverseboldGC;
281: else gc = screen->reverseGC;
282: else
283: if (flags & BOLD) gc = screen->normalboldGC;
284: else gc = screen->normalGC;
285: }
286:
287: if(chars[col] == 0)
288: chars[col] = ' ';
289: }
290:
291:
292: if ((flags & INVERSE) != 0)
293: if (flags & BOLD) gc = screen->reverseboldGC;
294: else gc = screen->reverseGC;
295: else
296: if (flags & BOLD) gc = screen->normalboldGC;
297: else gc = screen->normalGC;
298: XDrawImageString(screen->display, TextWindow(screen), gc,
299: x, y, &chars[lastind], n = col - lastind);
300: if((flags & BOLD) && screen->enbolden)
301: XDrawString(screen->display, TextWindow(screen), gc,
302: x + 1, y, &chars[lastind], n);
303: if(flags & UNDERLINE)
304: XDrawLine(screen->display, TextWindow(screen), gc,
305: x, y+1, x + n * FontWidth(screen), y+1);
306: }
307: }
308:
309: ClearBufRows (screen, first, last)
310: /*
311: Sets the rows first though last of the buffer of screen to spaces.
312: Requires first <= last; first, last are rows of screen->buf.
313: */
314: register TScreen *screen;
315: register int first, last;
316: {
317: first *= 2;
318: last = 2 * last + 1;
319: while (first <= last)
320: bzero (screen->buf [first++], (screen->max_col + 1));
321: }
322:
323: ScreenResize (screen, width, height, flags)
324: /*
325: Resizes screen:
326: 1. If new window would have fractional characters, sets window size so as to
327: discard fractional characters and returns -1.
328: Minimum screen size is 1 X 1.
329: Note that this causes another ExposeWindow event.
330: 2. Enlarges screen->buf if necessary. New space is appended to the bottom
331: and to the right
332: 3. Reduces screen->buf if necessary. Old space is removed from the bottom
333: and from the right
334: 4. Cursor is positioned as closely to its former position as possible
335: 5. Sets screen->max_row and screen->max_col to reflect new size
336: 6. Maintains the inner border.
337: 7. Clears origin mode and sets scrolling region to be entire screen.
338: 8. Returns 0
339: */
340: register TScreen *screen;
341: int width, height;
342: unsigned *flags;
343: {
344: register int rows, cols;
345: register int index;
346: register int savelines;
347: register ScrnBuf sb = screen->allbuf;
348: register ScrnBuf ab = screen->altbuf;
349: register int x;
350: register int border = 2 * screen->border;
351: register int i, j, k;
352: #ifdef sun
353: #ifdef TIOCSSIZE
354: struct ttysize ts;
355: #endif TIOCSSIZE
356: #else sun
357: #ifdef TIOCSWINSZ
358: struct winsize ws;
359: #endif TIOCSWINSZ
360: #endif sun
361:
362: /* round so that it is unlikely the screen will change size on */
363: /* small mouse movements. */
364: rows = (height + FontHeight(screen) / 2 - border) /
365: FontHeight(screen);
366: cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) /
367: FontWidth(screen);
368: if (rows < 1) rows = 1;
369: if (cols < 1) cols = 1;
370:
371: if ((width - border - screen->scrollbar) % FontWidth(screen)
372: != 0 || (height - border) % FontHeight(screen) != 0) {
373: XResizeWindow(
374: screen->display,
375: TextWindow(screen),
376: (unsigned) cols * FontWidth(screen) + border
377: + screen->scrollbar,
378: (unsigned) rows * FontHeight(screen) + border);
379: return (-1);
380: }
381:
382: /* change buffers if the screen has changed size */
383: if (screen->max_row != rows - 1 || screen->max_col != cols - 1) {
384: if(screen->cursor_state)
385: HideCursor();
386: savelines = screen->scrollWindow ? screen->savelines : 0;
387: j = screen->max_col + 1;
388: i = cols - j;
389: k = screen->max_row;
390: if(rows < k)
391: k = rows;
392: if(ab) {
393: /* resize current lines in alternate buf */
394: for (index = x = 0; index <= k; x += 2, index++) {
395: if ((ab[x] = realloc(ab[x], (unsigned) cols)) == NULL)
396: SysError(ERROR_SREALLOC);
397: if((ab[x + 1] = realloc(ab[x + 1], (unsigned) cols)) ==
398: NULL)
399: SysError (ERROR_SREALLOC2);
400: if (cols > j) {
401: bzero (ab [x] + j, i);
402: bzero (ab [x + 1] + j, i);
403: }
404: }
405: /* discard excess bottom rows in alt buf */
406: for (index = rows, x = 2 * k ; index <=
407: screen->max_row; x += 2, index++) {
408: free (ab [x]);
409: free (ab [x + 1]);
410: }
411: }
412: /* resize current lines */
413: k += savelines;
414: for (index = x = 0; index <= k; x += 2, index++) {
415: if ((sb[x] = realloc(sb[x], (unsigned) cols)) == NULL)
416: SysError(ERROR_SREALLOC3);
417: if((sb[x + 1] = realloc(sb[x + 1], (unsigned) cols)) == NULL)
418: SysError (ERROR_SREALLOC4);
419: if (cols > j) {
420: bzero (sb [x] + j, i);
421: bzero (sb [x + 1] + j, i);
422: }
423: }
424: /* discard excess bottom rows */
425: for (index = rows, x = 2 * k; index <= screen->max_row;
426: x += 2, index++) {
427: free (sb [x]);
428: free (sb [x + 1]);
429: }
430: if(ab) {
431: if((ab = (ScrnBuf)realloc((char *)ab,
432: (unsigned) 2 * sizeof(char *) * rows)) == NULL)
433: SysError (ERROR_RESIZE);
434: screen->altbuf = ab;
435: }
436: k = 2 * (rows + savelines);
437: /* resize sb */
438: if((sb = (ScrnBuf)realloc((char *) sb, (unsigned) k * sizeof(char *)))
439: == NULL)
440: SysError (ERROR_RESIZE2);
441: screen->allbuf = sb;
442: screen->buf = &sb[2 * savelines];
443:
444: if(ab) {
445: /* create additional bottom rows as required in alt */
446: for (index = screen->max_row + 1, x = 2 * index ;
447: index < rows; x += 2, index++) {
448: if((ab[x] = calloc ((unsigned) cols, sizeof(char))) == NULL)
449: SysError(ERROR_RESIZROW);
450: if((ab[x + 1] = calloc ((unsigned) cols, sizeof(char))) == NULL)
451: SysError(ERROR_RESIZROW2);
452: }
453: }
454: /* create additional bottom rows as required */
455: for (index = screen->max_row + 1, x = 2 * (index + savelines) ;
456: index < rows; x += 2, index++) {
457: if((sb[x] = calloc ((unsigned) cols, sizeof(char))) == NULL)
458: SysError(ERROR_RESIZROW3);
459: if((sb[x + 1] = calloc ((unsigned) cols, sizeof(char))) == NULL)
460: SysError(ERROR_RESIZROW4);
461: }
462:
463: screen->max_row = rows - 1;
464: screen->max_col = cols - 1;
465:
466: /* adjust scrolling region */
467: screen->top_marg = 0;
468: screen->bot_marg = screen->max_row;
469: *flags &= ~ORIGIN;
470:
471: if (screen->cur_row > screen->max_row)
472: screen->cur_row = screen->max_row;
473: if (screen->cur_col > screen->max_col)
474: screen->cur_col = screen->max_col;
475:
476: screen->fullVwin.height = height - border;
477: screen->fullVwin.width = width - border - screen->scrollbar;
478:
479: } else if(FullHeight(screen) == height && FullWidth(screen) == width)
480: return(0); /* nothing has changed at all */
481:
482: if(screen->scrollWindow)
483: ResizeScrollBar(screen->scrollWindow, -1, -1, height);
484:
485: screen->fullVwin.fullheight = height;
486: screen->fullVwin.fullwidth = width;
487: #ifdef sun
488: #ifdef TIOCSSIZE
489: /* Set tty's idea of window size */
490: ts.ts_lines = rows;
491: ts.ts_cols = cols;
492: ioctl (screen->respond, TIOCSSIZE, &ts);
493: #ifdef SIGWINCH
494: if(screen->pid > 1)
495: killpg(getpgrp(screen->pid), SIGWINCH);
496: #endif SIGWINCH
497: #endif TIOCSSIZE
498: #else sun
499: #ifdef TIOCSWINSZ
500: /* Set tty's idea of window size */
501: ws.ws_row = rows;
502: ws.ws_col = cols;
503: ws.ws_xpixel = width;
504: ws.ws_ypixel = height;
505: ioctl (screen->respond, TIOCSWINSZ, (char *)&ws);
506: #ifdef SIGWINCH
507: if(screen->pid > 1)
508: killpg(getpgrp((int)screen->pid), SIGWINCH);
509: #endif SIGWINCH
510: #endif TIOCSWINSZ
511: #endif sun
512: return (0);
513: }
514:
515:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.