Commit | Line | Data |
---|---|---|
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 | |
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 *KS = ""; /* :ks=: init string for cursor */ | |
93 | char *KE = ""; /* :ke=: restore string for cursor */ | |
94 | char *KU; /* :ku=: key sequence sent by up arrow */ | |
95 | char *KD; /* :kd=: key sequence sent by down arrow */ | |
96 | char *KL; /* :kl=: key sequence sent by left arrow */ | |
97 | char *KR; /* :kr=: key sequence sent by right arrow */ | |
98 | char *HM; /* :HM=: key sequence sent by the <Home> key */ | |
99 | char *EN; /* :EN=: key sequence sent by the <End> key */ | |
100 | char *PU; /* :PU=: key sequence sent by the <PgUp> key */ | |
101 | char *PD; /* :PD=: key sequence sent by the <PgDn> key */ | |
102 | char *KI; /* :kI=: key sequence sent by the <Insert> key */ | |
103 | #ifndef NO_FKEY | |
104 | char *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */ | |
105 | #endif | |
106 | char *IM = ""; /* :im=: insert mode start */ | |
107 | char *IC = ""; /* :ic=: insert the following character */ | |
108 | char *EI = ""; /* :ei=: insert mode end */ | |
109 | char *DC; /* :dc=: delete a character */ | |
110 | char *TI = ""; /* :ti=: terminal init */ /* GB */ | |
111 | char *TE = ""; /* :te=: terminal exit */ /* GB */ | |
112 | #ifndef NO_CURSORSHAPE | |
113 | #if 1 | |
114 | char *CQ = (char *)0;/* :cQ=: normal cursor */ | |
115 | char *CX = (char *)1;/* :cX=: cursor used for EX command/entry */ | |
116 | char *CV = (char *)2;/* :cV=: cursor used for VI command mode */ | |
117 | char *CI = (char *)3;/* :cI=: cursor used for VI input mode */ | |
118 | char *CR = (char *)4;/* :cR=: cursor used for VI replace mode */ | |
119 | #else | |
120 | char *CQ = ""; /* :cQ=: normal cursor */ | |
121 | char *CX = ""; /* :cX=: cursor used for EX command/entry */ | |
122 | char *CV = ""; /* :cV=: cursor used for VI command mode */ | |
123 | char *CI = ""; /* :cI=: cursor used for VI input mode */ | |
124 | char *CR = ""; /* :cR=: cursor used for VI replace mode */ | |
125 | #endif | |
126 | #endif | |
127 | char *aend = ""; /* end an attribute -- either UE or ME */ | |
128 | char ERASEKEY; /* backspace key taken from ioctl structure */ | |
129 | #ifndef NO_COLOR | |
130 | char normalcolor[16]; | |
131 | char SOcolor[16]; | |
132 | char SEcolor[16]; | |
133 | char UScolor[16]; | |
134 | char UEcolor[16]; | |
135 | char MDcolor[16]; | |
136 | char MEcolor[16]; | |
137 | char AScolor[16]; | |
138 | char AEcolor[16]; | |
139 | # ifndef NO_POPUP | |
140 | char POPUPcolor[16]; | |
141 | # endif | |
142 | # ifndef NO_VISIBLE | |
143 | char VISIBLEcolor[16]; | |
144 | # endif | |
145 | #endif | |
146 | ||
147 | #if ANY_UNIX | |
148 | # if UNIXV | |
149 | # ifdef TERMIOS | |
150 | static struct termios oldtermio; /* original tty mode */ | |
151 | static struct termios newtermio; /* cbreak/noecho tty mode */ | |
152 | # else | |
153 | static struct termio oldtermio; /* original tty mode */ | |
154 | static struct termio newtermio; /* cbreak/noecho tty mode */ | |
155 | # endif | |
156 | # else | |
157 | static struct sgttyb oldsgttyb; /* original tty mode */ | |
158 | static struct sgttyb newsgttyb; /* cbreak/nl/noecho tty mode */ | |
159 | static int oldint; /* ^C or DEL, the "intr" character */ | |
160 | # ifdef TIOCSLTC | |
161 | static int oldswitch; /* ^Z, the "suspend" character */ | |
162 | static int olddswitch; /* ^Y, the "delayed suspend" char */ | |
163 | static int oldquote; /* ^V, the "quote next char" char */ | |
164 | # endif | |
165 | # endif | |
166 | #endif | |
167 | ||
168 | #if OSK | |
169 | static struct sgbuf oldsgttyb; /* orginal tty mode */ | |
170 | static struct sgbuf newsgttyb; /* noecho tty mode */ | |
171 | #endif | |
172 | ||
173 | static char *capbuf; /* capability string buffer */ | |
174 | ||
175 | ||
176 | /* Initialize the Curses package. */ | |
177 | void 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. */ | |
272 | void 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 | ||
282 | static int curses_active = FALSE; | |
283 | ||
284 | /* Send any required termination strings. Turn off "raw" mode. */ | |
285 | void 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, <buf); | |
329 | ltbuf.t_suspc = oldswitch; | |
330 | ltbuf.t_dsuspc = olddswitch; | |
331 | ltbuf.t_lnextc = oldquote; | |
332 | ioctl(2, TIOCSLTC, <buf); | |
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 | */ | |
356 | void 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, <buf); | |
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, <buf); | |
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 */ | |
492 | static 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 */ | |
507 | static 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 | */ | |
528 | static 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 */ | |
545 | static 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 | */ | |
737 | int 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() */ | |
822 | int 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 | */ | |
833 | void 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 */ | |
853 | void 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 */ | |
880 | void 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 | ||
891 | void wrefresh() | |
892 | { | |
893 | if (stdscr != kbuf) | |
894 | { | |
895 | VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf))); | |
896 | stdscr = kbuf; | |
897 | } | |
898 | } | |
899 | ||
900 | void 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 */ | |
914 | int 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 | */ | |
930 | int 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 | */ | |
1009 | endcolor() | |
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 */ |