Bug 134: Remove lisp-initd-dir from startup.el. Usage of path-construct makes it...
[sxemacs] / contrib / tty-colors.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <fcntl.h>
4 #include <curses.h>
5 #include <term.h>
6 #include <string.h>
7 #include <termios.h>
8 #include <unistd.h>
9
10 /*
11  * For the terminal info
12  */
13 static char term_buffer[8192];
14
15 /*
16  * For the capabilities
17  */
18 char    *setfore = NULL, 
19         *setback = NULL,  
20         *resetcolor = NULL, 
21         *standstr = NULL, 
22         *exit_stand = NULL,
23         *inicolor_str = NULL, 
24         *clrnames  = NULL,
25         *bold = NULL,    
26         *dim = NULL,
27         *reverse = NULL,
28         *blinking = NULL,
29         *exit_attr = NULL, 
30         *opair = NULL;
31       
32 int      maxcolors = 0,
33         maxpairs  = 0,
34         do_force_16  = 0;
35
36
37
38
39
40 /******************
41  * Initialize the terminal info
42  */
43 void init_terminal_data ()
44 {
45   char *termtype = getenv ("TERM");
46   int success;
47
48   if (termtype == 0) {
49     fprintf(stderr,"Specify a terminal type with `setenv TERM <yourtype>'.\n");
50     exit(1);
51   }
52
53   success = tgetent (term_buffer, termtype);
54   if (success < 0) {
55     fprintf(stderr,"Could not access the termcap data base.\n");
56     exit(1);
57   }
58   if (success == 0) {
59     fprintf(stderr,"Terminal type `%s' is not defined.\n", termtype);
60     exit(1);
61   }
62 }
63
64 /*******************
65  * Print a band with background of all available colors
66  */
67 void colormap( int do_boldstand ) 
68 {
69         int back;
70         for( back = 0; back < maxcolors; back++ ) {
71                 char *strB;
72                 strB = strdup(tparm(setback,back));
73                 printf("%s        %s",strB,resetcolor);
74                 if( back%8 == 7 )
75                         printf("\n");
76         }
77         if (do_boldstand) {
78                 for( back = 0; back < maxcolors; back++ ) {
79                         char *strB;
80                         strB = strdup(tparm(setfore,back));
81                         printf("%s%s%s        %s%s%s",bold,standstr,strB,resetcolor,
82                                exit_stand,exit_attr);
83                         if( back%8 == 7 )
84                                 printf("\n");
85                 }
86         }
87         for ( back = 0; back < maxcolors; back++ ) {
88                 char *strB;
89                 strB = strdup(tparm(setfore,back));
90                 printf("%sXXXXXXXX%s",strB,resetcolor);
91                 if( back%8 == 7 )
92                         printf("\n");
93         }
94         if ( bold ) {
95                 for ( back = 0; back < maxcolors; back++ ) {
96                         char *strB;
97                         strB = strdup(tparm(setfore,back));
98                         printf("%s%sXXXXXXXX%s%s",bold,strB,resetcolor,exit_attr);
99                         if( back%8 == 7 )
100                                 printf("\n");
101                 }
102         }
103 }
104
105
106 /*********************
107  * Print a table with all the fore and background 
108  * color combinations, with bold and optionally standout
109  */
110 void combinations_of_colors(int do_standout, int do_boldstand) 
111 {
112         int fore, back;
113         for( fore = 0; fore < maxcolors; fore ++ ) 
114                 for( back = 0; back < maxcolors; back ++ ) {
115                         char *strF, *strB;
116                         char *sstrF, *sstrB;
117                         strB = strdup(tparm(setback,back));
118                         strF = strdup(tparm(setfore,fore));
119                         printf( "%s%s%s [%3d|%3d]%s%s", "",strF,strB,fore,back,resetcolor,"");
120                         /* Bold */
121                         printf( "%s%s%sB[%3d|%3d]%s%s", bold,strF,strB,fore,back,resetcolor,exit_attr);
122                         /* Standout usually does not work good... do only if asked for */
123                         /* Since standout usually reverses, we'll reverse the fore and back too */
124                         sstrB = strdup(tparm(setback,fore));
125                         sstrF = strdup(tparm(setfore,back));
126                         if (do_standout)
127                                 printf( "%s%s%sS[%3d|%3d]%s%s",standstr,sstrF,sstrB,fore,back,resetcolor,exit_stand);
128                         if (do_boldstand)
129                                 printf( "%s%s%s%sS[%3d|%3d]%s%s%s",bold,standstr,sstrF,sstrB,fore,back,resetcolor,exit_stand,exit_attr);
130                         printf( "\n" );
131                 }
132         printf( "\n" );
133           
134 }
135
136
137 /** Query and assign a capability 
138  */
139 void capability(char**buf,char*code,char**var,char*message)
140 {
141         char *val = tgetstr(code,buf);
142         if ( ! val ) {
143                 *var=NULL;
144                 printf("%s\n",message);
145         } else {
146                 *var=strdup(val);
147         }
148 }
149
150
151 /****************************
152  * Retrieve the capabilities
153  */
154 void get_capabilities()
155 {
156         char buffer[2500]="", *buf=buffer;
157
158         /*
159          * Get the capabilities
160          */
161         maxcolors = tgetnum("Co");
162         if ( maxcolors <= 0 ) {
163                 printf("I am sorry, your terminal does not show color in the capabilities\n");
164         }
165         maxpairs = tgetnum("pa");
166         if (maxpairs <= 0 ) {
167                 printf("I am sorry, your terminal does not have the max color pairs information\n");
168         }
169         
170         capability(&buf,"AF",&setfore,
171                    "I am sorry, your terminal does not have the set foreground color string in the capabilities");
172         capability(&buf,"AB",&setback,
173                    "I am sorry, your terminal does not have the set background color string in the capabilities");
174         capability(&buf,"op",&resetcolor,
175                    "I am sorry, your terminal does not have the reset current color string in the capabilities");
176         capability(&buf,"md",&bold,
177                    "I am sorry, your terminal does not have the bold string in the capabilities");
178         capability(&buf,"mh",&dim,
179                    "I am sorry, your terminal does not have the dim string in the capabilities");
180         capability(&buf,"mr",&reverse,
181                    "I am sorry, your terminal does not have the reverse string in the capabilities");
182         capability(&buf,"mb",&blinking,
183                    "I am sorry, your terminal does not have the blinking string in the capabilities");
184         capability(&buf,"so",&standstr,
185                    "I am sorry, your terminal does not have the standout string in the capabilities");
186         capability(&buf,"se",&exit_stand,
187                    "I am sorry, your terminal does not have the exit standout string in the capabilities");
188         capability(&buf,"me",&exit_attr,
189                    "I am sorry, your terminal does not have the exit attribute string in the capabilities");
190         capability(&buf,"Ic",&inicolor_str,
191                    "I am sorry, your terminal does not have the init color string in the capabilities");
192         capability(&buf,"Yw",&clrnames,
193                 "I am sorry, your terminal does not have the color names string in the capabilities");
194         capability(&buf,"op",&opair,
195                 "I am sorry, your terminal does not have the original pairs string in the capabilities");
196 }
197
198
199 /********************
200  * Query the RGB map
201  */
202 void query_rgb()
203 {
204         int i, fd=fileno(stdin);
205         long mode;
206         struct termios ts;
207         
208         if ( ! isatty(fd) || ! isatty(fileno(stdout)) ) 
209                 printf("Sorry, but stdin and/or stdout is not the terminal tty so I cannot query it\n");
210         else {
211                 if ( ! inicolor_str ) 
212                         printf("According to your terminal info this terminal rgb query will hang. Press ^C to abort the query.\n");
213
214                 /* 
215                  * We need to do the equivalent of cbreak()
216                  */
217                 tcgetattr(fd,&ts);
218                 mode=ts.c_lflag; /* Save mode so we can restore afterwards */
219                 ts.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
220                 tcsetattr(fd, TCSANOW,&ts);
221                 ts.c_lflag = mode;
222
223                 /* Ask for the colors */
224                 for ( i = 0 ; 1 ; i ++ ) {
225                         char buffer[1000], 
226                                 *buf=buffer, 
227                                 *end=buffer+sizeof(buffer)-1;
228                         int interrupted = 0;
229                         
230                         /* This is a string retrieved from Noah
231                          * Friedmans xterm-frobs.el. I could not find
232                          * any termcap entry that verifies it 
233                          */
234                         printf("\e]4;%d;?;\e\\",i);
235                         fflush(stdout);
236                         memset(buffer,0,sizeof(buffer));
237                         while( buf!=end ) {
238                                 fd_set fdsr, fdse,fdsw;
239                                 int fds;
240                                 struct timeval t;
241                                 
242                                 t.tv_sec = 0;
243                                 t.tv_usec = 100000; /* 100ms */
244
245                                 FD_ZERO(&fdsr);
246                                 FD_ZERO(&fdse);
247                                 FD_ZERO(&fdsw);
248                                 FD_SET(fd, &fdsr);
249                                 FD_SET(fd, &fdse);
250                                 fds = select(fd+1,&fdsr,&fdsw,&fdse,&t);
251                                 if ( fds < 1) {
252                                         tcsetattr(fd, TCSANOW,&ts);
253                                         return;
254                                 }
255                                 if ( ! FD_ISSET(fd, &fdsr) ) {
256                                         tcsetattr(fd, TCSANOW,&ts);
257                                         return;
258                                 }
259                                 read(fd,buf,1);
260                                 if ( *buf == '\\') {
261                                         /* The response sequence ends with the only "\" 
262                                            of the response
263                                         */
264                                         break;
265                                 }
266                                 if ( *buf == '\ 3' ) {
267                                         /* 
268                                            If the terminal did not reply, chances are 
269                                            this is not supported and the user used ^C
270                                         */
271                                         interrupted=1;
272                                         break;
273                                 }
274                                 *buf++;
275                         }
276                         if (interrupted)
277                                 break;
278
279                         /* Extract the rgb values */
280                         buf=strstr(buffer,"rgb:");
281                         if( buf ) {
282                                 buf+=4;
283                                 char *end = strstr(buf,"\e\\");
284                                 if(end)
285                                           *end='\0';
286                         } else {
287                                 buf="Did not find info";
288                         }
289                         printf("Color %d: %s\n",i,buf);
290                         fflush(stdout);
291                 }
292
293                 /* Restore terminal settings */
294                 tcsetattr(fd, TCSANOW,&ts);
295         }
296 }
297
298
299 /**************
300  * Fake the capabilities the ansi terminal info
301  * would return
302  */
303 void force_ansi()
304 {
305         if ( ! (maxcolors > 0) ) {
306                 maxcolors = 8;
307                 printf("WARNING: Forcing ANSI testing, 8 colors\n");
308         }
309         if ( maxcolors == 8 && do_force_16 ) {
310                 maxcolors = 16;
311                 printf("WARNING: Forcing 16 color testing\n");
312         }
313         if ( ! setfore ) {
314                 setfore="\e[3%p1%dm";
315                 printf("WARNING: Forcing ANSI set foreground: ^[%s\n", setfore+1);
316         }
317         if ( ! setback ) {
318                 setback="\e[4%p1%dm";
319                 printf("WARNING: Forcing ANSI set background: ^[%s\n", setback+1);
320         }
321         if ( ! resetcolor ) {
322                 resetcolor="\e[39;49m";
323                 printf("WARNING: Forcing ANSI reset colour  : ^[%s\n", resetcolor+1);
324         }
325 }
326
327
328
329 int
330 main( int argc, char *argv[] )
331 {
332   int     do_colormap = 0, 
333           do_combinations = 0, 
334           do_standout = 0, 
335           do_boldstand = 0,
336           do_query = 0;
337
338   { /* Process arguments */
339           int i;
340           
341           for( i = 1; i < argc; i++ ) {
342                   if( ! strcmp(argv[i],"-m") )
343                           do_colormap = 1;
344                   if( ! strcmp(argv[i],"-c") )
345                           do_combinations=1;
346                   if ( ! strcmp(argv[i], "-f" ) )
347                           do_force_16 = 1;
348                   if( ! strcmp(argv[i],"-s") )
349                           do_standout=1;
350                   if( ! strcmp(argv[i],"-bs") )
351                           do_boldstand=1;
352                   if( ! strcmp(argv[i],"-q") )
353                           do_query=1;
354           }
355   }
356
357   init_terminal_data();
358
359   get_capabilities();
360
361   /*
362    * Report the capabilities
363    */
364   printf("\n\nTerminal: %s\n",getenv("TERM"));
365   if ( maxcolors > 0 )
366     printf("You've got %d colours\n",maxcolors);
367   if ( maxpairs > 0 )
368     printf("You've got %d pairs of colors possible\n",maxpairs);
369
370   if ( setfore )    printf("To set foreground: ^[%s\n", setfore+1);
371   if ( setback )    printf("To set background: ^[%s\n", setback+1);
372   if ( resetcolor ) printf("To reset colours : ^[%s\n", resetcolor+1);
373   if ( standstr )   printf("To standout      : ^[%s\n", standstr+1);
374   if ( bold )       printf("To bold          : ^[%s\n", bold+1);
375   if ( dim )        printf("To dim           : ^[%s\n", dim+1);
376   if ( reverse )    printf("To reverse       : ^[%s\n", reverse+1);
377   if ( blinking )   printf("To blinking      : ^[%s\n", blinking+1);
378   if ( exit_stand ) printf("To exit standout : ^[%s\n", exit_stand+1);
379   if ( exit_attr )  printf("To exit attribute: ^[%s\n", exit_attr+1);
380   if ( inicolor_str ) printf("To init color    : ^[%s\n", inicolor_str+1);
381   if ( clrnames )   printf("To color names   : ^[%s\n", clrnames+1);
382   if ( opair )      printf("To original pairs: ^[%s\n",   opair+1);
383   
384   
385
386   /*
387    * Let's try the ANSI defaults
388    */
389   if ( do_colormap || do_combinations ) {
390           force_ansi();
391   }
392
393   if ( do_query ) {
394           printf("\nQuery the RGB from the terminal:\n");
395           query_rgb();
396   }
397
398   if ( do_colormap ) {
399           printf("\nColormap:\n");
400           colormap( do_boldstand );
401   }
402
403   if ( do_combinations ) {
404           printf("\nColor combinations:\n");
405           combinations_of_colors( do_standout,
406                                   do_boldstand);
407   }
408
409   return 0;
410 }