libutil: add O_NOCTTY back to old pty open code
[minix.git] / commands / elvis / curses.c
blobf8cc76742a3b0fa6467653448187458297e951df
1 /* curses.c */
3 /* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
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.
17 #include "config.h"
18 #include "vi.h"
20 #if ANY_UNIX
21 /* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
22 * (KJB)
24 # include <termios.h>
25 # if MINIX
26 # include <sys/ioctl.h>
27 # endif
28 #endif
30 #if TOS
31 # include <osbind.h>
32 #endif
34 #if OSK
35 # include <sgstat.h>
36 #endif
38 #if VMS
39 extern int VMS_read_raw; /* Set in initscr() */
40 #endif
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 */
49 #if OSK
50 char PC_; /* Pad char */
51 char *BC; /* backspace character string */
52 #else
53 char PC; /* Pad char */
54 #endif
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 */
71 #ifndef NO_VISIBLE
72 char *MV; /* :mv=: "visible" selection start */
73 #endif
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 */
79 #if OSK
80 char *SR_; /* :sr=: scroll reverse */
81 #else
82 char *SR; /* :sr=: scroll reverse */
83 #endif
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 */
95 #ifndef NO_FKEY
96 char *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */
97 #endif
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
105 #if 1
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 */
111 #else
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 */
117 #endif
118 #endif
119 char *aend = ""; /* end an attribute -- either UE or ME */
120 char ERASEKEY; /* backspace key taken from ioctl structure */
121 #ifndef NO_COLOR
122 char normalcolor[16];
123 char SOcolor[16];
124 char SEcolor[16];
125 char UScolor[16];
126 char UEcolor[16];
127 char MDcolor[16];
128 char MEcolor[16];
129 char AScolor[16];
130 char AEcolor[16];
131 # ifndef NO_POPUP
132 char POPUPcolor[16];
133 # endif
134 # ifndef NO_VISIBLE
135 char VISIBLEcolor[16];
136 # endif
137 #endif
139 #if ANY_UNIX
140 static struct termios oldtermio; /* original tty mode */
141 static struct termios newtermio; /* cbreak/noecho tty mode */
142 #endif
144 #if OSK
145 static struct sgbuf oldsgttyb; /* orginal tty mode */
146 static struct sgbuf newsgttyb; /* noecho tty mode */
147 #endif
149 static char *capbuf; /* capability string buffer */
152 /* Initialize the Curses package. */
153 void initscr()
155 /* make sure TERM variable is set */
156 termtype = getenv("TERM");
158 #if VMS
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");
165 #endif
166 #if MSDOS
167 /* For MS-DOS, if TERM is unset we can default to "pcbios", or
168 * maybe "rainbow".
170 if (!termtype)
172 #ifdef RAINBOW
173 if (*(unsigned char far*)(0xffff000eL) == 6 /* Rainbow 100a */
174 || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
176 termtype = "rainbow";
178 else
179 #endif
180 termtype = "pcbios";
182 if (!strcmp(termtype, "pcbios"))
183 #else
184 if (!termtype)
185 #endif
187 #if ANY_UNIX
188 write(2, "Environment variable TERM must be set\n", (unsigned)38);
189 exit(1);
190 #endif
191 #if OSK
192 writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
193 exit(1);
194 #endif
195 #if AMIGA
196 termtype = TERMTYPE;
197 starttcap(termtype);
198 #endif
199 #if MSDOS
200 starttcap("pcbios");
201 #endif
202 #if TOS
203 termtype = "vt52";
204 starttcap(termtype);
205 #endif
206 #if VMS
207 write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
208 exit(1);
209 #endif
211 else
213 #if MSDOS
214 *o_pcbios = 0;
215 #endif
216 /* start termcap stuff */
217 starttcap(termtype);
220 /* create stdscr and curscr */
221 stdscr = kbuf;
223 /* change the terminal mode to cbreak/noecho */
224 #if ANY_UNIX
225 tcgetattr(2, &oldtermio);
226 #endif
228 #if OSK
229 _gs_opt(0, &oldsgttyb);
230 #endif
232 #if VMS
233 VMS_read_raw = 1; /* cbreak/noecho */
234 vms_open_tty();
235 #endif
236 resume_curses(TRUE);
239 /* Shut down the Curses package. */
240 void endwin()
242 /* change the terminal mode back the way it was */
243 suspend_curses();
244 #if AMIGA
245 amiclosewin();
246 #endif
250 static int curses_active = FALSE;
252 /* Send any required termination strings. Turn off "raw" mode. */
253 void suspend_curses()
255 #ifndef NO_CURSORSHAPE
256 if (has_CQ)
258 do_CQ();
260 #endif
261 if (has_TE) /* GB */
263 do_TE();
265 if (has_KE)
267 do_KE();
269 #ifndef NO_COLOR
270 quitcolor();
271 #endif
272 refresh();
274 /* change the terminal mode back the way it was */
275 #if ANY_UNIX
276 tcsetattr(2, TCSADRAIN, &oldtermio);
277 #endif
278 #if OSK
279 _ss_opt(0, &oldsgttyb);
280 #endif
281 #if AMIGA
282 ttyshutdown();
283 #endif
284 #if MSDOS
285 raw_set_stdio(FALSE);
286 #endif
288 #if VMS
289 VMS_read_raw = 0;
290 #endif
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)
299 int quietly;
301 if (!curses_active)
303 /* change the terminal mode to cbreak/noecho */
304 #if ANY_UNIX
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);
316 #endif
317 #if OSK
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;
326 #endif
327 #if AMIGA
328 /* turn on window resize and RAW */
329 ttysetup();
330 #endif
331 #if MSDOS
332 raw_set_stdio(TRUE);
333 #endif
335 #if VMS
336 VMS_read_raw = 1;
337 { int c;
338 read(0,&c,0); /* Flush the tty buffer. */
340 ERASEKEY = '\177'; /* Accept <DEL> as <^H> for VMS */
341 #endif
343 if (has_TI) /* GB */
345 do_TI();
347 if (has_KS)
349 do_KS();
352 curses_active = TRUE;
355 /* If we're supposed to quit quietly, then we're done */
356 if (quietly)
358 return;
361 signal(SIGINT, SIG_IGN);
363 move(LINES - 1, 0);
364 do_SO();
365 #if VMS
366 qaddstr("\n[Press <RETURN> to continue]");
367 #else
368 qaddstr("[Press <RETURN> to continue]");
369 #endif
370 do_SE();
371 refresh();
372 ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
373 if (kbuf[0] == ':')
375 mode = MODE_COLON;
376 addch('\n');
377 refresh();
379 else
381 mode = MODE_VI;
382 redraw(MARK_UNSET, FALSE);
384 exwrote = 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 */
394 char *val;
396 val = tgetstr(s, &capbuf);
397 if (val)
399 *T = val;
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 */
409 mayhave(T, s);
410 if (!*T)
412 write(2, "This termcap entry lacks the :", (unsigned)30);
413 write(2, s, (unsigned)2);
414 write(2, "=: capability\n", (unsigned)14);
415 #if OSK
416 write(2, "\l", 1);
417 #endif
418 exit(1);
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 */
432 mayhave(T, sT);
433 mayhave(U, sU);
434 if (!**T || !**U)
436 *T = *U = "";
441 void getsize(int signo);
443 /* Read everything from termcap */
444 static void starttcap(term)
445 char *term;
447 static char cbmem[800];
449 /* allocate memory for capbuf */
450 capbuf = cbmem;
452 /* get the termcap entry */
453 switch (tgetent(kbuf, term))
455 case -1:
456 write(2, "Can't read /etc/termcap\n", (unsigned)24);
457 #if OSK
458 write(2, "\l", 1);
459 #endif
460 exit(2);
462 case 0:
463 write(2, "Unrecognized TERM type\n", (unsigned)23);
464 #if OSK
465 write(2, "\l", 1);
466 #endif
467 exit(3);
470 /* get strings */
471 musthave(&UP, "up");
472 mayhave(&VB, "vb");
473 musthave(&CM, "cm");
474 pair(&SO, &SE, "so", "se");
475 mayhave(&TI, "ti");
476 mayhave(&TE, "te");
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");
484 if (!*AS)
486 AS = US;
487 AE = UE;
490 #ifndef NO_VISIBLE
491 MV = SO; /* by default */
492 mayhave(&MV, "mv");
493 #endif
494 mayhave(&AL, "al");
495 mayhave(&DL, "dl");
496 musthave(&CE, "ce");
497 mayhave(&CD, "cd");
498 #if OSK
499 mayhave(&SR_, "sr");
500 #else
501 mayhave(&SR, "sr");
502 #endif
503 pair(&IM, &EI, "im", "ei");
504 mayhave(&IC, "ic");
505 mayhave(&DC, "dc");
507 /* other termcap stuff */
508 AM = (tgetflag("am") && !tgetflag("xn"));
509 PT = tgetflag("pt");
510 #if AMIGA
511 amiopenwin(termtype); /* Must run this before ttysetup(); */
512 ttysetup(); /* Must run this before getsize(0); */
513 #endif
514 getsize(0);
516 /* Key sequences */
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 */
527 #ifndef CRUNCH
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.) */
535 mayhave(&HM, "HM");
536 mayhave(&EN, "EN");
537 #endif
538 #ifndef NO_FKEY
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");
571 # ifndef NO_ALT_FKEY
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");
582 # endif
583 # endif
584 # endif
585 #endif
587 #ifndef NO_CURSORSHAPE
588 /* cursor shapes */
589 CQ = tgetstr("cQ", &capbuf);
590 if (has_CQ)
592 CX = tgetstr("cX", &capbuf);
593 if (!CX) CX = CQ;
594 CV = tgetstr("cV", &capbuf);
595 if (!CV) CV = CQ;
596 CI = tgetstr("cI", &capbuf);
597 if (!CI) CI = CQ;
598 CR = tgetstr("cR", &capbuf);
599 if (!CR) CR = CQ;
601 # ifndef CRUNCH
602 else
604 CQ = CV = "";
605 pair(&CQ, &CV, "ve", "vs");
606 CX = CI = CR = CQ;
608 # endif /* !CRUNCH */
609 #endif /* !NO_CURSORSHAPE */
611 #ifndef NO_COLOR
612 strcpy(SOcolor, SO);
613 strcpy(SEcolor, SE);
614 strcpy(AScolor, AS);
615 strcpy(AEcolor, AE);
616 strcpy(MDcolor, MD);
617 strcpy(MEcolor, ME);
618 strcpy(UScolor, US);
619 strcpy(UEcolor, UE);
620 # ifndef NO_POPUP
621 strcpy(POPUPcolor, SO);
622 # endif
623 # ifndef NO_VISIBLE
624 strcpy(VISIBLEcolor, MV);
625 # endif
626 #endif
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.
636 void getsize(signo)
637 int signo;
639 int lines;
640 int cols;
641 #ifdef TIOCGWINSZ
642 struct winsize size;
643 #endif
645 #ifdef SIGWINCH
646 /* reset the signal vector */
647 signal(SIGWINCH, getsize);
648 #endif
650 /* get the window size, one way or another. */
651 lines = cols = 0;
652 #ifdef TIOCGWINSZ
653 if (ioctl(2, TIOCGWINSZ, &size) >= 0)
655 lines = size.ws_row;
656 cols = size.ws_col;
658 #endif
659 #if AMIGA
660 /* Amiga gets window size by asking the console.device */
661 if (!strcmp(TERMTYPE, termtype))
663 auto long len;
664 auto char buf[30];
666 Write(Output(), "\2330 q", 4); /* Ask the console.device */
667 len = Read(Input(), buf, 29);
668 buf[len] = '\000';
669 sscanf(&buf[5], "%d;%d", &lines, &cols);
671 #endif
672 if ((lines == 0 || cols == 0) && signo == 0)
674 LINES = tgetnum("li");
675 COLS = tgetnum("co");
677 #if MSDOS
678 # ifdef RAINBOW
679 if (!strcmp(termtype, "rainbow"))
681 /* Determine whether Rainbow is in 80-column or 132-column mode */
682 cols = *(unsigned char far *)0xee000f57L;
684 else
685 # endif
687 lines = v_rows();
688 cols = v_cols();
690 #endif
691 if (lines >= 2)
693 LINES = lines;
696 if (cols >= 30)
698 COLS = cols;
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);
705 #if OSK
706 write(2, "\l", 1);
707 #endif
708 endwin();
709 exit(2);
712 #if AMIGA
713 if (*o_lines != LINES || *o_columns != COLS)
715 *o_lines = LINES;
716 *o_columns = COLS;
718 #endif
722 /* This is a function version of addch() -- it is used by tputs() */
723 int faddch(ch)
724 int ch;
726 addch(ch);
728 return 0;
731 /* This function quickly adds a string to the output queue. It does *NOT*
732 * convert \n into <CR><LF>.
734 void qaddstr(str)
735 char *str;
737 REG char *s_, *d_;
739 #if MSDOS
740 if (o_pcbios[0])
742 while (*str)
743 qaddch(*str++);
744 return;
746 #endif
747 for (s_=(str), d_=stdscr; *d_++ = *s_++; )
750 stdscr = d_ - 1;
753 /* Output the ESC sequence needed to go into any video mode, if supported */
754 void attrset(a)
755 int a;
757 do_aend();
758 if (a == A_BOLD)
760 do_MD();
761 aend = ME;
763 else if (a == A_UNDERLINE)
765 do_US();
766 aend = UE;
768 else if (a == A_ALTCHARSET)
770 do_AS();
771 aend = AE;
773 else
775 aend = "";
780 /* Insert a single character into the display */
781 void insch(ch)
782 int ch;
784 if (has_IM)
785 do_IM();
786 do_IC();
787 qaddch(ch);
788 if (has_EI)
789 do_EI();
792 void wrefresh()
794 if (stdscr != kbuf)
796 VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
797 stdscr = kbuf;
801 void wqrefresh()
803 if (stdscr - kbuf > 2000)
805 VOIDBIOS(stdscr = kbuf,
807 ttywrite(kbuf, (unsigned)(stdscr - kbuf));
808 stdscr = kbuf;
813 #ifndef NO_COLOR
814 /* This function is called during termination. It resets color modes */
815 int ansiquit()
817 /* if ANSI color terminal, then reset the colors */
818 if (!strcmp(UP, "\033[A"))
820 tputs("\033[37;40m\033[m", 1, faddch);
821 clrtoeol();
822 return 1;
824 return 0;
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");
841 return 0;
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 */
852 switch (cmode)
854 case A_NORMAL:
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);
866 break;
868 case A_BOLD:
869 strcpy(MDcolor, temp);
870 strcpy(MEcolor, normalcolor);
871 break;
873 case A_UNDERLINE:
874 strcpy(UScolor, temp);
875 strcpy(UEcolor, normalcolor);
876 break;
878 case A_ALTCHARSET:
879 strcpy(AScolor, temp);
880 strcpy(AEcolor, normalcolor);
881 break;
883 case A_STANDOUT:
884 strcpy(SOcolor, temp);
885 strcpy(SEcolor, normalcolor);
886 break;
888 #ifndef NO_POPUP
889 case A_POPUP:
890 strcpy(POPUPcolor, temp);
891 break;
892 #endif
894 #ifndef NO_VISIBLE
895 case A_VISIBLE:
896 strcpy(VISIBLEcolor, temp);
897 break;
898 #endif
901 return 1;
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.
910 endcolor()
912 if (aend == ME)
913 tputs(MEcolor, 1, faddch);
914 else if (aend == UE)
915 tputs(UEcolor, 1, faddch);
916 else if (aend == AE)
917 tputs(AEcolor, 1, faddch);
918 else if (aend == SE)
919 tputs(SEcolor, 1, faddch);
920 aend = "";
921 return 0;
925 #endif /* !NO_COLOR */