5 * 14407 SW Teal Blvd. #C
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.
21 /* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
26 # include <sys/ioctl.h>
39 extern int VMS_read_raw
; /* Set in initscr() */
43 extern char *getenv();
44 static void starttcap();
46 /* variables, publicly available & used in the macros */
47 char *termtype
; /* name of terminal entry */
48 short ospeed
; /* speed of the tty, eg B2400 */
50 char PC_
; /* Pad char */
51 char *BC
; /* backspace character string */
53 char PC
; /* Pad char */
55 WINDOW
*stdscr
; /* pointer into kbuf[] */
56 WINDOW kbuf
[KBSIZ
]; /* a very large output buffer */
57 int LINES
; /* :li#: number of rows */
58 int COLS
; /* :co#: number of columns */
59 int AM
; /* :am: boolean: auto margins? */
60 int PT
; /* :pt: boolean: physical tabs? */
61 char *VB
; /* :vb=: visible bell */
62 char *UP
; /* :up=: move cursor up */
63 char *SO
= ""; /* :so=: standout start */
64 char *SE
= ""; /* :se=: standout end */
65 char *US
= ""; /* :us=: underline start */
66 char *UE
= ""; /* :ue=: underline end */
67 char *MD
= ""; /* :md=: bold start */
68 char *ME
= ""; /* :me=: bold end */
69 char *AS
= ""; /* :as=: alternate (italic) start */
70 char *AE
= ""; /* :ae=: alternate (italic) end */
72 char *MV
; /* :mv=: "visible" selection start */
74 char *CM
; /* :cm=: cursor movement */
75 char *CE
; /* :ce=: clear to end of line */
76 char *CD
; /* :cd=: clear to end of screen */
77 char *AL
; /* :al=: add a line */
78 char *DL
; /* :dl=: delete a line */
80 char *SR_
; /* :sr=: scroll reverse */
82 char *SR
; /* :sr=: scroll reverse */
84 char *KS
= ""; /* :ks=: init string for cursor */
85 char *KE
= ""; /* :ke=: restore string for cursor */
86 char *KU
; /* :ku=: key sequence sent by up arrow */
87 char *KD
; /* :kd=: key sequence sent by down arrow */
88 char *KL
; /* :kl=: key sequence sent by left arrow */
89 char *KR
; /* :kr=: key sequence sent by right arrow */
90 char *HM
; /* :HM=: key sequence sent by the <Home> key */
91 char *EN
; /* :EN=: key sequence sent by the <End> key */
92 char *PU
; /* :PU=: key sequence sent by the <PgUp> key */
93 char *PD
; /* :PD=: key sequence sent by the <PgDn> key */
94 char *KI
; /* :kI=: key sequence sent by the <Insert> key */
96 char *FKEY
[NFKEYS
]; /* :k0=: ... :k9=: sequences sent by function keys */
98 char *IM
= ""; /* :im=: insert mode start */
99 char *IC
= ""; /* :ic=: insert the following character */
100 char *EI
= ""; /* :ei=: insert mode end */
101 char *DC
; /* :dc=: delete a character */
102 char *TI
= ""; /* :ti=: terminal init */ /* GB */
103 char *TE
= ""; /* :te=: terminal exit */ /* GB */
104 #ifndef NO_CURSORSHAPE
106 char *CQ
= (char *)0;/* :cQ=: normal cursor */
107 char *CX
= (char *)1;/* :cX=: cursor used for EX command/entry */
108 char *CV
= (char *)2;/* :cV=: cursor used for VI command mode */
109 char *CI
= (char *)3;/* :cI=: cursor used for VI input mode */
110 char *CR
= (char *)4;/* :cR=: cursor used for VI replace mode */
112 char *CQ
= ""; /* :cQ=: normal cursor */
113 char *CX
= ""; /* :cX=: cursor used for EX command/entry */
114 char *CV
= ""; /* :cV=: cursor used for VI command mode */
115 char *CI
= ""; /* :cI=: cursor used for VI input mode */
116 char *CR
= ""; /* :cR=: cursor used for VI replace mode */
119 char *aend
= ""; /* end an attribute -- either UE or ME */
120 char ERASEKEY
; /* backspace key taken from ioctl structure */
122 char normalcolor
[16];
135 char VISIBLEcolor
[16];
140 static struct termios oldtermio
; /* original tty mode */
141 static struct termios newtermio
; /* cbreak/noecho tty mode */
145 static struct sgbuf oldsgttyb
; /* orginal tty mode */
146 static struct sgbuf newsgttyb
; /* noecho tty mode */
149 static char *capbuf
; /* capability string buffer */
152 /* Initialize the Curses package. */
155 /* make sure TERM variable is set */
156 termtype
= getenv("TERM");
159 /* VMS getenv() handles TERM as a environment setting. Foreign
160 * terminal support can be implemented by setting the ELVIS_TERM
161 * logical or symbol to match a tinytcap entry.
163 if (!strcmp(termtype
,"unknown"))
164 termtype
= getenv("ELVIS_TERM");
167 /* For MS-DOS, if TERM is unset we can default to "pcbios", or
173 if (*(unsigned char far
*)(0xffff000eL
) == 6 /* Rainbow 100a */
174 || *(unsigned char far
*)(0xffff000eL
) == 148)/* Rainbow 100b */
176 termtype
= "rainbow";
182 if (!strcmp(termtype
, "pcbios"))
188 write(2, "Environment variable TERM must be set\n", (unsigned)38);
192 writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
207 write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
216 /* start termcap stuff */
220 /* create stdscr and curscr */
223 /* change the terminal mode to cbreak/noecho */
225 tcgetattr(2, &oldtermio
);
229 _gs_opt(0, &oldsgttyb
);
233 VMS_read_raw
= 1; /* cbreak/noecho */
239 /* Shut down the Curses package. */
242 /* change the terminal mode back the way it was */
250 static int curses_active
= FALSE
;
252 /* Send any required termination strings. Turn off "raw" mode. */
253 void suspend_curses()
255 #ifndef NO_CURSORSHAPE
274 /* change the terminal mode back the way it was */
276 tcsetattr(2, TCSADRAIN
, &oldtermio
);
279 _ss_opt(0, &oldsgttyb
);
285 raw_set_stdio(FALSE
);
291 curses_active
= FALSE
;
295 /* put the terminal in RAW mode. If "quietly" is FALSE, then ask the user
296 * to hit a key, and wait for keystroke before returning.
298 void resume_curses(quietly
)
303 /* change the terminal mode to cbreak/noecho */
305 ospeed
= cfgetospeed(&oldtermio
);
306 ERASEKEY
= oldtermio
.c_cc
[VERASE
];
307 newtermio
= oldtermio
;
308 newtermio
.c_iflag
&= (IXON
|IXOFF
|IXANY
|ISTRIP
|IGNBRK
);
309 newtermio
.c_oflag
&= ~OPOST
;
310 newtermio
.c_lflag
&= ISIG
;
311 newtermio
.c_cc
[VINTR
] = ctrl('C'); /* always use ^C for interrupts */
312 newtermio
.c_cc
[VMIN
] = 1;
313 newtermio
.c_cc
[VTIME
] = 0;
314 newtermio
.c_cc
[VSUSP
] = 0;
315 tcsetattr(2, TCSADRAIN
, &newtermio
);
318 newsgttyb
= oldsgttyb
;
319 newsgttyb
.sg_echo
= 0;
320 newsgttyb
.sg_eofch
= 0;
321 newsgttyb
.sg_kbach
= 0;
322 newsgttyb
.sg_kbich
= ctrl('C');
323 _ss_opt(0, &newsgttyb
);
324 ospeed
= oldsgttyb
.sg_baud
;
325 ERASEKEY
= oldsgttyb
.sg_bspch
;
328 /* turn on window resize and RAW */
338 read(0,&c
,0); /* Flush the tty buffer. */
340 ERASEKEY
= '\177'; /* Accept <DEL> as <^H> for VMS */
352 curses_active
= TRUE
;
355 /* If we're supposed to quit quietly, then we're done */
361 signal(SIGINT
, SIG_IGN
);
366 qaddstr("\n[Press <RETURN> to continue]");
368 qaddstr("[Press <RETURN> to continue]");
372 ttyread(kbuf
, 20, 0); /* in RAW mode, so <20 is very likely */
382 redraw(MARK_UNSET
, FALSE
);
386 signal(SIGINT
, (void(*)()) trapint
);
389 /* This function fetches an optional string from termcap */
390 static void mayhave(T
, s
)
391 char **T
; /* where to store the returned pointer */
392 char *s
; /* name of the capability */
396 val
= tgetstr(s
, &capbuf
);
404 /* This function fetches a required string from termcap */
405 static void musthave(T
, s
)
406 char **T
; /* where to store the returned pointer */
407 char *s
; /* name of the capability */
412 write(2, "This termcap entry lacks the :", (unsigned)30);
413 write(2, s
, (unsigned)2);
414 write(2, "=: capability\n", (unsigned)14);
423 /* This function fetches a pair of strings from termcap. If one of them is
424 * missing, then the other one is ignored.
426 static void pair(T
, U
, sT
, sU
)
427 char **T
; /* where to store the first pointer */
428 char **U
; /* where to store the second pointer */
429 char *sT
; /* name of the first capability */
430 char *sU
; /* name of the second capability */
441 void getsize(int signo
);
443 /* Read everything from termcap */
444 static void starttcap(term
)
447 static char cbmem
[800];
449 /* allocate memory for capbuf */
452 /* get the termcap entry */
453 switch (tgetent(kbuf
, term
))
456 write(2, "Can't read /etc/termcap\n", (unsigned)24);
463 write(2, "Unrecognized TERM type\n", (unsigned)23);
474 pair(&SO
, &SE
, "so", "se");
477 if (tgetnum("ug") <= 0)
479 pair(&US
, &UE
, "us", "ue");
480 pair(&MD
, &ME
, "md", "me");
482 /* get italics, or have it default to underline */
483 pair(&AS
, &AE
, "as", "ae");
491 MV
= SO
; /* by default */
503 pair(&IM
, &EI
, "im", "ei");
507 /* other termcap stuff */
508 AM
= (tgetflag("am") && !tgetflag("xn"));
511 amiopenwin(termtype
); /* Must run this before ttysetup(); */
512 ttysetup(); /* Must run this before getsize(0); */
517 pair(&KS
, &KE
, "ks", "ke");
518 mayhave(&KU
, "ku"); /* up */
519 mayhave(&KD
, "kd"); /* down */
520 mayhave(&KL
, "kl"); /* left */
521 mayhave(&KR
, "kr"); /* right */
522 mayhave(&PU
, "kP"); /* PgUp */
523 mayhave(&PD
, "kN"); /* PgDn */
524 mayhave(&HM
, "kh"); /* Home */
525 mayhave(&EN
, "kH"); /* End */
526 mayhave(&KI
, "kI"); /* Insert */
528 if (!PU
) mayhave(&PU
, "K2"); /* "3x3 pad" names for PgUp, etc. */
529 if (!PD
) mayhave(&PD
, "K5");
530 if (!HM
) mayhave(&HM
, "K1");
531 if (!EN
) mayhave(&EN
, "K4");
533 mayhave(&PU
, "PU"); /* old XENIX names for PgUp, etc. */
534 mayhave(&PD
, "PD"); /* (overrides others, if used.) */
539 mayhave(&FKEY
[0], "k0"); /* function key codes */
540 mayhave(&FKEY
[1], "k1");
541 mayhave(&FKEY
[2], "k2");
542 mayhave(&FKEY
[3], "k3");
543 mayhave(&FKEY
[4], "k4");
544 mayhave(&FKEY
[5], "k5");
545 mayhave(&FKEY
[6], "k6");
546 mayhave(&FKEY
[7], "k7");
547 mayhave(&FKEY
[8], "k8");
548 mayhave(&FKEY
[9], "k9");
549 # ifndef NO_SHIFT_FKEY
550 mayhave(&FKEY
[10], "s0"); /* shift function key codes */
551 mayhave(&FKEY
[11], "s1");
552 mayhave(&FKEY
[12], "s2");
553 mayhave(&FKEY
[13], "s3");
554 mayhave(&FKEY
[14], "s4");
555 mayhave(&FKEY
[15], "s5");
556 mayhave(&FKEY
[16], "s6");
557 mayhave(&FKEY
[17], "s7");
558 mayhave(&FKEY
[18], "s8");
559 mayhave(&FKEY
[19], "s9");
560 # ifndef NO_CTRL_FKEY
561 mayhave(&FKEY
[20], "c0"); /* control function key codes */
562 mayhave(&FKEY
[21], "c1");
563 mayhave(&FKEY
[22], "c2");
564 mayhave(&FKEY
[23], "c3");
565 mayhave(&FKEY
[24], "c4");
566 mayhave(&FKEY
[25], "c5");
567 mayhave(&FKEY
[26], "c6");
568 mayhave(&FKEY
[27], "c7");
569 mayhave(&FKEY
[28], "c8");
570 mayhave(&FKEY
[29], "c9");
572 mayhave(&FKEY
[30], "a0"); /* alt function key codes */
573 mayhave(&FKEY
[31], "a1");
574 mayhave(&FKEY
[32], "a2");
575 mayhave(&FKEY
[33], "a3");
576 mayhave(&FKEY
[34], "a4");
577 mayhave(&FKEY
[35], "a5");
578 mayhave(&FKEY
[36], "a6");
579 mayhave(&FKEY
[37], "a7");
580 mayhave(&FKEY
[38], "a8");
581 mayhave(&FKEY
[39], "a9");
587 #ifndef NO_CURSORSHAPE
589 CQ
= tgetstr("cQ", &capbuf
);
592 CX
= tgetstr("cX", &capbuf
);
594 CV
= tgetstr("cV", &capbuf
);
596 CI
= tgetstr("cI", &capbuf
);
598 CR
= tgetstr("cR", &capbuf
);
605 pair(&CQ
, &CV
, "ve", "vs");
608 # endif /* !CRUNCH */
609 #endif /* !NO_CURSORSHAPE */
621 strcpy(POPUPcolor
, SO
);
624 strcpy(VISIBLEcolor
, MV
);
631 /* This function gets the window size. It uses the TIOCGWINSZ ioctl call if
632 * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
633 * This function is called once during initialization, and thereafter it is
634 * called whenever the SIGWINCH signal is sent to this process.
646 /* reset the signal vector */
647 signal(SIGWINCH
, getsize
);
650 /* get the window size, one way or another. */
653 if (ioctl(2, TIOCGWINSZ
, &size
) >= 0)
660 /* Amiga gets window size by asking the console.device */
661 if (!strcmp(TERMTYPE
, termtype
))
666 Write(Output(), "\2330 q", 4); /* Ask the console.device */
667 len
= Read(Input(), buf
, 29);
669 sscanf(&buf
[5], "%d;%d", &lines
, &cols
);
672 if ((lines
== 0 || cols
== 0) && signo
== 0)
674 LINES
= tgetnum("li");
675 COLS
= tgetnum("co");
679 if (!strcmp(termtype
, "rainbow"))
681 /* Determine whether Rainbow is in 80-column or 132-column mode */
682 cols
= *(unsigned char far
*)0xee000f57L
;
701 /* Make sure we got values that we can live with */
702 if (LINES
< 2 || COLS
< 30)
704 write(2, "Screen too small\n", (unsigned)17);
713 if (*o_lines
!= LINES
|| *o_columns
!= COLS
)
722 /* This is a function version of addch() -- it is used by tputs() */
731 /* This function quickly adds a string to the output queue. It does *NOT*
732 * convert \n into <CR><LF>.
747 for (s_
=(str
), d_
=stdscr
; *d_
++ = *s_
++; )
753 /* Output the ESC sequence needed to go into any video mode, if supported */
763 else if (a
== A_UNDERLINE
)
768 else if (a
== A_ALTCHARSET
)
780 /* Insert a single character into the display */
796 VOIDBIOS(;,ttywrite(kbuf
, (unsigned)(stdscr
- kbuf
)));
803 if (stdscr
- kbuf
> 2000)
805 VOIDBIOS(stdscr
= kbuf
,
807 ttywrite(kbuf
, (unsigned)(stdscr
- kbuf
));
814 /* This function is called during termination. It resets color modes */
817 /* if ANSI color terminal, then reset the colors */
818 if (!strcmp(UP
, "\033[A"))
820 tputs("\033[37;40m\033[m", 1, faddch
);
827 /* This sets the color strings that work for ANSI terminals. If the TERMCAP
828 * doesn't look like an ANSI terminal, then it returns FALSE. If the colors
829 * aren't understood, it also returns FALSE. If all goes well, it returns TRUE
831 int ansicolor(cmode
, attrbyte
)
832 int cmode
; /* mode to set, e.g. A_NORMAL */
833 int attrbyte
; /* IBM PC attribute byte */
835 char temp
[16]; /* hold the new mode string */
837 /* if not ANSI-ish, then fail */
838 if (strcmp(UP
, "\033[A") && strcmp(UP
, "\033OA"))
840 msg("Don't know how to set colors for this terminal");
844 /* construct the color string */
845 sprintf(temp
, "\033[m\033[3%c;4%c%s%sm",
846 "04261537"[attrbyte
& 0x07],
847 "04261537"[(attrbyte
>> 4) & 0x07],
848 (attrbyte
& 0x08) ? ";1" : "",
849 (attrbyte
& 0x80) ? ";5" : "");
851 /* stick it in the right place */
855 if (!strcmp(MEcolor
, normalcolor
))
856 strcpy(MEcolor
, temp
);
857 if (!strcmp(UEcolor
, normalcolor
))
858 strcpy(UEcolor
, temp
);
859 if (!strcmp(AEcolor
, normalcolor
))
860 strcpy(AEcolor
, temp
);
861 if (!strcmp(SEcolor
, normalcolor
))
862 strcpy(SEcolor
, temp
);
864 strcpy(normalcolor
, temp
);
865 tputs(normalcolor
, 1, faddch
);
869 strcpy(MDcolor
, temp
);
870 strcpy(MEcolor
, normalcolor
);
874 strcpy(UScolor
, temp
);
875 strcpy(UEcolor
, normalcolor
);
879 strcpy(AScolor
, temp
);
880 strcpy(AEcolor
, normalcolor
);
884 strcpy(SOcolor
, temp
);
885 strcpy(SEcolor
, normalcolor
);
890 strcpy(POPUPcolor
, temp
);
896 strcpy(VISIBLEcolor
, temp
);
905 /* This function outputs the ESC sequence needed to switch the screen back
906 * to "normal" mode. On color terminals which haven't had their color set
907 * yet, this is one of the termcap strings; for color terminals that really
908 * have had colors defined, we just the "normal color" escape sequence.
913 tputs(MEcolor
, 1, faddch
);
915 tputs(UEcolor
, 1, faddch
);
917 tputs(AEcolor
, 1, faddch
);
919 tputs(SEcolor
, 1, faddch
);
925 #endif /* !NO_COLOR */