summaryrefslogtreecommitdiff
path: root/dviware/dvipage/findfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvipage/findfile.c')
-rw-r--r--dviware/dvipage/findfile.c503
1 files changed, 503 insertions, 0 deletions
diff --git a/dviware/dvipage/findfile.c b/dviware/dvipage/findfile.c
new file mode 100644
index 0000000000..21d85cd4e1
--- /dev/null
+++ b/dviware/dvipage/findfile.c
@@ -0,0 +1,503 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: findfile.c,v $
+ * Revision 1.1 88/11/28 18:40:44 hunt
+ * Initial revision
+ *
+ * Based upon `mitdrivers/findfile.c'
+ * Copyright 1985 Massachusetts Institute of Technology
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include "dvipage.h"
+
+forward bool find_file_in_path();
+forward bool find_best_file_in_path();
+forward bool scandir();
+forward bool scanpdir();
+forward int strdiff();
+
+
+/*
+ * find_file:
+ * Seaches for a font file in various places.
+ * dirpath is a colon separated list of possible pathnames.
+ * Returns TRUE if a usable file was found.
+ */
+
+bool find_font_file(dir_path, fontptr)
+char *dir_path;
+struct font_entry *fontptr;
+{
+ int min_df, min_dp, min_dm;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "find_font_file(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Search for exact match.
+ */
+ if(find_file_in_path(dir_path, fontptr))
+ return TRUE;
+
+ /*
+ * Search for nearest match.
+ */
+ min_df = min_dp = min_dm = MAXINT;
+ if(find_best_file_in_path(dir_path, fontptr,
+ &min_df, &min_dp, &min_dm))
+ {
+ message("Substituted font %s for %s.%d.",
+ fontptr->name, fontptr->n, fontptr->type == TYPE_PXL ?
+ fontptr->font_pxl_mag : fontptr->font_gf_mag);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * find_file_in_path:
+ * Searches path for a font file.
+ * Returns TRUE if a suitable match has been found.
+ */
+
+bool
+find_file_in_path(dirpath, fontptr)
+char *dirpath;
+struct font_entry *fontptr;
+{
+ char *p;
+ char dir[MAXPATHLEN];
+
+ while(*dirpath)
+ {
+ /*
+ * Copy first/next path prefix to dir[].
+ * Skip over the ':'.
+ */
+ for(p = dir; *dirpath; )
+ {
+ if(*dirpath == ':' || *dirpath == ';')
+ {
+ dirpath++;
+ break;
+ }
+ else
+ *p++ = *dirpath++;
+ }
+ *p = '\0';
+
+ if(use_pk)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dpk",
+ dir, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PK;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dpk",
+ dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PK;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+
+ if(use_gf)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dgf",
+ dir, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_GF;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dgf",
+ dir, fontptr->n, fontptr->n, fontptr->font_gf_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_GF;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+
+ if(use_pxl)
+ {
+ /*
+ * Try flat structure.
+ */
+ sprintf(fontptr->name, "%s/%s.%dpxl",
+ dir, fontptr->n, fontptr->font_pxl_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PXL;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+
+ /*
+ * Try hierarchical structure.
+ */
+ sprintf(fontptr->name, "%s/%s/%s.%dpxl",
+ dir, fontptr->n, fontptr->n, fontptr->font_pxl_mag);
+ if(access(fontptr->name, R_OK) == 0)
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; OK\n",
+ fontptr->name);
+ fontptr->type = TYPE_PXL;
+ return TRUE;
+ }
+ else
+ {
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " Try %s; No\n",
+ fontptr->name);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * find_best_file_in_path:
+ * Finds the best match to the desired font.
+ * Returns TRUE if a suitable match is found.
+ */
+
+bool
+find_best_file_in_path(dirpath, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dirpath;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ register char *p;
+ char dir[MAXPATHLEN];
+ bool status = FALSE;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, "find_best_font_file(%s .%dgf or %dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Scan over directories in dirpath.
+ */
+ while(*dirpath)
+ {
+ /*
+ * Copy first/next path prefix to dir[].
+ * Skip over the ':'.
+ */
+ for(p = dir; *dirpath != '\0'; )
+ {
+ if(*dirpath == ':' || *dirpath == ';')
+ {
+ dirpath++;
+ break;
+ }
+ else
+ *p++ = *dirpath++;
+ }
+ *p = '\0';
+
+ /*
+ * Scan the directory.
+ */
+ if(scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+
+ /*
+ * Scan any subdirectories.
+ */
+ if(scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+ }
+
+ return status;
+}
+
+/*
+ * scandir:
+ * Scan directory looking for plausible names,
+ * then recurse to subdirectories for plausible point sizes.
+ * Returns TRUE if found a more plausible candidate than previous best.
+ */
+
+bool
+scandir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dir;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ DIR *dirstream;
+ struct direct *dirrecord;
+ char pdir[MAXPATHLEN];
+ bool status = FALSE;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " scandir(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ if(! (dirstream = opendir(dir)))
+ return FALSE;
+
+ while(dirrecord = readdir(dirstream))
+ {
+ if(dirrecord->d_name[0] != '.')
+ continue;
+
+ if(strdiff(fontptr->n, dirrecord->d_name) <= *p_min_df)
+ {
+ sprintf(pdir, "%s/%s", dir, dirrecord->d_name);
+
+ if(scanpdir(pdir, fontptr,
+ p_min_df, p_min_dp, p_min_dm))
+ status = TRUE;
+ }
+ }
+
+ closedir(dirstream);
+
+ return status;
+}
+
+/*
+ * scanpdir:
+ * Scan directory looking for plausible names and point sizes.
+ * Returns TRUE if found a more plausible candidate than previous best.
+ */
+
+bool
+scanpdir(dir, fontptr, p_min_df, p_min_dp, p_min_dm)
+char *dir;
+struct font_entry *fontptr;
+int *p_min_df, *p_min_dp, *p_min_dm;
+{
+ DIR *dirstream;
+ struct direct *dirrecord;
+ char qfamily[MAXPATHLEN];
+ char qtype[MAXPATHLEN];
+ int qpoint, qmag, df, dp, dm;
+ bool status = FALSE;
+ char family[MAXPATHLEN];
+ int point;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr, " scanpdir(%s .%dgf or .%dpxl)\n",
+ fontptr->n, fontptr->font_gf_mag, fontptr->font_pxl_mag);
+
+ /*
+ * Split out family name, point size and magnification.
+ */
+ if(sscanf(fontptr->n, "%[^0123456789.]%d", family, &point) != 2)
+ {
+ message("Font name \"%s\" appears garbled.", fontptr->n);
+ return FALSE;
+ }
+
+ if(! (dirstream = opendir(dir)))
+ return FALSE;
+
+ while(dirrecord = readdir(dirstream))
+ {
+ if(sscanf(dirrecord->d_name, "%[^0123456789.]%d.%d%s",
+ qfamily, &qpoint, &qmag, qtype) != 4)
+ continue;
+
+ /*
+ * Is this a GF file.
+ */
+ if(use_gf && strcmp(qtype, "gf") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_gf_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_GF;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+
+ /*
+ * Is this a PXL file.
+ */
+ if(use_pxl && strcmp(qtype, "pxl") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_pxl_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_PXL;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+
+ /*
+ * Is this a PK file.
+ */
+ if(use_pk && strcmp(qtype, "pk") == 0)
+ {
+ df = strdiff(family, qfamily);
+ dp = abs(point - qpoint);
+ dm = abs(fontptr->font_gf_mag - qmag);
+ if((df < *p_min_df) ||
+ (df == *p_min_df && dp < *p_min_dp) ||
+ (df == *p_min_df && dp == *p_min_dp &&
+ dm < *p_min_dm))
+ {
+ *p_min_df = df;
+ *p_min_dp = dp;
+ *p_min_dm = dm;
+
+ sprintf(fontptr->name, "%s/%s",
+ dir, dirrecord->d_name);
+ fontptr->type = TYPE_PK;
+
+ if(verbose & DEBUG_FONTS)
+ fprintf(stderr,
+ " New best match (%d %d %d) is %s\n",
+ df, dp, dm, fontptr->name);
+
+ status = TRUE;
+ }
+ }
+ }
+
+ closedir(dirstream);
+
+ return status;
+}
+
+/*
+ * strdiff:
+ * Quantify differences in font names.
+ */
+
+int
+strdiff(s1, s2)
+char *s1, *s2;
+{
+ register int diff = 0;
+
+ while(*s1 && *s2)
+ diff += abs(*s1++ - *s2++);
+ while(*s1)
+ diff += *s1++;
+ while(*s2)
+ diff += *s2++;
+
+ return diff;
+}