/*
* font_open.c(font, font_ret, mag, mag_ret, magstepval, name)
* Find and open gf, pk, or pxl files in the given path, having the given
* name and magnification. It tries gf files first, followed by pk and pxl
* files. The path variable should be of the form path1:path2:...:pathn,
* and each of the paths will be tried successively. Strings in pathi of
* the form %f, %p, and %d will be replaced by the font name, "gf" or "pk"
* or "pxl", and the magnification, respectively. If no %f appears in a
* path specifier, then the string "/%f.%d%p" is added on the end. This
* procedure is repeated for each of the possible magnifications allowed,
* and if it fails then the procedure will try changing the point size
* as well. If all of the above fails, then alt_font will be tried.
*
* If the variable SEARCH_SUBDIRECTORIES is set, then the environment
* variable TEXFONTS_SUBDIR and the #define variable DEFAULT_SUBDIR_PATH
* will be enabled, as well as ``*'' and ``**'' specifiers. The
* SUBDIR_PATH things will be appended to the end of the usual path, with
* a `*' at the end of each component. The `*' means that subdirectories
* will be searched up to one level; `**' means that subdirectories
* will be recursively searched to any level. Neither specifier may be
* preceded by a `%' specifier (after the most recent colon).
*
* If the file is found, then a file pointer is returned, and the following
* values are set:
* *font_ret a pointer to a string containing the font name (if
* different from the font requested).
* *mag_ret the actual magnification found.
* *name a pointer to a string containing the file name
*
* If the file is not found, then the return value is NULL.
*
* Often there are so many fonts that we need to manage the number of
* simultaneously open files. For that reason, these routines call
* xfopen() instead of fopen(), which should manage the number of open
* font files.
*
*/
/* Declare the routine to get the current working directory. */
#ifdef HAVE_GETWD
extern char *getwd ();
#define GETCWD(b, len) ((b) ? getwd (b) : getwd (xmalloc (len, "getwd")))
#else
/* POSIX says getcwd result is undefined if the pointer is NULL; at least
on a Convex, the result is a coredump. Hence the GETCWD macro
below is defined, as it works regardless of what getcwd() does
with a NULL pointer */
#define GETCWD(b, len) ((b) ? getcwd (b,len) \
: getcwd (xmalloc (len, "getcwd"),len))
#ifdef _POSIX_SOURCE
#include <unistd.h> /* getcwd prototype */
#else
#if NeedFunctionPrototypes
extern char *getcwd (char *, int);
#else
extern char *getcwd ();
#endif /* not NeedFunctionPrototypes */
#endif /* not _POSIX_SOURCE */
#endif /* not HAVE_GETWD */
static char *cwd;
/* The following is a data structure containing the precomputed names of
subdirectories to be recursively searched. */
static struct subdir_entry {
char *name; /* partial string */
_Xconst char *index; /* reference point in {,default_}font_path */
struct subdir_entry *next; /* link in list */
}
*subdir_head = NULL,
*next_subdir;
/*
* Create the subdirectory linked list for the given initial string
*/
static void
add_subdirs(str, len, recurs)
_Xconst char *str;
int len;
Boolean recurs;
{
int len1 = len;
char temp[FILENAMESIZE];
struct subdir_entry *next_subdir;
DIR *dir;
directory_entry_type e;
bcopy(str, temp, len);
if (len > 0 && temp[len - 1] != '/') temp[len1++] = '/';
temp[len1] = '\0';
next_subdir = make_subdir_entry(str, temp + len);
do {
/* By changing directories, we save a bunch of string
concatenations (and make the pathnames the kernel looks up
shorter). */
Strcpy(temp + len, next_subdir->name);
if (chdir (temp) != 0) continue;
/* Change back to the current directory, in case the path
contains relative directory names. */
if (chdir (cwd) != 0) {
perror (cwd);
exit (errno);
}
}
while (recurs && (next_subdir = next_subdir->next) != NULL);
}
/*
* Recursively figure out the subdirectory tree and precompute the
* list of subdirectories to search.
*/
#ifdef SEARCH_SUBDIRECTORIES
p = getenv ("TEXFONTS_SUBDIR");
if (p == NULL) p = "";
q = xmalloc((unsigned) strlen(font_path)
+ extra_len(p, default_subdir_path) + 1,
"initializing font searching");
Strcpy(q, font_path);
add_subdir_paths(q + strlen(q), q, p, default_subdir_path);
font_path = q;
/* Unfortunately, we can't look in the environment for the current
directory, because if we are running under a program (let's say
Emacs), the PWD variable might have been set by Emacs' parent
to the current directory at the time Emacs was invoked. This
is not necessarily the same directory the user expects to be
in. So, we must always call getcwd(3) or getwd(3), even though
they are slow and prone to hang in networked installations. */
cwd = GETCWD ((char *) NULL, FILENAMESIZE + 2);
if (cwd == NULL) {
perror ("getcwd");
exit (errno);
}
compute_subdir_paths(font_path, default_font_path);
#endif
if (fontsubfile != (FILE *) NULL) {
/* look for the substitute font from file */
if ((sfont = (char *)subfont((FILE *)fontsubfile,font)) != (char *)NULL) {
/* try open font file again */
if ((f = formatted_open(p, sfont, "gf", pkmag, name, FIRST_TRY,DEFAULT_TAIL)) != NULL)
return f;
}
}
#endif
if (fontsubfile != (FILE *) NULL) {
/* look for the substitute font from file */
if ((sfont = (char *)subfont((FILE *)fontsubfile,font)) != (char *)NULL) {
/* try open font file again */
if ((f = formatted_open(p, sfont, "pxl", pkmag, name, FIRST_TRY,DEFAULT_TAIL)) != NULL)
return f;
}
}
#endif
/*
* Loop over sizes. Try actual size first, then closest sizes.
If the pathname is absolutely or explicitly relative, don't
use the usual paths to search for it; just look for it in the
directory specified.
*/