home *** CD-ROM | disk | FTP | other *** search
- /* -*-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
-
-