Revert Jim's earlier "fix" :)
[asterisk/asterisk.git] / term.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Channel Management
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/time.h>
18 #include <signal.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <asterisk/term.h>
25 #include <asterisk/options.h>
26 #include <asterisk/lock.h>
27 #include "asterisk.h"
28
29 static int vt100compat = 0;
30
31 static char prepdata[80] = "";
32 static char enddata[80] = "";
33 static char quitdata[80] = "";
34
35 static const char *termpath[] = {
36         "/usr/share/terminfo",
37         "/usr/local/share/misc/terminfo",
38         "/usr/lib/terminfo",
39         NULL
40         };
41
42 /* Ripped off from Ross Ridge, but it's public domain code (libmytinfo) */
43 static short convshort(char *s)
44 {
45         register int a,b;
46
47         a = (int) s[0] & 0377;
48         b = (int) s[1] & 0377;
49
50         if (a == 0377 && b == 0377)
51                 return -1;
52         if (a == 0376 && b == 0377)
53                 return -2;
54
55         return a + b * 256;
56 }
57
58 int term_init(void)
59 {
60         char *term = getenv("TERM");
61         char termfile[256] = "";
62         char buffer[512] = "";
63         int termfd = -1, parseokay = 0, i;
64
65         if (!term)
66                 return 0;
67         if (!option_console || option_nocolor || !option_nofork)
68                 return 0;
69
70         for (i=0 ;; i++) {
71                 if (termpath[i] == NULL) {
72                         break;
73                 }
74                 snprintf(termfile, sizeof(termfile), "%s/%c/%s", termpath[i], *term, term);
75                 termfd = open(termfile, O_RDONLY);
76                 if (termfd > -1) {
77                         break;
78                 }
79         }
80         if (termfd > -1) {
81                 int actsize = read(termfd, buffer, sizeof(buffer) - 1);
82                 short sz_names = convshort(buffer + 2);
83                 short sz_bools = convshort(buffer + 4);
84                 short n_nums   = convshort(buffer + 6);
85
86                 /* if ((sz_names + sz_bools) & 1)
87                         sz_bools++; */
88
89                 if (sz_names + sz_bools + n_nums < actsize) {
90                         /* Offset 13 is defined in /usr/include/term.h, though we do not
91                          * include it here, as it conflicts with include/asterisk/term.h */
92                         short max_colors = convshort(buffer + 12 + sz_names + sz_bools + 13 * 2);
93                         if (max_colors > 0) {
94                                 vt100compat = 1;
95                         }
96                         parseokay = 1;
97                 }
98                 close(termfd);
99         }
100
101         if (!parseokay) {
102                 /* These comparisons should not be substrings nor case-insensitive, as
103                  * terminal types are very particular about how they treat suffixes and
104                  * capitalization.  For example, terminal type 'linux-m' does NOT
105                  * support color, while 'linux' does.  Not even all vt100* terminals
106                  * support color, either (e.g. 'vt100+fnkeys'). */
107                 if (!strcmp(term, "linux")) {
108                         vt100compat = 1;
109                 } else if (!strcmp(term, "xterm")) {
110                         vt100compat = 1;
111                 } else if (!strcmp(term, "xterm-color")) {
112                         vt100compat = 1;
113                 } else if (!strncmp(term, "Eterm", 5)) {
114                         /* Both entries which start with Eterm support color */
115                         vt100compat = 1;
116                 } else if (!strcmp(term, "vt100")) {
117                         vt100compat = 1;
118                 } else if (!strncmp(term, "crt", 3)) {
119                         /* Both crt terminals support color */
120                         vt100compat = 1;
121                 }
122         }
123
124         if (vt100compat) {
125                 /* Make commands show up in nice colors */
126                 snprintf(prepdata, sizeof(prepdata), "%c[%d;%d;%dm", ESC, ATTR_BRIGHT, COLOR_BROWN, COLOR_BLACK + 10);
127                 snprintf(enddata, sizeof(enddata), "%c[%d;%d;%dm", ESC, ATTR_RESET, COLOR_WHITE, COLOR_BLACK + 10);
128                 snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
129         }
130         return 0;
131 }
132
133 char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
134 {
135         int attr=0;
136         char tmp[40];
137         if (!vt100compat) {
138                 strncpy(outbuf, inbuf, maxout -1);
139                 return outbuf;
140         }
141         if (!fgcolor && !bgcolor) {
142                 strncpy(outbuf, inbuf, maxout - 1);
143                 return outbuf;
144         }
145         if ((fgcolor & 128) && (bgcolor & 128)) {
146                 /* Can't both be highlighted */
147                 strncpy(outbuf, inbuf, maxout - 1);
148                 return outbuf;
149         }
150         if (!bgcolor)
151                 bgcolor = COLOR_BLACK;
152
153         if (bgcolor) {
154                 bgcolor &= ~128;
155                 bgcolor += 10;
156         }
157         if (fgcolor & 128) {
158                 attr = ATTR_BRIGHT;
159                 fgcolor &= ~128;
160         }
161         if (fgcolor && bgcolor) {
162                 snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
163         } else if (bgcolor) {
164                 snprintf(tmp, sizeof(tmp), "%d", bgcolor);
165         } else if (fgcolor) {
166                 snprintf(tmp, sizeof(tmp), "%d", fgcolor);
167         }
168         if (attr) {
169                 snprintf(outbuf, maxout, "%c[%d;%sm%s%c[0;%d;%dm", ESC, attr, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
170         } else {
171                 snprintf(outbuf, maxout, "%c[%sm%s%c[0;%d;%dm", ESC, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
172         }
173         return outbuf;
174 }
175
176 char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
177 {
178         int attr=0;
179         char tmp[40];
180         if ((!vt100compat) || (!fgcolor && !bgcolor)) {
181                 *outbuf = '\0';
182                 return outbuf;
183         }
184         if ((fgcolor & 128) && (bgcolor & 128)) {
185                 /* Can't both be highlighted */
186                 *outbuf = '\0';
187                 return outbuf;
188         }
189         if (!bgcolor)
190                 bgcolor = COLOR_BLACK;
191
192         if (bgcolor) {
193                 bgcolor &= ~128;
194                 bgcolor += 10;
195         }
196         if (fgcolor & 128) {
197                 attr = ATTR_BRIGHT;
198                 fgcolor &= ~128;
199         }
200         if (fgcolor && bgcolor) {
201                 snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
202         } else if (bgcolor) {
203                 snprintf(tmp, sizeof(tmp), "%d", bgcolor);
204         } else if (fgcolor) {
205                 snprintf(tmp, sizeof(tmp), "%d", fgcolor);
206         }
207         if (attr) {
208                 snprintf(outbuf, maxout, "%c[%d;%sm", ESC, attr, tmp);
209         } else {
210                 snprintf(outbuf, maxout, "%c[%sm", ESC, tmp);
211         }
212         return outbuf;
213 }
214
215 char *term_strip(char *outbuf, char *inbuf, int maxout)
216 {
217         char *outbuf_ptr = outbuf, *inbuf_ptr = inbuf;
218
219         while (outbuf_ptr < outbuf + maxout) {
220                 switch (*inbuf_ptr) {
221                         case ESC:
222                                 while (*inbuf_ptr && (*inbuf_ptr != 'm'))
223                                         inbuf_ptr++;
224                                 break;
225                         default:
226                                 *outbuf_ptr = *inbuf_ptr;
227                                 outbuf_ptr++;
228                 }
229                 if (! *inbuf_ptr)
230                         break;
231                 inbuf_ptr++;
232         }
233         return outbuf;
234 }
235
236 char *term_prompt(char *outbuf, const char *inbuf, int maxout)
237 {
238         if (!vt100compat) {
239                 strncpy(outbuf, inbuf, maxout -1);
240                 return outbuf;
241         }
242         snprintf(outbuf, maxout, "%c[%d;%d;%dm%c%c[%d;%d;%dm%s",
243                 ESC, ATTR_BRIGHT, COLOR_BLUE, COLOR_BLACK + 10,
244                 inbuf[0],
245                 ESC, 0, COLOR_WHITE, COLOR_BLACK + 10,
246                 inbuf + 1);
247         return outbuf;
248 }
249
250 char *term_prep(void)
251 {
252         return prepdata;
253 }
254
255 char *term_end(void)
256 {
257         return enddata;
258 }
259
260 char *term_quit(void)
261 {
262         return quitdata;
263 }