Initial import from FreeBSD RELENG_4:
[games.git] / usr.sbin / pcvt / scon / scon.c
1 /*
2  * Copyright (c) 1992,1993,1994 Hellmuth Michaelis and Joerg Wunsch
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by
17  *      Hellmuth Michaelis and Joerg Wunsch
18  * 4. The name authors may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/usr.sbin/pcvt/scon/scon.c,v 1.5.6.1 2001/05/12 10:11:42 kris Exp $
33  */
34
35 static char *id =
36         "@(#)scon.c, 3.20, Last Edit-Date: [Sun Sep 25 12:33:21 1994]";
37
38 /*---------------------------------------------------------------------------*
39  *
40  *      history:
41  *
42  *      -hm     moving fd for default device from 1 -> 0 for such things
43  *              as "scon -p list | more" to be possible
44  *              (reported by Gordon L. Burditt, gordon@sneaky.lonestar.org)
45  *      -hm     adding option "a" for just returning the type of video adaptor
46  *      -hm     removing explicit HGC support, same as MDA ...
47  *      -hm     vga type/family/132col support info on -l
48  *      -hm     force 24 lines in DEC 25 lines mode and HP 28 lines mode
49  *      -hm     fixed bug with 132 column mode display status display
50  *      -jw     added 132/80 col mode switching
51  *      -hm     removed -h flag, use -? now ... ;-)
52  *      -hm     S3 chipsets ..
53  *      -hm     Cirrus chipsets support from Onno van der Linden
54  *      -hm     -m option, display monitor type
55  *      -hm     bugfix, scon -c <screen-num> cleared dest screen, fixed
56  *
57  *---------------------------------------------------------------------------*/
58
59 #include <stdio.h>
60 #include <err.h>
61 #include <fcntl.h>
62 #include <machine/pcvt_ioctl.h>
63
64 #define DEFAULTFD 0
65
66 int aflag = -1;
67 int lflag = -1;
68 int mflag = -1;
69 int current = -1;
70 int pflag = -1;
71 int hflag = -1;
72 int res = -1;
73 char *device;
74 int dflag = -1;
75 int vflag = 0;
76 int Pflag = 0;
77 int tflag = 0;
78 int fflag = -1;
79 int colms = 0;
80 char *onoff;
81
82 unsigned timeout;
83 struct screeninfo screeninfo;
84
85 #define NVGAPEL 256
86
87 struct rgb {
88         unsigned r, g, b;
89         int dothis;
90 };
91
92 static struct rgb palette[NVGAPEL] = {
93         { 0x00,  0x00,  0x00, 0},               /*   0 - black          */
94         { 0x00,  0x00,  0x2a, 0},               /*   1 - blue           */
95         { 0x00,  0x2a,  0x00, 0},               /*   2 - green          */
96         { 0x00,  0x2a,  0x2a, 0},               /*   3 - cyan           */
97         { 0x2a,  0x00,  0x00, 0},               /*   4 - red            */
98         { 0x2a,  0x00,  0x2a, 0},               /*   5 - magenta        */
99         { 0x2a,  0x2a,  0x00, 0},               /*   6                  */
100         { 0x2a,  0x2a,  0x2a, 0},               /*   7 - lightgray      */
101         { 0x00,  0x00,  0x15, 0},               /*   8                  */
102         { 0x00,  0x00,  0x3f, 0},               /*   9                  */
103         { 0x00,  0x2a,  0x15, 0},               /*  10                  */
104         { 0x00,  0x2a,  0x3f, 0},               /*  11                  */
105         { 0x2a,  0x00,  0x15, 0},               /*  12                  */
106         { 0x2a,  0x00,  0x3f, 0},               /*  13                  */
107         { 0x2a,  0x2a,  0x15, 0},               /*  14                  */
108         { 0x2a,  0x2a,  0x3f, 0},               /*  15                  */
109         { 0x00,  0x15,  0x00, 0},               /*  16                  */
110         { 0x00,  0x15,  0x2a, 0},               /*  17                  */
111         { 0x00,  0x3f,  0x00, 0},               /*  18                  */
112         { 0x00,  0x3f,  0x2a, 0},               /*  19                  */
113         { 0x2a,  0x15,  0x00, 0},               /*  20 - brown          */
114         { 0x2a,  0x15,  0x2a, 0},               /*  21                  */
115         { 0x2a,  0x3f,  0x00, 0},               /*  22                  */
116         { 0x2a,  0x3f,  0x2a, 0},               /*  23                  */
117         { 0x00,  0x15,  0x15, 0},               /*  24                  */
118         { 0x00,  0x15,  0x3f, 0},               /*  25                  */
119         { 0x00,  0x3f,  0x15, 0},               /*  26                  */
120         { 0x00,  0x3f,  0x3f, 0},               /*  27                  */
121         { 0x2a,  0x15,  0x15, 0},               /*  28                  */
122         { 0x2a,  0x15,  0x3f, 0},               /*  29                  */
123         { 0x2a,  0x3f,  0x15, 0},               /*  30                  */
124         { 0x2a,  0x3f,  0x3f, 0},               /*  31                  */
125         { 0x15,  0x00,  0x00, 0},               /*  32                  */
126         { 0x15,  0x00,  0x2a, 0},               /*  33                  */
127         { 0x15,  0x2a,  0x00, 0},               /*  34                  */
128         { 0x15,  0x2a,  0x2a, 0},               /*  35                  */
129         { 0x3f,  0x00,  0x00, 0},               /*  36                  */
130         { 0x3f,  0x00,  0x2a, 0},               /*  37                  */
131         { 0x3f,  0x2a,  0x00, 0},               /*  38                  */
132         { 0x3f,  0x2a,  0x2a, 0},               /*  39                  */
133         { 0x15,  0x00,  0x15, 0},               /*  40                  */
134         { 0x15,  0x00,  0x3f, 0},               /*  41                  */
135         { 0x15,  0x2a,  0x15, 0},               /*  42                  */
136         { 0x15,  0x2a,  0x3f, 0},               /*  43                  */
137         { 0x3f,  0x00,  0x15, 0},               /*  44                  */
138         { 0x3f,  0x00,  0x3f, 0},               /*  45                  */
139         { 0x3f,  0x2a,  0x15, 0},               /*  46                  */
140         { 0x3f,  0x2a,  0x3f, 0},               /*  47                  */
141         { 0x15,  0x15,  0x00, 0},               /*  48                  */
142         { 0x15,  0x15,  0x2a, 0},               /*  49                  */
143         { 0x15,  0x3f,  0x00, 0},               /*  50                  */
144         { 0x15,  0x3f,  0x2a, 0},               /*  51                  */
145         { 0x3f,  0x15,  0x00, 0},               /*  52                  */
146         { 0x3f,  0x15,  0x2a, 0},               /*  53                  */
147         { 0x3f,  0x3f,  0x00, 0},               /*  54                  */
148         { 0x3f,  0x3f,  0x2a, 0},               /*  55                  */
149         { 0x15,  0x15,  0x15, 0},               /*  56 - darkgray       */
150         { 0x15,  0x15,  0x3f, 0},               /*  57 - lightblue      */
151         { 0x15,  0x3f,  0x15, 0},               /*  58 - lightgreen     */
152         { 0x15,  0x3f,  0x3f, 0},               /*  59 - lightcyan      */
153         { 0x3f,  0x15,  0x15, 0},               /*  60 - lightred       */
154         { 0x3f,  0x15,  0x3f, 0},               /*  61 - lightmagenta   */
155         { 0x3f,  0x3f,  0x15, 0},               /*  62 - yellow         */
156         { 0x3f,  0x3f,  0x3f, 0},               /*  63 - white          */
157         { 0x00,  0x00,  0x00, 0}                /*  64 ... - empty      */
158 };
159
160 static struct colname {
161         const char *name;
162         unsigned idx;
163 } colnames[] = {
164         {"black", 0},
165         {"blue", 1},
166         {"green", 2},
167         {"cyan", 3},
168         {"red", 4},
169         {"magenta", 5},
170         {"brown", 20},
171         {"lightgray", 7},
172         {"lightgrey", 7},
173         {"darkgray", 56},
174         {"darkgrey", 56},
175         {"lightblue", 57},
176         {"lightgreen", 58},
177         {"lightcyan", 59},
178         {"lightred", 60},
179         {"lightmagenta", 61},
180         {"yellow", 62},
181         {"white", 63},
182         /* must be terminator: */ {(const char *)NULL, 0}
183 };
184
185
186 static void parsepopt(char *arg, unsigned *idx,
187                       unsigned *r, unsigned *g, unsigned *b);
188 static void printpalette(int fd);
189
190 main(argc,argv)
191 int argc;
192 char *argv[];
193 {
194         extern int optind;
195         extern int opterr;
196         extern char *optarg;
197
198         int c;
199         int fd;
200
201         while( (c = getopt(argc, argv, "ac:d:f:HVlms:t:vp:18")) != -1)
202         {
203                 switch(c)
204                 {
205                         case 'a':
206                                 aflag = 1;
207                                 break;
208
209                         case 'l':
210                                 lflag = 1;
211                                 break;
212
213                         case 'm':
214                                 mflag = 1;
215                                 break;
216
217                         case 'c':
218                                 current = atoi(optarg);
219                                 break;
220
221                         case 'd':
222                                 device = optarg;
223                                 dflag = 1;
224                                 break;
225
226                         case 'f':
227                                 onoff = optarg;
228                                 fflag = 1;
229                                 break;
230
231                         case 'V':
232                                 pflag = 1;
233                                 break;
234
235                         case 'H':
236                                 hflag = 1;
237                                 break;
238
239                         case 's':
240                                 if     (!strncmp(optarg, "25", 2))
241                                         res = SIZ_25ROWS;
242                                 else if(!strncmp(optarg, "28", 2))
243                                         res = SIZ_28ROWS;
244                                 else if(!strncmp(optarg, "35", 2))
245                                         res = SIZ_35ROWS;
246                                 else if(!strncmp(optarg, "40", 2))
247                                         res = SIZ_40ROWS;
248                                 else if(!strncmp(optarg, "43", 2))
249                                         res = SIZ_43ROWS;
250                                 else if(!strncmp(optarg, "50", 2))
251                                         res = SIZ_50ROWS;
252                                 break;
253
254                         case 'v':
255                                 vflag++;
256                                 break;
257
258                         case 'p':
259                                 if(!strcmp(optarg, "list"))
260                                 {
261                                         if(Pflag)
262                                                 errx(2, "-p list is mutual exclusive with other -p options");
263                                         Pflag = 3;
264                                 }
265                                 else if(!strcmp(optarg, "default"))
266                                 {
267                                         if(Pflag)
268                                                 errx(2, "multiple -p default not allowed");
269                                         Pflag = 2;
270                                 } else {
271                                         unsigned idx, r, g, b;
272
273                                         if(Pflag > 1)
274                                                 errx(2, "-p default and -p i,r,g,b ambiguous");
275                                         Pflag = 1;
276                                         parsepopt(optarg, &idx, &r, &g, &b);
277                                         if(idx >= NVGAPEL)
278                                                 errx(2, "index %u in -p option out of range", idx);
279                                         palette[idx].r = r;
280                                         palette[idx].g = g;
281                                         palette[idx].b = b;
282                                         palette[idx].dothis = 1;
283                                 }
284                                 break;
285
286                         case 't':
287                                 tflag++;
288                                 timeout = atoi(optarg);
289                                 break;
290
291                         case '1':
292                                 colms = 132;
293                                 break;
294
295                         case '8':
296                                 colms = 80;
297                                 break;
298
299                         case '?':
300                         default:
301                                 usage();
302                                 break;
303                 }
304         }
305
306         if((pflag == 1) && (hflag == 1))
307                 usage();
308
309         if(dflag == -1 && lflag == -1 && current == -1 && pflag == -1 &&
310            hflag == -1 && res == -1 && Pflag == 0 && tflag == 0 && fflag == -1
311            && colms == 0 && mflag == -1)
312         {
313                 lflag = 1;
314         }
315
316         if(dflag == -1)
317         {
318                 if(vflag)
319                         printf("using current device\n");
320                 fd = DEFAULTFD;         /* -hm, Feb 12 1993 */
321         }
322         else
323         {
324                 if((fd = open(device, O_RDWR)) == -1)
325                         err(1, "ERROR opening %s", device);
326                 if(vflag)
327                         printf("using device %s\n",device);
328         }
329
330         if(aflag == 1)  /* return adaptor type */
331         {
332                 printadaptor(fd);
333                 exit(0);
334         }
335
336         if(mflag == 1)  /* return monitor type */
337         {
338                 printmonitor(fd);
339                 exit(0);
340         }
341
342         if(lflag == 1)  /* list information */
343         {
344                 if(vflag)
345                         printf("processing option -l, listing screen info\n");
346                 printinfo(fd);
347                 exit(0);
348         }
349
350         if(tflag)       /* set screen saver timeout */
351         {
352                 if(vflag)
353                 {
354                         printf(
355                         "processing option -t, setting screen saver timeout: "
356                         );
357                         if(timeout)
358                                 printf("new timeout = %d s\n", timeout);
359                         else
360                                 printf("turned off\n");
361                 }
362
363                 if(ioctl(fd, VGASCREENSAVER, &timeout) < 0)
364                 {
365                         warn("ioctl(VGASCREENSAVER)");
366                         fprintf(stderr, "Check the driver, the screensaver is probably not compiled in!\n");
367                         exit(2);
368                 }
369                 goto success;
370         }
371
372         if(colms)
373         {
374                 if(vflag)
375                         printf("Setting number of columns to %d\n", colms);
376                 if(ioctl(fd, VGASETCOLMS, &colms) < 0)
377                         err(2, "ioctl(VGASETCOLMS)");
378                 goto success;
379         }
380
381         if(Pflag == 3)
382         {
383                 /* listing VGA palette */
384                 if(vflag)
385                         printf("processing option -p list, "
386                                "listing VGA palette\n");
387
388                 printpalette(fd);
389                 goto success;
390         }
391
392         if(Pflag)
393         {
394                 unsigned int idx;
395
396                 /* setting VGA palette */
397                 if(vflag)
398                         printf("processing option -p, setting VGA palette%s\n",
399                                Pflag == 2? " to default": "");
400
401                 for(idx = 0; idx < NVGAPEL; idx++)
402                         if(Pflag == 2 || palette[idx].dothis)
403                         {
404                                 struct vgapel p;
405                                 p.idx = idx;
406                                 p.r = palette[idx].r;
407                                 p.g = palette[idx].g;
408                                 p.b = palette[idx].b;
409                                 if(ioctl(fd, VGAWRITEPEL, (caddr_t)&p) < 0)
410                                         err(2, "ioctl(fd, VGAWRITEPEL)");
411                         }
412                 goto success;
413         }
414
415         screeninfo.screen_no = -1; /* We are using fd */
416         screeninfo.current_screen = current;
417         screeninfo.pure_vt_mode = -1;
418         screeninfo.screen_size = res;
419         screeninfo.force_24lines = -1;
420
421         if(current != -1)       /* set current screen */
422         {
423                 if(vflag)
424                         printf("processing option -c, setting current screen to %d\n",current);
425
426                 if(ioctl(1, VGASETSCREEN, &screeninfo) == -1)
427                         err(1, "ioctl VGASETSCREEN failed");
428                 exit(0);
429         }
430
431         if(pflag == 1)
432         {
433                 if(vflag)
434                         printf("processing option -V, setting emulation to pure VT220\n");
435                 screeninfo.pure_vt_mode = M_PUREVT;
436         }
437         else if(hflag == 1)
438         {
439                 if(vflag)
440                         printf("processing option -H, setting emulation to VT220 + HP Labels\n");
441                 screeninfo.pure_vt_mode = M_HPVT;
442         }
443         else
444         {
445                 if(vflag)
446                         printf("no change in terminal emulation\n");
447         }
448
449         if(vflag)
450         {
451                 if(res == -1)
452                         printf("no change in screen resolution\n");
453                 else if(res == SIZ_25ROWS)
454                         printf("change screen resolution to 25 lines\n");
455                 else if(res == SIZ_28ROWS)
456                         printf("change screen resolution to 28 lines\n");
457                 else if(res == SIZ_35ROWS)
458                         printf("change screen resolution to 35 lines\n");
459                 else if(res == SIZ_40ROWS)
460                         printf("change screen resolution to 40 lines\n");
461                 else if(res == SIZ_43ROWS)
462                         printf("change screen resolution to 43 lines\n");
463                 else if(res == SIZ_50ROWS)
464                         printf("change screen resolution to 50 lines\n");
465         }
466
467         if(fflag == 1)  /* force 24 lines on/off */
468         {
469                 if(!strcmp(onoff, "on"))
470                 {
471                         fflag = 1;
472                 }
473                 else if(!strcmp(onoff, "off"))
474                 {
475                         fflag = 0;
476                 }
477                 else
478                 {
479                         fprintf(stderr,"you must specify 'on' or 'off' with -f option!\n");
480                         exit(1);
481                 }
482         }
483         screeninfo.force_24lines = fflag;
484
485         if(ioctl(fd, VGASETSCREEN, &screeninfo) == -1)
486                 err(1, "ioctl VGASETSCREEN failed");
487 success:
488         if(vflag)
489                 printf("successful execution of ioctl VGASETSCREEN!\n");
490         exit(0);
491 }
492
493 usage()
494 {
495         fprintf(stderr,"\nscon - screen control utility for the pcvt video driver\n");
496         fprintf(stderr,"usage: scon -a -l -m -v -c [n] -d [dev] -f [on|off] -V -H -s [n]\n");
497         fprintf(stderr,"usage: scon -p [default | list | i,r,g,b] | -t [sec] | -1 | -8\n");
498         fprintf(stderr,"       -a              list video adaptor type (MDA,CGA,EGA or VGA)\n");
499         fprintf(stderr,"       -c <screen no>  switch current virtual screen to <screen no>\n");
500         fprintf(stderr,"       -d <device>     set parameters(-V|-H|-s) for virtual device\n");
501         fprintf(stderr,"       -f <on|off>     force 24 lines in VT 25 lines and HP 28 lines mode\n");
502         fprintf(stderr,"       -H              set VT220/HP emulation mode for a virtual screen\n");
503         fprintf(stderr,"       -l              list current parameters for a virtual screen\n");
504         fprintf(stderr,"       -m              report monitor type (MONO/COLOR)\n");
505         fprintf(stderr,"       -p default      set default VGA palette\n");
506         fprintf(stderr,"       -p list         list current VGA palette\n");
507         fprintf(stderr,"       -p <i,r,g,b>    set VGA palette entry i to r/g/b\n");
508         fprintf(stderr,"       -p <name,r,g,b> set VGA palette entry for color name to r/g/b\n");
509         fprintf(stderr,"       -s <lines>      set 25, 28, 35, 40, 43 or 50 lines for a virtual screen\n");
510         fprintf(stderr,"       -t <timeout>    set screen saver timeout [seconds]\n");
511         fprintf(stderr,"       -1              set 132 columns mode\n");
512         fprintf(stderr,"       -8              set 80 columns mode\n");
513         fprintf(stderr,"       -v              verbose mode\n");
514         fprintf(stderr,"       -V              set pure VT220 emulation for a virtual screen\n");
515         fprintf(stderr,"       -?              display help (this message)\n\n");
516         exit(1);
517 }
518
519 printadaptor(fd)
520 int fd;
521 {
522         if(ioctl(fd, VGAGETSCREEN, &screeninfo) == -1)
523                 err(1, "ioctl VGAGETSCREEN failed");
524         switch(screeninfo.adaptor_type)
525         {
526                 default:
527                 case UNKNOWN_ADAPTOR:
528                         printf("UNKNOWN\n");
529                         break;
530
531                 case MDA_ADAPTOR:
532                         printf("MDA\n");
533                         break;
534
535                 case CGA_ADAPTOR:
536                         printf("CGA\n");
537                         break;
538
539                 case EGA_ADAPTOR:
540                         printf("EGA\n");
541                         break;
542
543                 case VGA_ADAPTOR:
544                         printf("VGA\n");
545                         break;
546         }
547 }
548
549 printmonitor(fd)
550 int fd;
551 {
552         if(ioctl(fd, VGAGETSCREEN, &screeninfo) == -1)
553                 err(1, "ioctl VGAGETSCREEN failed");
554         switch(screeninfo.monitor_type)
555         {
556                 default:
557                         printf("UNKNOWN\n");
558                         break;
559
560                 case MONITOR_MONO:
561                         printf("MONO\n");
562                         break;
563
564                 case MONITOR_COLOR:
565                         printf("COLOR\n");
566                         break;
567         }
568 }
569
570 char *vga_type(int number)
571 {
572         static char *vga_tab[] = {
573                 "Generic VGA",
574                 "ET4000",
575                 "ET3000",
576                 "PVGA1A",
577                 "WD90C00",
578                 "WD90C10",
579                 "WD90C11",
580                 "VIDEO 7 VEGA",
581                 "VIDEO 7 FAST",
582                 "VIDEO 7 VER5",
583                 "VIDEO 7 1024I",
584                 "Unknown VIDEO 7",
585                 "TVGA 8800BR",
586                 "TVGA 8800CS",
587                 "TVGA 8900B",
588                 "TVGA 8900C",
589                 "TVGA 8900CL",
590                 "TVGA 9000",
591                 "TVGA 9100",
592                 "TVGA 9200",
593                 "Unknown TRIDENT",
594                 "S3 80C911",
595                 "S3 80C924",
596                 "S3 80C801/80C805",
597                 "S3 80C928",
598                 "Unknown S3",
599                 "CL-GD5402",
600                 "CL-GD5402r1",
601                 "CL-GD5420",
602                 "CL-GD5420r1",
603                 "CL-GD5422",
604                 "CL-GD5424",
605                 "CL-GD5426",
606                 "CL-GD5428",
607
608         };
609         return(vga_tab[number]);
610 }
611
612 char *vga_family(int number)
613 {
614         static char *vga_tab[] = {
615                 "Generic VGA",
616                 "Tseng Labs",
617                 "Western Digital",
618                 "Video Seven",
619                 "Trident",
620                 "S3 Incorporated",
621                 "Cirrus Logic",
622         };
623         return(vga_tab[number]);
624 }
625
626 printinfo(fd)
627 int fd;
628 {
629         if(ioctl(fd, VGAGETSCREEN, &screeninfo) == -1)
630                 err(1, "ioctl VGAGETSCREEN failed");
631
632         printf( "\nVideo Adaptor Type           = ");
633
634         switch(screeninfo.adaptor_type)
635         {
636                 default:
637                 case UNKNOWN_ADAPTOR:
638                         printf("UNKNOWN Video Adaptor\n");
639                         break;
640
641                 case MDA_ADAPTOR:
642                         printf("MDA - Monochrome Display Adaptor\n");
643                         break;
644
645                 case CGA_ADAPTOR:
646                         printf("CGA - Color Graphics Adaptor\n");
647                         break;
648
649                 case EGA_ADAPTOR:
650                         printf("EGA - Enhanced Graphics Adaptor\n");
651                         break;
652
653                 case VGA_ADAPTOR:
654                         printf("VGA - Video Graphics Adaptor/Array\n");
655                         printf(" VGA Chipset Manufacturer    = %s\n",
656                                         vga_family(screeninfo.vga_family));
657                         printf(" VGA Chipset Type            = %s\n",
658                                         vga_type(screeninfo.vga_type));
659                         printf(" Support for 132 Column Mode = %s\n",
660                                         screeninfo.vga_132 ? "Yes" : "No");
661                         break;
662         }
663
664         printf( "Display Monitor Type         = ");
665
666         switch(screeninfo.monitor_type)
667         {
668                 default:
669                         printf("UNKNOWN Monitor Type\n");
670                         break;
671
672                 case MONITOR_MONO:
673                         printf("Monochrome Monitor\n");
674                         break;
675
676                 case MONITOR_COLOR:
677                         printf("Color Monitor\n");
678                         break;
679         }
680
681         printf( "Number of Downloadable Fonts = %d\n",screeninfo.totalfonts);
682         printf( "Number of Virtual Screens    = %d\n",screeninfo.totalscreens);
683         printf( "Info Request Screen Number   = %d\n",screeninfo.screen_no);
684         printf( "Current Displayed Screen     = %d\n",screeninfo.current_screen);
685
686         if(screeninfo.pure_vt_mode == M_PUREVT)
687                 printf( "Terminal Emulation Mode      = VT220\n");
688         else
689                 printf( "Terminal Emulation Mode      = VT220 with HP Features\n");
690
691         printf( "Lines                        = ");
692
693         switch(screeninfo.screen_size)
694         {
695                 case SIZ_25ROWS:
696                         printf( "25\n");
697                         break;
698
699                 case SIZ_28ROWS:
700                         printf( "28\n");
701                         break;
702
703                 case SIZ_35ROWS:
704                         printf( "35\n");
705                         break;
706
707                 case SIZ_40ROWS:
708                         printf( "40\n");
709                         break;
710
711                 case SIZ_43ROWS:
712                         printf( "43\n");
713                         break;
714
715                 case SIZ_50ROWS:
716                         printf( "50\n");
717                         break;
718
719                 default:
720                         printf( "UNKNOWN\n");
721                         break;
722         }
723         printf( "Force 24 Lines               = %s",
724                         screeninfo.force_24lines ? "Yes" : "No");
725
726         printf("\n\n");
727 }
728
729 static const char *findname(unsigned idx)
730 {
731         /* try to find a name for palette entry idx */
732         /* if multiple names exist, returns first matching */
733         register struct colname *cnp;
734
735         for(cnp = colnames; cnp->name; cnp++)
736                 if(cnp->idx == idx)
737                         return cnp->name;
738
739         /* not found */
740         return (const char *)NULL;
741 }
742
743 static void printpalette(int fd)
744 {
745         register unsigned idx, last;
746
747         for(idx = 0; idx < NVGAPEL; idx++)
748         {
749                 struct vgapel p;
750                 p.idx = idx;
751                 if(ioctl(fd, VGAREADPEL, &p) < 0)
752                         err(2, "ioctl(VGAREADPEL)");
753                 palette[idx].r = p.r;
754                 palette[idx].g = p.g;
755                 palette[idx].b = p.b;
756         }
757
758         /* find last non-empty entry */
759         for(last = NVGAPEL - 1; last; last--)
760                 if(palette[last].r || palette[last].g || palette[last].b)
761                         break;
762
763         if(last != NVGAPEL - 1)
764                 last++;
765
766         /* now, everything's collected. print out table */
767         printf("VGA palette status\n");
768         printf("index    red  green   blue  name\n");
769         for(idx = 0; idx < last; idx++)
770         {
771                 const char *cp;
772                 printf("%5d  %5d  %5d  %5d",
773                        idx, palette[idx].r, palette[idx].g, palette[idx].b);
774                 if(cp = findname(idx))
775                         printf("  %s\n", cp);
776                 else
777                         putchar('\n');
778         }
779         putchar('\n');
780 }
781
782
783 static void parsepopt(char *arg, unsigned *idx,
784                       unsigned *r, unsigned *g, unsigned *b)
785 {
786         char firstarg[21];
787         register unsigned i;
788
789         if(sscanf(arg, "%20[a-zA-Z0-9]%*[,:]%u,%u,%u", firstarg, r, g, b) < 4
790            || strlen(firstarg) == 0)
791                 errx(2, "too few args in -p i,r,g,b");
792
793         if(firstarg[0] >= '0' && firstarg[0] <= '9') {
794                 *idx = strtoul(firstarg, NULL, 10);
795                 return;
796         }
797
798         for(i = 0; colnames[i].name; i++)
799                 if(strcasecmp(colnames[i].name, firstarg) == 0) {
800                         *idx = colnames[i].idx;
801                         return;
802                 }
803         errx(2, "arg ``%s'' in -p option not recognized", firstarg);
804 }