|
|
1.1 root 1: /*
2: * Virtual terminal handler
3: * Written by Kenneth Almquist, AGS Computers (HO 4C601, X7105).
4: * Modified by Stephen Hemminger, to use TERMCAP (without curses)
5: */
6:
7: #ifdef SCCSID
8: static char *SccsId = "@(#)virtterm.c 1.10 1/17/86";
9: #endif /* SCCSID */
10:
11: /*LINTLIBRARY*/
12:
13: #include <stdio.h>
14: #include <ctype.h>
15: #include <sys/types.h>
16: #include <sys/ioctl.h>
17: #include <signal.h>
18: #ifdef USG
19: #include <termio.h>
20: #else /* !USG */
21: #include <sgtty.h>
22: #endif /* !USG */
23:
24: /*
25: * These values for MAXPLEN and MAXLLEN are used to dimension arrays
26: * that hold strings of relative cursor motions. The actual arrays that
27: * are used to hold screen images are malloc'd.
28: */
29: #define MAXPLEN 90
30: #define MAXLLEN 160
31:
32: #define BOTLINE (ROWS - 1)
33: #define DIRTY 01
34:
35: /* terminal escape sequences from termcap */
36: #define HO _tstr[0] /* home */
37: #define CL _tstr[1] /* clear screen */
38: #define CD _tstr[2] /* clear to end of screen */
39: #define CE _tstr[3] /* clear to end of line */
40: #define xUP _tstr[4] /* up one line */
41: #define DO _tstr[5] /* down one line */
42: #define US _tstr[6] /* underline */
43: #define UE _tstr[7] /* underline end */
44: #define BT _tstr[8] /* backtab */
45: #define xBC _tstr[9] /* backspace */
46: #define AL _tstr[10] /* insert line */
47: #define DL _tstr[11] /* delete line */
48: #define CM _tstr[12] /* cursor move */
49: #define CH _tstr[13] /* cursor horizontal move */
50: #define CV _tstr[14] /* cursor vertical move */
51: #define CS _tstr[15] /* scrolling region */
52: #define SF _tstr[16] /* scroll forwards */
53: #define SR _tstr[17] /* scroll backwards */
54: #define TI _tstr[18] /* start cursor mode */
55: #define TE _tstr[19] /* end cursor mode */
56: #define TA _tstr[20] /* tab char (if not \t) */
57: #define CR _tstr[21] /* carriage return (if not \r) */
58: #define xPC _tstr[22] /* for reading pad character */
59: char PC; /* pad character */
60: char *BC, *UP; /* external variables for tgoto */
61:
62: static char sname[] = "hoclcdceupdousuebtbcaldlcmchcvcssfsrtitetacrpc";
63: char *_tstr[23];
64: int HOlen; /* length of HO string */
65:
66:
67: /* terminal flags */
68: #define BS _tflg[0] /* can backspace */
69: #define AM _tflg[1] /* has auto margins */
70: #define XN _tflg[2] /* no newline after wrap */
71: #define RET !_tflg[3] /* has carriage return */
72: #define NS _tflg[4] /* has SF (scroll forward) */
73: #define PT _tflg[5] /* has tabs */
74: #define XT _tflg[6] /* tabs are destructive */
75: int GT = 1; /* tab stops on terminal are set */
76:
77: static char bname[] = "bsamxnncnsptxt";
78: char _tflg[7];
79:
80:
81: extern char *tgoto(), *tgetstr();
82: extern char *getenv(), *strcpy();
83:
84: #define ULINE 0200
85:
86: /* Constants accessable by user */
87: int hasscroll; /* scrolling type, 0 == no scrolling */
88: int ROWS; /* number of lines on screen */
89: int COLS; /* width of screen */
90:
91: struct line {
92: char len;
93: char flags;
94: char *l; /* pointer to actual line text, NO NULL @ end */
95: };
96:
97: int _row, _col;
98: int _srow, _scol;
99: struct line *_virt; /* what we want the screen to look like */
100: struct line *_actual; /* What it actually looks like */
101: int _uline = 0;
102: int _junked = 1;
103: int _curjunked;
104: int _dir = 1;
105: int _shifttop, _shiftbot;
106: int _shift;
107: int _scratched;
108: int vputc();
109:
110: /*
111: * Tell refresh to shift lines in region upwards count lines. Count
112: * may be negative. The virtual image is not shifted; this may change
113: * later. The variable _scratched is set to supress all attempts to
114: * shift.
115: */
116:
117: ushift(top, bot, count)
118: {
119: if (_scratched)
120: return;
121: if (_shift != 0 && (_shifttop != top || _shiftbot != bot)) {
122: _scratched++;
123: return;
124: }
125: _shifttop = top;
126: _shiftbot = bot;
127: _shift += count;
128: }
129:
130: /*
131: * generate a beep on the terminal
132: */
133: beep()
134: {
135: vputc('\7');
136: }
137:
138: /*
139: * Move to one line below the bottom of the screen.
140: */
141: botscreen()
142: {
143: _amove(BOTLINE, 0);
144: vputc('\n');
145: vflush();
146: }
147:
148: move(row, col)
149: {
150: if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
151: return;
152: _row = row;
153: _col = col;
154: }
155:
156:
157:
158: /*
159: * Output string at specified location.
160: */
161: mvaddstr(row, col, str)
162: char *str;
163: {
164: move(row, col);
165: addstr(str);
166: }
167:
168: addstr(s)
169: char *s;
170: {
171: register char *p;
172: register struct line *lp;
173: register int col = _col;
174:
175: lp = &_virt[_row];
176: if (lp->len < col) {
177: p = &lp->l[lp->len];
178: while (lp->len < col) {
179: *p++ = ' ';
180: lp->len++;
181: }
182: }
183: for (p = s; *p != '\0'; p++) {
184: if (*p == '\n') {
185: lp->len = col;
186: lp->flags |= DIRTY;
187: col = 0;
188: if (++_row >= ROWS)
189: _row = 0;
190: lp = &_virt[_row];
191: }
192: else {
193: lp->l[col] = *p;
194: lp->flags |= DIRTY;
195: if (++col >= COLS) {
196: lp->len = COLS;
197: col = 0;
198: if (++_row >= ROWS)
199: _row = 0;
200: lp = &_virt[_row];
201: }
202: }
203: }
204: if (lp->len <= col)
205: lp->len = col;
206: _col = col;
207: }
208:
209: addch(c)
210: {
211: register struct line *lp;
212: register char *p;
213:
214: lp = &_virt[_row];
215: if (lp->len < _col) {
216: p = &lp->l[lp->len];
217: while (lp->len < _col) {
218: *p++ = ' ';
219: lp->len++;
220: }
221: }
222: lp->l[_col] = c;
223: if (lp->len == _col)
224: lp->len++;
225: if (++_col >= COLS) {
226: _col = 0;
227: if (++_row >= ROWS)
228: _row = 0;
229: }
230: lp->flags |= DIRTY;
231: }
232:
233: /*
234: * Clear an entire line.
235: */
236: clrline(row)
237: {
238: register struct line *lp;
239:
240: lp = &_virt[row];
241: if (lp->len > 0) {
242: lp->len = 0;
243: lp->flags |= DIRTY;
244: }
245: }
246:
247: erase()
248: {
249: register i;
250:
251: for (i = 0; i < ROWS; i++) {
252: _virt[i].len = 0;
253: _virt[i].flags |= DIRTY;
254: }
255: }
256:
257: refresh()
258: {
259: register i;
260: register char *p, *q;
261: register int j, len;
262:
263: if (checkin())
264: return;
265: i = 1;
266: if (_junked) {
267: _sclear();
268: _junked = 0;
269: } else if (! _scratched) {
270: if (_shift > 0) {
271: _ushift(_shifttop, _shiftbot, _shift);
272: } else if (_shift < 0) {
273: i = _dshift(_shifttop, _shiftbot, -_shift);
274: } else {
275: i = _dir;
276: }
277: }
278: _dir = i;
279: _shift = 0;
280: if (checkin())
281: return;
282: _fixlines();
283: for (i = _dir > 0 ? 0 : BOTLINE; i >= 0 && i < ROWS; i += _dir) {
284: if ((_virt[i].flags & DIRTY) == 0)
285: continue;
286: _ckclrlin(i); /* decide whether to do a clear line */
287: /* probably should consider cd too */
288: len = _virt[i].len;
289: if (_actual[i].len < len)
290: len = _actual[i].len;
291: p = _virt[i].l;
292: q = _actual[i].l;
293: for (j = 0; j < len; j++) {
294: if (*p != *q) {
295: /* Inline test for speed */
296: if (i != _srow || j != _scol || _curjunked)
297: _amove(i, j);
298: _aputc(*p);
299: *q = *p;
300: }
301: p++;
302: q++;
303: }
304: len = _virt[i].len;
305: if (_actual[i].len > len) {
306: _clrtoeol(i, len);
307: } else {
308: for (; j < len; j++) {
309: if (*p != ' ') {
310: /* Inline test for speed */
311: if (i != _srow || j != _scol || _curjunked)
312: _amove(i, j);
313: _aputc(*p);
314: }
315: *q++ = *p++;
316: }
317: _actual[i].len = len;
318: }
319: if (checkin())
320: return;
321: }
322: _dir = 1;
323: _amove(_row, _col);
324: vflush(); /* flush output buffer */
325: _scratched = 0;
326: }
327:
328: _dshift(top, bot, count)
329: {
330: register i;
331:
332: if (count >= bot - top || hasscroll < 4) { /* must have CS or AL/DL */
333: _scratched++;
334: return 1;
335: }
336: for (i = bot - count; _actual[i].len == 0; i--)
337: if (i == top)
338: return 1;
339: for (i = top; i <= bot; i++)
340: _virt[i].flags |= DIRTY;
341: for (i = bot; i >= top + count; i--) {
342: /* FIXME, this should be done by recirculating the pointers */
343: register j;
344: j = _actual[i].len = _actual[i - count].len;
345: _actual[i].flags = _actual[i - count].flags;
346: strncpy(_actual[i].l, _actual[i - count].l, j);
347: }
348: for (; i >= top; i--)
349: _actual[i].len = 0;
350:
351: if (hasscroll != 5) { /* can we define scrolling region, and scroll back */
352: tputs(tgoto(CS, bot, top), 1, vputc);/* define scroll region */
353: _curjunked = 1;
354: _amove(top, 0);
355: for (i = count; --i >= 0;)
356: tputs(SR, 1, vputc);/* scroll back */
357: tputs(tgoto(CS, BOTLINE, 0), 1, vputc);
358: _curjunked = 1;
359: } else {
360: _amove(bot - count + 1, 0);
361: if (CD && bot == BOTLINE)
362: tputs(CD, 1, vputc);
363: else {
364: for (i = count; --i >= 0;)
365: tputs(DL, ROWS - _srow, vputc);
366: }
367: _amove(top, 0);
368: for (i = count; --i >= 0;)
369: tputs(AL, ROWS - _srow, vputc);
370: }
371: return -1;
372: }
373:
374:
375: _ushift(top, bot, count)
376: {
377: register i;
378:
379: if (count >= bot - top || hasscroll == 0) {
380: _scratched++;
381: return;
382: }
383: for (i = top + count; _actual[i].len == 0; i++)
384: if (i == bot)
385: return;
386: if (hasscroll == 1 || hasscroll == 3) {
387: /* we cheat and shift the entire screen */
388: /* be sure we are shifting more lines into than out of position */
389: if ((bot - top + 1) - count <= ROWS - (bot - top + 1))
390: return;
391: top = 0, bot = BOTLINE;
392: }
393: for (i = top; i <= bot; i++)
394: _virt[i].flags |= DIRTY;
395: for (i = top; i <= bot - count; i++) {
396: /* FIXME, this should be done by recirculating the pointers */
397: register int j;
398: j = _actual[i].len = _actual[i + count].len;
399: _actual[i].flags = _actual[i + count].flags;
400: strncpy(_actual[i].l, _actual[i + count].l, j);
401: }
402: for (; i <= bot; i++)
403: for (; i <= bot; i++)
404: _actual[i].len = 0;
405:
406: if (hasscroll != 5) {
407: if (top != 0 || bot != BOTLINE) {
408: tputs(tgoto(CS, bot, top), 0, vputc);
409: _curjunked = 1;
410: }
411: _amove(bot, 0); /* move to bottom */
412: for (i = 0; i < count; i++) {
413: if (SF) /* scroll forward */
414: tputs(SF, 1, vputc);
415: else
416: vputc('\n');
417: }
418: if (top != 0 || bot != BOTLINE) {
419: tputs(tgoto(CS, BOTLINE, 0), 0, vputc);
420: _curjunked = 1;
421: }
422: } else {
423: _amove(top, 0);
424: for (i = count; --i >= 0;)
425: tputs(DL, ROWS - _srow, vputc);
426: if (bot < BOTLINE) {
427: _amove(bot - count + 1, 0);
428: for (i = count; --i >= 0;)
429: tputs(AL, ROWS - _srow, vputc);
430: }
431: }
432: }
433:
434: _sclear()
435: {
436: register struct line *lp;
437:
438: tputs(CL, 0, vputc);
439: _srow = _scol = 0;
440: for (lp = _actual; lp < &_actual[ROWS]; lp++) {
441: lp->len = 0;
442: }
443: for (lp = _virt; lp < &_virt[ROWS]; lp++) {
444: if (lp->len != 0)
445: lp->flags |= DIRTY;
446: }
447: }
448:
449: _clrtoeol(row, col)
450: {
451: register struct line *lp = &_actual[row];
452: register i;
453:
454: if (CE && lp->len > col + 1) {
455: _amove(row, col);
456: tputs(CE, 1, vputc);
457: } else {
458: for (i = col ; i < lp->len ; i++) {
459: if (lp->l[i] != ' ') {
460: _amove(row, i);
461: _aputc(' ');
462: }
463: }
464: }
465: lp->len = col;
466: }
467:
468: _fixlines()
469: {
470: register struct line *lp;
471: register char *p;
472: register int i;
473:
474: for (i = 0; i < ROWS; i++) {
475: lp = &_virt[i];
476: if (lp->flags & DIRTY) {
477: for (p = &lp->l[lp->len]; --p >= lp->l && *p == ' ';)
478: ;
479: lp->len = (int) (p - lp->l) + 1;
480: if (lp->len == _actual[i].len && strncmp(lp->l, _actual[i].l, lp->len) == 0)
481: lp->flags &= ~DIRTY;
482: }
483: }
484: }
485:
486:
487: /*
488: * Consider clearing the line before overwriting it.
489: * We always clear a line if it has underlined characters in it
490: * because these can cause problems. Otherwise decide whether
491: * that will decrease the number of characters to change. This
492: * routine could probably be simplified with no great loss.
493: */
494:
495: _ckclrlin(i)
496: {
497: int eval;
498: int len;
499: int first;
500: register struct line *vp, *ap;
501: register int j;
502:
503: if (!CE)
504: return;
505: ap = &_actual[i];
506: vp = &_virt[i];
507: len = ap->len;
508: eval = -strlen(CE);
509: if (len > vp->len) {
510: len = vp->len;
511: eval = 0;
512: }
513: for (j = 0; j < len && vp->l[j] == ap->l[j]; j++)
514: ;
515: if (j == len)
516: return;
517: first = j;
518: while (j < len) {
519: if (vp->l[j] == ' ') {
520: if (ap->l[j] != ' ') {
521: while (++j < len && vp->l[j] == ' ' && ap->l[j] != ' ') {
522: eval++;
523: }
524: if (j == len)
525: eval++;
526: continue;
527: }
528: }
529: else {
530: if (vp->l[j] == ap->l[j]) {
531: while (++j < len && vp->l[j] == ap->l[j]) {
532: eval--;
533: }
534: continue;
535: }
536: }
537: j++;
538: }
539: if (US) {
540: for (j = 0 ; j < ap->len ; j++) {
541: if (ap->l[j] & ULINE) {
542: eval = 999;
543: if (first > j)
544: first = j;
545: break;
546: }
547: }
548: }
549: for (j = first; --j >= 0;)
550: if (vp->l[j] != ' ')
551: break;
552: if (j < 0)
553: first = 0;
554: if (eval > 0) {
555: _amove(i, first);
556: tputs(CE, 0, vputc);
557: _actual[i].len = first;
558: }
559: }
560:
561:
562:
563: /*
564: * Move routine
565: * first compute direct cursor address string and cost
566: * then relative motion string and cost,
567: * then home then relative and cost
568: * choose smallest and do it.
569: *
570: * The plod stuff is to build the strings (with padding) then decide
571: */
572: static char *plodstr; /* current location in relmove string */
573:
574: plodput(c)
575: {
576: *plodstr++ = c;
577: }
578:
579: /* FIXME: speedup 1-char horiz moves: print the char that's there. */
580: /* FIXME: avoid funniness if cm works. */
581: /* FIXME: Avoid setul(0) if cursor motion OK in standout (XM?) */
582: _amove(row, col)
583: {
584: char direct[20];
585: char rel[MAXPLEN*10 + MAXLLEN*10]; /* longest move is full screen */
586: char ho[MAXPLEN*10 + MAXLLEN*10];
587: int cost, newcost;
588: register char *movstr;
589:
590: if (row == _srow && col == _scol && _curjunked == 0)
591: return;
592: if (_uline)
593: _setul(0); /* Inline test for speed */
594:
595: cost = 999;
596: if (CM) {
597: plodstr = direct;
598: tputs(tgoto(CM, col, row), 0, plodput);
599: cost = plodstr - direct;
600: movstr = direct;
601: }
602: if (_curjunked == 0) {
603: plodstr = rel;
604: if (_vmove(_srow, row) >= 0
605: && (plodstr - rel) < cost /* after vmove */
606: && _hmove(_scol, col, row) >= 0
607: && (newcost = plodstr - rel) < cost) { /* after both */
608: cost = newcost;
609: movstr = rel;
610: }
611: }
612: if (cost > HOlen) { /* is it worth calculating */
613: plodstr = ho;
614: tputs(HO, 0, plodput);
615: if (_vmove(0, row) >= 0
616: && (plodstr - ho) < cost /* after ho, vmove */
617: && _hmove(0, col, row) >= 0
618: && (newcost = plodstr - ho) < cost) { /* after all three */
619: cost = newcost;
620: movstr = ho;
621: }
622: }
623:
624: if (cost < 999)
625: while (--cost >= 0)
626: vputc(*movstr++);
627:
628: _srow = row;
629: _scol = col;
630: _curjunked = 0;
631: }
632:
633: _vmove(orow, nrow)
634: {
635: char direct[128];
636: char *saveplod = plodstr;
637:
638: if (CV) {
639: plodstr = direct;
640: tputs(tgoto(CV, nrow, nrow), 0, plodput);
641: *plodstr = '\0';
642: plodstr = saveplod;
643: }
644: if (orow > nrow) { /* cursor up */
645: if (! UP)
646: return -1;
647: while (orow > nrow) {
648: tputs(UP, 1, plodput);
649: orow--;
650: }
651: }
652: while (orow < nrow) { /* cursor down */
653: if (DO)
654: tputs(DO, 1, plodput);
655: else
656: *plodstr++ = '\n';
657: orow++;
658: }
659: if (CV && plodstr - saveplod >= strlen(direct)) {
660: register char *p;
661: plodstr = saveplod;
662: for (p = direct ; *plodstr = *p++ ; plodstr++)
663: ;
664: }
665: return 0;
666: }
667:
668: _hmove(ocol, ncol, row)
669: {
670: char direct[128];
671: char ret[MAXLLEN*10];
672: char *saveplod = plodstr;
673: char *movstr;
674: int cost, newcost;
675:
676: cost = 999;
677: if (CH) {
678: plodstr = direct;
679: tputs(tgoto(CH, ncol, ncol), 0, plodput);
680: cost = plodstr - direct;
681: movstr = direct;
682: plodstr = saveplod;
683: }
684: if (RET && ocol > ncol) { /* consider doing carriage return */
685: plodstr = ret;
686: if (CR)
687: tputs(CR, 1, plodput);
688: else
689: *plodstr++ = '\r';
690: if (_relhmove(0, ncol, row) >= 0
691: && (newcost = plodstr - ret) < cost) {
692: cost = newcost;
693: movstr = ret;
694: }
695: plodstr = saveplod;
696: }
697: if (_relhmove(ocol, ncol, row) < 0) {
698: if (cost == 999)
699: return -1;
700: goto copy;
701: }
702: if (plodstr - saveplod > cost) {
703: copy: plodstr = saveplod;
704: while (--cost >= 0)
705: *plodstr++ = *movstr++;
706: }
707: return 0;
708: }
709:
710: _relhmove(ocol, ncol, row)
711: {
712: int tab;
713:
714: if (ocol < ncol && PT && GT) { /* tab (nondestructive) */
715: while ((tab = (ocol + 8) & ~07) <= ncol) {
716: if (TA)
717: tputs(TA, 1, plodput);
718: else
719: *plodstr++ = '\t';
720: ocol = tab;
721: }
722: if (tab < COLS && tab - ncol < ncol - ocol) {
723: if (TA)
724: tputs(TA, 1, plodput);
725: else
726: *plodstr++ = '\t';
727: ocol = tab;
728: }
729: } else if (BT && GT && ocol > ncol) { /* backwards tab */
730: while ((tab = (ocol - 1) &~ 07) >= ncol) {
731: if (BS && tab == ocol - 1) {
732: if (BC)
733: tputs(BC, 1, plodput);
734: else
735: *plodstr++ = '\b';
736: } else
737: tputs(BT, 1, plodput);
738: ocol = tab;
739: }
740: if (ncol - tab + 1 < ocol - ncol) {
741: tputs(BT, 1, plodput);
742: ocol = tab;
743: }
744: }
745: if (ocol > ncol) { /* cursor left */
746: if (! BS)
747: return -1;
748: while (ocol > ncol) {
749: if (BC != NULL)
750: tputs(BC, 1, plodput);
751: else
752: *plodstr++ = '\b';
753: ocol--;
754: }
755: }
756: if (ocol < ncol) { /* cursor right */
757: register struct line *lp = &_actual[row];
758: /*
759: * This code doesn't move over underlined characters properly,
760: * but in practice this doesn't seem to matter.
761: */
762: while (ocol < ncol) {
763: if (ocol < lp->len)
764: *plodstr++ = lp->l[ocol];
765: else
766: *plodstr++ = ' ';
767: ocol++;
768: }
769: }
770: return 0;
771: }
772:
773: _aputc(c)
774: {
775: if (_uline != (c & ULINE)) /* Inline for speed */
776: _setul(c & ULINE);
777: if (++_scol >= COLS) {
778: if (_srow == ROWS - 1) {
779: /* Don't ever paint last char of last line */
780: _scol--;
781: return;
782: }
783: _curjunked++; /* Don't assume AM is right */
784: }
785: vputc(c & ~ULINE);
786: }
787:
788:
789: _setul(on)
790: {
791: if (on) {
792: if (_uline == 0 && US != NULL) {
793: tputs(US, 1, vputc);
794: _uline = ULINE;
795: }
796: }
797: else {
798: if (_uline != 0 && UE != NULL) {
799: tputs(UE, 1, vputc);
800: _uline = 0;
801: }
802: }
803: }
804:
805: /*
806: * Initialize termcap strings for later use.
807: */
808: initterm()
809: {
810: static char tcbuf[1024]; /* termcap buffer */
811: register char *cp;
812: #ifdef USG
813: struct termio tio;
814: #else /* !USG */
815: struct sgttyb ttyb;
816: #endif /* !USG */
817:
818: if ((cp = getenv("TERM")) == NULL)
819: xerror("TERM not set in environment");
820:
821: switch (tgetent(tcbuf, cp)) {
822: case 0:
823: xerror("Terminal not found in TERMCAP");
824: case -1:
825: xerror("Can't open /etc/termcap");
826: case 1:
827: break;
828: }
829: #ifdef TIOCGWINSZ
830: {
831: struct winsize ws;
832: int winch();
833:
834: COLS = ROWS = -1;
835: if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
836: ROWS = ws.ws_row;
837: COLS = ws.ws_col;
838: }
839: if(ROWS <= 0)
840: ROWS = tgetnum("li");
841: if(COLS <= 0)
842: COLS = tgetnum("co");
843: if ((ROWS <= 0) || (COLS <= 0))
844: xerror("Can't get screen size");
845:
846: signal(SIGWINCH, winch); /* allow for changing window size */
847: }
848: #else /* !TIOCGWINSZ */
849: if ((ROWS = tgetnum("li")) == -1
850: || (COLS = tgetnum("co")) == -1)
851: xerror("Can't get screen size");
852: #endif /* !TIOCGWINSZ */
853: _zap();
854:
855: if (CL == NULL)
856: xerror ("No clear screen defined");
857:
858: if (HO == NULL && CM == NULL)
859: xerror("No home or cursor addressing");
860: if (HO)
861: HOlen = strlen(HO);
862: else
863: HOlen = 999;
864:
865: PC = xPC ? xPC[0] : 0;
866: BC = xBC;
867: UP = xUP;
868:
869: if (tgetnum("ug") > 0)
870: US = UE = NULL;
871:
872: if (XT) /* Destructive tab code not included */
873: PT = 0; /* to keep things simple */
874:
875: #ifdef USG
876: if (ioctl(0, TCGETA, &tio) == 0)
877: GT = tio.c_oflag&TAB3;
878: #else /* !USG */
879: if (ioctl(0, TIOCGETP, &ttyb) == 0)
880: GT = ttyb.sg_flags&XTABS;
881: #endif /* !USG */
882:
883: {
884: char *thelines;
885: int i;
886: char *malloc();
887:
888: thelines = malloc(2 * ROWS * COLS);
889: _virt = (struct line *)malloc(2 * ROWS * sizeof (struct line));
890: _actual = _virt + ROWS;
891: for (i = 0; i < ROWS; i++) {
892: _virt[i].len = 0;
893: _virt[i].flags = 0;
894: _actual[i].len = 0;
895: _actual[i].flags = 0;
896: _virt[i].l = thelines;
897: thelines += COLS;
898: _actual[i].l = thelines;
899: thelines += COLS;
900: }
901: }
902:
903: /* Select article scrolling algorithm. We prefer scrolling region
904: over insert/delete line because it's faster on the HP */
905: hasscroll = 0;
906: if (!NS) {
907: hasscroll = 1;
908: if (SR)
909: hasscroll = 3;
910: if (CS)
911: hasscroll++;
912: }
913: if (AL && DL && hasscroll != 4)
914: hasscroll = 5;
915: }
916:
917: rawterm()
918: {
919: if (TI != NULL)
920: tputs(TI, 0, vputc);
921: }
922:
923: cookedterm()
924: {
925: if (TE != NULL) {
926: tputs(TE, 0, vputc);
927: vflush();
928: }
929: }
930:
931: /* get strings from termcap */
932: _zap()
933: {
934: static char tstrbuf[1024];
935: static char *tp;
936: register char *namp, **sp, *bp;
937:
938: tp = tstrbuf;
939: sp = _tstr;
940: for (namp = sname; *namp; namp += 2) {
941: *sp++ = tgetstr(namp, &tp);
942: }
943: bp = _tflg;
944: for (namp = bname; *namp; namp += 2) {
945: *bp++ = tgetflag(namp, &tp);
946: }
947: }
948: #ifdef TIOCGWINSZ
949: /*
950: * window changed size -- update ROWS and COLS
951: * and then redraw screen
952: */
953: winch()
954: {
955: struct winsize ws;
956: int cols, rows;
957:
958: cols = rows = -1;
959: if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
960: rows = ws.ws_row;
961: cols = ws.ws_col;
962: }
963: if (rows == ROWS && cols == COLS) { /* just redraw it if no change */
964: _junked = 1; /* redraw */
965: updscr();
966: return;
967: }
968:
969: if(rows > 0)
970: ROWS = rows;
971: if(cols > 0)
972: COLS = cols;
973:
974: if (ROWS > MAXPLEN)
975: ROWS = MAXPLEN;
976: if (COLS > MAXLLEN) {
977: COLS = MAXLLEN;
978: AM = XN = 1;
979: }
980:
981: winch_upd();
982: }
983: #endif TIOCGWINSZ
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.