fnt2bdf.c 18.1 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5 6 7
/************************************************
 *
 * Extract fonts from .fnt or Windows DLL files
 * and convert them to the .bdf format.
 *
 * Copyright 1994-1996 Kevin Carothers and Alex Korobka
 *
8 9 10 11 12 13 14 15 16 17 18 19
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
21 22
 */

23
#include "config.h"
24
#include "wine/port.h"
25 26 27 28

#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
29 30
#include <sys/types.h>
#include <sys/stat.h>
31
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
32 33
#include <stdlib.h>
#include <string.h>
34 35 36
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
37
#include <fcntl.h>
38 39 40 41
#ifdef HAVE_IO_H
# include <io.h>
#endif

Alexandre Julliard's avatar
Alexandre Julliard committed
42 43 44 45 46 47 48 49
#include "fnt2bdf.h"

#define FILE_ERROR	0
#define FILE_DLL	1
#define FILE_FNT	2

/* global options */

50 51 52
int dump_bdf( fnt_fontS* cpe_font_struct, unsigned char* file_buffer);
int dump_bdf_hdr(FILE* fs, fnt_fontS* cpe_font_struct, unsigned char* file_buffer);

Alexandre Julliard's avatar
Alexandre Julliard committed
53 54 55
char*	g_lpstrFileName = NULL;
char*	g_lpstrCharSet = NULL;
char*   g_lpstrInputFile = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
56
int     g_outputPoints = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
57

58 59 60 61 62 63 64
static const char*  errorDLLRead = "Unable to read Windows DLL.\n";
static const char*  errorFNTRead = "Unable to read .FNT file.\n";
static const char*  errorOpenFile = "Unable to open file.\n";
static const char*  errorMemory = "Memory allocation error.\n";
static const char*  errorFile = "Corrupt or invalid file.\n";
static const char*  errorFontData = "Unable to parse font data: Error ";
static const char*  errorEmpty = "No fonts found.\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
65 66 67

/* info */

