summaryrefslogtreecommitdiff
path: root/dviware/beebe/src/openfont.h
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/beebe/src/openfont.h')
-rw-r--r--dviware/beebe/src/openfont.h324
1 files changed, 324 insertions, 0 deletions
diff --git a/dviware/beebe/src/openfont.h b/dviware/beebe/src/openfont.h
new file mode 100644
index 0000000000..ff785609dd
--- /dev/null
+++ b/dviware/beebe/src/openfont.h
@@ -0,0 +1,324 @@
+/* -*-C-*- openfont.h */
+/*-->openfont*/
+/**********************************************************************/
+/****************************** openfont ******************************/
+/**********************************************************************/
+
+void
+openfont(fontname)
+char *fontname;
+
+/***********************************************************************
+ The original version of this DVI driver reopened the font file each
+ time the font changed, resulting in an enormous number of relatively
+ expensive file openings. This version keeps a cache of up to
+ MAXOPEN open files, so that when a font change is made, the file
+ pointer, fontfp, can usually be updated from the cache. When the
+ file is not found in the cache, it must be opened. In this case,
+ the next empty slot in the cache is assigned, or if the cache is
+ full, the least used font file is closed and its slot reassigned for
+ the new file. Identification of the least used file is based on the
+ counts of the number of times each file has been "opened" by this
+ routine. On return, the file pointer is always repositioned to the
+ beginning of the file.
+
+ If the first open attempt fails, an attempt will be made to use a
+ substitute font, then neighboring magnifications (with the same font
+ name), or substitutes for them.
+***********************************************************************/
+
+{
+ register INT16 i,j,k; /* loop indices */
+ INT16 current;
+ INT16 least_used;
+ INT16 maxopen = MAXOPEN;
+
+#if OS_VAXVMS
+ long *jpi;
+#endif
+
+ struct font_entry *tfontptr;
+ char subfont[MAXFNAME];
+ int submag;
+ char* filelist[MAXFORMATS]; /* pointers to templist[][] */
+ char templist[MAXFORMATS][MAXFNAME];
+
+#if VIRTUAL_FONTS
+ struct stat statbuf; /* so fstat() can get file size */
+ char *p;
+#endif
+
+ if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr))
+ return; /* we need not have been called */
+
+ for (j = 0; j < MAXFORMATS; ++j) /* initialize fontlist pointers */
+ filelist[j] = &templist[j][0];
+
+#if IBM_PC_MICROSOFT
+ /* This code required rewriting to get around a fatal compiler
+ assertion error occasioned by the code in the #else part */
+ for (current = 1; current <= nopen; ++current)
+ {
+ FILE* pfp;
+
+ pfp = font_files[current].font_id;
+ if (pfp == fontptr->font_file_id)
+ break;
+ }
+#else
+ for (current = 1;
+ (current <= nopen) &&
+ (font_files[current].font_id != fontptr->font_file_id);
+ ++current)
+ ; /* try to find file in open list */
+#endif
+
+ if (current <= nopen) /* file already open, lookup its id */
+ fontfp = font_files[current].font_id;
+ else
+ {
+ /***************************************************************
+ The file was not in list of open files. If the list is not
+ full, add it to the list; otherwise close the least-used file
+ and remove it from the font_entry containing it. Finally, open
+ the file, or its closest neighbor in the magnification family.
+ A warning is issued if no file can be opened. The caller can
+ then proceed with zero font metrics if desired.
+ ***************************************************************/
+
+#if OS_VAXVMS
+ /***************************************************************
+ VAX VMS has many user quotas, one of which is the maximum number
+ of files that can be open, which need have no relation to the
+ number that C permits. If we do not determine the limit at
+ run-time, the drivers may attempt to open too many files, and in
+ such a case, will fail. There are two relevant quotas, FILLM
+ (open file limit), and FILCNT (remaining open file quota). We
+ use the latter, and leave one available file for a possible
+ error log.
+ ***************************************************************/
+
+ jpi = (long*)getjpi(JPI$_FILCNT);
+ if (jpi == (long*)NULL)
+ maxopen = MAXOPEN; /* should never happen */
+ else
+ maxopen = nopen - 1 + *jpi;
+ maxopen = MIN(maxopen,MAXOPEN); /* we have arrays of size MAXFONT */
+ /* so do not exceed that limit */
+#endif /* OS_VAXVMS */
+
+ if (nopen < maxopen) /* just add it to list */
+ current = ++nopen;
+ else /* list full -- find least used file, */
+ { /* close it, and reuse slot for new file */
+ least_used = 1;
+ for (i = 2; i <= maxopen; ++i)
+ if (font_files[least_used].use_count >
+ font_files[i].use_count)
+ least_used = i;
+
+ fontfp = font_files[least_used].font_id;
+ tfontptr = hfontptr;
+ while (tfontptr != (struct font_entry*)NULL)
+ { /* remove file pointer from its font_entry */
+ if (tfontptr->font_file_id == fontfp)
+ {
+ tfontptr->font_file_id = (FILE*)NULL;
+ break;
+ }
+ tfontptr = tfontptr->next;
+ }
+
+#if VIRTUAL_FONTS
+ if (virt_font && (fontfp != (FILE*)NULL))
+ (void)virtfree(fontfp);
+#endif
+
+ (void)fclose(fontfp);
+ fontfp = (FILE*)NULL;
+ current = least_used;
+ }
+ (void)actfact(fontptr->font_mag); /* Get global mag_index */
+
+ fontfp = (FILE*)NULL;
+
+ /***************************************************************
+ Try the requested font, then any substitute font, then for each
+ neighboring magnification from nearest to furthest, try the
+ requested font, and then any substitute font.
+ ***************************************************************/
+
+ for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k)
+ { /* loop over mag family */
+ for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k))
+ { /* try smaller, then larger */
+ if (IN(0,mag_index+i,MAGTABSIZE-1))
+ {
+ (void)fontfile(filelist, ((fontptr->a==0)?fontpath:""),
+ fontname, (int)MAGSIZE(mag_table[mag_index+i]));
+ for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
+ {
+ fontfp = FOPEN(filelist[j],RB_OPEN);
+ DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
+ if (fontfp != (FILE *)NULL)
+ {
+ strcpy(fontptr->name,filelist[j]);
+ break;
+ }
+ }
+ if ((k > 0) && (fontfp != (FILE*)NULL))
+ {
+ (void)sprintf(message,
+ "Font file [%s [mag %d]] could not be opened.\n\
+---using nearest neighbor [%s [mag %d]] instead.",
+ fontname,(int)MAGSIZE(mag_table[mag_index]),
+ fontptr->name,
+ (int)MAGSIZE(mag_table[mag_index+i]));
+ (void)warning(message);
+ }
+
+ if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag,
+ fontname,(int)MAGSIZE(mag_table[mag_index+i])))
+ {
+ (void)fontfile(filelist,((fontptr->a==0)?fontpath:""),
+ subfont,(submag ? submag :
+ (int)MAGSIZE(mag_table[mag_index+i])));
+ for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
+ {
+ fontfp = FOPEN(filelist[j],RB_OPEN);
+ DEBUG_OPEN(fontfp,filelist[j],RB_OPEN);
+ if (fontfp != (FILE *)NULL)
+ {
+ strcpy(fontptr->name,filelist[j]);
+ break;
+ }
+ }
+
+ if (fontfp != (FILE*)NULL)
+ {
+ (void)sprintf(message,
+ "Substituting font file [%s [mag %d]] \
+by [%s [mag %d]]",
+ fontname,(int)MAGSIZE(mag_table[mag_index]),
+ fontptr->name,
+ (int)MAGSIZE(mag_table[mag_index+i]));
+ (void)warning(message);
+ }
+ }
+ }
+ } /* end for (i) -- loop over smaller and larger neighbors */
+ } /* end for (k) -- loop over mag family */
+
+ if (fontfp == (FILE*)NULL)
+ {
+ --nopen; /* don't count this failed open */
+ (void)sprintf(message,"Font file [%s [mag %d]] could not be \
+opened; %d font files are open\n\
+Proceeding with zero size characters for this font",
+ fontname,(int)MAGSIZE(mag_table[mag_index]),nopen);
+ (void)warning(message);
+ }
+
+ font_files[current].font_id = fontfp;
+ font_files[current].use_count = 0;
+
+#if VIRTUAL_FONTS
+ /*
+ ****************************************************************
+ This code is implementation-dependent. On many C compilers,
+ FILE points to a struct of the form
+
+ struct _iobuf {
+ char *_ptr; // pointer to next available char
+ int _cnt; // number of chars left in buffer
+ char *_base; // pointer to start of buffer
+ int _flag; // assorted flags
+ int _file; // file number handle
+ }
+
+ To implement virtual fonts, we save the pointers in a private
+ global array, get the file size from fstat(), malloc() a buffer
+ for it, read the entire file in, and replace the pointers in the
+ FILE variable with ones for the new buffer. Just before the
+ file is closed, the space is freed and the old pointers are
+ restored. Although many C implementations use malloc() to get
+ the buffer space in the first place, which would make this
+ saving unnecessary, not all do; see the implementation given in
+ Kernighan and Ritchie "The C Programming Language", p. 168.
+
+ In implementing this code on any new machine, the
+ implementations of fread(), read(), fseek(), and rewind() should
+ be checked to choose the most efficient one (e.g. one system
+ call for entire file read, and no double buffering), and make
+ sure that fseek() and rewind() do not unnecessarily discard
+ input buffer contents. fseek() and rewind() are defined in
+ terms of macros FSEEK() and REWIND() in machdefs.h to facilitate
+ replacement.
+ ****************************************************************
+ */
+ if (virt_font)
+ {
+ virt_save[fileno(fontfp)].base = (char *)NULL;
+ (void)fstat(fileno(fontfp),&statbuf); /* get file size */
+ p = (char *)MALLOC((int)statbuf.st_size); /* get file buffer */
+ if (p != (char *)NULL)
+ {
+ if (READ(fileno(fontfp),p,(int)statbuf.st_size)
+ == (int)statbuf.st_size)
+ { /* read successful */
+ virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp);
+ virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp);
+ virt_save[fileno(fontfp)].base = FILE_BASE(fontfp);
+ FILE_PTR(fontfp) = p;
+ FILE_BASE(fontfp) = p;
+ FILE_CNT(fontfp) = (int)statbuf.st_size;
+ }
+ else /* failure */
+ {
+ (void)REWIND(fontfp);
+ (void)free(p); /* free dynamic buffer */
+ }
+ }
+ if (DBGOPT(DBG_FONT_CACHE))
+ {
+ (void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ",
+ (int)fileno(fontfp),fontptr->name);
+ if (p == (char *)NULL)
+ (void)fprintf(stderr,
+ "cannot callocate buffer for entire file\n");
+ else
+ (void)fprintf(stderr,
+ "buffer length 0x%x\told buffer at 0x%lx\t\
+new buffer at 0x%lx\n",
+ (int)statbuf.st_size,
+ (long)virt_save[fileno(fontfp)].base,
+ (long)FILE_BASE(fontfp));
+ }
+ }
+#endif
+
+ } /* end if (file is in open list) */
+
+ pfontptr = fontptr; /* make previous = current font */
+ fontptr->font_file_id = fontfp; /* set file identifier */
+ font_files[current].use_count++; /* update reference count */
+}
+
+#if VIRTUAL_FONTS
+void
+virtfree(fp) /* free buffer space before close */
+FILE *fp;
+{
+ if (virt_font && (fp != (FILE*)NULL) &&
+ (virt_save[fileno(fp)].base != (char *)NULL))
+ {
+ (void)fflush(fp);
+ (void)free(FILE_BASE(fp));
+ FILE_PTR(fp) = virt_save[fileno(fp)].ptr;
+ FILE_CNT(fp) = virt_save[fileno(fp)].cnt;
+ FILE_BASE(fp) = virt_save[fileno(fp)].base;
+ virt_save[fileno(fp)].base = (char *)NULL;
+ }
+}
+#endif
+