/* * 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 #include #include #include #include /* For MAXPATHLEN */ #include #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; }