68
static void usage(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
69
{
Alexandre Julliard's avatar
Alexandre Julliard committed
70 71
    printf("Usage: fnt2bdf [-t] [-c charset] [-o basename] [input file]\n");
    printf("  -c charset\tcharset name for OEM_CHARSET fonts\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
72
    printf("  -f basename\tbasic output filename\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
73
    printf("  -t \t\toutput files by point size instead of pixel height\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
74 75 76 77 78
    printf("  input file\tMSWindows .fon, .fnt, .dll, or .exe file.\n");
    printf("\nExample:\n  fnt2bdf -c winsys vgasys.fnt\n\n");
    exit(-1);
}

79
/* convert little-endian value to the local format */
Alexandre Julliard's avatar
Alexandre Julliard committed
80

81
static int return_data_value(enum data_types dtype, void * pChr)
Alexandre Julliard's avatar
Alexandre Julliard committed
82 83 84 85
{
int   ret_val = 0;

    switch(dtype) {
86
        case (dfChar):
Alexandre Julliard's avatar
Alexandre Julliard committed
87 88
            ret_val = (int) *(unsigned char *)pChr;
            break;
89 90

        case(dfShort):
Alexandre Julliard's avatar
Alexandre Julliard committed
91 92 93
            ret_val = *(unsigned char *)pChr;
            ret_val += (*((unsigned char *)pChr + 1) << 8);
            break;
94

Alexandre Julliard's avatar
Alexandre Julliard committed
95 96 97 98 99 100 101 102
        case(dfLong): {
            int  i;

            for(i=3; i >= 0; i--)  {
                ret_val += *((unsigned char *)pChr + i) << (8*i);
                }
            break;
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
103 104
		case(dfString):
			break;
105
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
106 107 108
    return ret_val;
}

109
static int make_bdf_filename(char* name, fnt_fontS* cpe_font_struct, unsigned char* file_buffer)
Alexandre Julliard's avatar
Alexandre Julliard committed
110
{
111
long	l_nameoffset = return_data_value(dfLong, &cpe_font_struct->hdr.fi.dfFace);
Alexandre Julliard's avatar
Alexandre Julliard committed
112 113 114 115
char*   lpChar;

  if( !g_lpstrFileName )
  {
116
    if( !l_nameoffset ||
117
         l_nameoffset > return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) + 1 )
Alexandre Julliard's avatar
Alexandre Julliard committed
118 119 120 121 122 123 124
         return ERROR_DATA;
    lpChar =  (char*)(file_buffer + l_nameoffset);
  }
    else lpChar = g_lpstrFileName;

  strcpy( name, lpChar );

125
  while( (lpChar = strchr( name, ' ')) )
Alexandre Julliard's avatar
Alexandre Julliard committed
126 127 128 129
         *lpChar = '-';

  /* construct a filename from the font typeface, slant, weight, and size */

130
  if( cpe_font_struct->hdr.fi.dfItalic ) strcat(name, "_i" );
Alexandre Julliard's avatar
Alexandre Julliard committed
131 132 133
  else strcat(name, "_r" );

  lpChar = name + strlen( name );
134 135 136
  sprintf(lpChar, "%d-%d.bdf", return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfWeight),
          (g_outputPoints) ? return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints)
			   : return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixHeight) );
Alexandre Julliard's avatar
Alexandre Julliard committed
137 138 139 140 141
  return 0;
}

/* parse FONT resource and write .bdf file */

142
static int parse_fnt_data(unsigned char* file_buffer, int length)
Alexandre Julliard's avatar
Alexandre Julliard committed
143
{
144
  fnt_fontS	cpe_font_struct;
Alexandre Julliard's avatar
Alexandre Julliard committed
145 146
  int     	ic=0, t;

Alexandre Julliard's avatar
Alexandre Julliard committed
147
  memcpy((char *) &cpe_font_struct.hdr, file_buffer, sizeof(fnt_hdrS));
Alexandre Julliard's avatar
Alexandre Julliard committed
148 149 150

  /* check font header */

151
  t = return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion);
Alexandre Julliard's avatar
Alexandre Julliard committed
152 153
  if( t != 0x300 && t != 0x200) return ERROR_VERSION;

154 155 156 157 158 159 160
  t = return_data_value(dfShort, &cpe_font_struct.hdr.fi.dfType);
  if (t & 1)
  {
    fprintf(stderr, "Vector fonts not supported\n");
    return ERROR_DATA;
  }

161
  t = return_data_value(dfLong, &cpe_font_struct.hdr.dfSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
162 163
  if( t > length ) return ERROR_SIZE;
  else
164
  {
Alexandre Julliard's avatar
Alexandre Julliard committed
165 166
    /* set up the charWidth/charOffset  structure pairs (dfCharTable)... */

167
    int l_fchar = return_data_value(dfChar, &cpe_font_struct.hdr.fi.dfFirstChar),
168
	l_lchar = return_data_value(dfChar, &cpe_font_struct.hdr.fi.dfLastChar);
169 170 171 172 173 174
    int l_len   = l_lchar - l_fchar + 1;
    int l_ptr = sizeof(fnt_hdrS);

    /* some fields were introduced for Windows 3.x fonts */
    if( return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion) == 0x200 )
	l_ptr -= 30;
Alexandre Julliard's avatar
Alexandre Julliard committed
175 176 177

    /* malloc size = (# chars) * sizeof(WinCharS) */

178
    if((cpe_font_struct.dfCharTable = (WinCharS *) calloc(sizeof(WinCharS), l_len)) == NULL)
Alexandre Julliard's avatar
Alexandre Julliard committed
179 180 181 182 183 184 185 186 187
	return ERROR_MEMORY;

    /* NOW, convert them all to UNIX (lton) notation... */

    for(ic=0; ic < l_len; ic++) {
   	cpe_font_struct.dfCharTable[ic].charWidth = return_data_value(dfShort, &file_buffer[l_ptr]);
	l_ptr += 2;	/* bump by sizeof(short) */


188
	if( return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion) == 0x200) {
189
	    cpe_font_struct.dfCharTable[ic].charOffset =
Alexandre Julliard's avatar
Alexandre Julliard committed
190
			return_data_value(dfShort, &file_buffer[l_ptr]);
191
	    l_ptr += 2;	/* bump by sizeof(short) */
Alexandre Julliard's avatar
Alexandre Julliard committed
192 193
	    }
	else { 	/*  Windows Version 3.0 type font */
194
	    cpe_font_struct.dfCharTable[ic].charOffset =
Alexandre Julliard's avatar
Alexandre Julliard committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208
			return_data_value(dfLong, &file_buffer[l_ptr]);
	    l_ptr += 4;	/* bump by sizeof(long) */
	    }
	}
    t = dump_bdf(&cpe_font_struct, file_buffer);
    free( cpe_font_struct.dfCharTable );
  }
  return t;
}

