summaryrefslogtreecommitdiff
path: root/dviware/kyocera/kyofonts.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/kyocera/kyofonts.c
Initial commit
Diffstat (limited to 'dviware/kyocera/kyofonts.c')
-rw-r--r--dviware/kyocera/kyofonts.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/dviware/kyocera/kyofonts.c b/dviware/kyocera/kyofonts.c
new file mode 100644
index 0000000000..fb18b306aa
--- /dev/null
+++ b/dviware/kyocera/kyofonts.c
@@ -0,0 +1,668 @@
+/* kyofonts.c: font module for dvi printing on Kyocera laser printers
+ * Adapted from the qmsfonts module from Massachusetts Institute of Technology
+ */
+
+#include <stdio.h>
+#include "util.h"
+#include "fonts.h"
+#include "findfile.h"
+#include "kyo.h"
+#include "preload.h"
+#include <sys/stat.h>
+
+#define MAXDVIFONTS 256 /* Max number of fonts allowed in a DVI file*/
+#define MAXFNTDIR 16 /* Max number of dirs to look for fonts */
+
+unsigned char *malloc();
+char *strcat();
+char *strcpy();
+char *strncpy();
+char *strncmp();
+char *strcmp();
+
+long numerator,denominator,half_denominator,jobmag;
+
+long freewords = KYOMAXWORDS; /* free space on printer */
+FILE *kyo; /* output device */
+char *filter_name; /* the name of the calling prog */
+char *fntdirvec[MAXFNTDIR];
+int fntdirveclen;
+
+int nkyofonts;
+struct kyofont *curfnt; /* ptr to current and last font */
+long timestamp; /* Timestamp for stamping kyo fonts */
+int nloaded; /* Number of fonts already loaded */
+char *loadfile = PRLOAD ;
+char fontnums[MAXKYOFONTS];
+
+#define PR_USED 0x0001
+#define PR_LOADED 0x0002
+
+struct preload {
+ struct preload_info *pr_font;
+ short pr_info;
+} loaded[MAXKYOFONTS];
+
+/* The dvifont struct provides a (possible) many-to-one mapping
+ * because several DVI fonts can map to the same Kyocera font during font
+ * substitution.
+ */
+struct dvifont {
+ unsigned long df_num; /* DVI font number */
+ struct kyofont *df_kyofont; /* Font which contains */
+} dvifonts[MAXDVIFONTS];
+int ndvifonts;
+
+long max(a,b)
+ long a,b;
+{
+ return((a>b)? a:b);
+}
+
+long min(a,b)
+ long a,b;
+{
+ return((a<b)? a:b);
+}
+
+/* called at the beginning of the driver program */
+f_init(printer,pgmnam,dirvec,dirveclen,num,den,mag,options)
+ FILE *printer;
+ char *pgmnam,*dirvec[];
+ int dirveclen;
+ long num,den,mag;
+ unsigned long options;
+{
+ int i, n, loadf;
+ struct stat s;
+ struct preload_info *fnt;
+
+ numerator = num;
+ denominator = den;
+ half_denominator = denominator / 2;
+ jobmag = mag;
+ fntdirveclen = min(MAXFNTDIR,dirveclen);
+ for (i = 0; i < fntdirveclen; i++) fntdirvec[i] = dirvec[i];
+ ndvifonts = 0;
+ nkyofonts = 0;
+ timestamp = 0;
+ kyo = printer;
+ filter_name = pgmnam;
+
+ /* Try to read the file with information about the
+ * fonts loaded in the Kyocera at this moment
+ * The preload file should exist and have a length
+ * that is a multiple of the length of a preload-record
+ * This to protect against corrupted preload information
+ * When no preload information is present or when it is corrupt
+ * dump an explicit DAF (delete all fonts) command
+ */
+ if (((loadf = open(loadfile, 0)) >= 0) &&
+ (stat(loadfile, &s) == 0) &&
+ (s.st_size > 0) &&
+ ((s.st_size % sizeof(struct preload_info)) == 0)) {
+ n = s.st_size / sizeof(struct preload_info);
+ debug("%d fonts were preloaded\n", n);
+ for (i=0; i<n; i++) {
+ if (!(loaded[nloaded].pr_font = fnt =
+ (struct preload_info *) malloc(sizeof(struct preload_info))))
+ croak("malloc %d",sizeof(struct preload_info));
+ loaded[nloaded++].pr_info = PR_LOADED;
+ if (read(loadf, fnt, sizeof(struct preload_info)) !=
+ sizeof(struct preload_info)) {
+ nloaded--;
+ debug("Could read the info of only %d preloaded fonts\n",
+ nloaded);
+ break;
+ }
+ freewords -= fnt->pr_words_used;
+ fontnums[fnt->pr_kyonumber-KF_NUMBASE] = KF_USED;
+ debug("%s\n", fnt->pr_name);
+ }
+ close(loadf);
+ } else fprintf(kyo, "!R! DAF;EXIT;");
+ debug("Free font memory %ld words\n",freewords);
+ /* Clear the preload file before going on
+ * So when the driver crashes, it will not leave the next jobs
+ * with incorrect preload information
+ */
+ close(creat(loadfile, 0644));
+}
+
+/* Called at the end of the driver program. */
+f_term()
+{
+ int i, j, loadf;
+ struct kyofont *fnt;
+ struct kyochar *c;
+ struct preload_info font;
+ struct preload *pfnt;
+
+ if ((loadf = creat(loadfile, 0644)) < 0) {
+ debug("Cannot create %s\n", loadfile);
+ return;
+ }
+
+ /* Just copy back the information for fonts not used by this job */
+ for (i=0; i<nloaded; i++) {
+ pfnt = &loaded[i];
+ if (!(pfnt->pr_info & PR_USED) &&
+ (pfnt->pr_info & PR_LOADED))
+ write(loadf, pfnt->pr_font, sizeof(struct preload_info));
+ }
+
+ /* Write back the information about the fonts that are used by this job */
+ for (i=0; i<nkyofonts; i++) {
+ fnt = kyofonts[i];
+ if (fnt->kf_info & KF_LOADED) {
+ font.pr_kyonumber = fnt->kf_kyonumber;
+ strcpy(font.pr_name, fnt->kf_name);
+ font.pr_mag = fnt->kf_mag;
+ font.pr_words_used = fnt->kf_words_used;
+ font.pr_tfm_checksum = fnt->kf_tfm_checksum;
+ for (j=0; j<4; j++) font.pr_charvec[j] = 0;
+ for (j=0; j<MAXCHARS; j++) {
+ c = &(fnt->kf_char[j]);
+ if (c->kc_info & KC_LOADED)
+ font.pr_charvec[j/32] |= (1 << (j % 32));
+ }
+ write(loadf, &font, sizeof(struct preload_info));
+ }
+ }
+ debug( "Font memory left: %ld words\n", freewords);
+}
+
+/* This routine provides for an independent numbering scheme
+ * for the fonts loaded into the Kyocera
+ * It returns the first free number
+ * Fonts are numbered starting at KF_NUMBASE
+ */
+short next_kyonumber()
+{
+ int i;
+
+ for (i=0; i<MAXKYOFONTS; i++)
+ if (!fontnums[i]) {
+ fontnums[i] = KF_USED;
+ return(i+KF_NUMBASE);
+ }
+}
+
+/* Look if font "name" is preloaded
+ * If it is return a pointer to the preload information
+ * Ohterwise return 0
+ */
+struct preload *
+preloaded(name, tfmchecksum, mag)
+char *name;
+long tfmchecksum;
+{
+ int i;
+ struct preload *pnt;
+ register struct preload_info *fnt;
+
+ for (i=0; i<nloaded; i++) {
+ pnt = &loaded[i];
+ fnt = pnt->pr_font;
+ /* The name, magnification and tfm-checksum should match */
+ if ((pnt->pr_info & PR_LOADED) &&
+ (strcmp(fnt->pr_name, name) == 0) &&
+ (fnt->pr_mag == mag) &&
+ (fnt->pr_tfm_checksum == tfmchecksum)) {
+ return(pnt);
+ }
+ }
+ return((struct preload *) 0);
+}
+
+/* Try to locate the font "name" with the specified attributes
+ * in "area"
+ */
+struct kyofont *
+find_kyofont(area,name,texmag,s,tfmchecksum)
+ char *area,*name;
+ long texmag,s,tfmchecksum;
+{
+ char fname[MAXNAMLEN],nname[128];
+ int i,nmag;
+ int mag = (texmag * 3 + 1) / 2;
+ struct kyofont *fnt;
+ struct preload *pfnt;
+ struct preload_info *pnt;
+
+ /* try to find a font file */
+ if (!findfile(fntdirvec,fntdirveclen,area,name,mag,fname,nname,&nmag))
+ croak("no font %s.%d",name,texmag);
+
+ /* make a new kyocera font */
+ if (nkyofonts >= MAXKYOFONTS) croak("too many kyo fonts");
+
+ if (!(kyofonts[nkyofonts++] = fnt =
+ (struct kyofont *) malloc(sizeof(struct kyofont))))
+ croak("malloc %d",sizeof(struct kyofont));
+ fnt->kf_mag = nmag;
+ fnt->kf_timestamp = 0;
+ fnt->kf_s = s;
+ fnt->kf_tfm_checksum = tfmchecksum;
+ strcpy(fnt->kf_name,nname);
+ strcpy(fnt->kf_filename,fname);
+ for (i=0; i<MAXCHARS; i++)
+ fnt->kf_char[i].kc_info = 0;
+
+ if (pfnt = preloaded(nname, tfmchecksum,nmag)) {
+ pnt = pfnt->pr_font;
+ fnt->kf_kyonumber = pnt->pr_kyonumber;
+ fnt->kf_words_needed = 0;
+ fnt->kf_words_used = pnt->pr_words_used;
+ for (i=0; i<MAXCHARS; i++)
+ if (pnt->pr_charvec[i/32] & ( 1 << (i % 32)))
+ fnt->kf_char[i].kc_info = KC_LOADED;
+ fnt->kf_info = KF_FILE | KF_LOADED;
+ pfnt->pr_info |= PR_USED;
+ } else {
+ fnt->kf_kyonumber = next_kyonumber();
+ fnt->kf_words_needed = KF_MIN;
+ fnt->kf_words_used = 0;
+ fnt->kf_info = KF_FILE;
+ }
+ return(fnt);
+}
+
+/* Read the font information from the pxl file
+ * and remember that it is done
+ */
+getfontfromfile(fnt)
+ struct kyofont *fnt;
+{
+ char fname[MAXNAMLEN];
+ FILE *f;
+ int i;
+
+ readpxlfile(fnt,fnt->kf_filename);
+ fnt->kf_info &= ~KF_FILE;
+}
+
+/* Calculate the number of words needed by symbol "c"
+ * for its pxl raster
+ */
+int char_words_needed(c)
+ struct kyochar *c;
+{
+ return(((c->kc_width + 15) / 16) * c->kc_height);
+}
+
+/* Define a font.
+ * Can be called more than once for the same font.
+ */
+f_define_font(num,options,area,name,texmag,s,tfmchecksum)
+char *area,*name;
+unsigned long num,options,texmag,s,tfmchecksum;
+{
+ int i;
+
+ /* check to see if font is already defined */
+ for(i = 0; i < ndvifonts ; i++) if (dvifonts[i].df_num == num) return;
+
+ /* Does this make too many fonts defined? */
+ if (ndvifonts >= MAXDVIFONTS) croak("too many dvi fonts");
+ dvifonts[ndvifonts].df_num = num;
+ dvifonts[ndvifonts++].df_kyofont = find_kyofont(area,name,texmag
+ ,s,tfmchecksum);
+}
+
+/* Try to find DVI font with number "fontnum"
+ * in the dvi-fonttable
+ * Timestamp it to enable LRU font removal
+ */
+struct kyofont *
+find_dvi_font(fontnum)
+ unsigned long fontnum;
+{
+ register int i;
+
+ /* scan through the dvi font list. */
+ for(i = 0; i < ndvifonts ; i++)
+ if (dvifonts[i].df_num == fontnum) {
+ dvifonts[i].df_kyofont->kf_timestamp = timestamp++;
+ return(dvifonts[i].df_kyofont);
+ }
+ croak("no dvi font %d defined",fontnum);
+}
+
+/* Select a font as the current font */
+f_use_font(fontnum,font_space)
+unsigned long fontnum;
+long *font_space;
+{
+ curfnt = find_dvi_font(fontnum);
+ /* The font should be loaded already
+ * because loading fonts while printing a page
+ * could cause the Kyocera to emit the sheet
+ * that is printed on at this moment
+ */
+ if (!(curfnt->kf_info & KF_LOADED))
+ croak("cannot load font %d while printing page", fontnum);
+ /* Start using it */
+ fprintf(kyo,"!R! FONT %1d;EXIT;",curfnt->kf_kyonumber);
+ *font_space = curfnt->kf_s / 6;
+}
+
+/* Put symbol "ch" to the printer
+ * "xsize" is the horizontal width of the character in pixels
+ */
+f_setc(ch, xsize)
+unsigned long ch;
+int xsize;
+{
+ register struct kyochar *c = &(curfnt->kf_char[ch]);
+
+ /* When the symbol is to high it must be sent in raster format
+ * and canoot be loaded into the Kyocera
+ * Symbols higher than MAXKYOHEIGHT pixels cannot be loaded
+ */
+ if (c->kc_info & KC_RASTER)
+ dev_raster(c);
+ else
+ dev_setc(ch, xsize);
+}
+
+/* Hints as to what fonts are to be used.
+ * This is called once per page to give fonts module instrucions as what fonts
+ * and characters in those fonts have to be loaded for this page.
+ * "fontvec" contains a list of fonts used for this page
+ * "veclen" is the number of fonts used on this page
+ * "charvec" contains the per font information about the symbols needed
+ */
+f_newpage(fontvec,charvec,veclen)
+ unsigned long fontvec[];
+ unsigned long charvec[][4];
+ int veclen;
+{
+ struct kyochar *c;
+ register int i,j;
+ struct kyofont *f;
+
+ for (i = 0; i < veclen; i++) {
+ /* Lookup font in the dvi-fonttable
+ * and read the pxlfile if needed
+ */
+ f = find_dvi_font(fontvec[i]);
+ if (f->kf_info & KF_FILE) getfontfromfile(f);
+ /* If not not loaded initialize space requirements */
+ if (!(f->kf_info & KF_LOADED)) {
+ f->kf_words_used = 0;
+ f->kf_words_needed = KF_MIN;
+
+ }
+ /* Determine which symbols should be loaded from this font */
+ for (j = 0; j < MAXCHARS; j++)
+ if (charvec[i][j/32] & (1 << (j % 32))) {
+ c = &(f->kf_char[j]);
+ c->kc_info |= KC_NEEDED;
+ if (!(c->kc_info & KC_LOADED))
+ f->kf_words_needed += char_words_needed(c);
+ } else f->kf_char[j].kc_info &= ~KC_NEEDED;
+ /* Load the symbols needed and not yet loaded */
+ download_font(f);
+ }
+}
+
+
+/* Load a font into the Kyocera */
+download_font(fnt)
+ struct kyofont *fnt;
+{
+ register int i;
+
+ /* Make free space if needed */
+ if (fnt->kf_words_needed > freewords)
+ kyofree(fnt->kf_words_needed);
+ freewords -= fnt->kf_words_needed;
+ fnt->kf_words_used += fnt->kf_words_needed;
+
+ /* Load needed symbols that are not yet loaded */
+ for (i = 0; i < MAXCHARS; i++)
+ if ((fnt->kf_char[i].kc_info & KC_NEEDED)
+ && !(fnt->kf_char[i].kc_info & KC_LOADED))
+ load_char(i,fnt);
+
+ /* If font is loaded for the first time set its font attributes */
+ if (!(fnt->kf_info & KF_LOADED))
+ fprintf(kyo, "!R! FONT %1d; SFA 0,0,P,0;EXIT;",fnt->kf_kyonumber);
+
+ debug("Loaded %d words for font %s, %d\n",
+ fnt->kf_words_needed, fnt->kf_name, fnt->kf_kyonumber);
+ fnt->kf_words_needed = 0;
+ fnt->kf_info |= KF_LOADED;
+}
+
+/* Load symbol "ch" from font "fnt" */
+load_char(ch,fnt)
+ unsigned long ch;
+ struct kyofont *fnt;
+{
+ register unsigned short *bp;
+ register int w;
+ struct kyochar *c = &(fnt->kf_char[ch]);
+ int row,bw;
+
+ /* If symbol is too high it cannot be loaded
+ * and should be send as a raster each time it is used
+ */
+ if (c->kc_height > MAXKYOHEIGHT) {
+ c->kc_info |= KC_RASTER;
+ return;
+ }
+
+ /* Does this symbol exist */
+ if (!(c->kc_glyph.l))
+ croak("Char %#x not in font %s\n",ch, fnt->kf_name);
+
+ /* Load metrics information about the symbol */
+ fprintf(kyo, "!R! LDFC %1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,0;"
+ ,fnt->kf_kyonumber, visual(ch), c->kc_height, c->kc_width
+ ,32*c->kc_yoffset,32*c->kc_xoffset
+ ,32*c->kc_kyowidth, 16*c->kc_kyowidth);
+
+ /* Load the pixel raster */
+ bp = c->kc_glyph.p;
+ bw = (c->kc_width + 15) / 16;
+ for (row = 0; row < c->kc_height; row++) {
+ for (w = 0; w < bw; w++) convert(*bp++);
+ }
+ fprintf(kyo, "; EXIT;"); fflush(kyo);
+ c->kc_info |= KC_LOADED;
+}
+
+/* Convert pixel information into the format needed by the Kyocera */
+convert(w)
+ unsigned short w;
+{
+ char c;
+
+ c = ((w >> 10) & 077) + 64;
+ if (c == 127) c = '/'; putc(c, kyo);
+ c = ((w >> 4) & 077) + 64;
+ if (c == 127) c = '/'; putc(c, kyo);
+ c = (w & 017) + 48; putc(c, kyo);
+}
+
+/* Read the information for font "fnt" from file "fname" */
+int readpxlfile(fnt,fname)
+ struct kyofont *fnt;
+ char *fname;
+{
+ long pxl_id,pxl_dir_ptr;
+ long pxlchecksum;
+ FILE *f;
+
+ if (!(f = fopen(fname,"r"))) croak("no pxl file %s",fname);
+ if ((pxl_id = sget4(f)) != 1001)
+ croak("%d bad initial pxl ID; %s doesn't look like a pxl file",
+ pxl_id, fnt->kf_filename);
+
+ debug("OK This is a PXL file\n");
+ /* Read the last 5 longs from the pxl file */
+ (void) fseek(f, (long)(-5*4), 2);
+ pxlchecksum = sget4(f);
+ fnt->kf_pxl_mag_val = sget4(f);
+ fnt->kf_pxl_design_size = sget4(f);
+ pxl_dir_ptr = sget4(f);
+ if ((pxl_id = sget4(f)) != 1001)
+ croak("%d bad final pxl ID; %s doesn't look like a pxl file",
+ pxl_id, fnt->kf_filename);
+ if (pxl_dir_ptr != ftell(f) / 4 - 517)
+ croak("%s pxl dir ptr is %x, should be %x",
+ fnt->kf_filename, pxl_dir_ptr, ftell(f) / 4 - 517);
+ debug("pxl: checksum %d mag %d designsize %d dir %x\n",
+ pxlchecksum,fnt->kf_pxl_mag_val,
+ fnt->kf_pxl_design_size,pxl_dir_ptr);
+
+ if (fnt->kf_tfm_checksum & (pxlchecksum != fnt->kf_tfm_checksum)) {
+ fprintf(stderr, "Checksum mismatch: %s\n",fnt->kf_filename);
+ fprintf(stderr, " pxl file: %ld, tfm_file: %ld\n",
+ pxlchecksum, fnt->kf_tfm_checksum);
+ }
+
+ /* Read the directory */
+ (void) fseek(f, pxl_dir_ptr * 4, 0);
+ getpxldir(fnt,f);
+ debug(" %s max_height=%d\n",fnt->kf_filename,fnt->kf_maxheight);
+
+ /* Read in all the glyphs */
+ getglyphs(fnt,f);
+
+ (void) fclose(f);
+}
+
+/* Read the pixel directory for font "fnt" from file "f" */
+getpxldir(fnt,f)
+ struct kyofont *fnt;
+ FILE *f;
+{
+ int i;
+ struct kyochar *c;
+ double ds = ((double) fnt->kf_s) / ((double) (1 << 20));
+
+ /* Each symbol has an entry of 16 bytes */
+ fnt->kf_maxheight = 0;
+ for (i = 0; i < MAXCHARS; i++) {
+ c = &(fnt->kf_char[i]);
+ c->kc_width = sget2(f);
+ c->kc_height = sget2(f);
+ c->kc_xoffset = sget2(f);
+ c->kc_yoffset = sget2(f);
+ c->kc_glyph.l = get4(f);
+ c->kc_pxlwidth = sget4(f);
+ c->kc_texwidth = (long) (((double) c->kc_pxlwidth) * ds);
+ c->kc_kyowidth =
+ (c->kc_texwidth * numerator + half_denominator) / denominator;
+ /* Determine the maximum height of the font */
+ fnt->kf_maxheight = max(fnt->kf_maxheight,c->kc_height);
+ }
+}
+
+/* Read the raster information for font "fnt" from file "f"
+ * The information per symbol is a multiple of 4 bytes
+ * The information per symbol that will be loaded is a multiple of 2 bytes
+ */
+getglyphs(fnt,f)
+ struct kyofont *fnt;
+ FILE *f;
+{
+ register int j,row;
+ register unsigned short *p;
+ int i,fbw,bw;
+ struct kyochar *c;
+
+ for (i = 0; i < MAXCHARS; i++) {
+ c = &(fnt->kf_char[i]);
+ if (c->kc_glyph.l) {
+ (void) fseek(f, c->kc_glyph.l * 4, 0);
+ fbw = ((c->kc_width + 31) / 32) * 2;
+ bw = (c->kc_width + 15) / 16;
+ if (!(p = (unsigned short *)malloc(2*bw * c->kc_height)))
+ croak("malloc %d",2*bw * c->kc_height);
+ c->kc_glyph.p = p;
+ for (row = 0; row < c->kc_height; row++) {
+ for (j = 0; j < bw; j++) *p++ = get2(f);
+ /* get rid of empty trailing bytes */
+ for (j = bw; j < fbw; j++) (void) get2(f);
+ }
+ }
+ }
+}
+
+/* This procedure is called for every character so it must be fast
+ * It returns the TeX width and the device width of symbol "ch"
+ */
+f_use_char(ch,texwidth,devwidth)
+unsigned long ch;
+long *texwidth,*devwidth;
+{
+ register struct kyochar *c = &(curfnt->kf_char[ch]);
+
+ *texwidth = c->kc_texwidth;
+ *devwidth = c->kc_kyowidth;
+}
+
+
+/* free words by deleting font(s) using LRU strategy
+ * at least "words" words should be free
+ */
+int kyofree(words)
+ int words;
+{
+ int i,oldtime;
+ struct kyofont *oldfont;
+ struct preload *oldpr;
+
+ while (words > freewords) {
+ oldpr = NULL;
+ /* First try preloaded fonts not yet used by this job */
+ for (i=0; i<nloaded; i++)
+ if (loaded[i].pr_info & PR_LOADED) {
+ oldpr = &loaded[i];
+ break;
+ }
+ /* Found one, delete it */
+ if (oldpr) {
+ oldpr->pr_info &= ~PR_LOADED;
+ fprintf(kyo,"!R! DELF %1d;EXIT;",oldpr->pr_font->pr_kyonumber);
+ fflush(kyo);
+ debug("Left free %ld\n", freewords);
+ debug("PRELOADED FONT %s, %d deleted, size %ld\n",
+ oldpr->pr_font->pr_name,
+ oldpr->pr_font->pr_kyonumber,
+ oldpr->pr_font->pr_words_used );
+ freewords += oldpr->pr_font->pr_words_used;
+ } else {
+ /* Try the other fonts now */
+ oldfont = NULL;
+ oldtime = timestamp;
+ for (i = 0; i < nkyofonts; i++)
+ if ((kyofonts[i]->kf_info & KF_LOADED)
+ && (kyofonts[i]->kf_timestamp < oldtime)) {
+ oldfont = kyofonts[i];
+ oldtime = oldfont->kf_timestamp;
+ }
+ if (!oldfont) croak("kyofree bug");
+ oldfont->kf_info &= ~KF_LOADED;
+ oldfont->kf_words_needed = KF_MIN;
+ oldfont->kf_words_used = 0;
+ fprintf(kyo,"!R! DELF %1d;EXIT;",oldfont->kf_kyonumber);
+ fflush(kyo);
+ debug("Left free %ld\n", freewords);
+ debug("FONT %s, %d deleted, size %ld\n",
+ oldfont->kf_name,
+ oldfont->kf_kyonumber,
+ oldfont->kf_words_used);
+ freewords += oldfont->kf_words_used;
+ for (i = 0; i < MAXCHARS; i++) {
+ oldfont->kf_char[i].kc_info &= ~KC_LOADED;
+ if (oldfont->kf_char[i].kc_info & KC_NEEDED)
+ oldfont->kf_words_needed+=char_words_needed(&(oldfont->kf_char[i]));
+ }
+ }
+ }
+}