fnt2bdf.c 17.1 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4 5 6 7 8 9
/************************************************
 *
 * Extract fonts from .fnt or Windows DLL files
 * and convert them to the .bdf format.
 *
 * Copyright 1994-1996 Kevin Carothers and Alex Korobka
 *
 */

10 11 12 13 14
#include "config.h"

#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
15 16
#include <sys/types.h>
#include <sys/stat.h>
17
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

#include "fnt2bdf.h"
#include "module.h"

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

/* global options */

32 33 34
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
35 36 37
char*	g_lpstrFileName = NULL;
char*	g_lpstrCharSet = NULL;
char*   g_lpstrInputFile = NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
38
int     g_outputPoints = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
39 40 41 42 43 44 45 46 47 48 49

static char*	errorDLLRead = "Unable to read Windows DLL.\n";
static char*    errorFNTRead = "Unable to read .FNT file.\n";
static char*    errorOpenFile = "Unable to open file.\n";
static char*    errorMemory = "Memory allocation error.\n";
static char*    errorFile = "Corrupt or invalid file.\n";
static char*    errorFontData = "Unable to parse font data: Error ";
static char*    errorEmpty = "No fonts found.\n";

/* info */

50
void usage(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
51
{
Alexandre Julliard's avatar
Alexandre Julliard committed
52 53
    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
54
    printf("  -f basename\tbasic output filename\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
55
    printf("  -t \t\toutput files by point size instead of pixel height\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
56 57 58 59 60
    printf("  input file\tMSWindows .fon, .fnt, .dll, or .exe file.\n");
    printf("\nExample:\n  fnt2bdf -c winsys vgasys.fnt\n\n");
    exit(-1);
}

61
/* convert little-endian value to the local format */
Alexandre Julliard's avatar
Alexandre Julliard committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

int return_data_value(enum data_types dtype, void * pChr)
{
int   ret_val = 0;

    switch(dtype) {
        case (dfChar): 
            ret_val = (int) *(unsigned char *)pChr;
            break;
            
        case(dfShort): 
            ret_val = *(unsigned char *)pChr;
            ret_val += (*((unsigned char *)pChr + 1) << 8);
            break;
            
        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
85 86
		case(dfString):
			break;
Alexandre Julliard's avatar
Alexandre Julliard committed
87 88 89 90 91 92
        } 
    return ret_val;
}

int make_bdf_filename(char* name, fnt_fontS* cpe_font_struct, unsigned char* file_buffer)
{
93
long	l_nameoffset = return_data_value(dfLong, &cpe_font_struct->hdr.fi.dfFace);
Alexandre Julliard's avatar
Alexandre Julliard committed
94 95 96 97 98
char*   lpChar;

  if( !g_lpstrFileName )
  {
    if( !l_nameoffset || 
99
         l_nameoffset > return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) + 1 )
Alexandre Julliard's avatar
Alexandre Julliard committed
100 101 102 103 104 105 106 107 108 109 110 111
         return ERROR_DATA;
    lpChar =  (char*)(file_buffer + l_nameoffset);
  }
    else lpChar = g_lpstrFileName;

  strcpy( name, lpChar );

  while( (lpChar = strchr( name, ' ')) ) 
         *lpChar = '-';

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

112
  if( cpe_font_struct->hdr.fi.dfItalic ) strcat(name, "_i" );
Alexandre Julliard's avatar
Alexandre Julliard committed
113 114 115
  else strcat(name, "_r" );

  lpChar = name + strlen( name );
116 117 118
  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
119 120 121 122 123 124 125 126 127 128
  return 0;
}

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

int parse_fnt_data(unsigned char* file_buffer, int length)
{
  fnt_fontS	cpe_font_struct; 
  int     	ic=0, t;

Alexandre Julliard's avatar
Alexandre Julliard committed
129
  memcpy((char *) &cpe_font_struct.hdr, file_buffer, sizeof(fnt_hdrS));
Alexandre Julliard's avatar
Alexandre Julliard committed
130 131 132

  /* check font header */

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

136
  t = return_data_value(dfLong, &cpe_font_struct.hdr.dfSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
137 138 139 140 141
  if( t > length ) return ERROR_SIZE;
  else
  {    	
    /* set up the charWidth/charOffset  structure pairs (dfCharTable)... */

142 143 144 145 146 147 148 149
    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); 
    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
150 151 152 153 154 155 156 157 158 159 160 161 162

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

    if((cpe_font_struct.dfCharTable = (WinCharS *) calloc(sizeof(WinCharS), l_len)) == NULL) 
	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) */


163
	if( return_data_value(dfShort, &cpe_font_struct.hdr.dfVersion) == 0x200) {
Alexandre Julliard's avatar
Alexandre Julliard committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	    cpe_font_struct.dfCharTable[ic].charOffset = 
			return_data_value(dfShort, &file_buffer[l_ptr]);
	    l_ptr += 2;	/* bump by sizeof(long) */
	    }
	else { 	/*  Windows Version 3.0 type font */
	    cpe_font_struct.dfCharTable[ic].charOffset = 
			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;
184 185
  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
186

Alexandre Julliard's avatar
Alexandre Julliard committed
187
  int     l_len = l_lchar-l_fchar + 1,
188 189
	  l_hgt = return_data_value(dfChar, &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
190 191 192 193 194 195 196 197 198 199 200
  char    l_filename[256];

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

    if((fp = fopen(l_filename, "w")) == (FILE *) 0)   
    {
      fprintf(stderr, "Couldn't open \"%s\" for output.\n", l_filename);
      return ERROR_FILE;
    }

Alexandre Julliard's avatar
Alexandre Julliard committed
201 202
    ic = dump_bdf_hdr(fp, cpe_font_struct, file_buffer);
    if (ic) return (ic);
Alexandre Julliard's avatar
Alexandre Julliard committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290

    /* 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;

	l_span = (int) (cpe_font_struct->dfCharTable[ic].charWidth-1)/8; 

	fprintf(fp, "STARTCHAR %d  \n", ic);
	fprintf(fp, "ENCODING %d\n",   l_fchar);
	fprintf(fp, "SWIDTH    %d    %d \n", 
		cpe_font_struct->dfCharTable[ic].charWidth*1000, 
		0);

	fprintf(fp, "DWIDTH    %d    %d \n", 
		cpe_font_struct->dfCharTable[ic].charWidth, 0);

	fprintf(fp, "BBX  %d  %d  %d   %d\n",
		cpe_font_struct->dfCharTable[ic].charWidth, l_hgt, 0, 
		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;
		    }
		
		case(1):	/* 8-15 pixels wide font */
		    {
		    fprintf(fp, "%02X%02X", 
			(int) file_buffer[l_idx+rowidx], file_buffer[l_idx+l_hgt+rowidx]);
		    fprintf(fp, "\n");
		    break;
		    }

		case(2):	/* 16-23 pixels wide font */
		    {
		    fprintf(fp, "%02X%02X%02X", 
			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 */
		    {
		    fprintf(fp, "%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]);
		    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)
{
291 292
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
293
int     l_len = l_lchar - l_fchar + 1;
294 295 296
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
297 298 299 300 301 302

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

    /* Compose font name */

    if( l_nameoffset && 
303
	l_nameoffset < return_data_value(dfLong, &cpe_font_struct->hdr.dfSize) )
Alexandre Julliard's avatar
Alexandre Julliard committed
304 305 306
    {
      int     dpi, point_size;
      char*   lpFace = (char*)(file_buffer + l_nameoffset), *lpChar;
307
      short   tmWeight = return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfWeight);
Alexandre Julliard's avatar
Alexandre Julliard committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325

      while((lpChar = strchr(lpFace, '-')) ) 
	    *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);

326
      if( cpe_font_struct->hdr.fi.dfItalic )	/* slant */
Alexandre Julliard's avatar
Alexandre Julliard committed
327 328 329 330 331
	  fputs("i-", fs);
      else fputs("r-", fs);

      /* style */

332
      if( (cpe_font_struct->hdr.fi.dfPitchAndFamily & 0xF0) == FF_SWISS )
Alexandre Julliard's avatar
Alexandre Julliard committed
333 334 335 336 337
	  fputs("normal-sans-", fs);
      else fputs("normal--", fs);	/* still can be -sans */

      /* y extents */

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

341 342 343
      fprintf(fs, "%d-%d-%d-%d-",l_cellheight, point_size, 
            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
344 345 346

      /* spacing */

347
      if( return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPixWidth) ) fputs("c-", fs);
Alexandre Julliard's avatar
Alexandre Julliard committed
348
      else fputs("p-", fs);
Alexandre Julliard's avatar
Alexandre Julliard committed
349 350 351
	
      /* average width */

352
      fprintf( fs, "%d-", 10 * return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfAvgWidth) );
Alexandre Julliard's avatar
Alexandre Julliard committed
353 354 355

      /* charset */

356 357
     if( g_lpstrCharSet ) fprintf(fs, "%s\n", g_lpstrCharSet);
     else
358
      switch( cpe_font_struct->hdr.fi.dfCharSet )
Alexandre Julliard's avatar
Alexandre Julliard committed
359
      {
Alexandre Julliard's avatar
Alexandre Julliard committed
360 361
	/* Microsoft just had to invent its own charsets! */

362
	case ANSI_CHARSET: 	fputs("microsoft-cp1252\n", fs); break;
Alexandre Julliard's avatar
Alexandre Julliard committed
363 364 365 366 367 368 369 370
	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;
	case EE_CHARSET: 	fputs("microsoft-cp1250\n", fs); break; 
	case SYMBOL_CHARSET: 	fputs("microsoft-symbol\n", fs); break;
Alexandre Julliard's avatar
Alexandre Julliard committed
371 372 373
	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
374 375
	default:
	case OEM_CHARSET: 
Alexandre Julliard's avatar
Alexandre Julliard committed
376 377
		    fputs("Undefined charset, use -c option.\n", stderr); 
		    return ERROR_DATA; 
Alexandre Julliard's avatar
Alexandre Julliard committed
378 379 380 381 382
      }
    }
    else return ERROR_DATA;

    fprintf(fs, "SIZE  %d  %d   %d\n",  
383
        return_data_value(dfShort, &cpe_font_struct->hdr.fi.dfPoints ),
384 385
	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
386 387

    fprintf(fs, "FONTBOUNDINGBOX %d  %d  %d  %d\n",
388 389
	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
390 391 392 393 394 395 396
   	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 -
397 398
                                   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
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421

    fprintf(fs, "ENDPROPERTIES\n");

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



void parse_options(int argc, char **argv)
{
  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
422 423
    case 7:
    case 8:
Alexandre Julliard's avatar
Alexandre Julliard committed
424 425 426 427 428
	 for( i = 1; i < argc - 1; i++ )
	 {
	   if( argv[i][0] != '-' ||
	       strlen(argv[i]) != 2 ) break;

Alexandre Julliard's avatar
Alexandre Julliard committed
429 430
	   if( argv[i][1] == 'c' ) 
	       g_lpstrCharSet = argv[i+1];
Alexandre Julliard's avatar
Alexandre Julliard committed
431
	   else 
Alexandre Julliard's avatar
Alexandre Julliard committed
432 433 434 435 436 437 438 439
	   if( argv[i][1] == 'f' ) 
	       g_lpstrFileName = argv[i+1];
	   else
	   if( argv[i][1] == 't' )
	   {
	      g_outputPoints = 1;
	      continue;
	   }
Alexandre Julliard's avatar
Alexandre Julliard committed
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
	   else
	   usage();

	   i++;
	 } 
	 if( i == argc - 1 )
	 {
	   g_lpstrInputFile = argv[i];
	   break;
	 }
    default: usage();
  }
    
}

/* read file data and return file type */

int get_resource_table(int fd, unsigned char** lpdata, int fsize)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
459 460
  IMAGE_DOS_HEADER mz_header;
  IMAGE_OS2_HEADER ne_header;
461 462
  long s, offset, size;
  int retval;
Alexandre Julliard's avatar
Alexandre Julliard committed
463 464 465 466 467 468

  lseek( fd, 0, SEEK_SET );

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

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

Alexandre Julliard's avatar
Alexandre Julliard committed
471
  if( s == IMAGE_DOS_SIGNATURE)		/* looks like .dll file so far... */
Alexandre Julliard's avatar
Alexandre Julliard committed
472
  {
Alexandre Julliard's avatar
Alexandre Julliard committed
473
    s = return_data_value(dfShort, &mz_header.e_lfanew);
Alexandre Julliard's avatar
Alexandre Julliard committed
474 475 476 477 478 479 480
    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
481
    if( s == IMAGE_NT_SIGNATURE)
Alexandre Julliard's avatar
Alexandre Julliard committed
482 483 484 485
    {
       fprintf( stderr, "Do not know how to handle 32-bit Windows DLLs.\n");
       return FILE_ERROR; 
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
486
    else if ( s != IMAGE_OS2_SIGNATURE) return FILE_ERROR;
Alexandre Julliard's avatar
Alexandre Julliard committed
487

488 489
    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
490 491 492 493

    if( size > fsize ) return FILE_ERROR;

    size -= s;
Alexandre Julliard's avatar
Alexandre Julliard committed
494
    offset = s + return_data_value(dfShort, &mz_header.e_lfanew);
Alexandre Julliard's avatar
Alexandre Julliard committed
495 496 497 498 499 500

    if( size <= sizeof(NE_TYPEINFO) ) return FILE_ERROR;
    retval = FILE_DLL;
  }
  else if( s == 0x300 || s == 0x200 )		/* maybe .fnt ? */
  {
501
    size = return_data_value(dfLong, &((fnt_hdrS *)&mz_header)->dfSize);
Alexandre Julliard's avatar
Alexandre Julliard committed
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553

    if( size != fsize ) return FILE_ERROR;
    offset  = 0;
    retval = FILE_FNT; 
  }
  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);

  if( (fd = open( g_lpstrInputFile, O_RDONLY)) ) 
  {
    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;

	       while( (i = return_data_value(dfShort, &pTInfo->type_id)) ) 
	       {
		  j = return_data_value(dfShort, &pTInfo->count);
		  if( i == NE_RSCTYPE_FONT )
		  {
		    count = j;
		    pFontStorage = (NE_NAMEINFO*)(pTInfo + 1);
554
		    break; /* found one */
Alexandre Julliard's avatar
Alexandre Julliard committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
		  }

		  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;
		 unsigned		length;

		 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;
		    
		    if( !(lpfont = (unsigned char*) realloc( lpfont, length )) )
		    {
			fprintf(stderr, errorMemory );
Alexandre Julliard's avatar
Alexandre Julliard committed
574
			exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
575 576 577 578 579 580
		    }

		    lseek( fd, offset, SEEK_SET );
		    if( read(fd, lpfont, length) != length )
		    {
			fprintf(stderr, errorDLLRead );
Alexandre Julliard's avatar
Alexandre Julliard committed
581
			exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
582 583 584
		    }

		    if( (i = parse_fnt_data( lpfont, length )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
585
		    {
Alexandre Julliard's avatar
Alexandre Julliard committed
586
			fprintf(stderr, "%s%d\n", errorFontData, i );
Alexandre Julliard's avatar
Alexandre Julliard committed
587 588
			exit(1);
		    }
Alexandre Julliard's avatar
Alexandre Julliard committed
589 590
		 }
		 free(lpfont); free(lpdata);
Alexandre Julliard's avatar
Alexandre Julliard committed
591 592 593 594 595 596
		 exit(0);
	       }
	       else
	       {
		 fprintf(stderr, errorEmpty );
		 exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
597 598 599
	       }
	       free( lpdata );
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
600 601 602 603 604
	     else
	     {
	       fprintf(stderr, errorDLLRead);
	       exit(1);
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
605 606 607 608 609 610
	     break;

	case FILE_FNT:
	     if( lpdata )
	     {
	       if( (i = parse_fnt_data( lpdata, file_stat.st_size )) )
Alexandre Julliard's avatar
Alexandre Julliard committed
611
	       {
Alexandre Julliard's avatar
Alexandre Julliard committed
612
		   fprintf(stderr, "%s%d\n", errorFontData, i );
Alexandre Julliard's avatar
Alexandre Julliard committed
613 614
		   exit(1);
	       }
Alexandre Julliard's avatar
Alexandre Julliard committed
615 616
	       free( lpdata );
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
617 618 619 620 621
	     else
	     {
	       fprintf(stderr, errorFNTRead);
	       exit(1);
	     }
Alexandre Julliard's avatar
Alexandre Julliard committed
622 623 624 625
	     break;

	case FILE_ERROR:
	     fprintf(stderr, errorFile );
Alexandre Julliard's avatar
Alexandre Julliard committed
626
	     exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
627 628
    }
    close(fd);
Alexandre Julliard's avatar
Alexandre Julliard committed
629 630 631 632 633 634
    exit(0);
  }
  else
  {
    fprintf(stderr, errorOpenFile );
    exit(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
635 636
  }
}