int dump_bdf( fnt_fontS* cpe_font_struct, unsigned char* file_buffer)
{
  FILE*   fp;
  int	  ic;
209 210
  int	  l_fchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfFirstChar),
	  l_lchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfLastChar);
Alexandre Julliard's avatar
Alexandre Julliard committed
211

Alexandre Julliard's avatar
Alexandre Julliard committed
212
  int     l_len = l_lchar-l_fchar + 1,
213
	  l_hgt = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfPixHeight);
214
  int	  l_ascent = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAscent);
Alexandre Julliard's avatar
Alexandre Julliard committed
215 216 217 218 219
  char    l_filename[256];

    if( (ic = make_bdf_filename(l_filename, cpe_font_struct, file_buffer)) )
	return ic;

220
    if((fp = fopen(l_filename, "w")) == (FILE *) 0)
Alexandre Julliard's avatar
Alexandre Julliard committed
221 222 223 224 225
    {
      fprintf(stderr, "Couldn't open \"%s\" for output.\n", l_filename);
      return ERROR_FILE;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
226 227
    ic = dump_bdf_hdr(fp, cpe_font_struct, file_buffer);
    if (ic) return (ic);
Alexandre Julliard's avatar
Alexandre Julliard committed
228 229 230 231 232 233 234

    /* NOW, convert all chars to UNIX (lton) notation... */

    for(ic=0; ic < l_len; ic++) {
	int rowidx, l_span,		/* how many char-cols wide is char? */
	    l_idx = cpe_font_struct->dfCharTable[ic].charOffset;

235
	l_span = (int) (cpe_font_struct->dfCharTable[ic].charWidth-1)/8;
Alexandre Julliard's avatar
Alexandre Julliard committed
236 237 238

	fprintf(fp, "STARTCHAR %d  \n", ic);
	fprintf(fp, "ENCODING %d\n",   l_fchar);
239 240
	fprintf(fp, "SWIDTH    %d    %d \n",
		cpe_font_struct->dfCharTable[ic].charWidth*1000,
Alexandre Julliard's avatar
Alexandre Julliard committed
241 242
		0);

243
	fprintf(fp, "DWIDTH    %d    %d \n",
Alexandre Julliard's avatar
Alexandre Julliard committed
244 245 246
		cpe_font_struct->dfCharTable[ic].charWidth, 0);

	fprintf(fp, "BBX  %d  %d  %d   %d\n",
247
		cpe_font_struct->dfCharTable[ic].charWidth, l_hgt, 0,
Alexandre Julliard's avatar
Alexandre Julliard committed
248 249 250 251 252 253 254 255 256 257
		l_ascent - l_hgt);

	fprintf(fp, "BITMAP\n");
	for(rowidx=0; rowidx < l_hgt; rowidx++) {
	    switch(l_span) {
		case(0):	/* 1-7 pixels wide font */
		    {
		    fprintf(fp, "%02X\n", (int) file_buffer[l_idx+rowidx]);
		    break;
		    }
258

Alexandre Julliard's avatar
Alexandre Julliard committed
259 260
		case(1):	/* 8-15 pixels wide font */
		    {
261
		    fprintf(fp, "%02X%02X",
Alexandre Julliard's avatar
Alexandre Julliard committed
262 263 264 265 266 267 268
			(int) file_buffer[l_idx+rowidx], file_buffer[l_idx+l_hgt+rowidx]);
		    fprintf(fp, "\n");
		    break;
		    }

		case(2):	/* 16-23 pixels wide font */
		    {
269
		    fprintf(fp, "%02X%02X%02X",
Alexandre Julliard's avatar
Alexandre Julliard committed
270 271 272 273 274 275 276 277 278
			file_buffer[l_idx+rowidx],
		        file_buffer[l_idx+l_hgt+rowidx],
		        file_buffer[l_idx+(2*l_hgt)+rowidx]);
		    fprintf(fp, "\n");
		    break;
		    }

		case(3):	/* 24-31 pixels wide font */
		    {
279
		    fprintf(fp, "%02X%02X%02X%02X",
Alexandre Julliard's avatar
Alexandre Julliard committed
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
			file_buffer[l_idx+rowidx],
			file_buffer[l_idx+l_hgt+rowidx],
			file_buffer[l_idx+(2*l_hgt)+rowidx],
			file_buffer[l_idx+(3*l_hgt)+rowidx]);
		    fprintf(fp, "\n");
		    break;
		    }
		case(4):	/* 32-39 */
		    {
		    fprintf(fp, "%02X%02X%02X%02X%02X",
			file_buffer[l_idx+rowidx],
			file_buffer[l_idx+l_hgt+rowidx],
                        file_buffer[l_idx+(2*l_hgt)+rowidx],
                        file_buffer[l_idx+(3*l_hgt)+rowidx],
			file_buffer[l_idx+(4*l_hgt)+rowidx]);
		    fprintf(fp, "\n");
                    break;
                    }
		default:
		    fclose(fp);
		    unlink(l_filename);
		    return ERROR_DATA;
		}
	    }
	fprintf(fp, "ENDCHAR\n");

	l_fchar++;	/* Go to next one */
	}
fprintf(fp, "ENDFONT\n");
fclose(fp);
return 0;
}


