Add pancyrillic font
[platform/upstream/kbd.git] / src / showconsolefont.c
1 /* showfont.c - aeb, 940207 - updated 2001-02-06 */
2 /* renamed to showconsolefont.c to avoid clash with the X showfont */
3
4 #include <stdio.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9 #include <linux/kd.h>
10 #include "nls.h"
11 #include "getfd.h"
12 #include "version.h"
13 #include "kdmapop.h"
14 #include "kdfontop.h"
15
16 /*
17  * Showing the font is nontrivial mostly because testing whether
18  * we are in utf8 mode cannot be done in an easy and clean way.
19  * So, we set up things here in such a way that it does not matter
20  * whether we are in utf8 mode.
21  */
22
23 unsigned short obuf[E_TABSZ], nbuf[E_TABSZ];
24 struct unimapdesc ounimap, nunimap;
25 int fd = 0;
26 int have_obuf = 0;
27 int have_ounimap = 0;
28
29 static void __attribute__ ((noreturn))
30 leave(int n) {
31         if (have_obuf && loaduniscrnmap(fd,obuf)) {
32                 fprintf(stderr,
33                         _("failed to restore original translation table\n"));
34                 n = 1;
35         }
36         if (have_ounimap && loadunimap(fd,NULL,&ounimap)) {
37                 fprintf(stderr,
38                         _("failed to restore original unimap\n"));
39                 n = 1;
40         }
41         exit(n);
42 }
43
44 static void
45 settrivialscreenmap(void) {
46         int i;
47
48         if (getuniscrnmap(fd,obuf))
49                 exit(1);
50         have_obuf = 1;
51
52         for(i=0; i<E_TABSZ; i++)
53                 nbuf[i] = i;
54
55         if (loaduniscrnmap(fd,nbuf)) {
56                 fprintf(stderr, _("cannot change translation table\n"));
57                 exit(1);
58         }
59 }
60
61 static void __attribute__ ((noreturn))
62 out_of_memory(void) {
63         fprintf(stderr, _("%s: out of memory?\n"), progname);
64         leave(1);
65 }
66
67 static void
68 getoldunicodemap(void) {
69         struct unimapdesc descr;
70
71         if (getunimap(fd, &descr))
72                 leave(1);
73         ounimap = descr;
74         have_ounimap = 1;
75 }
76
77 #define BASE    041             /* ' '+1 */
78
79 static void
80 setnewunicodemap(int *list, int cnt) {
81         int i;
82
83         if (!nunimap.entry_ct) {
84                 nunimap.entry_ct = 512;
85                 nunimap.entries = (struct unipair *)
86                         malloc(nunimap.entry_ct * sizeof(struct unipair));
87                 if (nunimap.entries == NULL)
88                         out_of_memory();
89         }
90         for (i=0; i<512; i++) {
91                 nunimap.entries[i].fontpos = i;
92                 nunimap.entries[i].unicode = 0;
93         }
94         for (i=0; i<cnt; i++)
95                 nunimap.entries[list[i]].unicode = BASE+i;
96
97         if (loadunimap(fd, NULL, &nunimap))
98                 leave(1);
99 }
100
101 static void __attribute__ ((noreturn))
102 usage(void) {
103         fprintf(stderr,
104                 _("usage: showconsolefont -V|--version\n"
105                   "       showconsolefont [-C tty] [-v] [-i]\n"
106                   "(probably after loading a font with `setfont font')\n"
107                   "\n"
108                   "Valid options are:\n"
109                   " -C tty   Device to read the font from. Default: current tty.\n"
110                   " -v       Be more verbose.\n"
111                   " -i       Don't print out the font table, just show\n"
112                   "          ROWSxCOLSxCOUNT and exit.\n"));
113         exit(1);
114 }
115
116 int
117 main (int argc, char **argv) {
118         int c, n, cols, rows, nr, i, j, k;
119         int mode;
120         char *space, *sep, *console = NULL;
121         int list[64], lth, info = 0, verbose = 0;
122
123         set_progname(argv[0]);
124
125         setlocale(LC_ALL, "");
126         bindtextdomain(PACKAGE_NAME, LOCALEDIR);
127         textdomain(PACKAGE_NAME);
128
129         if (argc == 2 &&
130             (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")))
131                 print_version_and_exit();
132
133         while ((c = getopt(argc, argv, "ivC:")) != EOF) {
134                 switch (c) {
135                 case 'i':
136                         info = 1;
137                         break;
138                 case 'v':
139                         verbose = 1;
140                         break;
141                 case 'C':
142                         console = optarg;
143                         break;
144                 default:
145                         usage();
146                 }
147         }
148
149         if (optind != argc)
150                 usage();
151
152         fd = getfd(console);
153
154         if (ioctl(fd, KDGKBMODE, &mode)) {
155                 perror("KDGKBMODE");
156                 leave(1);
157         }
158         if (mode == K_UNICODE)
159                 space = "\xef\x80\xa0"; /* U+F020 (direct-to-font space) */
160         else
161                 space = " ";
162
163         if (info) {
164             nr = rows = cols = 0;
165             n = getfont(fd, NULL, &nr, &rows, &cols);
166             if (n != 0)
167               leave(1);
168
169             if (verbose) {
170                 printf(_("Character count: %d\n"), nr);
171                 printf(_("Font width     : %d\n"), rows);
172                 printf(_("Font height    : %d\n"), cols);
173             }
174             else
175                 printf("%dx%dx%d\n", rows, cols, nr);
176             leave(0);
177           }
178
179         settrivialscreenmap();
180         getoldunicodemap();
181
182         n = getfontsize(fd);
183         if (verbose)
184                 printf(_("Showing %d-char font\n\n"), n);
185         cols = ((n > 256) ? 32 : 16);
186         nr = 64/cols;
187         rows = (n+cols-1)/cols;
188         sep = ((cols == 16) ? "%1$s%1$s" : "%1$s");
189
190         for (i=0; i<rows; i++) {
191                 if (i % nr == 0) {
192                         lth = 0;
193                         for (k=i; k<i+nr; k++)
194                                 for (j=0; j < cols; j++)
195                                         list[lth++] = k+j*rows;
196                         setnewunicodemap(list, lth);
197                 }
198                 printf("%1$s%1$s%1$s%1$s", space);
199                 for(j=0; j < cols && i+j*rows < n; j++) {
200                         putchar(BASE + (i%nr)*cols+j);
201                         printf(sep, space);
202                         if (j%8 == 7)
203                                 printf(sep, space);
204                 }
205                 putchar('\n');
206                 if (i%8 == 7)
207                         putchar('\n');
208                 fflush(stdout);
209         }
210
211         leave(0);
212         exit(0);                        /* make gcc happy */
213 }