contrib: Add utility to remove all kernel keymaps
[platform/upstream/kbd.git] / contrib / codepage.c
1 /*
2  * CPI.C: A program to examine MSDOS codepage files (*.cpi)
3  * and extract specific codepages.
4  * Compiles under Linux & DOS (using BC++ 3.1).
5  *
6  * Compile: gcc -o cpi cpi.c
7  * Call: codepage [-a|-l|nnn] file.cpi
8  *
9  * Author: Ahmed M. Naas (ahmed@oea.xs4all.nl)
10  * Many changes: aeb@cwi.nl  [changed until it would handle all
11  *      *.cpi files people have sent me; I have no documentation,
12  *      so all this is experimental]
13  * Remains to do: DRDOS fonts.
14  *
15  * Copyright: Public domain.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 int handle_codepage(int);
24 void handle_fontfile(void);
25
26 #define PACKED __attribute__ ((packed))
27 /* Use this (instead of the above) to compile under MSDOS */
28 /*#define PACKED  */
29
30 struct {
31         unsigned char id0 PACKED;
32         unsigned char id[7] PACKED;
33         unsigned char res[8] PACKED;
34         unsigned short pnum PACKED;      /* number of pointers */
35         unsigned char ptyp PACKED;       /* type of pointers */
36         unsigned long fih_offset PACKED; /* FontInfoHeader offset */
37 } FontFileHeader;
38
39 int drfont = 0;
40
41 #define N       4
42 struct {
43         unsigned char num_fonts PACKED;     /* N = 4 fonts per code page*/
44         unsigned char font_height[N] PACKED;
45         unsigned long dfd_offset[N] PACKED; /* DisplayFontData offset */
46 } DRDOS_ExtendedFontFileHeader;
47
48 struct {
49         unsigned short num_codepages PACKED;
50 } FontInfoHeader;
51
52 struct {
53         unsigned short size PACKED;
54         unsigned long off_nexthdr PACKED;
55         unsigned short device_type PACKED; /* screen=1; printer=2 */
56         unsigned char device_name[8] PACKED;
57         unsigned short codepage PACKED;
58         unsigned char res[6] PACKED;
59         unsigned long off_font PACKED;
60 } CPEntryHeader;
61
62 struct {
63         unsigned short reserved PACKED;
64         unsigned short num_fonts PACKED;
65         unsigned short size PACKED;
66 } CPInfoHeader;
67
68 struct {
69         unsigned char height PACKED;
70         unsigned char width PACKED;
71         unsigned short reserved PACKED;
72         unsigned short num_chars PACKED;
73 } ScreenFontHeader;
74
75 struct {
76         unsigned short printer_type PACKED;
77         unsigned short seqlength PACKED;
78 } PrinterFontHeader;
79
80 FILE *in, *out;
81 void usage(void);
82
83 int opta, optc, optl, optL, optx;
84 extern int optind;
85 extern char *optarg;
86
87 unsigned short codepage;
88
89 int main (int argc, char *argv[]) {
90         if (argc < 2)
91                 usage();
92
93         opta = optc = optl = optL = optx = 0;
94
95         if (argc == 2)
96                 optl = 1;
97         else
98         while(1) {
99             switch(getopt(argc, argv, "alLc")) {
100               case 'a':
101                 opta = 1;
102                 continue;
103               case 'c':
104                 optc = 1;
105                 continue;
106               case 'L':
107                 optL = 1;
108                 continue;
109               case 'l':
110                 optl = 1;
111                 continue;
112               case '?':
113               default:
114                 usage();
115               case -1:
116                 break;
117             }
118             break;
119         }
120
121         if (optind < argc) {
122             if ((in = fopen(argv[optind], "r")) == NULL) {
123                 printf("\nUnable to open file %s.\n", argv[optind]);
124                 exit(0);
125             }
126             optind++;
127         } else
128             usage();
129         
130         if (optind != argc) {
131             if (optind != argc-1 || opta)
132               usage();
133             codepage = atoi(argv[optind]);
134             optx = 1;
135         }
136
137         if (optc)
138           handle_codepage(0);
139         else
140           handle_fontfile();
141
142         if (optx) {
143             printf("no page %d found\n", codepage);
144             exit(1);
145         }
146
147         fclose(in);
148         return (0);
149 }
150
151 void
152 handle_fontfile(){
153         int i, j;
154
155         j = fread(&FontFileHeader, 1, sizeof(FontFileHeader), in);
156         if (j != sizeof(FontFileHeader)) {
157             printf("error reading FontFileHeader - got %d chars\n", j);
158             exit (1);
159         }
160         if (optL)
161           printf("FontFileHeader: id=0x%x \"%7.7s\" res=%8.8s "
162                  "num=%d typ=%d fih_offset=%ld\n\n",
163                  FontFileHeader.id0, FontFileHeader.id, FontFileHeader.res,
164                  FontFileHeader.pnum, FontFileHeader.ptyp,
165                  FontFileHeader.fih_offset);
166
167         if (!strcmp(FontFileHeader.id, "DRFONT ")) {
168             drfont = 1;
169             j = fread(&DRDOS_ExtendedFontFileHeader, 1,
170                       sizeof(DRDOS_ExtendedFontFileHeader), in);
171             if (j != sizeof(DRDOS_ExtendedFontFileHeader)) {
172                 printf("error reading ExtendedFontFileHeader - "
173                        "got %d chars\n", j);
174                 exit (1);
175             }
176             if (DRDOS_ExtendedFontFileHeader.num_fonts != N) {
177                 printf("found %d instead of 4 fonts in drfont\n",
178                        DRDOS_ExtendedFontFileHeader.num_fonts);
179                 exit (1);
180             }
181             if (optL) {
182                 printf("ExtendedFontFileHeader:\n");
183                 for (j=0; j<N; j++) {
184                         printf("font%d: height %d dfd_offset %d\n", j,
185                            DRDOS_ExtendedFontFileHeader.font_height[j],
186                            DRDOS_ExtendedFontFileHeader.dfd_offset[j]);
187                 }
188                 printf("\n");
189             }
190         }
191
192         j = fread(&FontInfoHeader, 1, sizeof(FontInfoHeader), in);
193         if (j != sizeof(FontInfoHeader)) {
194             printf("error reading FontInfoHeader - got %d chars\n", j);
195             exit (1);
196         }
197         if (optL)
198           printf("FontInfoHeader: num_codepages=%d\n\n",
199                  FontInfoHeader.num_codepages);
200
201 #if 1
202         if (drfont) {
203             printf("this program cannot handle DRDOS font files\n");
204             exit(1);
205         }
206 #endif
207
208         for (i = FontInfoHeader.num_codepages; i; i--)
209           if (handle_codepage(i-1))
210             break;
211 }
212
213 int
214 handle_codepage(int more_to_come) {
215         int j;
216         char outfile[20];
217         unsigned char *fonts;
218         long inpos, nexthdr;
219
220         j = fread(&CPEntryHeader, 1, sizeof(CPEntryHeader), in);
221         if (j != sizeof(CPEntryHeader)) {
222             printf("error reading CPEntryHeader - got %d chars\n", j);
223             exit(1);
224         }
225         if (optL) {
226             int t = CPEntryHeader.device_type;
227             printf("CPEntryHeader: size=%d dev=%d [%s] name=%8.8s "
228 "codepage=%d\n\t\tres=%6.6s nxt=%ld off_font=%ld\n\n",
229                    CPEntryHeader.size,
230                    t, (t==1) ? "screen" : (t==2) ? "printer" : "?",
231                    CPEntryHeader.device_name,
232                    CPEntryHeader.codepage,
233                    CPEntryHeader.res,
234                    CPEntryHeader.off_nexthdr, CPEntryHeader.off_font);
235         } else if (optl) {
236             printf("\nCodepage = %d\n", CPEntryHeader.codepage);
237             printf("Device = %.8s\n", CPEntryHeader.device_name);
238         }
239 #if 0
240         if (CPEntryHeader.size != sizeof(CPEntryHeader)) {
241             /* seen 26 and 28, so that the difference below is -2 or 0 */
242             if (optl)
243               printf("Skipping %d bytes of garbage\n",
244                      CPEntryHeader.size - sizeof(CPEntryHeader));
245             fseek(in, CPEntryHeader.size - sizeof(CPEntryHeader),
246                   SEEK_CUR);
247         }
248 #endif
249         if (!opta && (!optx || CPEntryHeader.codepage != codepage) && !optc)
250           goto next;
251
252         inpos = ftell(in);
253         if (inpos != CPEntryHeader.off_font && !optc) {
254             if (optL)
255               printf("pos=%ld font at %ld\n", inpos, CPEntryHeader.off_font);
256             fseek(in, CPEntryHeader.off_font, SEEK_SET);
257         }
258
259         j = fread(&CPInfoHeader, 1, sizeof(CPInfoHeader), in);
260         if (j != sizeof(CPInfoHeader)) {
261             printf("error reading CPInfoHeader - got %d chars\n", j);
262             exit(1);
263         }
264         if (optl) {
265             printf("Number of Fonts = %d\n", CPInfoHeader.num_fonts);
266             printf("Size of Bitmap = %d\n", CPInfoHeader.size);
267         }
268         if (CPInfoHeader.num_fonts == 0)
269           goto next;
270         if (optc)
271           return 0;
272
273         sprintf(outfile, "%d.cp", CPEntryHeader.codepage);
274         if ((out = fopen(outfile, "w")) == NULL) {
275             printf("\nUnable to open file %s.\n", outfile);
276             exit(1);            
277         } else printf("\nWriting %s\n", outfile);
278
279         fonts = (unsigned char *) malloc(CPInfoHeader.size);
280                 
281         fread(fonts, CPInfoHeader.size, 1, in);
282         fwrite(&CPEntryHeader, sizeof(CPEntryHeader), 1, out);
283         fwrite(&CPInfoHeader, sizeof(CPInfoHeader), 1, out);
284         j = fwrite(fonts, 1, CPInfoHeader.size, out);
285         if (j != CPInfoHeader.size) {
286             printf("error writing %s - wrote %d chars\n", outfile, j);
287             exit(1);
288         }
289         fclose(out);
290         free(fonts);
291         if (optx) exit(0);
292       next:
293         /*
294          * It seems that if entry headers and fonts are interspersed,
295          * then nexthdr will point past the font, regardless of
296          * whether more entries follow.
297          * Otherwise, first all entry headers are given, and then
298          * all fonts; in this case nexthdr will be 0 in the last entry.
299          */
300         nexthdr = CPEntryHeader.off_nexthdr;
301         if (nexthdr == 0 || nexthdr == -1) {
302             if (more_to_come) {
303                 printf("more codepages expected, but nexthdr=%ld\n",
304                        nexthdr);
305                 exit(1);
306             } else
307                 return 1;
308         }
309
310         inpos = ftell(in);
311         if (inpos != CPEntryHeader.off_nexthdr) {
312             if (optL)
313               printf("pos=%ld nexthdr at %ld\n", inpos, nexthdr);
314             if (opta && !more_to_come) {
315                 printf("no more code pages, but nexthdr != 0\n");
316                 return 1;
317             }
318
319             fseek(in, CPEntryHeader.off_nexthdr, SEEK_SET);
320         }
321
322         return 0;
323 }
324
325 void usage(void)
326 {
327         printf("\nUsage: cpi code_page_file [-c] [-L] [-l] [-a|nnn]\n");
328         printf(" -c: input file is a single codepage\n");
329         printf(" -L: print header info (you don't want to see this)\n");
330         printf(" -l or no option: list all codepages contained in the file\n");
331         printf(" -a: extract all codepages from the file\n");
332         printf(" nnn (3 digits): extract codepage nnn from the file\n");
333         printf("Example: cpi ega.cpi 850 \n");
334         printf(" will create a file 850.cp containing the requested codepage.\n\n");
335         exit(1);
336 }