int dump_bdf_hdr(FILE* fs, fnt_fontS* cpe_font_struct, unsigned char* file_buffer)
{
316
int	l_fchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfFirstChar),
317
	l_lchar = return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfLastChar);
Alexandre Julliard's avatar
Alexandre Julliard committed
318
int     l_len = l_lchar - l_fchar + 1;
319 320 321
long	l_nameoffset = return_data_value(dfLong, &cpe_font_struct->hdr.fi.dfFace);
int	l_cellheight = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixHeight);
int	l_ascent = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAscent);
Alexandre Julliard's avatar
Alexandre Julliard committed
322 323 324 325 326

    fprintf(fs, "STARTFONT   2.1\n");

    /* Compose font name */

327
    if( l_nameoffset &&
328
	l_nameoffset < return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) )
Alexandre Julliard's avatar
Alexandre Julliard committed
329 330 331
    {
      int     dpi, point_size;
      char*   lpFace = (char*)(file_buffer + l_nameoffset), *lpChar;
332
      short   tmWeight = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfWeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
333

334
      while((lpChar = strchr(lpFace, '-')) )
Alexandre Julliard's avatar
Alexandre Julliard committed
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
	    *lpChar = ' ';

      fprintf(fs, "FONT -windows-%s-", lpFace );

      if( tmWeight == 0 )			/* weight */
	  fputs("medium-", fs);
      else if( tmWeight <= FW_LIGHT )
	  fputs("light-", fs);
      else if( tmWeight <= FW_MEDIUM )
	  fputs("medium-", fs);
      else if( tmWeight <= FW_DEMIBOLD )
	  fputs("demibold-", fs);
      else if( tmWeight <= FW_BOLD )
	  fputs("bold-", fs);
      else fputs("black-", fs);

351
      if( cpe_font_struct->hdr.fi.dfItalic )	/* slant */
Alexandre Julliard's avatar
Alexandre Julliard committed
352 353 354 355 356
	  fputs("i-", fs);
      else fputs("r-", fs);

      /* style */

357
      if( (cpe_font_struct->hdr.fi.dfPitchAndFamily & 0xF0) == FF_SWISS )
Alexandre Julliard's avatar
Alexandre Julliard committed
358 359 360 361 362
	  fputs("normal-sans-", fs);
      else fputs("normal--", fs);	/* still can be -sans */

      /* y extents */

363
      point_size = 10 * return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints );
Alexandre Julliard's avatar
Alexandre Julliard committed
364 365
      dpi = (l_cellheight * 720) / point_size;

366
      fprintf(fs, "%d-%d-%d-%d-",l_cellheight, point_size,
367 368
            return_data_value (dfShort, &cpe_font_struct->hdr.fi.dfHorizRes),
            return_data_value (dfShort, &cpe_font_struct->hdr.fi.dfVertRes));
Alexandre Julliard's avatar
Alexandre Julliard committed
369 370 371

      /* spacing */

372
      if( return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixWidth) ) fputs("c-", fs);
Alexandre Julliard's avatar
Alexandre Julliard committed
373
      else fputs("p-", fs);
374

Alexandre Julliard's avatar
Alexandre Julliard committed
375 376
      /* average width */

377
      fprintf( fs, "%d-", 10 * return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAvgWidth) );
Alexandre Julliard's avatar
Alexandre Julliard committed
378 379 380

      /* charset */

