Add pancyrillic font
[platform/upstream/kbd.git] / src / setfont.c
1 /*
2  * setfont.c - Eugene Crosser & Andries Brouwer
3  *
4  * Version 1.05
5  *
6  * Loads the console font, and possibly the corresponding screen map(s).
7  * We accept two kind of screen maps, one [-m] giving the correspondence
8  * between some arbitrary 8-bit character set currently in use and the
9  * font positions, and the second [-u] giving the correspondence between
10  * font positions and Unicode values.
11  */
12
13 #include <stdio.h>
14 #include <memory.h>
15 #include <fcntl.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/ioctl.h>
22 #include <linux/kd.h>
23 #include <endian.h>
24 #include <sysexits.h>
25 #include "paths.h"
26 #include "getfd.h"
27 #include "findfile.h"
28 #include "loadunimap.h"
29 #include "psf.h"
30 #include "psffontop.h"
31 #include "kdfontop.h"
32 #include "kdmapop.h"
33 #include "xmalloc.h"
34 #include "nls.h"
35 #include "version.h"
36
37 static int position_codepage(int iunit);
38 static void saveoldfont(int fd, char *ofil);
39 static void saveoldfontplusunicodemap(int fd, char *Ofil);
40 static void loadnewfont(int fd, char *ifil,
41                         int iunit, int hwunit, int no_m, int no_u);
42 static void loadnewfonts(int fd, char **ifiles, int ifilct,
43                         int iunit, int hwunit, int no_m, int no_u);
44 extern void saveoldmap(int fd, char *omfil);
45 extern void loadnewmap(int fd, char *mfil);
46 extern void activatemap(int fd);
47 extern void disactivatemap(int fd);
48
49 int verbose = 0;
50 int force = 0;
51 int debug = 0;
52
53 /* search for the font in these directories (with trailing /) */
54 const char *const fontdirpath[] = { "", DATADIR "/" FONTDIR "/", 0 };
55 const char *const fontsuffixes[] = { "", ".psfu", ".psf", ".cp", ".fnt", 0 };
56 /* hide partial fonts a bit - loading a single one is a bad idea */
57 const char *const partfontdirpath[] = { "", DATADIR "/" FONTDIR "/" PARTIALDIR "/", 0 };
58 const char *const partfontsuffixes[] = { "", 0 };
59
60 static inline int
61 findfont(char *fnam, lkfile_t *fp) {
62     return lk_findfile(fnam, fontdirpath, fontsuffixes, fp);
63 }
64
65 static inline int
66 findpartialfont(char *fnam, lkfile_t *fp) {
67     return lk_findfile(fnam, partfontdirpath, partfontsuffixes, fp);
68 }
69
70 static void __attribute__ ((noreturn))
71 usage(void)
72 {
73         fprintf(stderr, _(
74 "Usage: setfont [write-options] [-<N>] [newfont..] [-m consolemap] [-u unicodemap]\n"
75 "  write-options (take place before file loading):\n"
76 "    -o  <filename>  Write current font to <filename>\n"
77 "    -O  <filename>  Write current font and unicode map to <filename>\n"
78 "    -om <filename>  Write current consolemap to <filename>\n"
79 "    -ou <filename>  Write current unicodemap to <filename>\n"
80 "If no newfont and no -[o|O|om|ou|m|u] option is given,\n"
81 "a default font is loaded:\n"
82 "    setfont         Load font \"default[.gz]\"\n"
83 "    setfont -<N>    Load font \"default8x<N>[.gz]\"\n"
84 "The -<N> option selects a font from a codepage that contains three fonts:\n"
85 "    setfont -{8|14|16} codepage.cp[.gz]   Load 8x<N> font from codepage.cp\n"
86 "Explicitly (with -m or -u) or implicitly (in the fontfile) given mappings\n"
87 "will be loaded and, in the case of consolemaps, activated.\n"
88 "    -h<N>      (no space) Override font height.\n"
89 "    -m <fn>    Load console screen map.\n"
90 "    -u <fn>    Load font unicode map.\n"
91 "    -m none    Suppress loading and activation of a screen map.\n"
92 "    -u none    Suppress loading of a unicode map.\n"
93 "    -v         Be verbose.\n"
94 "    -C <cons>  Indicate console device to be used.\n"
95 "    -V         Print version and exit.\n"
96 "Files are loaded from the current directory or %s/*/.\n"
97 ), DATADIR);
98         exit(EX_USAGE);
99 }
100
101 #define MAXIFILES 256
102
103 int
104 main(int argc, char *argv[]) {
105         char *ifiles[MAXIFILES];
106         char *mfil, *ufil, *Ofil, *ofil, *omfil, *oufil, *console;
107         int ifilct = 0, fd, i, iunit, hwunit, no_m, no_u;
108         int restore = 0;
109
110         set_progname(argv[0]);
111
112         setlocale(LC_ALL, "");
113         bindtextdomain(PACKAGE_NAME, LOCALEDIR);
114         textdomain(PACKAGE_NAME);
115
116         ifiles[0] = mfil = ufil = Ofil = ofil = omfil = oufil = NULL;
117         iunit = hwunit = 0;
118         no_m = no_u = 0;
119         console = NULL;
120
121         /*
122          * No getopt() here because of the -om etc options.
123          */
124         for (i = 1; i < argc; i++) {
125             if (!strcmp(argv[i], "-V")) {
126                 print_version_and_exit();
127             } else if (!strcmp(argv[i], "-v")) {
128                 verbose++;
129             } else if (!strcmp(argv[i], "-R")) {
130                 restore = 1;
131             } else if (!strcmp(argv[i], "-C")) {
132                 if (++i == argc || console)
133                   usage();
134                 console = argv[i];
135             } else if (!strcmp(argv[i], "-O")) {
136                 if (++i == argc || Ofil)
137                   usage();
138                 Ofil = argv[i];
139             } else if (!strcmp(argv[i], "-o")) {
140                 if (++i == argc || ofil)
141                   usage();
142                 ofil = argv[i];
143             } else if (!strcmp(argv[i], "-om")) {
144                 if (++i == argc || omfil)
145                   usage();
146                 omfil = argv[i];
147             } else if (!strcmp(argv[i], "-ou")) {
148                 if (++i == argc || oufil)
149                   usage();
150                 oufil = argv[i];
151             } else if (!strcmp(argv[i], "-m")) {
152                 if (++i == argc || mfil)
153                   usage();
154                 if (!strcmp(argv[i], "none"))
155                   no_m = 1;
156                 else
157                   mfil = argv[i];
158             } else if (!strcmp(argv[i], "-u")) {
159                 if (++i == argc || ufil)
160                   usage();
161                 if (!strcmp(argv[i], "none"))
162                   no_u = 1;
163                 else
164                   ufil = argv[i];
165             } else if (!strcmp(argv[i], "-f")) {
166                 force = 1;
167             } else if (!strncmp(argv[i], "-h", 2)) {
168                 hwunit = atoi(argv[i]+2);
169                 if (hwunit <= 0 || hwunit > 32)
170                   usage();
171             } else if (argv[i][0] == '-') {
172                 iunit = atoi(argv[i]+1);
173                 if(iunit <= 0 || iunit > 32)
174                   usage();
175             } else {
176                 if (ifilct == MAXIFILES) {
177                     fprintf(stderr, _("setfont: too many input files\n"));
178                     exit(EX_USAGE);
179                 }
180                 ifiles[ifilct++] = argv[i];
181             }
182         }
183
184         if (ifilct && restore) {
185             fprintf(stderr, _("setfont: cannot both restore from character ROM"
186                               " and from file. Font unchanged.\n"));
187             exit(EX_USAGE);
188         }
189
190         fd = getfd(console);
191
192         int kd_mode = -1;
193         if (!ioctl(fd, KDGETMODE, &kd_mode) && (kd_mode == KD_GRAPHICS))
194           {
195             /*
196              * PIO_FONT will fail on a console which is in foreground and in KD_GRAPHICS mode.
197              * 2005-03-03, jw@suse.de.
198              */
199             if (verbose)
200               printf("setfont: graphics console %s skipped\n", console?console:"");
201             close(fd);
202             return 0;
203           }
204
205         if (!ifilct && !mfil && !ufil &&
206             !Ofil && !ofil && !omfil && !oufil && !restore)
207           /* reset to some default */
208           ifiles[ifilct++] = "";
209
210         if (Ofil)
211           saveoldfontplusunicodemap(fd, Ofil);
212
213         if (ofil)
214           saveoldfont(fd, ofil);
215
216         if (omfil)
217           saveoldmap(fd, omfil);
218
219         if (oufil)
220           saveunicodemap(fd, oufil);
221
222         if (mfil) {
223             loadnewmap(fd, mfil);
224             activatemap(fd);
225             no_m = 1;
226         }
227
228         if (ufil)
229           no_u = 1;
230
231         if (restore)
232           restorefont(fd);
233
234         if (ifilct)
235           loadnewfonts(fd, ifiles, ifilct, iunit, hwunit, no_m, no_u);
236
237         if (ufil)
238           loadunicodemap(fd, ufil);
239
240         return 0;
241 }
242
243 /*
244  * 0 - do not test, 1 - test and warn, 2 - test and wipe, 3 - refuse
245  */
246 static int erase_mode = 1;
247
248 static void
249 do_loadfont(int fd, char *inbuf, int width, int height, int hwunit,
250             int fontsize, char *filename) {
251         unsigned char *buf;
252         int i, buflen;
253         int bytewidth = (width+7)/8;
254         int charsize = height * bytewidth;
255         int kcharsize = 32 * bytewidth;
256         int bad_video_erase_char = 0;
257
258         if (height < 1 || height > 32) {
259                 fprintf(stderr, _("Bad character height %d\n"), height);
260                 exit(EX_DATAERR);
261         }
262         if (width < 1 || width > 32) {
263                 fprintf(stderr, _("Bad character width %d\n"), width);
264                 exit(EX_DATAERR);
265         }
266
267         if (!hwunit)
268                 hwunit = height;
269
270         buflen = kcharsize * ((fontsize < 128) ? 128 : fontsize);
271         buf = xmalloc(buflen);
272         memset(buf,0,buflen);
273
274         for (i = 0; i < fontsize; i++)
275                 memcpy(buf+(i*kcharsize), inbuf+(i*charsize), charsize);
276
277         /*
278          * Due to a kernel bug, font position 32 is used
279          * to erase the screen, regardless of maps loaded.
280          * So, usually this font position should be blank.
281          */
282         if (erase_mode) {
283                 for (i = 0; i < kcharsize; i++)
284                         if (buf[32*kcharsize+i])
285                                 bad_video_erase_char = 1;
286                 if (bad_video_erase_char) {
287                         fprintf(stderr,
288                                 _("%s: font position 32 is nonblank\n"),
289                                 progname);
290                         switch(erase_mode) {
291                         case 3:
292                                 exit(EX_DATAERR);
293                         case 2:
294                                 for (i = 0; i < kcharsize; i++)
295                                         buf[32*kcharsize+i] = 0;
296                                 fprintf(stderr, _("%s: wiped it\n"), progname);
297                                 break;
298                         case 1:
299                                 fprintf(stderr,
300                                         _("%s: background will look funny\n"),
301                                         progname);
302                         }
303                         fflush(stderr);
304                         sleep(2);
305                 }
306         }
307
308         if (verbose) {
309                 if (height == hwunit && filename)
310                         printf(_("Loading %d-char %dx%d font from file %s\n"),
311                                fontsize, width, height, filename);
312                 else if (height == hwunit)
313                         printf(_("Loading %d-char %dx%d font\n"),
314                                fontsize, width, height);
315                 else if (filename)
316                         printf(_("Loading %d-char %dx%d (%d) font from file %s\n"),
317                                fontsize, width, height, hwunit, filename);
318                 else
319                         printf(_("Loading %d-char %dx%d (%d) font\n"),
320                                fontsize, width, height, hwunit);
321         }
322
323         if (putfont(fd, buf, fontsize, width, hwunit))
324                 exit(EX_OSERR);
325 }
326
327 static void
328 do_loadtable(int fd, struct unicode_list *uclistheads, int fontsize) {
329         struct unimapdesc ud;
330         struct unipair *up;
331         int i, ct = 0, maxct;
332         struct unicode_list *ul;
333         struct unicode_seq *us;
334
335         maxct = 0;
336         for (i = 0; i < fontsize; i++) {
337                 ul = uclistheads[i].next;
338                 while(ul) {
339                         us = ul->seq;
340                         if (us && ! us->next)
341                                 maxct++;
342                         ul = ul->next;
343                 }
344         }
345         up = xmalloc(maxct * sizeof(struct unipair));
346         for (i = 0; i < fontsize; i++) {
347                 ul = uclistheads[i].next;
348                 if (debug) printf ("char %03x:", i);
349                 while(ul) {
350                         us = ul->seq;
351                         if (us && ! us->next) {
352                                 up[ct].unicode = us->uc;
353                                 up[ct].fontpos = i;
354                                 ct++;
355                                 if (debug) printf (" %04x", us->uc);
356                         }
357                         else
358                                 if (debug) {
359                                         printf (" seq: <");
360                                         while (us) {
361                                                 printf (" %04x", us->uc);
362                                                 us = us->next;
363                                         }
364                                         printf (" >");
365                                 }
366                         ul = ul->next;
367                         if (debug) printf (",");
368                 }
369                 if (debug) printf ("\n");
370         }
371         if (ct != maxct) {
372                 char *u = _("%s: bug in do_loadtable\n");
373                 fprintf(stderr, u, progname);
374                 exit(EX_SOFTWARE);
375         }
376
377         if (verbose)
378           printf(_("Loading Unicode mapping table...\n"));
379
380         ud.entry_ct = ct;
381         ud.entries = up;
382         if (loadunimap(fd, NULL, &ud))
383                 exit(EX_OSERR);
384 }
385
386 static void
387 loadnewfonts(int fd, char **ifiles, int ifilct,
388              int iunit, int hwunit, int no_m, int no_u)
389 {
390         char *ifil, *inbuf, *fontbuf, *bigfontbuf;
391         int inputlth, fontbuflth, fontsize, height, width, bytewidth;
392         int bigfontbuflth, bigfontsize, bigheight, bigwidth;
393         struct unicode_list *uclistheads;
394         int i;
395         lkfile_t fp;
396
397         if (ifilct == 1) {
398                 loadnewfont(fd, ifiles[0], iunit, hwunit, no_m, no_u);
399                 return;
400         }
401
402         /* several fonts that must be merged */
403         /* We just concatenate the bitmaps - only allow psf fonts */
404         bigfontbuf = NULL;
405         bigfontbuflth = 0;
406         bigfontsize = 0;
407         uclistheads = NULL;
408         bigheight = 0;
409         bigwidth = 0;
410
411         for (i=0; i<ifilct; i++) {
412                 ifil = ifiles[i];
413                 if (findfont(ifil, &fp) && findpartialfont(ifil, &fp)) {
414                         fprintf(stderr, _("Cannot open font file %s\n"), ifil);
415                         exit(EX_NOINPUT);
416                 }
417
418                 inbuf = fontbuf = NULL;
419                 inputlth = fontbuflth = 0;
420                 fontsize = 0;
421
422                 if(readpsffont(fp.fd, &inbuf, &inputlth, &fontbuf, &fontbuflth,
423                                &width, &fontsize, bigfontsize,
424                                no_u ? NULL : &uclistheads)) {
425                         fprintf(stderr, _("When loading several fonts, all "
426                                           "must be psf fonts - %s isn't\n"),
427                                 fp.pathname);
428                         lk_fpclose(&fp);
429                         exit(EX_DATAERR);
430                 }
431                 lk_fpclose(&fp);                // avoid zombies, jw@suse.de (#88501)
432                 bytewidth = (width+7) / 8;
433                 height = fontbuflth / (bytewidth * fontsize);
434                 if (verbose)
435                         printf(_("Read %d-char %dx%d font from file %s\n"),
436                                fontsize, width, height, fp.pathname);
437
438                 if (bigheight == 0)
439                         bigheight = height;
440                 else if (bigheight != height) {
441                         fprintf(stderr, _("When loading several fonts, all "
442                                           "must have the same height\n"));
443                         exit(EX_DATAERR);
444                 }
445                 if (bigwidth == 0)
446                         bigwidth = width;
447                 else if (bigwidth != width) {
448                         fprintf(stderr, _("When loading several fonts, all "
449                                           "must have the same width\n"));
450                         exit(EX_DATAERR);
451                 }
452
453                 bigfontsize += fontsize;
454                 bigfontbuflth += fontbuflth;
455                 bigfontbuf = xrealloc(bigfontbuf, bigfontbuflth);
456                 memcpy(bigfontbuf+bigfontbuflth-fontbuflth,
457                        fontbuf, fontbuflth);
458         }
459         do_loadfont(fd, bigfontbuf, bigwidth, bigheight, hwunit,
460                     bigfontsize, NULL);
461
462         if (uclistheads && !no_u)
463                 do_loadtable(fd, uclistheads, bigfontsize);
464 }
465
466 static void
467 loadnewfont(int fd, char *ifil, int iunit, int hwunit, int no_m, int no_u)
468 {
469         lkfile_t fp;
470         char defname[20];
471         int height, width, bytewidth, def = 0;
472         char *inbuf, *fontbuf;
473         int inputlth, fontbuflth, fontsize, offset;
474         struct unicode_list *uclistheads;
475
476         if (!*ifil) {
477                 /* try to find some default file */
478
479                 def = 1;                /* maybe also load default unimap */
480
481                 if (iunit < 0 || iunit > 32)
482                         iunit = 0;
483                 if (iunit == 0) {
484                         if (findfont(ifil = "default", &fp) &&
485                             findfont(ifil = "default8x16", &fp) &&
486                             findfont(ifil = "default8x14", &fp) &&
487                             findfont(ifil = "default8x8", &fp)) {
488                                 fprintf(stderr, _("Cannot find default font\n"));
489                                 exit(EX_NOINPUT);
490                         }
491                 } else {
492                         sprintf(defname, "default8x%d", iunit);
493                         if (findfont(ifil = defname, &fp) &&
494                             findfont(ifil = "default", &fp)) {
495                                 fprintf(stderr, _("Cannot find %s font\n"), ifil);
496                                 exit(EX_NOINPUT);
497                         }
498                 }
499         } else {
500                 if (findfont(ifil, &fp)) {
501                         fprintf(stderr, _("Cannot open font file %s\n"), ifil);
502                         exit(EX_NOINPUT);
503                 }
504         }
505
506         if (verbose > 1)
507                 printf(_("Reading font file %s\n"), ifil);
508
509         inbuf = fontbuf = NULL;
510         inputlth = fontbuflth = fontsize = 0;
511         width = 8;
512         uclistheads = NULL;
513         if(readpsffont(fp.fd, &inbuf, &inputlth, &fontbuf, &fontbuflth,
514                        &width, &fontsize, 0,
515                        no_u ? NULL : &uclistheads) == 0) {
516                 lk_fpclose(&fp);
517                 /* we've got a psf font */
518                 bytewidth = (width+7) / 8;
519                 height = fontbuflth / (bytewidth * fontsize);
520
521                 do_loadfont(fd, fontbuf, width, height, hwunit,
522                             fontsize, fp.pathname);
523                 if (uclistheads && !no_u)
524                         do_loadtable(fd, uclistheads, fontsize);
525 #if 1
526                 if (!uclistheads && !no_u && def)
527                         loadunicodemap(fd, "def.uni");
528 #endif
529                 return;
530         }
531         lk_fpclose(&fp);                // avoid zombies, jw@suse.de (#88501)
532
533         /* instructions to combine fonts? */
534         { char *combineheader = "# combine partial fonts\n";
535           int chlth = strlen(combineheader);
536           char *p, *q;
537           if (inputlth >= chlth && !strncmp(inbuf, combineheader, chlth)) {
538                   char *ifiles[MAXIFILES];
539                   int ifilct = 0;
540                   q = inbuf + chlth;
541                   while(q < inbuf + inputlth) {
542                           p = q;
543                           while (q < inbuf+inputlth && *q != '\n')
544                                   q++;
545                           if (q == inbuf+inputlth) {
546                                   fprintf(stderr,
547                                           _("No final newline in combine file\n"));
548                                   exit(EX_DATAERR);
549                           }
550                           *q++ = 0;
551                           if (ifilct == MAXIFILES) {
552                                   fprintf(stderr,
553                                           _("Too many files to combine\n"));
554                                   exit(EX_DATAERR);
555                           }
556                           ifiles[ifilct++] = p;
557                   }
558                   /* recursive call */
559                   loadnewfonts(fd, ifiles, ifilct, iunit, hwunit, no_m, no_u);
560                   return;
561           }
562         }
563
564         /* file with three code pages? */
565         if (inputlth == 9780) {
566                 offset = position_codepage(iunit);
567                 height = iunit;
568                 fontsize = 256;
569                 width = 8;
570         } else if (inputlth == 32768) {
571                 /* restorefont -w writes a SVGA font to file
572                    restorefont -r restores it
573                    These fonts have size 32768, for two 512-char fonts.
574                    In fact, when BROKEN_GRAPHICS_PROGRAMS is defined,
575                    and it always is, there is no default font that is saved,
576                    so probably the second half is always garbage. */
577                 fprintf(stderr, _("Hmm - a font from restorefont? "
578                                   "Using the first half.\n"));
579                 inputlth = 16384;       /* ignore rest */
580                 fontsize = 512;
581                 offset = 0;
582                 width = 8;
583                 height = 32;
584                 if (!hwunit)
585                         hwunit = 16;
586         } else {
587                 int rem = (inputlth % 256);
588                 if (rem == 0 || rem == 40) {
589                         /* 0: bare code page bitmap */
590                         /* 40: preceded by .cp header */
591                         /* we might check some header details */
592                         offset = rem;
593                 } else {
594                         fprintf(stderr, _("Bad input file size\n"));
595                         exit(EX_DATAERR);
596                 }
597                 fontsize = 256;
598                 width = 8;
599                 height = inputlth/256;
600         }
601         do_loadfont(fd, inbuf+offset, width, height, hwunit, fontsize,
602                     fp.pathname);
603 }
604
605 static int
606 position_codepage(int iunit) {
607         int offset;
608
609         /* code page: first 40 bytes, then 8x16 font,
610            then 6 bytes, then 8x14 font,
611            then 6 bytes, then 8x8 font */
612
613         if (!iunit) {
614             fprintf(stderr,
615                     _("This file contains 3 fonts: 8x8, 8x14 and 8x16."
616                       " Please indicate\n"
617                       "using an option -8 or -14 or -16 "
618                       "which one you want loaded.\n"));
619             exit(EX_USAGE);
620         }
621         switch (iunit) {
622           case 8:
623             offset = 7732; break;
624           case 14:
625             offset = 4142; break;
626           case 16:
627             offset = 40; break;
628           default:
629             fprintf(stderr, _("You asked for font size %d, "
630                               "but only 8, 14, 16 are possible here.\n"),
631                     iunit);
632             exit(EX_USAGE);
633         }
634         return offset;
635 }
636
637 static void
638 do_saveoldfont(int fd, char *ofil, FILE *fpo, int unimap_follows,
639                int *count, int *utf8) {
640
641 /* this is the max font size the kernel is willing to handle */
642 #define MAXFONTSIZE     65536
643         unsigned char buf[MAXFONTSIZE];
644
645         int i, ct, width, height, bytewidth, charsize, kcharsize;
646
647         ct = sizeof(buf)/(32*32/8);     /* max size 32x32, 8 bits/byte */
648         if (getfont(fd, buf, &ct, &width, &height))
649                 exit(EX_OSERR);
650
651         /* save as efficiently as possible */
652         bytewidth = (width + 7) / 8;
653         height = font_charheight(buf, ct, width);
654         charsize = height * bytewidth;
655         kcharsize = 32 * bytewidth;
656
657         /* Do we need a psf header? */
658         /* Yes if ct==512 - otherwise we cannot distinguish
659            a 512-char 8x8 and a 256-char 8x16 font. */
660 #define ALWAYS_PSF_HEADER       1
661
662         if (ct != 256 || width != 8 || unimap_follows || ALWAYS_PSF_HEADER) {
663                 int psftype = 1;
664                 int flags = 0;
665
666                 if (unimap_follows)
667                         flags |= WPSFH_HASTAB;
668                 writepsffontheader (fpo, width, height, ct, &psftype, flags);
669                 if (utf8)
670                         *utf8 = (psftype == 2);
671         }
672
673         if (height == 0) {
674                 fprintf(stderr, _("Found nothing to save\n"));
675         } else {
676                 for (i = 0; i < ct; i++) {
677                         if (fwrite(buf+(i*kcharsize), charsize, 1, fpo) != 1) {
678                                 fprintf(stderr, _("Cannot write font file"));
679                                 exit(EX_IOERR);
680                         }
681                 }
682                 if (verbose) {
683                         printf(_("Saved %d-char %dx%d font file on %s\n"),
684                                ct, width, height, ofil);
685                 }
686         }
687
688         if (count)
689                 *count = ct;
690 }
691
692 static void
693 saveoldfont(int fd, char *ofil) {
694     FILE *fpo;
695
696     if((fpo = fopen(ofil, "w")) == NULL) {
697         perror(ofil);
698         exit(EX_CANTCREAT);
699     }
700     do_saveoldfont(fd, ofil, fpo, 0, NULL, NULL);
701     fclose(fpo);
702 }
703
704 static void
705 saveoldfontplusunicodemap(int fd, char *Ofil) {
706     FILE *fpo;
707     int ct;
708     int utf8 = 0;
709
710     if((fpo = fopen(Ofil, "w")) == NULL) {
711         perror(Ofil);
712         exit(EX_CANTCREAT);
713     }
714     ct = 0;
715     do_saveoldfont(fd, Ofil, fpo, 1, &ct, &utf8);
716     appendunicodemap(fd, fpo, ct, utf8);
717     fclose(fpo);
718 }
719
720 /* Only on the current console? On all allocated consoles? */
721 /* A newly allocated console has NORM_MAP by default -
722    probably it should copy the default from the current console?
723    But what if we want a new one because the current one is messed up? */
724 /* For the moment: only the current console, only the G0 set */
725
726 static void
727 send_escseq(int fd, char *seq, int n) {
728         if (write(fd, seq, n) != n)  /* maybe fd is read-only */
729                 printf("%s", seq);
730 }
731
732 void
733 activatemap(int fd) {
734         send_escseq(fd, "\033(K", 3);
735 }
736
737 void
738 disactivatemap(int fd) {
739         send_escseq(fd, "\033(B", 3);
740 }