/* * Fix the Netscape executable for specified font widths * * (c) 1999 Copyright by Sergey Babkin * see COPYRIGHT */ #include #include #include #include #include /************************** DEFINES *************************/ #undef DEBUG /* we can handle at most this many fonts */ #define MAXFONTS 20 /* maximal line buffer size */ #define MAXLINE 512 /* there may be multiple strings with the same contents */ #define MAXDUPS 10 /* file read buffer size */ #define FILEBF 40960 /* bits in the hardware page offset */ #define BITSPERPAGE 12 /* size of page in bytes */ #define PAGESIZE (1< \n"); } /************************** readconfig **********************/ void readconfig(fn) char *fn; { char s[MAXLINE]; char afmsuffix[MAXLINE], pfasuffix[MAXLINE]; int lineno=0; FILE *f; if(( f=fopen(fn, "r") )==NULL) { sprintf(msg,"nsfix: open %s",fn); perror(msg); exit(1); } while( fgets(s, MAXLINE, f) ) { lineno++; if(s[0]=='#' || s[0]=='\n') continue; if(nfonts>=MAXFONTS) { fprintf(stderr, "nsfix: only %d fonts are supported at once\n", MAXFONTS); exit(1); } if( sscanf(s, "%s %s %s %s", font[nfonts].nsname, font[nfonts].afmname, afmsuffix, pfasuffix) != 4 ) { fprintf(stderr, "nsfix: syntax error at line %d of %s\n", lineno, fn); exit(1); } strcpy(font[nfonts].pfaname, font[nfonts].afmname); strcat(font[nfonts].afmname, afmsuffix); strcat(font[nfonts].pfaname, pfasuffix); nfonts++; } if(nfonts==0) { fprintf(stderr, "nsfix: no fonts are defined in %s\n", fn); exit(1); } fclose(f); } /************************** readmetrics *********************/ void readmetrics(void) { int i; char s[MAXLINE]; FILE *f; int n; int lineno; int code, width, llx, lly, urx, ury; char gn[MAXLINE]; struct glyphmetrics *gm; for(i=0; i=32 && code<=255) { font[i].metrics.glyphs[code].width=width; font[i].metrics.glyphs[code].bbox.llx=llx; font[i].metrics.glyphs[code].bbox.lly=lly; font[i].metrics.glyphs[code].bbox.urx=urx; font[i].metrics.glyphs[code].bbox.ury=ury; } } } fclose(f); } #ifdef DEBUG for(i=0; iwidth, gm->bbox.llx, gm->bbox.lly, gm->bbox.urx, gm->bbox.ury); printf(" w=0x%04x [0x%04x 0x%04x 0x%04x 0x%04x]\n", gm->width & 0xffff, gm->bbox.llx & 0xffff, gm->bbox.lly & 0xffff, gm->bbox.urx & 0xffff, gm->bbox.ury & 0xffff); } } exit(0); #endif } /************************** replacefonts ********************/ void replacefonts(fn) char *fn; { int f; /* don't use stdio */ char bf[FILEBF]; char *bfend, *p; int len; off_t pos; off_t zerooff[MAXFONTS*MAXDUPS]; /* offset of zero strings */ tptr nameaddr[MAXFONTS*MAXDUPS]; /* name pointers before these zero strings */ int zeroid[MAXFONTS*MAXDUPS]; /* font number for this zero block */ int nzeroes; short matched[MAXFONTS]; /* counters how many matches we have for each requested font */ struct fontmetrics *fp; struct { int noff; int nz; off_t off[MAXDUPS]; /* there may be multiple strings with the same contents */ } o[MAXFONTS]; int maxnlen; int i, j, k, n; static struct glyphmetrics gm[32]; /* 0-initialized */ if(( f=open(fn, O_RDWR) )<0) { sprintf(msg,"nsfix: open %s",fn); perror(msg); exit(1); } /* get the maximal font name length */ maxnlen=0; for(i=0; imaxnlen) maxnlen=len; } /* fprintf(stderr,"maxnlen= 0x%x\n", maxnlen); /* */ /* try to find the literal strings of the font names */ pos=0; bfend=bf; while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) { /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */ /* the last position to check */ if(len>=maxnlen) /* leave the rest with the next block */ bfend+= len-maxnlen; else { /* we are very near to the end of file, check * up to the very last byte */ bfend+= len-2; memset(bfend+2, 0, maxnlen); } for(p=bf; p<=bfend; p++) for(i=0; i pos + PAGESIZE/2) { /* bad */ fprintf(stderr, "eliminated %s at 0x%lx\n", font[j].nsname, (long)o[j].off[k] ); for(n=k+1; n=0 ) { /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */ /* the last position to check */ bfend+= len-maxnlen; /* don't look beyond the EOF */ for(p=bf; p<=bfend; p+=4 /* 4-byte aligned */ ) { fp=(struct fontmetrics *)p; if(fp->name==0) continue; if( memcmp(gm, fp->glyphs, sizeof gm) ) continue; /* OK, looks like it, see if we can match it to any name */ n= fp->name & PAGEMASK; for(i=0; iname; zeroid[nzeroes]=i; o[i].nz++; fprintf(stderr, "matched %s at 0x%lx\n", font[i].nsname, (long) zerooff[nzeroes]); nzeroes++; matched[i]++; break; } } } if(len==0) break; memmove(bf, bfend, maxnlen); pos+= (bfend-bf); bfend= (bf+maxnlen); } if(len<0) { sprintf(msg,"nsfix: read %s",fn); perror(msg); exit(1); } fprintf(stderr,"---\n"); /* make sure that all the fonts got one match */ k=0; /* flag: have non-matched fonts */ n=0; /* flag: have ambiguities */ for(i=0; i1) n=1; if(k) { fprintf(stderr,"nsfix: can't find match for some of the fonts\n"); fprintf(stderr,"nsfix: maybe wrong byte order, aborting\n"); exit(1); } if(n) { fprintf(stderr,"nsfix: got multiple matches for some of the fonts\n"); fprintf(stderr,"nsfix: can't resolve, aborting\n"); exit(1); } /* now finally write the updated tables */ for(i=0; i