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