|
|
1.1 root 1: /* curses.c */
2:
3: /* Author:
4: * Steve Kirkendall
5: * 14407 SW Teal Blvd. #C
6: * Beaverton, OR 97005
7: * [email protected]
8: */
9:
10:
11: /* This file contains the functions & variables needed for a tiny subset of
12: * curses. The principle advantage of this version of curses is its
13: * extreme speed. Disadvantages are potentially larger code, few supported
14: * functions, limited compatibility with full curses, and only stdscr.
15: */
16:
17: #include "config.h"
18: #include "vi.h"
19:
20: #if ANY_UNIX
21: # if UNIXV
22: # ifdef TERMIOS
23: # include <termios.h>
24: # else
25: # include <termio.h>
26: # endif
27: # ifdef S5WINSIZE
28: # include <sys/stream.h> /* winsize struct defined in one of these? */
29: # include <sys/ptem.h>
30: # else
31: # undef TIOCGWINSZ /* we can't handle it correctly yet */
32: # endif
33: # else
34: # include <sgtty.h>
35: # endif
36: #endif
37:
38: #if TOS
39: # include <osbind.h>
40: #endif
41:
42: #if OSK
43: # include <sgstat.h>
44: #endif
45:
46: #if VMS
47: extern int VMS_read_raw; /* Set in initscr() */
48: #endif
49:
50:
51: extern char *getenv();
52: static void starttcap();
53:
54: /* variables, publicly available & used in the macros */
55: char *termtype; /* name of terminal entry */
56: short ospeed; /* speed of the tty, eg B2400 */
57: #if OSK
58: char PC_; /* Pad char */
59: char *BC; /* backspace character string */
60: #else
61: char PC; /* Pad char */
62: #endif
63: WINDOW *stdscr; /* pointer into kbuf[] */
64: WINDOW kbuf[KBSIZ]; /* a very large output buffer */
65: int LINES; /* :li#: number of rows */
66: int COLS; /* :co#: number of columns */
67: int AM; /* :am: boolean: auto margins? */
68: int PT; /* :pt: boolean: physical tabs? */
69: char *VB; /* :vb=: visible bell */
70: char *UP; /* :up=: move cursor up */
71: char *SO = ""; /* :so=: standout start */
72: char *SE = ""; /* :se=: standout end */
73: char *US = ""; /* :us=: underline start */
74: char *UE = ""; /* :ue=: underline end */
75: char *MD = ""; /* :md=: bold start */
76: char *ME = ""; /* :me=: bold end */
77: char *AS = ""; /* :as=: alternate (italic) start */
78: char *AE = ""; /* :ae=: alternate (italic) end */
79: #ifndef NO_VISIBLE
80: char *MV; /* :mv=: "visible" selection start */
81: #endif
82: char *CM; /* :cm=: cursor movement */
83: char *CE; /* :ce=: clear to end of line */
84: char *CD; /* :cd=: clear to end of screen */
85: char *AL; /* :al=: add a line */
86: char *DL; /* :dl=: delete a line */
87: #if OSK
88: char *SR_; /* :sr=: scroll reverse */
89: #else
90: char *SR; /* :sr=: scroll reverse */
91: #endif
92: char *KU; /* :ku=: key sequence sent by up arrow */
93: char *KD; /* :kd=: key sequence sent by down arrow */
94: char *KL; /* :kl=: key sequence sent by left arrow */
95: char *KR; /* :kr=: key sequence sent by right arrow */
96: char *HM; /* :HM=: key sequence sent by the <Home> key */
97: char *EN; /* :EN=: key sequence sent by the <End> key */
98: char *PU; /* :PU=: key sequence sent by the <PgUp> key */
99: char *PD; /* :PD=: key sequence sent by the <PgDn> key */
100: char *KI; /* :kI=: key sequence sent by the <Insert> key */
101: #ifndef NO_FKEY
102: char *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */
103: #endif
104: char *IM = ""; /* :im=: insert mode start */
105: char *IC = ""; /* :ic=: insert the following character */
106: char *EI = ""; /* :ei=: insert mode end */
107: char *DC; /* :dc=: delete a character */
108: char *TI = ""; /* :ti=: terminal init */ /* GB */
109: char *TE = ""; /* :te=: terminal exit */ /* GB */
110: #ifndef NO_CURSORSHAPE
111: #if 1
112: char *CQ = (char *)0;/* :cQ=: normal cursor */
113: char *CX = (char *)1;/* :cX=: cursor used for EX command/entry */
114: char *CV = (char *)2;/* :cV=: cursor used for VI command mode */
115: char *CI = (char *)3;/* :cI=: cursor used for VI input mode */
116: char *CR = (char *)4;/* :cR=: cursor used for VI replace mode */
117: #else
118: char *CQ = ""; /* :cQ=: normal cursor */
119: char *CX = ""; /* :cX=: cursor used for EX command/entry */
120: char *CV = ""; /* :cV=: cursor used for VI command mode */
121: char *CI = ""; /* :cI=: cursor used for VI input mode */
122: char *CR = ""; /* :cR=: cursor used for VI replace mode */
123: #endif
124: #endif
125: char *aend = ""; /* end an attribute -- either UE or ME */
126: char ERASEKEY; /* backspace key taken from ioctl structure */
127: #ifndef NO_COLOR
128: char normalcolor[16];
129: char SOcolor[16];
130: char SEcolor[16];
131: char UScolor[16];
132: char UEcolor[16];
133: char MDcolor[16];
134: char MEcolor[16];
135: char AScolor[16];
136: char AEcolor[16];
137: # ifndef NO_POPUP
138: char POPUPcolor[16];
139: # endif
140: # ifndef NO_VISIBLE
141: char VISIBLEcolor[16];
142: # endif
143: #endif
144:
145: #if ANY_UNIX
146: # if UNIXV
147: # ifdef TERMIOS
148: static struct termios oldtermio; /* original tty mode */
149: static struct termios newtermio; /* cbreak/noecho tty mode */
150: # else
151: static struct termio oldtermio; /* original tty mode */
152: static struct termio newtermio; /* cbreak/noecho tty mode */
153: # endif
154: # else
155: static struct sgttyb oldsgttyb; /* original tty mode */
156: static struct sgttyb newsgttyb; /* cbreak/nl/noecho tty mode */
157: static int oldint; /* ^C or DEL, the "intr" character */
158: # ifdef TIOCSLTC
159: static int oldswitch; /* ^Z, the "suspend" character */
160: static int olddswitch; /* ^Y, the "delayed suspend" char */
161: static int oldquote; /* ^V, the "quote next char" char */
162: # endif
163: # endif
164: #endif
165:
166: #if OSK
167: static struct sgbuf oldsgttyb; /* orginal tty mode */
168: static struct sgbuf newsgttyb; /* noecho tty mode */
169: #endif
170:
171: static char *capbuf; /* capability string buffer */
172:
173:
174: /* Initialize the Curses package. */
175: void initscr()
176: {
177: /* make sure TERM variable is set */
178: termtype = getenv("TERM");
179:
180: #if VMS
181: /* VMS getenv() handles TERM as a environment setting. Foreign
182: * terminal support can be implemented by setting the ELVIS_TERM
183: * logical or symbol to match a tinytcap entry.
184: */
185: if (!strcmp(termtype,"unknown"))
186: termtype = getenv("ELVIS_TERM");
187: #endif
188: #if MSDOS
189: /* For MS-DOS, if TERM is unset we can default to "pcbios", or
190: * maybe "rainbow".
191: */
192: if (!termtype)
193: {
194: #ifdef RAINBOW
195: if (*(unsigned char far*)(0xffff000eL) == 6 /* Rainbow 100a */
196: || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
197: {
198: termtype = "rainbow";
199: }
200: else
201: #endif
202: termtype = "pcbios";
203: }
204: if (!strcmp(termtype, "pcbios"))
205: #else
206: if (!termtype)
207: #endif
208: {
209: #if ANY_UNIX
210: write(2, "Environment variable TERM must be set\n", (unsigned)38);
211: exit(2);
212: #endif
213: #if OSK
214: writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
215: exit(2);
216: #endif
217: #if AMIGA
218: termtype = TERMTYPE;
219: starttcap(termtype);
220: #endif
221: #if MSDOS
222: starttcap("pcbios");
223: #endif
224: #if TOS
225: termtype = "vt52";
226: starttcap(termtype);
227: #endif
228: #if VMS
229: write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
230: exit(2);
231: #endif
232: }
233: else
234: {
235: #if MSDOS
236: *o_pcbios = 0;
237: #endif
238: /* start termcap stuff */
239: starttcap(termtype);
240: }
241:
242: /* create stdscr and curscr */
243: stdscr = kbuf;
244:
245: /* change the terminal mode to cbreak/noecho */
246: #if ANY_UNIX
247: # if UNIXV
248: # ifdef TERMIOS
249: tcgetattr(2, &oldtermio);
250: # else
251: ioctl(2, TCGETA, &oldtermio);
252: # endif
253: # else
254: ioctl(2, TIOCGETP, &oldsgttyb);
255: # endif
256: #endif
257:
258: #if OSK
259: _gs_opt(0, &oldsgttyb);
260: #endif
261:
262: #if VMS
263: VMS_read_raw = 1; /* cbreak/noecho */
264: vms_open_tty();
265: #endif
266: resume_curses(TRUE);
267: }
268:
269: /* Shut down the Curses package. */
270: void endwin()
271: {
272: /* change the terminal mode back the way it was */
273: suspend_curses();
274: #if AMIGA
275: amiclosewin();
276: #endif
277: }
278:
279:
280: static int curses_active = FALSE;
281:
282: /* Send any required termination strings. Turn off "raw" mode. */
283: void suspend_curses()
284: {
285: #if ANY_UNIX && !UNIXV
286: struct tchars tbuf;
287: # ifdef TIOCSLTC
288: struct ltchars ltbuf;
289: # endif
290: #endif
291: #ifndef NO_CURSORSHAPE
292: if (has_CQ)
293: {
294: do_CQ();
295: }
296: #endif
297: if (has_TE) /* GB */
298: {
299: do_TE();
300: }
301: #ifndef NO_COLOR
302: quitcolor();
303: #endif
304: refresh();
305:
306: /* change the terminal mode back the way it was */
307: #if ANY_UNIX
308: # if UNIXV
309: # if TERMIOS
310: tcsetattr(2, TCSADRAIN, &oldtermio);
311: # else
312: ioctl(2, TCSETAW, &oldtermio);
313: # endif
314: # else
315: ioctl(2, TIOCSETP, &oldsgttyb);
316:
317: ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf);
318: tbuf.t_intrc = oldint;
319: ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf);
320:
321: # ifdef TIOCSLTC
322: ioctl(2, TIOCGLTC, <buf);
323: ltbuf.t_suspc = oldswitch;
324: ltbuf.t_dsuspc = olddswitch;
325: ltbuf.t_lnextc = oldquote;
326: ioctl(2, TIOCSLTC, <buf);
327: # endif
328: # endif
329: #endif
330: #if OSK
331: _ss_opt(0, &oldsgttyb);
332: #endif
333: #if AMIGA
334: ttyshutdown();
335: #endif
336: #if MSDOS
337: raw_set_stdio(FALSE);
338: #endif
339:
340: #if VMS
341: VMS_read_raw = 0;
342: #endif
343: curses_active = FALSE;
344: }
345:
346:
347: /* put the terminal in RAW mode. If "quietly" is FALSE, then ask the user
348: * to hit a key, and wait for keystroke before returning.
349: */
350: void resume_curses(quietly)
351: int quietly;
352: {
353: if (!curses_active)
354: {
355: /* change the terminal mode to cbreak/noecho */
356: #if ANY_UNIX
357: # if UNIXV
358: ospeed = (oldtermio.c_cflag & CBAUD);
359: ERASEKEY = oldtermio.c_cc[VERASE];
360: newtermio = oldtermio;
361: newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
362: newtermio.c_oflag &= ~OPOST;
363: newtermio.c_lflag &= ISIG;
364: newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
365: newtermio.c_cc[VMIN] = 1;
366: newtermio.c_cc[VTIME] = 0;
367: # ifdef VSWTCH
368: newtermio.c_cc[VSWTCH] = 0;
369: # endif
370: # ifdef VSUSP
371: newtermio.c_cc[VSUSP] = 0;
372: # endif
373: # ifdef TERMIOS
374: tcsetattr(2, TCSADRAIN, &newtermio);
375: # else
376: ioctl(2, TCSETAW, &newtermio);
377: # endif
378: # else /* BSD or V7 or Coherent or Minix */
379: struct tchars tbuf;
380: # ifdef TIOCSLTC
381: struct ltchars ltbuf;
382: # endif
383:
384: ospeed = oldsgttyb.sg_ospeed;
385: ERASEKEY = oldsgttyb.sg_erase;
386: newsgttyb = oldsgttyb;
387: newsgttyb.sg_flags |= CBREAK;
388: newsgttyb.sg_flags &= ~(CRMOD|ECHO|XTABS);
389: ioctl(2, TIOCSETP, &newsgttyb);
390:
391: ioctl(2, TIOCGETC, (struct sgttyb *) &tbuf);
392: oldint = tbuf.t_intrc;
393: tbuf.t_intrc = ctrl('C'); /* always use ^C for interrupts */
394: ioctl(2, TIOCSETC, (struct sgttyb *) &tbuf);
395:
396: # ifdef TIOCSLTC
397: ioctl(2, TIOCGLTC, <buf);
398: oldswitch = ltbuf.t_suspc;
399: ltbuf.t_suspc = 0; /* disable ^Z for elvis */
400: olddswitch = ltbuf.t_dsuspc;
401: ltbuf.t_dsuspc = 0; /* disable ^Y for elvis */
402: oldquote = ltbuf.t_lnextc;
403: ltbuf.t_lnextc = 0; /* disable ^V for elvis */
404: ioctl(2, TIOCSLTC, <buf);
405: # endif
406:
407: # endif
408: #endif
409: #if OSK
410: newsgttyb = oldsgttyb;
411: newsgttyb.sg_echo = 0;
412: newsgttyb.sg_eofch = 0;
413: newsgttyb.sg_kbach = 0;
414: newsgttyb.sg_kbich = ctrl('C');
415: _ss_opt(0, &newsgttyb);
416: ospeed = oldsgttyb.sg_baud;
417: ERASEKEY = oldsgttyb.sg_bspch;
418: #endif
419: #if AMIGA
420: /* turn on window resize and RAW */
421: ttysetup();
422: #endif
423: #if MSDOS
424: raw_set_stdio(TRUE);
425: #endif
426:
427: #if VMS
428: VMS_read_raw = 1;
429: { int c;
430: read(0,&c,0); /* Flush the tty buffer. */
431: }
432: ERASEKEY = '\177'; /* Accept <DEL> as <^H> for VMS */
433: #endif
434:
435: curses_active = TRUE;
436: }
437:
438: /* If we're supposed to quit quietly, then we're done */
439: if (quietly)
440: {
441: if (has_TI) /* GB */
442: {
443: do_TI();
444: }
445:
446: return;
447: }
448:
449: signal(SIGINT, SIG_IGN);
450:
451: move(LINES - 1, 0);
452: do_SO();
453: #if VMS
454: qaddstr("\n[Press <RETURN> to continue]");
455: #else
456: qaddstr("[Press <RETURN> to continue]");
457: #endif
458: do_SE();
459: refresh();
460: ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
461: if (has_TI)
462: {
463: do_TI();
464: }
465: if (kbuf[0] == ':')
466: {
467: mode = MODE_COLON;
468: addch('\n');
469: refresh();
470: }
471: else
472: {
473: mode = MODE_VI;
474: redraw(MARK_UNSET, FALSE);
475: }
476: exwrote = FALSE;
477:
478: #if TURBOC || __GNUC__
479: signal(SIGINT, (void(*)()) trapint);
480: #else
481: signal(SIGINT, trapint);
482: #endif
483: }
484:
485: /* This function fetches an optional string from termcap */
486: static void mayhave(T, s)
487: char **T; /* where to store the returned pointer */
488: char *s; /* name of the capability */
489: {
490: char *val;
491:
492: val = tgetstr(s, &capbuf);
493: if (val)
494: {
495: *T = val;
496: }
497: }
498:
499:
500: /* This function fetches a required string from termcap */
501: static void musthave(T, s)
502: char **T; /* where to store the returned pointer */
503: char *s; /* name of the capability */
504: {
505: mayhave(T, s);
506: if (!*T)
507: {
508: write(2, "This termcap entry lacks the :", (unsigned)30);
509: write(2, s, (unsigned)2);
510: write(2, "=: capability\n", (unsigned)14);
511: #if OSK
512: write(2, "\l", 1);
513: #endif
514: exit(2);
515: }
516: }
517:
518:
519: /* This function fetches a pair of strings from termcap. If one of them is
520: * missing, then the other one is ignored.
521: */
522: static void pair(T, U, sT, sU)
523: char **T; /* where to store the first pointer */
524: char **U; /* where to store the second pointer */
525: char *sT; /* name of the first capability */
526: char *sU; /* name of the second capability */
527: {
528: mayhave(T, sT);
529: mayhave(U, sU);
530: if (!**T || !**U)
531: {
532: *T = *U = "";
533: }
534: }
535:
536:
537:
538: /* Read everything from termcap */
539: static void starttcap(term)
540: char *term;
541: {
542: static char cbmem[800];
543:
544: /* allocate memory for capbuf */
545: capbuf = cbmem;
546:
547: /* get the termcap entry */
548: switch (tgetent(kbuf, term))
549: {
550: case -1:
551: write(2, "Can't read /etc/termcap\n", (unsigned)24);
552: #if OSK
553: write(2, "\l", 1);
554: #endif
555: exit(2);
556:
557: case 0:
558: write(2, "Unrecognized TERM type\n", (unsigned)23);
559: #if OSK
560: write(2, "\l", 1);
561: #endif
562: exit(3);
563: }
564:
565: /* get strings */
566: musthave(&UP, "up");
567: mayhave(&VB, "vb");
568: musthave(&CM, "cm");
569: pair(&SO, &SE, "so", "se");
570: mayhave(&TI, "ti");
571: mayhave(&TE, "te");
572: if (tgetnum("ug") <= 0)
573: {
574: pair(&US, &UE, "us", "ue");
575: pair(&MD, &ME, "md", "me");
576:
577: /* get italics, or have it default to underline */
578: pair(&AS, &AE, "as", "ae");
579: if (!*AS)
580: {
581: AS = US;
582: AE = UE;
583: }
584: }
585: #ifndef NO_VISIBLE
586: MV = SO; /* by default */
587: mayhave(&MV, "mv");
588: #endif
589: mayhave(&AL, "al");
590: mayhave(&DL, "dl");
591: musthave(&CE, "ce");
592: mayhave(&CD, "cd");
593: #if OSK
594: mayhave(&SR_, "sr");
595: #else
596: mayhave(&SR, "sr");
597: #endif
598: pair(&IM, &EI, "im", "ei");
599: mayhave(&IC, "ic");
600: mayhave(&DC, "dc");
601:
602: /* other termcap stuff */
603: AM = (tgetflag("am") && !tgetflag("xn"));
604: PT = tgetflag("pt");
605: #if AMIGA
606: amiopenwin(termtype); /* Must run this before ttysetup(); */
607: ttysetup(); /* Must run this before getsize(0); */
608: #endif
609: getsize(0);
610:
611: /* Key sequences */
612: mayhave(&KU, "ku"); /* up */
613: mayhave(&KD, "kd"); /* down */
614: mayhave(&KL, "kl"); /* left */
615: mayhave(&KR, "kr"); /* right */
616: #if COHERENT
617: if (KL && KL[0]=='\b' && !KL[1])
618: {
619: /* never use '\b' as a left arrow! */
620: KL = (char *)0;
621: }
622: #else
623: if (KR && KR[0]=='\b' && !KR[1])
624: {
625: /* never use '\b' as a right arrow! */
626: KR = (char *)0;
627: }
628: #endif
629: mayhave(&PU, "kP"); /* PgUp */
630: mayhave(&PD, "kN"); /* PgDn */
631: mayhave(&HM, "kh"); /* Home */
632: mayhave(&EN, "kH"); /* End */
633: mayhave(&KI, "kI"); /* Insert */
634: #ifndef CRUNCH
635: if (!PU) mayhave(&PU, "K2"); /* "3x3 pad" names for PgUp, etc. */
636: if (!PD) mayhave(&PD, "K5");
637: if (!HM) mayhave(&HM, "K1");
638: if (!EN) mayhave(&EN, "K4");
639:
640: mayhave(&PU, "PU"); /* old XENIX names for PgUp, etc. */
641: mayhave(&PD, "PD"); /* (overrides others, if used.) */
642: mayhave(&HM, "HM");
643: mayhave(&EN, "EN");
644: #endif
645: #ifndef NO_FKEY
646: mayhave(&FKEY[0], "k0"); /* function key codes */
647: mayhave(&FKEY[1], "k1");
648: mayhave(&FKEY[2], "k2");
649: mayhave(&FKEY[3], "k3");
650: mayhave(&FKEY[4], "k4");
651: mayhave(&FKEY[5], "k5");
652: mayhave(&FKEY[6], "k6");
653: mayhave(&FKEY[7], "k7");
654: mayhave(&FKEY[8], "k8");
655: mayhave(&FKEY[9], "k9");
656: # ifndef NO_SHIFT_FKEY
657: mayhave(&FKEY[10], "s0"); /* shift function key codes */
658: mayhave(&FKEY[11], "s1");
659: mayhave(&FKEY[12], "s2");
660: mayhave(&FKEY[13], "s3");
661: mayhave(&FKEY[14], "s4");
662: mayhave(&FKEY[15], "s5");
663: mayhave(&FKEY[16], "s6");
664: mayhave(&FKEY[17], "s7");
665: mayhave(&FKEY[18], "s8");
666: mayhave(&FKEY[19], "s9");
667: # ifndef NO_CTRL_FKEY
668: mayhave(&FKEY[20], "c0"); /* control function key codes */
669: mayhave(&FKEY[21], "c1");
670: mayhave(&FKEY[22], "c2");
671: mayhave(&FKEY[23], "c3");
672: mayhave(&FKEY[24], "c4");
673: mayhave(&FKEY[25], "c5");
674: mayhave(&FKEY[26], "c6");
675: mayhave(&FKEY[27], "c7");
676: mayhave(&FKEY[28], "c8");
677: mayhave(&FKEY[29], "c9");
678: # ifndef NO_ALT_FKEY
679: mayhave(&FKEY[30], "a0"); /* alt function key codes */
680: mayhave(&FKEY[31], "a1");
681: mayhave(&FKEY[32], "a2");
682: mayhave(&FKEY[33], "a3");
683: mayhave(&FKEY[34], "a4");
684: mayhave(&FKEY[35], "a5");
685: mayhave(&FKEY[36], "a6");
686: mayhave(&FKEY[37], "a7");
687: mayhave(&FKEY[38], "a8");
688: mayhave(&FKEY[39], "a9");
689: # endif
690: # endif
691: # endif
692: #endif
693:
694: #ifndef NO_CURSORSHAPE
695: /* cursor shapes */
696: CQ = tgetstr("cQ", &capbuf);
697: if (has_CQ)
698: {
699: CX = tgetstr("cX", &capbuf);
700: if (!CX) CX = CQ;
701: CV = tgetstr("cV", &capbuf);
702: if (!CV) CV = CQ;
703: CI = tgetstr("cI", &capbuf);
704: if (!CI) CI = CQ;
705: CR = tgetstr("cR", &capbuf);
706: if (!CR) CR = CQ;
707: }
708: # ifndef CRUNCH
709: else
710: {
711: CQ = CV = "";
712: pair(&CQ, &CV, "ve", "vs");
713: CX = CI = CR = CQ;
714: }
715: # endif /* !CRUNCH */
716: #endif /* !NO_CURSORSHAPE */
717:
718: #ifndef NO_COLOR
719: strcpy(SOcolor, SO);
720: strcpy(SEcolor, SE);
721: strcpy(AScolor, AS);
722: strcpy(AEcolor, AE);
723: strcpy(MDcolor, MD);
724: strcpy(MEcolor, ME);
725: strcpy(UScolor, US);
726: strcpy(UEcolor, UE);
727: # ifndef NO_POPUP
728: strcpy(POPUPcolor, SO);
729: # endif
730: # ifndef NO_VISIBLE
731: strcpy(VISIBLEcolor, MV);
732: # endif
733: #endif
734:
735: }
736:
737:
738: /* This function gets the window size. It uses the TIOCGWINSZ ioctl call if
739: * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
740: * This function is called once during initialization, and thereafter it is
741: * called whenever the SIGWINCH signal is sent to this process.
742: */
743: int getsize(signo)
744: int signo;
745: {
746: int lines;
747: int cols;
748: #ifdef TIOCGWINSZ
749: struct winsize size;
750: #endif
751:
752: #ifdef SIGWINCH
753: /* reset the signal vector */
754: signal(SIGWINCH, getsize);
755: #endif
756:
757: /* get the window size, one way or another. */
758: lines = cols = 0;
759: #ifdef TIOCGWINSZ
760: if (ioctl(2, TIOCGWINSZ, &size) >= 0)
761: {
762: lines = size.ws_row;
763: cols = size.ws_col;
764: }
765: #endif
766: #if AMIGA
767: /* Amiga gets window size by asking the console.device */
768: if (!strcmp(TERMTYPE, termtype))
769: {
770: auto long len;
771: auto char buf[30];
772:
773: Write(Output(), "\2330 q", 4); /* Ask the console.device */
774: len = Read(Input(), buf, 29);
775: buf[len] = '\000';
776: sscanf(&buf[5], "%d;%d", &lines, &cols);
777: }
778: #endif
779: if ((lines == 0 || cols == 0) && signo == 0)
780: {
781: #if COHERENT
782: char * temp;
783:
784: temp = getenv("COLUMNS");
785: if (temp)
786: COLS = atoi(temp);
787: else
788: COLS = tgetnum("co");
789:
790: temp = getenv("LINES");
791: if (temp)
792: LINES = atoi(temp);
793: else
794: LINES = tgetnum("li");
795: #else
796: LINES = tgetnum("li");
797: COLS = tgetnum("co");
798: #endif
799: }
800: #if MSDOS
801: # ifdef RAINBOW
802: if (!strcmp(termtype, "rainbow"))
803: {
804: /* Determine whether Rainbow is in 80-column or 132-column mode */
805: cols = *(unsigned char far *)0xee000f57L;
806: }
807: else
808: # endif
809: {
810: lines = v_rows();
811: cols = v_cols();
812: }
813: #endif
814: if (lines >= 2 && cols >= 30)
815: {
816: LINES = lines;
817: COLS = cols;
818: }
819:
820: /* Make sure we got values that we can live with */
821: if (LINES < 2 || COLS < 30)
822: {
823: write(2, "Screen too small\n", (unsigned)17);
824: #if OSK
825: write(2, "\l", 1);
826: #endif
827: endwin();
828: exit(2);
829: }
830:
831: #if AMIGA
832: if (*o_lines != LINES || *o_columns != COLS)
833: {
834: *o_lines = LINES;
835: *o_columns = COLS;
836: }
837: #endif
838:
839: return 0;
840: }
841:
842:
843: /* This is a function version of addch() -- it is used by tputs() */
844: int faddch(ch)
845: int ch;
846: {
847: #if 0
848: if (stdscr)
849: addch(ch);
850: else
851: msg("OOPS! tried to access null stdscr");
852: #else
853: addch(ch);
854: #endif
855:
856: return 0;
857: }
858:
859: /* This function quickly adds a string to the output queue. It does *NOT*
860: * convert \n into <CR><LF>.
861: */
862: void qaddstr(str)
863: char *str;
864: {
865: REG char *s_, *d_;
866:
867: #if MSDOS
868: if (o_pcbios[0])
869: {
870: while (*str)
871: qaddch(*str++);
872: return;
873: }
874: #endif
875: for (s_=(str), d_=stdscr; *d_++ = *s_++; )
876: {
877: }
878: stdscr = d_ - 1;
879: }
880:
881: /* Output the ESC sequence needed to go into any video mode, if supported */
882: void attrset(a)
883: int a;
884: {
885: do_aend();
886: if (a == A_BOLD)
887: {
888: do_MD();
889: aend = ME;
890: }
891: else if (a == A_UNDERLINE)
892: {
893: do_US();
894: aend = UE;
895: }
896: else if (a == A_ALTCHARSET)
897: {
898: do_AS();
899: aend = AE;
900: }
901: else
902: {
903: aend = "";
904: }
905: }
906:
907:
908: /* Insert a single character into the display */
909: void insch(ch)
910: int ch;
911: {
912: if (has_IM)
913: do_IM();
914: do_IC();
915: qaddch(ch);
916: if (has_EI)
917: do_EI();
918: }
919:
920: void wrefresh()
921: {
922: if (stdscr != kbuf)
923: {
924: VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
925: stdscr = kbuf;
926: }
927: }
928:
929: void wqrefresh()
930: {
931: if (stdscr - kbuf > 2000)
932: {
933: VOIDBIOS(stdscr = kbuf,
934: {
935: ttywrite(kbuf, (unsigned)(stdscr - kbuf));
936: stdscr = kbuf;
937: });
938: }
939: }
940:
941: #ifndef NO_COLOR
942: /* This function is called during termination. It resets color modes */
943: int ansiquit()
944: {
945: /* if ANSI color terminal, then reset the colors */
946: if (!strcmp(UP, "\033[A"))
947: {
948: tputs("\033[37;40m\033[m", 1, faddch);
949: clrtoeol();
950: return 1;
951: }
952: return 0;
953: }
954:
955: /* This sets the color strings that work for ANSI terminals. If the TERMCAP
956: * doesn't look like an ANSI terminal, then it returns FALSE. If the colors
957: * aren't understood, it also returns FALSE. If all goes well, it returns TRUE
958: */
959: int ansicolor(cmode, attrbyte)
960: int cmode; /* mode to set, e.g. A_NORMAL */
961: int attrbyte; /* IBM PC attribute byte */
962: {
963: char temp[16]; /* hold the new mode string */
964:
965: /* if not ANSI-ish, then fail */
966: if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
967: {
968: #if COHERENT
969: return 1;
970: #else
971: msg("Don't know how to set colors for this terminal");
972: return 0;
973: #endif
974: }
975:
976: /* construct the color string */
977: sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
978: "04261537"[attrbyte & 0x07],
979: "04261537"[(attrbyte >> 4) & 0x07],
980: (attrbyte & 0x08) ? ";1" : "",
981: (attrbyte & 0x80) ? ";5" : "");
982:
983: /* stick it in the right place */
984: switch (cmode)
985: {
986: case A_NORMAL:
987: if (!strcmp(MEcolor, normalcolor))
988: strcpy(MEcolor, temp);
989: if (!strcmp(UEcolor, normalcolor))
990: strcpy(UEcolor, temp);
991: if (!strcmp(AEcolor, normalcolor))
992: strcpy(AEcolor, temp);
993: if (!strcmp(SEcolor, normalcolor))
994: strcpy(SEcolor, temp);
995:
996: strcpy(normalcolor, temp);
997: tputs(normalcolor, 1, faddch);
998: break;
999:
1000: case A_BOLD:
1001: strcpy(MDcolor, temp);
1002: strcpy(MEcolor, normalcolor);
1003: break;
1004:
1005: case A_UNDERLINE:
1006: strcpy(UScolor, temp);
1007: strcpy(UEcolor, normalcolor);
1008: break;
1009:
1010: case A_ALTCHARSET:
1011: strcpy(AScolor, temp);
1012: strcpy(AEcolor, normalcolor);
1013: break;
1014:
1015: case A_STANDOUT:
1016: strcpy(SOcolor, temp);
1017: strcpy(SEcolor, normalcolor);
1018: break;
1019:
1020: #ifndef NO_POPUP
1021: case A_POPUP:
1022: strcpy(POPUPcolor, temp);
1023: break;
1024: #endif
1025:
1026: #ifndef NO_VISIBLE
1027: case A_VISIBLE:
1028: strcpy(VISIBLEcolor, temp);
1029: break;
1030: #endif
1031: }
1032:
1033: return 1;
1034: }
1035:
1036:
1037: /* This function outputs the ESC sequence needed to switch the screen back
1038: * to "normal" mode. On color terminals which haven't had their color set
1039: * yet, this is one of the termcap strings; for color terminals that really
1040: * have had colors defined, we just the "normal color" escape sequence.
1041: */
1042: int
1043: endcolor()
1044: {
1045: if (aend == ME)
1046: tputs(MEcolor, 1, faddch);
1047: else if (aend == UE)
1048: tputs(UEcolor, 1, faddch);
1049: else if (aend == AE)
1050: tputs(AEcolor, 1, faddch);
1051: else if (aend == SE)
1052: tputs(SEcolor, 1, faddch);
1053: aend = "";
1054: return 0;
1055: }
1056:
1057:
1058: #endif /* !NO_COLOR */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.