|
|
1.1 root 1: /*
2: * $Source: /u1/X/xterm/RCS/screen.c,v $
3: * $Header: screen.c,v 10.100 86/12/01 14:45:17 jg Rel $
4: */
5:
6: #include <X/mit-copyright.h>
7:
8: /* Copyright Massachusetts Institute of Technology 1984, 1985 */
9:
10: /* screen.c */
11:
12: #ifndef lint
13: static char csrg_id[] = "@(#)screen.c 1.6\t(Berkeley/CSRG)\t9/21/87";
14: static char sccs_id[] = "@(#)screen.c\tX10/6.6B\t12/26/86";
15: #endif lint
16:
17: #include <X/Xlib.h>
18: #include <stdio.h>
19: #include <sys/ioctl.h>
20: #include <signal.h>
21: #include "scrollbar.h"
22: #include "ptyx.h"
23: #include "error.h"
24:
25: extern char *calloc();
26: extern char *malloc();
27: extern char *realloc();
28:
29: ScrnBuf Allocate (nrow, ncol)
30: /*
31: allocates memory for a 2-dimensional array of chars and returns a pointer
32: thereto
33: each line is formed from a pair of char arrays. The first (even) one is
34: the actual character array and the second (odd) one is the attributes.
35: */
36: register int nrow, ncol;
37: {
38: register ScrnBuf base;
39:
40: if ((base = (ScrnBuf) calloc ((nrow *= 2), sizeof (char *))) == 0)
41: SysError (ERROR_SCALLOC);
42:
43: for (nrow--; nrow >= 0; nrow--)
44: if ((base [nrow] = calloc (ncol, sizeof(char))) == 0)
45: SysError (ERROR_SCALLOC2);
46:
47: return (base);
48: }
49:
50: ScreenWrite (screen, str, flags, length)
51: /*
52: Writes str into buf at row row and column col. Characters are set to match
53: flags.
54: */
55: Screen *screen;
56: char *str;
57: register unsigned flags;
58: register int length; /* length of string */
59: {
60: register char *att;
61: register int avail = screen->max_col - screen->cur_col + 1;
62: register char *col;
63:
64: if (length > avail)
65: length = avail;
66: if (length <= 0)
67: return;
68:
69: col = screen->buf[avail = 2 * screen->cur_row] + screen->cur_col;
70: att = screen->buf[avail + 1] + screen->cur_col;
71: flags &= ATTRIBUTES;
72: bcopy(str, col, length);
73: while(length-- > 0)
74: *att++ = flags;
75: }
76:
77: ScrnInsertLine (sb, last, where, n, size)
78: /*
79: Inserts n blank lines at sb + where, treating last as a bottom margin.
80: Size is the size of each entry in sb.
81: Requires: 0 <= where < where + n <= last
82: n <= MAX_ROWS
83: */
84: register ScrnBuf sb;
85: int last;
86: register int where, n, size;
87: {
88: register int i;
89: char *save [2 * MAX_ROWS];
90:
91: /* save n lines at bottom */
92: bcopy ((char *) &sb [2 * (last -= n - 1)], (char *) save,
93: 2 * sizeof (char *) * n);
94:
95: /* clear contents of old rows */
96: for (i = 2 * n - 1; i >= 0; i--)
97: bzero ((char *) save [i], size);
98:
99: /* move down lines */
100: bcopy ((char *) &sb [2 * where], (char *) &sb [2 * (where + n)],
101: 2 * sizeof (char *) * (last - where));
102:
103: /* reuse storage for new lines at where */
104: bcopy ((char *)save, (char *) &sb[2 * where], 2 * sizeof(char *) * n);
105: }
106:
107:
108: ScrnDeleteLine (sb, last, where, n, size)
109: /*
110: Deletes n lines at sb + where, treating last as a bottom margin.
111: Size is the size of each entry in sb.
112: Requires 0 <= where < where + n < = last
113: n <= MAX_ROWS
114: */
115: register ScrnBuf sb;
116: register int n, last, size;
117: int where;
118: {
119: register int i;
120: char *save [2 * MAX_ROWS];
121:
122: /* save n lines at where */
123: bcopy ((char *) &sb[2 * where], (char *)save, 2 * sizeof(char *) * n);
124:
125: /* clear contents of old rows */
126: for (i = 2 * n - 1 ; i >= 0 ; i--)
127: bzero ((char *) save [i], size);
128:
129: /* move up lines */
130: bcopy ((char *) &sb[2 * (where + n)], (char *) &sb[2 * where],
131: 2 * sizeof (char *) * ((last -= n - 1) - where));
132:
133: /* reuse storage for new bottom lines */
134: bcopy ((char *)save, (char *) &sb[2 * last],
135: 2 * sizeof(char *) * n);
136: }
137:
138:
139: ScrnInsertChar (sb, row, col, n, size)
140: /*
141: Inserts n blanks in sb at row, col. Size is the size of each row.
142: */
143: ScrnBuf sb;
144: int row, size;
145: register int col, n;
146: {
147: register int i, j;
148: register char *ptr = sb [2 * row];
149: register char *att = sb [2 * row + 1];
150:
151: for (i = size - 1; i >= col + n; i--) {
152: ptr[i] = ptr[j = i - n];
153: att[i] = att[j];
154: }
155:
156: bzero (ptr + col, n);
157: bzero (att + col, n);
158: }
159:
160:
161: ScrnDeleteChar (sb, row, col, n, size)
162: /*
163: Deletes n characters in sb at row, col. Size is the size of each row.
164: */
165: ScrnBuf sb;
166: register int row, size;
167: register int n, col;
168: {
169: register char *ptr = sb[2 * row];
170: register char *att = sb[2 * row + 1];
171: register nbytes = (size - n - col);
172:
173: bcopy (ptr + col + n, ptr + col, nbytes);
174: bcopy (att + col + n, att + col, nbytes);
175: bzero (ptr + size - n, n);
176: bzero (att + size - n, n);
177: }
178:
179:
180: ScrnRefresh (screen, toprow, leftcol, nrows, ncols)
181: /*
182: Repaints the area enclosed by the parameters.
183: Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are
184: coordinates of characters in screen;
185: nrows and ncols positive.
186: */
187: register Screen *screen;
188: int toprow, leftcol, nrows, ncols;
189: {
190: int y = toprow * FontHeight(screen) + screen->border + Titlebar(screen);
191: register int row;
192: register int topline = screen->topline;
193: int maxrow = toprow + nrows - 1;
194: int scrollamt = screen->scroll_amt;
195: int max = screen->max_row;
196: int dostatus = 0, left, width;
197:
198:
199: if(screen->statusline && maxrow == screen->max_row + 1) {
200: dostatus++;
201: maxrow--;
202: }
203: if(screen->cursor_col >= leftcol && screen->cursor_col <=
204: (leftcol + ncols - 1) && screen->cursor_row >= toprow + topline &&
205: screen->cursor_row <= maxrow + topline)
206: screen->cursor_state = OFF;
207: for( ; ; ) {
208: for (row = toprow; row <= maxrow; y += FontHeight(screen), row++)
209: {
210: register char *chars;
211: register char *att;
212: register int col = leftcol;
213: int maxcol = leftcol + ncols - 1;
214: int lastind;
215: int flags;
216: int gxfunction;
217: Font fnt;
218: int x, yb, pix, n;
219:
220: lastind = row - scrollamt;
221: if (lastind < 0 || lastind > max)
222: continue;
223: chars = screen->buf [2 * (lastind + topline)];
224: att = screen->buf [2 * (lastind + topline) + 1];
225:
226: while (col <= maxcol && (att[col] & ~BOLD) == 0 &&
227: (chars[col] & ~040) == 0)
228: col++;
229:
230: while (col <= maxcol && (att[maxcol] & ~BOLD) == 0 &&
231: (chars[maxcol] & ~040) == 0)
232: maxcol--;
233:
234: if (col > maxcol) continue;
235:
236: flags = att[col];
237:
238: fnt = ActiveIcon(screen)
239: ? screen->fnt_icon
240: : (flags & BOLD)
241: ? screen->fnt_bold
242: : screen->fnt_norm;
243:
244: x = col * FontWidth(screen) + screen->border;
245: lastind = col;
246:
247: for (; col <= maxcol; col++) {
248: if (att[col] != flags) {
249: if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
250: screen->reversestatus))
251: XText (VWindow(screen), x, y, &chars[lastind],
252: n = col - lastind, fnt,
253: pix = screen->background, screen->foreground);
254: else
255: XText (VWindow(screen), x, y, &chars[lastind],
256: n = col - lastind, fnt,
257: pix = screen->foreground, screen->background);
258: if((flags & BOLD) && screen->enbolden)
259: XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
260: n, fnt, pix);
261: if(flags & UNDERLINE) {
262: yb = y + FontHeight(screen) - 2;
263: XLine(VWindow(screen), x, yb, x + n * FontWidth(screen),
264: yb, 1, 1, pix, GXcopy, AllPlanes);
265: }
266:
267: x += (col - lastind) * FontWidth(screen);
268:
269: lastind = col;
270:
271: flags = att[col];
272:
273: fnt = ActiveIcon(screen)
274: ? screen->fnt_icon
275: : (flags & BOLD)
276: ? screen->fnt_bold
277: : screen->fnt_norm;
278: }
279:
280: if(chars[col] == 0)
281: chars[col] = ' ';
282: }
283:
284: if (((flags & INVERSE) != 0) ^ (dostatus < 0 &&
285: screen->reversestatus))
286: XText (VWindow(screen), x, y, &chars[lastind],
287: n = col - lastind, fnt, pix = screen->background,
288: screen->foreground);
289: else
290: XText (VWindow(screen), x, y, &chars[lastind],
291: n = col - lastind, fnt, pix = screen->foreground,
292: screen->background);
293: if((flags & BOLD) && screen->enbolden)
294: XTextMask (VWindow(screen), x + 1, y, &chars[lastind],
295: n, fnt, pix);
296: if(flags & UNDERLINE) {
297: yb = y + FontHeight(screen) - 2;
298: XLine(VWindow(screen), x, yb, x + n * FontWidth(screen), yb, 1, 1,
299: pix, GXcopy, AllPlanes);
300: }
301: }
302: if(dostatus <= 0)
303: break;
304: dostatus = -1;
305: topline = 0;
306: scrollamt = 0;
307: toprow = maxrow = max = screen->max_row + 1;
308: left = leftcol * FontWidth(screen) + screen->border;
309: width = ncols * FontWidth(screen);
310: if(leftcol == 0) {
311: left--;
312: width++;
313: }
314: if(leftcol + ncols - 1 >= screen->max_col)
315: width++;
316: XPixSet(VWindow(screen), left, y, width, screen->statusheight,
317: screen->reversestatus ? screen->foreground : screen->background);
318: if(!screen->reversestatus)
319: StatusBox(screen);
320: y++;
321: }
322: }
323:
324: ClearBufRows (screen, first, last)
325: /*
326: Sets the rows first though last of the buffer of screen to spaces.
327: Requires first <= last; first, last are rows of screen->buf.
328: */
329: register Screen *screen;
330: register int first, last;
331: {
332: first *= 2;
333: last = 2 * last + 1;
334: while (first <= last)
335: bzero (screen->buf [first++], (screen->max_col + 1));
336: }
337:
338: ScreenResize (screen, width, height, flags)
339: /*
340: Resizes screen:
341: 1. If new window would have fractional characters, sets window size so as to
342: discard fractional characters and returns -1.
343: Minimum screen size is 1 X 1.
344: Note that this causes another ExposeWindow event.
345: 2. Enlarges screen->buf if necessary. New space is appended to the bottom
346: and to the right
347: 3. Reduces screen->buf if necessary. Old space is removed from the bottom
348: and from the right
349: 4. Cursor is positioned as closely to its former position as possible
350: 5. Sets screen->max_row and screen->max_col to reflect new size
351: 6. Maintains the inner border.
352: 7. Clears origin mode and sets scrolling region to be entire screen.
353: 8. Returns 0
354: */
355: register Screen *screen;
356: int width, height;
357: unsigned *flags;
358: {
359: register int rows, cols;
360: register int index;
361: register int savelines;
362: register ScrnBuf sb = screen->allbuf;
363: register ScrnBuf ab = screen->altbuf;
364: register int x;
365: register int border = 2 * screen->border;
366: register int extra, i, j, k;
367: register char *sl0, *sl1; /* keep status line */
368: double scale_x, scale_y;
369: #ifdef TIOCSWINSZ
370: struct winsize ws;
371: #endif TIOCSWINSZ
372:
373:
374: /* don't resize on icon exposure */
375: if (ActiveIcon(screen))
376: return( 0 );
377:
378: extra = Titlebar(screen) + screen->statusheight;
379: /* round so that it is unlikely the screen will change size on */
380: /* small mouse movements. */
381: rows = (height + FontHeight(screen) / 2 - border - extra) /
382: FontHeight(screen);
383: cols = (width + FontWidth(screen) / 2 - border - screen->scrollbar) /
384: FontWidth(screen);
385: if (rows < 1) rows = 1;
386: if (cols < 1) cols = 1;
387:
388: if ((width - border - screen->scrollbar) % FontWidth(screen)
389: != 0 || (height - border - extra) % FontHeight(screen) != 0 ||
390: rows < screen->minrows) {
391: XChangeWindow (VWindow(screen),
392: cols * FontWidth(screen) + border + screen->scrollbar,
393: (rows < screen->minrows ? screen->minrows : rows) *
394: FontHeight(screen) + border + extra);
395: return (-1);
396: }
397:
398: /* change buffers if the screen has changed size */
399: if (screen->max_row != rows - 1 || screen->max_col != cols - 1) {
400: if(screen->cursor_state)
401: HideCursor();
402: savelines = screen->sb ? screen->savelines : 0;
403: j = screen->max_col + 1;
404: i = cols - j;
405: k = screen->max_row;
406: if(ab) {
407: /* resize current lines in alternate buf */
408: for (index = x = 0; index <= k; x += 2, index++) {
409: if ((ab[x] = realloc(ab[x], cols)) == NULL)
410: SysError(ERROR_SREALLOC);
411: if((ab[x + 1] = realloc(ab[x + 1], cols)) ==
412: NULL)
413: SysError (ERROR_SREALLOC2);
414: if (cols > j) {
415: bzero (ab [x] + j, i);
416: bzero (ab [x + 1] + j, i);
417: }
418: }
419: }
420: /* resize current lines */
421: k += savelines + 1; /* includes status line */
422: for (index = x = 0; index <= k; x += 2, index++) {
423: if ((sb[x] = realloc(sb[x], cols)) == NULL)
424: SysError(ERROR_SREALLOC3);
425: if((sb[x + 1] = realloc(sb[x + 1], cols)) == NULL)
426: SysError (ERROR_SREALLOC4);
427: if (cols > j) {
428: bzero (sb [x] + j, i);
429: bzero (sb [x + 1] + j, i);
430: }
431: }
432:
433: /*
434: * Adjust the number of lines, either discarding the
435: * oldest (if we're getting shorter) or padding at
436: * the "old" end with blanks (if we're getting taller.
437: *
438: * Throughout this section, i is the number of lines
439: * we need, j is the number we currently have & index
440: * is the difference.
441: */
442: i = rows + savelines + 1;
443: j = screen->max_row + savelines + 2;
444: index = j - i;
445: if (index > 0) {
446: /* we're getting shorter - free the oldest lines */
447: for (x = 0; x < 2*index; ) {
448: free (sb[x++]);
449: }
450: /* move the newer stuff into the right place */
451: k = i * 2 * sizeof(*sb);
452: bcopy (&sb[2*index], sb, k);
453: sb = (ScrnBuf) realloc (sb, k);
454: if (! sb)
455: SysError (ERROR_RESIZE2);
456:
457: /* do the same thing for the alternate buf */
458: if (ab) {
459: for (x = 0; x < 2*index;) {
460: free (ab[x++]);
461: }
462: k = (screen->max_row + 1)* sizeof(*sb);
463: bcopy (&ab[2*index], ab, k);
464: ab = (ScrnBuf) realloc (ab, k);
465: if (! ab)
466: SysError (ERROR_RESIZE);
467: }
468: }
469: else if (index < 0) {
470: /* we're getting taller - add 'index' lines */
471: /* at the "old" end of the saved lines */
472: sb = (ScrnBuf) realloc (sb, i * 2 * sizeof(*sb));
473: if (! sb)
474: SysError (ERROR_RESIZE2);
475:
476: /* move up the stuff we want at the new end */
477: /* of the buffer and fill the hole with blanks */
478: k = -2 * index;
479: bcopy (sb, &sb[k], j * 2 * sizeof(*sb));
480:
481: for (x = 0; x < k; ) {
482: if (! (sb[x++] = calloc (cols, sizeof(**sb))))
483: SysError(ERROR_RESIZROW3);
484: }
485:
486: /* do the same thing with the alternate buffer */
487: if (ab) {
488: ab = (ScrnBuf) realloc (ab, rows*2*sizeof(*ab));
489: if (! ab)
490: SysError (ERROR_RESIZE);
491:
492: bcopy (ab, &ab[k], (screen->max_row + 1) *
493: 2 * sizeof(*ab));
494: for (x = 0; x < k; ) {
495: if (! (ab[x++] = calloc (cols,
496: sizeof(**ab))))
497: SysError(ERROR_RESIZROW4);
498: }
499: }
500: }
501: screen->allbuf = sb;
502: screen->buf = &sb[2 * savelines];
503: screen->altbuf = ab;
504:
505: /* add the new lines to the old screen size & pos */
506: screen->max_row -= index;
507: if (! screen->instatus)
508: screen->cur_row -= index;
509: else
510: screen->cur_row = screen->max_row + 1;
511:
512: screen->max_row = rows - 1;
513: screen->max_col = cols - 1;
514:
515: /* adjust scrolling region */
516: screen->top_marg = 0;
517: screen->bot_marg = screen->max_row;
518: *flags &= ~ORIGIN;
519:
520: if (screen->cur_row > screen->max_row)
521: screen->cur_row = screen->max_row;
522: else if (screen->cur_row < 0)
523: screen->cur_row = 0;
524: if (screen->cur_col > screen->max_col)
525: screen->cur_col = screen->max_col;
526: else if (screen->cur_col < 0)
527: screen->cur_col = 0;
528:
529: screen->fullVwin.height = height - extra;
530: screen->fullVwin.width = width;
531:
532: if (screen->active_icon)
533: SetIconSize( screen );
534:
535: }
536: else if(FullHeight(screen) == height && FullWidth(screen) == width)
537: return(0); /* nothing has changed at all */
538:
539: if(screen->sb)
540: ResizeScrollBar(screen->sb, width - SCROLLBARWIDTH,
541: Titlebar(screen) - 1, height - Titlebar(screen), rows);
542: if(screen->title.tbar && FullWidth(screen) != width)
543: VTTitleResize(width);
544:
545: screen->fullVwin.fullheight = height;
546: screen->fullVwin.fullwidth = width;
547: #ifdef TIOCSWINSZ
548: /* Set tty's idea of window size */
549: ws.ws_row = rows;
550: ws.ws_col = cols;
551: ws.ws_xpixel = width;
552: ws.ws_ypixel = height;
553: ioctl (screen->respond, TIOCSWINSZ, &ws);
554: #ifdef SIGWINCH
555: if(screen->pid > 1)
556: killpg(getpgrp(screen->pid), SIGWINCH);
557: #endif SIGWINCH
558: #endif TIOCSWINSZ
559: return (0);
560: }
561:
562:
563: SetIconSize( screen )
564: Screen *screen;
565: {
566: if (screen->active_icon) {
567: screen->iconVwin.width = (screen->max_col + 1)
568: * screen->iconVwin.f_width
569: + screen->border * 2;
570: screen->iconVwin.height = (screen->max_row + 1)
571: * screen->iconVwin.f_height
572: + screen->border * 2;
573: XChangeWindow( screen->iconVwin.window,
574: screen->iconVwin.width,
575: screen->iconVwin.height );
576: } else {
577: IconRecalc( screen );
578: }
579:
580: screen->iconVwin.fullwidth = screen->iconVwin.width;
581: screen->iconVwin.fullheight = screen->iconVwin.height;
582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.