/*
 * 5799-CGZ (C) COPYRIGHT IBM CORPORATION 1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header: width3812.c,v 12.0 88/11/11 12:37:51 root dec88 $ */
/* $ACIS:width3812.c 9.2$ */
/* $Source: /ibm/acis/usr/src/ibm/fdb_ca/src/RCS/width3812.c,v $ */

#ifndef lint
static char *rcsid = "$Header: width3812.c,v 12.0 88/11/11 12:37:51 root dec88 $";
#endif

/*
 * extract the widths of a font and store for ditroff's use.
 *
 * include project and standard type defs
 */
#include "itc.h"
#include <sys/file.h>
/*
 * include appropriate header files
 */
#include <stdio.h>
#include "font3812.h"
#include "symtab.h"

/* 
 * Global data objects
 */
#define MAXSIZES 20
#define MAXCHARS 300
  int NormalFontSize[] = { 6,7,8,9,10,11,12,14,16,18,20,24,30,36, 0};
  int FontSize[MAXSIZES];
  int FontOffset[MAXSIZES];
  int sizecnt = 0;        /* count of sizes for the font*/
 
  
  index_data key_data[MAXCHARS];
  char       key_name[MAXCHARS][9];
  symtab_type *symtab;
static int fp,fpi;     
static int addr,f_len;
char *progname;
printusage()  {
    fprintf(stderr, "Usage: %s [-c codepagefile] [-s sizes 0] [-n fontname] [filename]\n", progname);
    exit(1);
}
/*
 * Get the length of a character.  Passed the character name and will return
 * the length.
 * This routine assumes that the font has been opened.
 */
int acisCharLen(charname)
char *charname;
{ 
  index_data *key;
  int len, dc, lc;
  char_info c_data;

  addr = 0;          /* initialize address to 0 */
  f_len= 0;          /* length of font data, init to 0 */
  len =  0;	     /* return 0 if not found */
     if ( symtab_find(symtab,charname,&key) == 0) {
        addr = key ->offset;
        f_len= key ->length;
        if ((lc = lseek(fp,addr,0)) == -1) {
           printf("error(%d) seeking to %d for %s\n",lc,addr,charname);
        } else 
             if ((dc = read(fp,&c_data,CharInfoLen)) == 0) {
                printf("error(%d) reading data for %s\n",dc,charname);    
             } else
                  len = c_data.a_space +c_data.c_space +c_data.x;
     }
  return(len);
}
/*
 * read the index file in and build a hash table to the data
 */
  readIndex()
  {
   int i;

   symtab =(symtab_type *)symtab_create(300); /* create a hash symbol table */

   i = 0;
   while ( read(fpi,&key_data[i],IndexDataLen) !=0) {
       strncpy(key_name[i],&key_data[i],8);
       symtab_add(symtab,key_name[i],&key_data[i]);
       i++;
       if (i == MAXCHARS) {
	   printf("i=:%d, maxchars:%d\n",i,MAXCHARS);
	   printf("More than maximum (%d) chracters in font\n",MAXCHARS);
	   exit(1);
       }
   }
}

