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