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