Commit | Line | Data |
---|---|---|
7e6ae4ba AJ |
1 | /************************************************ |
2 | * | |
3 | * Extract fonts from .fnt or Windows DLL files | |
4 | * and convert them to the .bdf format. | |
5 | * | |
6 | * Copyright 1994-1996 Kevin Carothers and Alex Korobka | |
7 | * | |
0799c1a7 AJ |
8 | * This library is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
7e6ae4ba AJ |
21 | */ |
22 | ||
96336324 | 23 | #include "config.h" |
49b7fdcf | 24 | #include "wine/port.h" |
96336324 PS |
25 | |
26 | #ifdef HAVE_SYS_PARAM_H | |
27 | # include <sys/param.h> | |
28 | #endif | |
7e6ae4ba AJ |
29 | #include <sys/types.h> |
30 | #include <sys/stat.h> | |
fef71865 | 31 | #include <stdio.h> |
7e6ae4ba AJ |
32 | #include <stdlib.h> |
33 | #include <string.h> | |
c63d9803 DT |
34 | #ifdef HAVE_UNISTD_H |
35 | # include <unistd.h> | |
36 | #endif | |
7e6ae4ba | 37 | #include <fcntl.h> |
c63d9803 DT |
38 | #ifdef HAVE_IO_H |
39 | # include <io.h> | |
40 | #endif | |
41 | ||
7e6ae4ba | 42 | #include "fnt2bdf.h" |
7e6ae4ba | 43 | |
7e6ae4ba AJ |
44 | #define FILE_ERROR 0 |
45 | #define FILE_DLL 1 | |
46 | #define FILE_FNT 2 | |
47 | ||
48 | /* global options */ | |
49 | ||
fef71865 DT |
50 | int dump_bdf( fnt_fontS* cpe_font_struct, unsigned char* file_buffer); |
51 | int dump_bdf_hdr(FILE* fs, fnt_fontS* cpe_font_struct, unsigned char* file_buffer); | |
52 | ||
7e6ae4ba AJ |
53 | char* g_lpstrFileName = NULL; |
54 | char* g_lpstrCharSet = NULL; | |
55 | char* g_lpstrInputFile = NULL; | |
23946ad2 | 56 | int g_outputPoints = 0; |
7e6ae4ba | 57 | |
9bb19ac2 DM |
58 | static const char* errorDLLRead = "Unable to read Windows DLL.\n"; |
59 | static const char* errorFNTRead = "Unable to read .FNT file.\n"; | |
60 | static const char* errorOpenFile = "Unable to open file.\n"; | |
61 | static const char* errorMemory = "Memory allocation error.\n"; | |
62 | static const char* errorFile = "Corrupt or invalid file.\n"; | |
63 | static const char* errorFontData = "Unable to parse font data: Error "; | |
64 | static const char* errorEmpty = "No fonts found.\n"; | |
7e6ae4ba AJ |
65 | |
66 | /* info */ | |
67 | ||
763aff61 | 68 | static void usage(void) |
7e6ae4ba | 69 | { |
23946ad2 AJ |
70 | printf("Usage: fnt2bdf [-t] [-c charset] [-o basename] [input file]\n"); |
71 | printf(" -c charset\tcharset name for OEM_CHARSET fonts\n"); | |
7e6ae4ba | 72 | printf(" -f basename\tbasic output filename\n"); |
23946ad2 | 73 | printf(" -t \t\toutput files by point size instead of pixel height\n"); |
7e6ae4ba AJ |
74 | printf(" input file\tMSWindows .fon, .fnt, .dll, or .exe file.\n"); |
75 | printf("\nExample:\n fnt2bdf -c winsys vgasys.fnt\n\n"); | |
76 | exit(-1); | |
77 | } | |
78 | ||
fef71865 | 79 | /* convert little-endian value to the local format */ |
7e6ae4ba | 80 | |
763aff61 | 81 | static int return_data_value(enum data_types dtype, void * pChr) |
7e6ae4ba AJ |
82 | { |
83 | int ret_val = 0; | |
84 | ||
85 | switch(dtype) { | |
9a624916 | 86 | case (dfChar): |
7e6ae4ba AJ |
87 | ret_val = (int) *(unsigned char *)pChr; |
88 | break; | |
9a624916 VB |
89 | |
90 | case(dfShort): | |
7e6ae4ba AJ |
91 | ret_val = *(unsigned char *)pChr; |
92 | ret_val += (*((unsigned char *)pChr + 1) << 8); | |
93 | break; | |
9a624916 | 94 | |
7e6ae4ba AJ |
95 | case(dfLong): { |
96 | int i; | |
97 | ||
98 | for(i=3; i >= 0; i--) { | |
99 | ret_val += *((unsigned char *)pChr + i) << (8*i); | |
100 | } | |
101 | break; | |
102 | } | |
a11d7b1a AJ |
103 | case(dfString): |
104 | break; | |
9a624916 | 105 | } |
7e6ae4ba AJ |
106 | return ret_val; |
107 | } | |
108 | ||
763aff61 | 109 | static int make_bdf_filename(char* name, fnt_fontS* cpe_font_struct, unsigned char* file_buffer) |
7e6ae4ba | 110 | { |
fef71865 | 111 | long l_nameoffset = return_data_value(dfLong, &cpe_font_struct->hdr.fi.dfFace); |
7e6ae4ba AJ |
112 | char* lpChar; |
113 | ||
114 | if( !g_lpstrFileName ) | |
115 | { | |
9a624916 | 116 | if( !l_nameoffset || |
fef71865 | 117 | l_nameoffset > return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) + 1 ) |
7e6ae4ba AJ |
118 | return ERROR_DATA; |
119 | lpChar = (char*)(file_buffer + l_nameoffset); | |
120 | } | |
121 | else lpChar = g_lpstrFileName; | |
122 | ||
123 | strcpy( name, lpChar ); | |
124 | ||
9a624916 | 125 | while( (lpChar = strchr( name, ' ')) ) |
7e6ae4ba AJ |
126 | *lpChar = '-'; |
127 | ||
128 | /* construct a filename from the font typeface, slant, weight, and size */ | |
129 | ||
fef71865 | 130 | if( cpe_font_struct->hdr.fi.dfItalic ) strcat(name, "_i" ); |
7e6ae4ba AJ |
131 | else strcat(name, "_r" ); |
132 | ||
133 | lpChar = name + strlen( name ); | |
fef71865 DT |
134 | sprintf(lpChar, "%d-%d.bdf", return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfWeight), |
135 | (g_outputPoints) ? return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints) | |
136 | : return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixHeight) ); | |
7e6ae4ba AJ |
137 | return 0; |
138 | } | |
139 | ||
140 | /* parse FONT resource and write .bdf file */ | |
141 | ||
763aff61 | 142 | static int parse_fnt_data(unsigned char* file_buffer, int length) |
7e6ae4ba | 143 | { |
9a624916 | 144 | fnt_fontS cpe_font_struct; |
7e6ae4ba AJ |
145 | int ic=0, t; |
146 | ||
c6c09442 | 147 | memcpy((char *) &cpe_font_struct.hdr, file_buffer, sizeof(fnt_hdrS)); |
7e6ae4ba AJ |
148 | |
149 | /* check font header */ | |
150 | ||
fef71865 | 151 | t = return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion); |
7e6ae4ba AJ |
152 | if( t != 0x300 && t != 0x200) return ERROR_VERSION; |
153 | ||
c63d9803 DT |
154 | t = return_data_value(dfShort, &cpe_font_struct.hdr.fi.dfType); |
155 | if (t & 1) | |
156 | { | |
157 | fprintf(stderr, "Vector fonts not supported\n"); | |
158 | return ERROR_DATA; | |
159 | } | |
160 | ||
fef71865 | 161 | t = return_data_value(dfLong, &cpe_font_struct.hdr.dfSize); |
7e6ae4ba AJ |
162 | if( t > length ) return ERROR_SIZE; |
163 | else | |
9a624916 | 164 | { |
7e6ae4ba AJ |
165 | /* set up the charWidth/charOffset structure pairs (dfCharTable)... */ |
166 | ||
fef71865 | 167 | int l_fchar = return_data_value(dfChar, &cpe_font_struct.hdr.fi.dfFirstChar), |
9a624916 | 168 | l_lchar = return_data_value(dfChar, &cpe_font_struct.hdr.fi.dfLastChar); |
fef71865 DT |
169 | int l_len = l_lchar - l_fchar + 1; |
170 | int l_ptr = sizeof(fnt_hdrS); | |
171 | ||
172 | /* some fields were introduced for Windows 3.x fonts */ | |
173 | if( return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion) == 0x200 ) | |
174 | l_ptr -= 30; | |
7e6ae4ba AJ |
175 | |
176 | /* malloc size = (# chars) * sizeof(WinCharS) */ | |
177 | ||
9a624916 | 178 | if((cpe_font_struct.dfCharTable = (WinCharS *) calloc(sizeof(WinCharS), l_len)) == NULL) |
7e6ae4ba AJ |
179 | return ERROR_MEMORY; |
180 | ||
181 | /* NOW, convert them all to UNIX (lton) notation... */ | |
182 | ||
183 | for(ic=0; ic < l_len; ic++) { | |
184 | cpe_font_struct.dfCharTable[ic].charWidth = return_data_value(dfShort, &file_buffer[l_ptr]); | |
185 | l_ptr += 2; /* bump by sizeof(short) */ | |
186 | ||
187 | ||
fef71865 | 188 | if( return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion) == 0x200) { |
9a624916 | 189 | cpe_font_struct.dfCharTable[ic].charOffset = |
7e6ae4ba | 190 | return_data_value(dfShort, &file_buffer[l_ptr]); |
c63d9803 | 191 | l_ptr += 2; /* bump by sizeof(short) */ |
7e6ae4ba AJ |
192 | } |
193 | else { /* Windows Version 3.0 type font */ | |
9a624916 | 194 | cpe_font_struct.dfCharTable[ic].charOffset = |
7e6ae4ba AJ |
195 | return_data_value(dfLong, &file_buffer[l_ptr]); |
196 | l_ptr += 4; /* bump by sizeof(long) */ | |
197 | } | |
198 | } | |
199 | t = dump_bdf(&cpe_font_struct, file_buffer); | |
200 | free( cpe_font_struct.dfCharTable ); | |
201 | } | |
202 | return t; | |
203 | } | |
204 | ||
205 | int dump_bdf( fnt_fontS* cpe_font_struct, unsigned char* file_buffer) | |
206 | { | |
207 | FILE* fp; | |
208 | int ic; | |
9a624916 VB |
209 | int l_fchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfFirstChar), |
210 | l_lchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfLastChar); | |
7e6ae4ba | 211 | |
23946ad2 | 212 | int l_len = l_lchar-l_fchar + 1, |
9a624916 | 213 | l_hgt = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfPixHeight); |
fef71865 | 214 | int l_ascent = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAscent); |
7e6ae4ba AJ |
215 | char l_filename[256]; |
216 | ||
217 | if( (ic = make_bdf_filename(l_filename, cpe_font_struct, file_buffer)) ) | |
218 | return ic; | |
219 | ||
9a624916 | 220 | if((fp = fopen(l_filename, "w")) == (FILE *) 0) |
7e6ae4ba AJ |
221 | { |
222 | fprintf(stderr, "Couldn't open \"%s\" for output.\n", l_filename); | |
223 | return ERROR_FILE; | |
224 | } | |
225 | ||
02e90087 AJ |
226 | ic = dump_bdf_hdr(fp, cpe_font_struct, file_buffer); |
227 | if (ic) return (ic); | |
7e6ae4ba AJ |
228 | |
229 | /* NOW, convert all chars to UNIX (lton) notation... */ | |
230 | ||
231 | for(ic=0; ic < l_len; ic++) { | |
232 | int rowidx, l_span, /* how many char-cols wide is char? */ | |
233 | l_idx = cpe_font_struct->dfCharTable[ic].charOffset; | |
234 | ||
9a624916 | 235 | l_span = (int) (cpe_font_struct->dfCharTable[ic].charWidth-1)/8; |
7e6ae4ba AJ |
236 | |
237 | fprintf(fp, "STARTCHAR %d \n", ic); | |
238 | fprintf(fp, "ENCODING %d\n", l_fchar); | |
9a624916 VB |
239 | fprintf(fp, "SWIDTH %d %d \n", |
240 | cpe_font_struct->dfCharTable[ic].charWidth*1000, | |
7e6ae4ba AJ |
241 | 0); |
242 | ||
9a624916 | 243 | fprintf(fp, "DWIDTH %d %d \n", |
7e6ae4ba AJ |
244 | cpe_font_struct->dfCharTable[ic].charWidth, 0); |
245 | ||
246 | fprintf(fp, "BBX %d %d %d %d\n", | |
9a624916 | 247 | cpe_font_struct->dfCharTable[ic].charWidth, l_hgt, 0, |
7e6ae4ba AJ |
248 | l_ascent - l_hgt); |
249 | ||
250 | fprintf(fp, "BITMAP\n"); | |
251 | for(rowidx=0; rowidx < l_hgt; rowidx++) { | |
252 | switch(l_span) { | |
253 | case(0): /* 1-7 pixels wide font */ | |
254 | { | |
255 | fprintf(fp, "%02X\n", (int) file_buffer[l_idx+rowidx]); | |
256 | break; | |
257 | } | |
9a624916 | 258 | |
7e6ae4ba AJ |
259 | case(1): /* 8-15 pixels wide font */ |
260 | { | |
9a624916 | 261 | fprintf(fp, "%02X%02X", |
7e6ae4ba AJ |
262 | (int) file_buffer[l_idx+rowidx], file_buffer[l_idx+l_hgt+rowidx]); |
263 | fprintf(fp, "\n"); | |
264 | break; | |
265 | } | |
266 | ||
267 | case(2): /* 16-23 pixels wide font */ | |
268 | { | |
9a624916 | 269 | fprintf(fp, "%02X%02X%02X", |
7e6ae4ba AJ |
270 | file_buffer[l_idx+rowidx], |
271 | file_buffer[l_idx+l_hgt+rowidx], | |
272 | file_buffer[l_idx+(2*l_hgt)+rowidx]); | |
273 | fprintf(fp, "\n"); | |
274 | break; | |
275 | } | |
276 | ||
277 | case(3): /* 24-31 pixels wide font */ | |
278 | { | |
9a624916 | 279 | fprintf(fp, "%02X%02X%02X%02X", |
7e6ae4ba AJ |
280 | file_buffer[l_idx+rowidx], |
281 | file_buffer[l_idx+l_hgt+rowidx], | |
282 | file_buffer[l_idx+(2*l_hgt)+rowidx], | |
283 | file_buffer[l_idx+(3*l_hgt)+rowidx]); | |
284 | fprintf(fp, "\n"); | |
285 | break; | |
286 | } | |
287 | case(4): /* 32-39 */ | |
288 | { | |
289 | fprintf(fp, "%02X%02X%02X%02X%02X", | |
290 | file_buffer[l_idx+rowidx], | |
291 | file_buffer[l_idx+l_hgt+rowidx], | |
292 | file_buffer[l_idx+(2*l_hgt)+rowidx], | |
293 | file_buffer[l_idx+(3*l_hgt)+rowidx], | |
294 | file_buffer[l_idx+(4*l_hgt)+rowidx]); | |
295 | fprintf(fp, "\n"); | |
296 | break; | |
297 | } | |
298 | default: | |
299 | fclose(fp); | |
300 | unlink(l_filename); | |
301 | return ERROR_DATA; | |
302 | } | |
303 | } | |
304 | fprintf(fp, "ENDCHAR\n"); | |
305 | ||
306 | l_fchar++; /* Go to next one */ | |
307 | } | |
308 | fprintf(fp, "ENDFONT\n"); | |
309 | fclose(fp); | |
310 | return 0; | |
311 | } | |
312 | ||
313 | ||
314 | int dump_bdf_hdr(FILE* fs, fnt_fontS* cpe_font_struct, unsigned char* file_buffer) | |
315 | { | |
9a624916 | 316 | int l_fchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfFirstChar), |
fef71865 | 317 | l_lchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfLastChar); |
23946ad2 | 318 | int l_len = l_lchar - l_fchar + 1; |
fef71865 DT |
319 | long l_nameoffset = return_data_value(dfLong, &cpe_font_struct->hdr.fi.dfFace); |
320 | int l_cellheight = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixHeight); | |
321 | int l_ascent = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAscent); | |
7e6ae4ba AJ |
322 | |
323 | fprintf(fs, "STARTFONT 2.1\n"); | |
324 | ||
325 | /* Compose font name */ | |
326 | ||
9a624916 | 327 | if( l_nameoffset && |
fef71865 | 328 | l_nameoffset < return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) ) |
7e6ae4ba AJ |
329 | { |
330 | int dpi, point_size; | |
331 | char* lpFace = (char*)(file_buffer + l_nameoffset), *lpChar; | |
fef71865 | 332 | short tmWeight = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfWeight); |
7e6ae4ba | 333 | |
9a624916 | 334 | while((lpChar = strchr(lpFace, '-')) ) |
7e6ae4ba AJ |
335 | *lpChar = ' '; |
336 | ||
337 | fprintf(fs, "FONT -windows-%s-", lpFace ); | |
338 | ||
339 | if( tmWeight == 0 ) /* weight */ | |
340 | fputs("medium-", fs); | |
341 | else if( tmWeight <= FW_LIGHT ) | |
342 | fputs("light-", fs); | |
343 | else if( tmWeight <= FW_MEDIUM ) | |
344 | fputs("medium-", fs); | |
345 | else if( tmWeight <= FW_DEMIBOLD ) | |
346 | fputs("demibold-", fs); | |
347 | else if( tmWeight <= FW_BOLD ) | |
348 | fputs("bold-", fs); | |
349 | else fputs("black-", fs); | |
350 | ||
fef71865 | 351 | if( cpe_font_struct->hdr.fi.dfItalic ) /* slant */ |
7e6ae4ba AJ |
352 | fputs("i-", fs); |
353 | else fputs("r-", fs); | |
354 | ||
355 | /* style */ | |
356 | ||
fef71865 | 357 | if( (cpe_font_struct->hdr.fi.dfPitchAndFamily & 0xF0) == FF_SWISS ) |
7e6ae4ba AJ |
358 | fputs("normal-sans-", fs); |
359 | else fputs("normal--", fs); /* still can be -sans */ | |
360 | ||
361 | /* y extents */ | |
362 | ||
fef71865 | 363 | point_size = 10 * return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints ); |
7e6ae4ba AJ |
364 | dpi = (l_cellheight * 720) / point_size; |
365 | ||
9a624916 | 366 | fprintf(fs, "%d-%d-%d-%d-",l_cellheight, point_size, |
4eb22c68 BM |
367 | return_data_value (dfShort, &cpe_font_struct->hdr.fi.dfHorizRes), |
368 | return_data_value (dfShort, &cpe_font_struct->hdr.fi.dfVertRes)); | |
7e6ae4ba AJ |
369 | |
370 | /* spacing */ | |
371 | ||
fef71865 | 372 | if( return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixWidth) ) fputs("c-", fs); |
23946ad2 | 373 | else fputs("p-", fs); |
9a624916 | 374 | |
7e6ae4ba AJ |
375 | /* average width */ |
376 | ||
fef71865 | 377 | fprintf( fs, "%d-", 10 * return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAvgWidth) ); |
7e6ae4ba AJ |
378 | |
379 | /* charset */ | |
380 | ||
5c13c218 SS |
381 | if( g_lpstrCharSet ) fprintf(fs, "%s\n", g_lpstrCharSet); |
382 | else | |
fef71865 | 383 | switch( cpe_font_struct->hdr.fi.dfCharSet ) |
7e6ae4ba | 384 | { |
23946ad2 AJ |
385 | /* Microsoft just had to invent its own charsets! */ |
386 | ||
b13f23e4 | 387 | case ANSI_CHARSET: fputs("microsoft-cp1252\n", fs); break; |
d30dfd24 AJ |
388 | case GREEK_CHARSET: fputs("microsoft-cp1253\n", fs); break; |
389 | case TURKISH_CHARSET: fputs("microsoft-cp1254\n", fs); break; | |
390 | case HEBREW_CHARSET: fputs("microsoft-cp1255\n", fs); break; | |
391 | case ARABIC_CHARSET: fputs("microsoft-cp1256\n", fs); break; | |
392 | case BALTIC_CHARSET: fputs("microsoft-cp1257\n", fs); break; | |
393 | case RUSSIAN_CHARSET: fputs("microsoft-cp1251\n", fs); break; | |
9a624916 | 394 | case EE_CHARSET: fputs("microsoft-cp1250\n", fs); break; |
d30dfd24 | 395 | case SYMBOL_CHARSET: fputs("microsoft-symbol\n", fs); break; |
23946ad2 AJ |
396 | case SHIFTJIS_CHARSET: fputs("jisx0208.1983-0\n", fs); break; |
397 | case DEFAULT_CHARSET: fputs("iso8859-1\n", fs); break; | |
398 | ||
7e6ae4ba | 399 | default: |
9a624916 VB |
400 | case OEM_CHARSET: |
401 | fputs("Undefined charset, use -c option.\n", stderr); | |
402 | return ERROR_DATA; | |
7e6ae4ba AJ |
403 | } |
404 | } | |
405 | else return ERROR_DATA; | |
406 | ||
9a624916 | 407 | fprintf(fs, "SIZE %d %d %d\n", |
4eb22c68 | 408 | return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints ), |
fef71865 DT |
409 | return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfHorizRes), |
410 | return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfVertRes)); /* dfVertRes[2] */ | |
7e6ae4ba AJ |
411 | |
412 | fprintf(fs, "FONTBOUNDINGBOX %d %d %d %d\n", | |
fef71865 DT |
413 | return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfMaxWidth), |
414 | return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfPixHeight), | |
7e6ae4ba AJ |
415 | 0, l_ascent - l_cellheight ); |
416 | ||
417 | fprintf(fs, "STARTPROPERTIES 4\n"); | |
418 | ||
419 | fprintf(fs, "FONT_ASCENT %d\n", l_ascent ); /* dfAscent[2] */ | |
420 | fprintf(fs, "FONT_DESCENT %d\n", l_cellheight - l_ascent ); | |
421 | fprintf(fs, "CAP_HEIGHT %d\n", l_ascent - | |
fef71865 DT |
422 | return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfInternalLeading)); |
423 | fprintf(fs, "DEFAULT_CHAR %d\n", return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfDefaultChar)); | |
7e6ae4ba AJ |
424 | |
425 | fprintf(fs, "ENDPROPERTIES\n"); | |
426 | ||
427 | fprintf(fs, "CHARS %d\n", l_len); | |
428 | return 0; | |
429 | } | |
430 | ||
431 | ||
432 | ||
763aff61 | 433 | static void parse_options(int argc, char **argv) |
7e6ae4ba AJ |
434 | { |
435 | int i; | |
436 | ||
437 | switch( argc ) | |
438 | { | |
439 | case 2: | |
440 | g_lpstrInputFile = argv[1]; | |
441 | break; | |
442 | ||
443 | case 3: | |
444 | case 4: | |
445 | case 5: | |
446 | case 6: | |
23946ad2 AJ |
447 | case 7: |
448 | case 8: | |
7e6ae4ba AJ |
449 | for( i = 1; i < argc - 1; i++ ) |
450 | { | |
451 | if( argv[i][0] != '-' || | |
452 | strlen(argv[i]) != 2 ) break; | |
453 | ||
9a624916 | 454 | if( argv[i][1] == 'c' ) |
23946ad2 | 455 | g_lpstrCharSet = argv[i+1]; |
9a624916 VB |
456 | else |
457 | if( argv[i][1] == 'f' ) | |
23946ad2 AJ |
458 | g_lpstrFileName = argv[i+1]; |
459 | else | |
460 | if( argv[i][1] == 't' ) | |
461 | { | |
462 | g_outputPoints = 1; | |
463 | continue; | |
464 | } | |
7e6ae4ba AJ |
465 | else |
466 | usage(); | |
467 | ||
468 | i++; | |
9a624916 | 469 | } |
7e6ae4ba AJ |
470 | if( i == argc - 1 ) |
471 | { | |
472 | g_lpstrInputFile = argv[i]; | |
473 | break; | |
474 | } | |
475 | default: usage(); | |
476 | } | |
9a624916 | 477 | |
7e6ae4ba AJ |
478 | } |
479 | ||
480 | /* read file data and return file type */ | |
481 | ||
763aff61 | 482 | static int get_resource_table(int fd, unsigned char** lpdata, int fsize) |
7e6ae4ba | 483 | { |
23946ad2 AJ |
484 | IMAGE_DOS_HEADER mz_header; |
485 | IMAGE_OS2_HEADER ne_header; | |
fef71865 DT |
486 | long s, offset, size; |
487 | int retval; | |
7e6ae4ba | 488 | |
7e6ae4ba AJ |
489 | lseek( fd, 0, SEEK_SET ); |
490 | ||
9a624916 | 491 | if( read(fd, &mz_header, sizeof(mz_header)) != sizeof(mz_header) ) |
7e6ae4ba AJ |
492 | return FILE_ERROR; |
493 | ||
23946ad2 | 494 | s = return_data_value(dfShort, &mz_header.e_magic); |
7e6ae4ba | 495 | |
23946ad2 | 496 | if( s == IMAGE_DOS_SIGNATURE) /* looks like .dll file so far... */ |
7e6ae4ba | 497 | { |
23946ad2 | 498 | s = return_data_value(dfShort, &mz_header.e_lfanew); |
7e6ae4ba AJ |
499 | lseek( fd, s, SEEK_SET ); |
500 | ||
501 | if( read(fd, &ne_header, sizeof(ne_header)) != sizeof(ne_header) ) | |
502 | return FILE_ERROR; | |
503 | ||
504 | s = return_data_value(dfShort, &ne_header.ne_magic); | |
505 | ||
23946ad2 | 506 | if( s == IMAGE_NT_SIGNATURE) |
7e6ae4ba AJ |
507 | { |
508 | fprintf( stderr, "Do not know how to handle 32-bit Windows DLLs.\n"); | |
9a624916 | 509 | return FILE_ERROR; |
7e6ae4ba | 510 | } |
23946ad2 | 511 | else if ( s != IMAGE_OS2_SIGNATURE) return FILE_ERROR; |
7e6ae4ba | 512 | |
180a088b AJ |
513 | s = return_data_value(dfShort, &ne_header.ne_rsrctab); |
514 | size = return_data_value(dfShort, &ne_header.ne_restab); | |
7e6ae4ba AJ |
515 | |
516 | if( size > fsize ) return FILE_ERROR; | |
517 | ||
518 | size -= s; | |
23946ad2 | 519 | offset = s + return_data_value(dfShort, &mz_header.e_lfanew); |
7e6ae4ba AJ |
520 | |
521 | if( size <= sizeof(NE_TYPEINFO) ) return FILE_ERROR; | |
522 | retval = FILE_DLL; | |
523 | } | |
524 | else if( s == 0x300 || s == 0x200 ) /* maybe .fnt ? */ | |
525 | { | |
fef71865 | 526 | size = return_data_value(dfLong, &((fnt_hdrS *)&mz_header)->dfSize); |
7e6ae4ba AJ |
527 | |
528 | if( size != fsize ) return FILE_ERROR; | |
529 | offset = 0; | |
9a624916 | 530 | retval = FILE_FNT; |
7e6ae4ba AJ |
531 | } |
532 | else return FILE_ERROR; | |
533 | ||
534 | *lpdata = (unsigned char*)malloc(size); | |
535 | ||
536 | if( *lpdata ) | |
537 | { | |
538 | lseek( fd, offset, SEEK_SET ); | |
539 | if( read(fd, *lpdata, size) != size ) | |
540 | { free( *lpdata ); *lpdata = NULL; } | |
541 | } | |
542 | return retval; | |
543 | } | |
544 | ||
545 | ||
546 | /* entry point */ | |
547 | ||
548 | int main(int argc, char **argv) | |
549 | { | |
550 | unsigned char* lpdata = NULL; | |
551 | int fd; | |
552 | ||
553 | parse_options( argc, argv); | |
554 | ||
c63d9803 | 555 | if( (fd = open( g_lpstrInputFile, O_RDONLY | O_BINARY)) ) |
7e6ae4ba AJ |
556 | { |
557 | int i; | |
558 | struct stat file_stat; | |
559 | ||
560 | fstat( fd, &file_stat); | |
561 | i = get_resource_table( fd, &lpdata, file_stat.st_size ); | |
562 | ||
563 | switch(i) | |
564 | { | |
565 | case FILE_DLL: | |
566 | if( lpdata ) | |
567 | { | |
568 | int j, count = 0; | |
569 | NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(lpdata + 2); | |
570 | NE_NAMEINFO* pFontStorage = NULL; | |
571 | ||
9a624916 | 572 | while( (i = return_data_value(dfShort, &pTInfo->type_id)) ) |
7e6ae4ba AJ |
573 | { |
574 | j = return_data_value(dfShort, &pTInfo->count); | |
575 | if( i == NE_RSCTYPE_FONT ) | |
576 | { | |
577 | count = j; | |
578 | pFontStorage = (NE_NAMEINFO*)(pTInfo + 1); | |
fef71865 | 579 | break; /* found one */ |
7e6ae4ba AJ |
580 | } |
581 | ||
582 | pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1) + j*sizeof(NE_NAMEINFO)); | |
583 | } | |
584 | if( pFontStorage && count ) | |
585 | { | |
586 | unsigned short size_shift = return_data_value(dfShort, lpdata); | |
587 | unsigned char* lpfont = NULL; | |
588 | unsigned offset; | |
c63d9803 | 589 | int length; |
7e6ae4ba AJ |
590 | |
591 | for( j = 0; j < count; j++, pFontStorage++ ) | |
592 | { | |
593 | length = return_data_value(dfShort, &pFontStorage->length) << size_shift; | |
594 | offset = return_data_value(dfShort, &pFontStorage->offset) << size_shift; | |
9a624916 | 595 | |
7e6ae4ba AJ |
596 | if( !(lpfont = (unsigned char*) realloc( lpfont, length )) ) |
597 | { | |
598 | fprintf(stderr, errorMemory ); | |
02e90087 | 599 | exit(1); |
7e6ae4ba AJ |
600 | } |
601 | ||
602 | lseek( fd, offset, SEEK_SET ); | |
603 | if( read(fd, lpfont, length) != length ) | |
604 | { | |
605 | fprintf(stderr, errorDLLRead ); | |
02e90087 | 606 | exit(1); |
7e6ae4ba AJ |
607 | } |
608 | ||
609 | if( (i = parse_fnt_data( lpfont, length )) ) | |
02e90087 | 610 | { |
7e6ae4ba | 611 | fprintf(stderr, "%s%d\n", errorFontData, i ); |
02e90087 AJ |
612 | exit(1); |
613 | } | |
7e6ae4ba AJ |
614 | } |
615 | free(lpfont); free(lpdata); | |
02e90087 AJ |
616 | exit(0); |
617 | } | |
618 | else | |
619 | { | |
620 | fprintf(stderr, errorEmpty ); | |
621 | exit(1); | |
7e6ae4ba | 622 | } |
7e6ae4ba AJ |
623 | free( lpdata ); |
624 | } | |
02e90087 AJ |
625 | else |
626 | { | |
627 | fprintf(stderr, errorDLLRead); | |
628 | exit(1); | |
629 | } | |
7e6ae4ba AJ |
630 | break; |
631 | ||
632 | case FILE_FNT: | |
633 | if( lpdata ) | |
634 | { | |
635 | if( (i = parse_fnt_data( lpdata, file_stat.st_size )) ) | |
02e90087 | 636 | { |
7e6ae4ba | 637 | fprintf(stderr, "%s%d\n", errorFontData, i ); |
02e90087 AJ |
638 | exit(1); |
639 | } | |
7e6ae4ba AJ |
640 | free( lpdata ); |
641 | } | |
02e90087 AJ |
642 | else |
643 | { | |
644 | fprintf(stderr, errorFNTRead); | |
645 | exit(1); | |
646 | } | |
7e6ae4ba AJ |
647 | break; |
648 | ||
649 | case FILE_ERROR: | |
650 | fprintf(stderr, errorFile ); | |
02e90087 | 651 | exit(1); |
7e6ae4ba AJ |
652 | } |
653 | close(fd); | |
02e90087 AJ |
654 | exit(0); |
655 | } | |
656 | else | |
657 | { | |
658 | fprintf(stderr, errorOpenFile ); | |
659 | exit(1); | |
7e6ae4ba | 660 | } |
7e6ae4ba | 661 | } |