main (argc, argv)
int argc;
char *argv[];
{
    FILE *cpf; 
    char *fontname;
    char filedata[50];
    char fileindex[50];
    char *outputFilename;
    char offsetfile[50];
    char *codepageName;
    char suffix[50];
    char ntemp[3];
    char stemp[9];
    char CodeName[MAXCHARS][9];
    char CharName[MAXCHARS][3];
    int special;
    int widths[MAXCHARS][MAXSIZES];
    int sizeok[MAXSIZES]; 	/*flag to indicate size does exist */
    int em;
    int em_one_sixth[MAXSIZES];
    int em_one_twelvth[MAXSIZES];

    int char_cnt;	/* count of characters in this codetable */
    int dup_cnt;	/* count of duplicates in this codetable */
    int actual_cnt;	/* count of characters minus duplicates */

    cp_index offsetdata;
    cp_index undefdata;
    int undef_width;
   
    int cpi;    
    int i, j, k;
    int size;
    char doublequote;
    int keepit, alias;

    progname = argv[0];
    /*
     * get font name and  code page tag
     */
    codepageName = "stdcp";
    fontname = "unknown";
    outputFilename = NULL;
    doublequote = 042;
    special = 0;
    while (argc > 1)  {
	if (argv[1][0] == '-')  {
	    /* Handle options here */

	    switch (argv[1][1])  {
		case 'c':
		    if (argv[1][2] != '\0')  {
			codepageName = &argv[1][2];
		    }
		    else if (--argc > 1)  {
			argv++;
			codepageName = argv[1];
		    }
		    else
		        printusage();
		    break;
		case 's':
		    while (--argc > 1)  {
			argv++;
			size = atoi(argv[1]);
			if (size == 0) break;
			FontSize[sizecnt++] = size;
		    }
		    if (size != 0)
		        printusage();
		    break;
		case 'n':
		    if (argv[1][2] != '\0')  {
			outputFilename = &argv[1][2];
		    }
		    else if (--argc > 1)  {
			argv++;
			outputFilename = argv[1];
		    }
		    else
		        printusage();
		    break;
		case 'S':
		    special = 1;
		    break;
		default:
		    printusage();
		    break;
	    }
	}
	else  {
	    /* Handle Arguments Here */

	    fontname = argv[1];
	}
	argc--;
	argv++;
    }
    if(outputFilename == NULL) {
       outputFilename = fontname;
       printf("outputfile:%s\n",outputFilename);

    }
	
    if (sizecnt == 0)  {
	for (i = 0; NormalFontSize[i] != 0; i++)
	    FontSize[i] = NormalFontSize[i];
	sizecnt = i;
    }
    /*
     *remove the path from the CodepageName
     */
    j =  0;
    for (i = strlen(codepageName);i>0;i--) {
	if ( codepageName[i-1] == '/' ) {
	   j= i;
	   break;
	}
    } 
    /*construct name for the offset file*/
     sprintf(suffix,"%s",&codepageName[j]);

    if ((cpf = fopen(codepageName,"r")) == NULL) {
         printf("Can not find codepage: %s\n",codepageName);
         exit(1);
    }
    dup_cnt= 0;
    for (i= 0;i<MAXCHARS;i++) {
        if ( fscanf(cpf,"%*14c%3s%9s",ntemp,stemp) == 2) {
           strncpy(CodeName[i],stemp,8);
	   if ((CodeName[i][0] == doublequote) & ( i> 0)) {
		dup_cnt = dup_cnt + 1;
	    }
           strncpy(CharName[i],ntemp,2);
	} else break;
    }
    printf("codepage:%s sizecnt:%d\n",codepageName,sizecnt);

    char_cnt = i ;
    close (cpf);   
    actual_cnt = char_cnt-dup_cnt;
    /* 
     * get widths
     */
 
    for (i = 0;i < sizecnt; i++) {
    	/*construct name for the offset file*/
    	sprintf(offsetfile,"%s.%d.%s",fontname,FontSize[i],suffix);
    	/*open offset file*/
    	if ((cpi = open(offsetfile,O_WRONLY+O_CREAT+O_TRUNC,0644)) <=0) {
	    printf("failed to open %s\n",offsetfile);
	    exit(1);
	}
	write(cpi,&actual_cnt,sizeof actual_cnt);  /*write total num of chars*/
        sprintf(fileindex,"%s.%d.ndx",fontname,FontSize[i]);
        sprintf(filedata,"%s.%d.dat",fontname,FontSize[i]);
	printf("i=%d, input file:%s, create offset file: %s\n",
						i,filedata,offsetfile);
        if ((fp = open(filedata,O_RDONLY)) <= 0) {
	   printf("failed to open %s\n",filedata);
           sizeok[i] = 0;
	   continue;
	} else 
        if ((fpi = open (fileindex,O_RDONLY)) <= 0) {
	   printf("failed to open %s\n",fileindex);
           sizeok[i] = 0;
           close (fp);
	   continue;
        } else
        sizeok[i] = 1;			 /* size does exist      */
        FontOffset[i] =  lseek(cpi,0,L_INCR);  

	readIndex();
        /* 
	 * Look up the replacement character (SV320000) in this font.  Save the 
	 * address, width and length.  We will use this when a
	 * character is not defined in this size of the font, but
	 * is going to be included in the code page because it
	 * is defined for another size of this font.  If the replacement 
	 * character does not exist in this font, we will use the Y-bar 
	 * character (SC050000), instead.
	 *
	 * This is all done so that we print out a reasonable character 
	 * for undefined characters, rather than printing out garbage.  
	 * 
	 */
	if ( (undef_width = acisCharLen("SV320000")) == 0 ) {
		undef_width = acisCharLen("SC050000"); 
	}
	undefdata.offset = addr;
	undefdata.length = f_len;

	/* 
	 * special chars
	 * Two special characters are included in width files
 	 * They are \| and \^: 1/6 em, 1/12 em
	 * The em is the lower case 'm' (IBM char LM010000).  
	 * If the lower case 'm' character does not exist in this font, 
	 * then use whatever character we are using for the undefined 
	 * character (either SC320000 or SC050000).
	 * Now calculate these characters.
	 */
	if ( (em = acisCharLen("LM010000") ) <= 0 ) {
		em = undef_width;
	}
        em_one_sixth[i] = (em > 0) ? (em / 6) : 0;
        em_one_twelvth[i] = (em > 0) ? (em / 12) : 0;

        for (j=0;j<char_cnt;j++) {
	    if ((CodeName[j][0] == doublequote) & ( j > 0)) {
		widths[j][i] = widths[j-1][i];
	    } else {
	        if ( ( widths[j][i] = acisCharLen(CodeName[j]) ) == 0) {
			/*
			 * character is undefined, point to undef character
			 * instead (see comment above)
			 */
			widths[j][i] = undef_width;
			offsetdata.offset = undefdata.offset;
			offsetdata.length = undefdata.length;
		} else {
			offsetdata.offset = addr;
			offsetdata.length = f_len; 
		}
		/* save offset & len of font data */
		write(cpi,&offsetdata,cpIndexLen);
	    }
	}
        close(fp);
        symtab_distroy(symtab);
        close(fpi);
	close(cpi); /* close offset file */
    }
    /*
     * open widths file
     */
    printf("output:%s\n",outputFilename);
    cpf= fopen(outputFilename,"w");
    /*
     *print header for width file
     */  
    fprintf(cpf,"#Codepage Name %s\n",suffix);
    fprintf(cpf,"name %s\n",outputFilename);
    fprintf(cpf,"internalname %s.%s\n",fontname,suffix);
    if (special ==1) {
       fprintf(cpf,"special\n");
    }
    fprintf(cpf,"ligatures ff fi fl ffi ffl 0\n");
    fprintf(cpf,"sizes ");
    for (i=0;i<sizecnt;i++) {       
        if (sizeok[i]) fprintf(cpf," %d ",FontSize[i]);
    }
    fprintf(cpf,"0 \n\n");
    fprintf(cpf,"charset \n");
    /*
     *print special characters
     */
    fprintf(cpf, "\134| ");     /* for 1/6 em space*/
    for (i=0;i<sizecnt;i++){
	if (sizeok[i]) {
	   fprintf(cpf," %4d ",em_one_sixth[i]);
	}
    }
    fprintf(cpf," 0    0\n");    
    fprintf(cpf, "\134^ ");     /* for 1/12 em space*/
    for (i=0;i<sizecnt;i++){
	if (sizeok[i]) {
	   fprintf(cpf," %4d ",em_one_twelvth[i]);
	}
    }
    fprintf(cpf," 0    0\n");    

 
    /*
     * print widths
     */
    k =0;
    for (j=0;j<char_cnt;j++) {
	keepit = 0; alias = 0;
	/*
	 * If at least one size of the font has the character then keep it.
	 */
        for (i=0;i<sizecnt; i++)
	    if ((sizeok[i]) & (widths[j][i] > 0)) {
		keepit = 1;
		break;
	    }

	if ((CodeName[j][0] == doublequote) & ( j > 0)) 
	    alias = 1;
	if (keepit) {
            fprintf(cpf, "%2s ",CharName[j]);
	    /*
	     * If this is a alias, just put out the quote mark.
	     */
	    if ( alias ) {
	        fprintf(cpf," %8s\n",CodeName[j]);
	    } else {
                for (i=0;i<sizecnt; i++){
                    if (sizeok[i]) {
                        fprintf(cpf," %4d ",widths[j][i]);
		    }
                }     
                fprintf(cpf," 0 %4d\n",k);
	    }
	}
	if ( !alias ) k=k+1;
    }
    close(cpf);
    exit(0);
}