381 382
     if( g_lpstrCharSet ) fprintf(fs, "%s\n", g_lpstrCharSet);
     else
383
      switch( cpe_font_struct->hdr.fi.dfCharSet )
Alexandre Julliard's avatar
Alexandre Julliard committed
384
      {
Alexandre Julliard's avatar
Alexandre Julliard committed
385 386
	/* Microsoft just had to invent its own charsets! */

387
	case ANSI_CHARSET: 	fputs("microsoft-cp1252\n", fs); break;
Alexandre Julliard's avatar
Alexandre Julliard committed
388 389 390 391 392 393
	case GREEK_CHARSET: 	fputs("microsoft-cp1253\n", fs); break;
	case TURKISH_CHARSET: 	fputs("microsoft-cp1254\n", fs); break;
	case HEBREW_CHARSET: 	fputs("microsoft-cp1255\n", fs); break;
	case ARABIC_CHARSET: 	fputs("microsoft-cp1256\n", fs); break;
	case BALTIC_CHARSET: 	fputs("microsoft-cp1257\n", fs); break;
	case RUSSIAN_CHARSET: 	fputs("microsoft-cp1251\n", fs); break;
394
	case EE_CHARSET: 	fputs("microsoft-cp1250\n", fs); break;
Alexandre Julliard's avatar
Alexandre Julliard committed
395
	case SYMBOL_CHARSET: 	fputs("microsoft-symbol\n", fs); break;
Alexandre Julliard's avatar
Alexandre Julliard committed
396 397 398
	case SHIFTJIS_CHARSET: 	fputs("jisx0208.1983-0\n", fs); break;
	case DEFAULT_CHARSET:	fputs("iso8859-1\n", fs); break;

Alexandre Julliard's avatar
Alexandre Julliard committed
399
	default:
400 401 402
	case OEM_CHARSET:
		    fputs("Undefined charset, use -c option.\n", stderr);
		    return ERROR_DATA;
Alexandre Julliard's avatar
Alexandre Julliard committed
403 404 405 406
      }
    }
    else return ERROR_DATA;

407
    fprintf(fs, "SIZE  %d  %d   %d\n",
408
        return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints ),
409 410
	return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfHorizRes),
	return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfVertRes));   /* dfVertRes[2] */
Alexandre Julliard's avatar
Alexandre Julliard committed
411 412

    fprintf(fs, "FONTBOUNDINGBOX %d  %d  %d  %d\n",
413 414
	return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfMaxWidth),
	return_data_value(dfChar, &cpe_font_struct->hdr.fi.dfPixHeight),
Alexandre Julliard's avatar
Alexandre Julliard committed
415 416 417 418 419 420 421
   	0, l_ascent - l_cellheight );

    fprintf(fs, "STARTPROPERTIES  4\n");

    fprintf(fs, "FONT_ASCENT %d\n", l_ascent );                       /*  dfAscent[2] */
    fprintf(fs, "FONT_DESCENT %d\n", l_cellheight - l_ascent );
    fprintf(fs, "CAP_HEIGHT %d\n", l_ascent -
422 423
                                   return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfInternalLeading));
    fprintf(fs, "DEFAULT_CHAR %d\n", return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfDefaultChar));
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425 426 427 428 429 430 431 432

    fprintf(fs, "ENDPROPERTIES\n");

    fprintf(fs, "CHARS  %d\n",  l_len);
    return 0;
}



433
static void parse_options(int argc, char **argv)
Alexandre Julliard's avatar
Alexandre Julliard committed
434 435 436 437 438 439 440 441 442 443 444 445 446
{
  int i;

  switch( argc )
  {
    case 2:
	 g_lpstrInputFile = argv[1];
	 break;

    case 3:
    case 4:
    case 5:
    case 6:
Alexandre Julliard's avatar
Alexandre Julliard committed
447 448
    case 7:
    case 8:
Alexandre Julliard's avatar
Alexandre Julliard committed
449 450 451 452 453
	 for( i = 1; i < argc - 1; i++ )
	 {
	   if( argv[i][0] != '-' ||
	       strlen(argv[i]) != 2 ) break;

454
	   if( argv[i][1] == 'c' )
Alexandre Julliard's avatar
Alexandre Julliard committed
455
	       g_lpstrCharSet = argv[i+1];
456 457
	   else
	   if( argv[i][1] == 'f' )
Alexandre Julliard's avatar
Alexandre Julliard committed
458 459 460 461 462 463 464
	       g_lpstrFileName = argv[i+1];
	   else
	   if( argv[i][1] == 't' )
	   {
	      g_outputPoints = 1;
	      continue;
	   }
Alexandre Julliard's avatar
Alexandre Julliard committed
465 466 467 468
	   else
	   usage();

	   i++;
469
	 }
Alexandre Julliard's avatar
Alexandre Julliard committed
470 471 472 473 474 475 476
	 if( i == argc - 1 )
	 {
	   g_lpstrInputFile = argv[i];
	   break;
	 }
    default: usage();
  }
477

Alexandre Julliard's avatar
Alexandre Julliard committed
478 479 480 481
}

/* read file data and return file type */

482
static int get_resource_table(int fd, unsigned char** lpdata, int fsize)
Alexandre Julliard's avatar
Alexandre Julliard committed
483
{
Alexandre Julliard's avatar
Alexandre Julliard committed
484 485
  IMAGE_DOS_HEADER mz_header;
  IMAGE_OS2_HEADER ne_header;
486 487
  long s, offset, size;
  int retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
488 489 490

  lseek( fd, 0, SEEK_SET );

491
  if( read(fd, &mz_header, sizeof(mz_header)) != sizeof(mz_header) )
Alexandre Julliard's avatar
Alexandre Julliard committed
492 493
      return FILE_ERROR;

Alexandre Julliard's avatar
Alexandre Julliard committed
494
  s = return_data_value(dfShort, &mz_header.e_magic);
Alexandre Julliard's avatar
Alexandre Julliard committed
495

Alexandre Julliard's avatar
Alexandre Julliard committed
496
  if( s == IMAGE_DOS_SIGNATURE)		/* looks like .dll file so far... */
Alexandre Julliard's avatar
Alexandre Julliard committed
497
  {
Alexandre Julliard's avatar
Alexandre Julliard committed
498
    s = return_data_value(dfShort, &mz_header.e_lfanew);
Alexandre Julliard's avatar
Alexandre Julliard committed
499 500 501 502 503 504 505
    lseek( fd, s, SEEK_SET );

    if( read(fd, &ne_header, sizeof(ne_header)) != sizeof(ne_header) )
	return FILE_ERROR;

    s = return_data_value(dfShort, &ne_header.ne_magic);

Alexandre Julliard's avatar
Alexandre Julliard committed
506
    if( s == IMAGE_NT_SIGNATURE)
Alexandre Julliard's avatar
Alexandre Julliard committed
507 508
    {
       fprintf( stderr, "Do not know how to handle 32-bit Windows DLLs.\n");
509
       return FILE_ERROR;
Alexandre Julliard's avatar
Alexandre Julliard committed
510
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
511
    else if ( s != IMAGE_OS2_SIGNATURE) return FILE_ERROR;
Alexandre Julliard's avatar
Alexandre Julliard committed
512

513 514
    s = return_data_value(dfShort, &ne_header.ne_rsrctab);
    size = return_data_value(dfShort, &ne_header.ne_restab);
Alexandre Julliard's avatar
Alexandre Julliard committed
515 516 517 518

    if( size > fsize ) return FILE_ERROR;

    size -= s;
Alexandre Julliard's avatar
Alexandre Julliard committed
519
    offset = s + return_data_value(dfShort, &mz_header.e_lfanew);
Alexandre Julliard's avatar
Alexandre Julliard committed
520 521 522 523 524 525

    if( size <= sizeof(NE_TYPEINFO) ) return FILE_ERROR;
    retval = FILE_DLL;
  }
  else if( s == 0x300 || s == 0x200 )		/* maybe .fnt ? */
  {
526
    size = return_data_value(dfLong, &((fnt_hdrS *)&mz_header)->dfSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
527 528 529

    if( size != fsize ) return FILE_ERROR;
    offset  = 0;
530
    retval = FILE_FNT;
Alexandre Julliard's avatar
Alexandre Julliard committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
  }
  else return FILE_ERROR;

  *lpdata = (unsigned char*)malloc(size);

  if( *lpdata )
  {
    lseek( fd, offset, SEEK_SET );
    if( read(fd, *lpdata, size) != size )
           { free( *lpdata ); *lpdata = NULL; }
  }
  return retval;
}


/* entry point */

int main(int argc, char **argv)
{
  unsigned char* lpdata = NULL;
  int 		 fd;

  parse_options( argc, argv);

555
  if( (fd = open( g_lpstrInputFile, O_RDONLY | O_BINARY)) )
Alexandre Julliard's avatar
Alexandre Julliard committed
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
  {
    int    i;
    struct stat file_stat;

    fstat( fd, &file_stat);
    i = get_resource_table( fd, &lpdata, file_stat.st_size );

    switch(i)
    {
	case FILE_DLL:
	     if( lpdata )
	     {
	       int	    j, count = 0;
	       NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(lpdata + 2);
	       NE_NAMEINFO* pFontStorage = NULL;

572
	       while( (i = return_data_value(dfShort, &pTInfo->type_id)) )
Alexandre Julliard's avatar
Alexandre Julliard committed
573 574 575 576 577 578
	       {
		  j = return_data_value(dfShort, &pTInfo->count);
		  if( i == NE_RSCTYPE_FONT )
		  {
		    count = j;
		    pFontStorage = (NE_NAMEINFO*)(pTInfo + 1);
579
		    break; /* found one */
Alexandre Julliard's avatar
Alexandre Julliard committed
580 581 582 583 584 585 586 587 588
		  }

		  pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1) + j*sizeof(NE_NAMEINFO));
	       }
	       if( pFontStorage && count )
	       {
		 unsigned short		size_shift = return_data_value(dfShort, lpdata);
		 unsigned char*		lpfont = NULL;
		 unsigned		offset;
589
		 int			length;
Alexandre Julliard's avatar
Alexandre Julliard committed
590 591 592 593 594

		 for( j = 0; j < count; j++, pFontStorage++ )
		 {
		    length = return_data_value(dfShort, &pFontStorage->length) << size_shift;
		    offset = return_data_value(dfShort, &pFontStorage->offset) << size_shift;
595

Alexandre Julliard's avatar
Alexandre Julliard committed
596 597 598
		    if( !(lpfont = (unsigned char*) realloc( lpfont, length )) )
		    {
			fprintf(stderr, errorMemory );
Alexandre Julliard's avatar
Alexandre Julliard committed
599
			exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
600 601 602 603 604 605
		    }

		    lseek( fd, offset, SEEK_SET );
		    if( read(fd, lpfont, length) != length )
		    {
			fprintf(stderr, errorDLLRead );
Alexandre Julliard's avatar
Alexandre Julliard committed
606
			exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
607 608 609
		    }

		    if( (i = parse_fnt_data( lpfont, length )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
610
		    {
Alexandre Julliard's avatar
Alexandre Julliard committed
611
			fprintf(stderr, "%s%d\n", errorFontData, i );
Alexandre Julliard's avatar
Alexandre Julliard committed
612 613
			exit(1);
		    }
Alexandre Julliard's avatar
Alexandre Julliard committed
614 615
		 }
		 free(lpfont); free(lpdata);
Alexandre Julliard's avatar
Alexandre Julliard committed
616 617 618 619 620 621
		 exit(0);
	       }
	       else
	       {
		 fprintf(stderr, errorEmpty );
		 exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
622 623 624
	       }
	       free( lpdata );
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
625 626 627 628 629
	     else
	     {
	       fprintf(stderr, errorDLLRead);
	       exit(1);
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
630 631 632 633 634 635
	     break;

	case FILE_FNT:
	     if( lpdata )
	     {
	       if( (i = parse_fnt_data( lpdata, file_stat.st_size )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
636
	       {
Alexandre Julliard's avatar
Alexandre Julliard committed
637
		   fprintf(stderr, "%s%d\n", errorFontData, i );
Alexandre Julliard's avatar
Alexandre Julliard committed
638 639
		   exit(1);
	       }
Alexandre Julliard's avatar
Alexandre Julliard committed
640 641
	       free( lpdata );
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
642 643 644 645 646
	     else
	     {
	       fprintf(stderr, errorFNTRead);
	       exit(1);
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
647 648 649 650
	     break;

	case FILE_ERROR:
	     fprintf(stderr, errorFile );
Alexandre Julliard's avatar
Alexandre Julliard committed
651
	     exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
652 653
    }
    close(fd);
Alexandre Julliard's avatar
Alexandre Julliard committed
654 655 656 657 658 659
    exit(0);
  }
  else
  {
    fprintf(stderr, errorOpenFile );
    exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
660 661
  }
}