1 /* Utility and Unix shadow routines for XEmacs on Windows NT.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94 */
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */
25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */
26 /* Adapted to fpTeX 0.4 by Fabrice Popineau <Fabrice.Popineau@supelec.fr> */
30 #include <kpathsea/config.h>
31 #include <kpathsea/c-proto.h>
32 #include <kpathsea/win32lib.h>
33 #include <kpathsea/lib.h>
35 /* Normalize filename by converting all path separators to
36 the specified separator. Also conditionally convert upper
37 case path name components to lower case.
38 Returns the index of the first meaningful char in the path
39 past any drive specifier of unc name specifier.
40 Remove any multiple path separators after a leading
41 drive specifier or double path separator.
45 normalize_filename (char *fp, char path_sep)
50 /* Always lower-case drive letters a-z, even if the filesystem
51 preserves case in filenames.
52 This is so filenames can be compared by string comparison
53 functions that are case-sensitive. Even case-preserving filesystems
54 do not distinguish case in drive letters. */
55 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z') {
59 /* Remove unneeded double slashes */
60 ret = (IS_UNC_NAME(fp) ? 2 :
61 NAME_BEGINS_WITH_DEVICE(fp) ?
62 (IS_DIR_SEP(*(fp+2)) ? 3 : 2) : IS_DIR_SEP(*fp) ? 1 : 0);
63 for (i = ret, p = fp+i;
67 int len = strlen(fp+i);
68 /* remove unneeded slashes, for the sake of win95 */
70 fprintf(stderr, "moving %s to %s\n", fp+ret, fp+i);
72 memcpy(fp+ret, fp+i, len);
73 *(char *)(fp+ret+len) = '\0';
76 /* conditionnally rewrite to same path_sep, slash preferably */
84 fprintf(stderr, "normalize_filename returned (%d) %s\n", ret, fp);
91 /* Destructively turn backslashes into slashes. */
93 dostounix_filename (char *p)
95 normalize_filename (p, '/');
98 /* Destructively turn slashes into backslashes. */
100 unixtodos_filename (char *p)
102 normalize_filename (p, '\\');
105 /* Remove all CR's that are followed by a LF.
106 (From msdos.c...probably should figure out a way to share it,
107 although this code isn't going to ever change.) */
109 crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count)
111 unsigned char *np = buf;
112 unsigned char *startp = buf;
113 unsigned char *endp = buf + n;
117 while (buf < endp - 1)
123 if (*(++buf) != 0x0a)
138 /* Parse the root part of file name, if present. Return length and
139 optionally store pointer to char after root. */
141 _parse_root (char * name, char ** pPath)
148 /* find the root name of the volume if given */
149 if (isalpha (name[0]) && name[1] == ':')
151 /* skip past drive specifier */
153 if (IS_DIR_SEP (name[0]))
156 else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1]))
162 if (IS_DIR_SEP (*name) && --slashes == 0)
167 if (IS_DIR_SEP (name[0]))
177 /* Get long base name for name; name is assumed to be absolute. */
179 get_long_basename (char * name, char * buf, int size)
181 WIN32_FIND_DATA find_data;
187 /* If the last component of NAME has a wildcard character,
188 return it as the basename. */
189 p = name + strlen (name);
190 while (*p != '\\' && *p != ':' && p > name) p--;
192 if (strchr (p, '*') || strchr (p, '?'))
194 if ((len = strlen (p)) < size)
195 memcpy (buf, p, len + 1);
202 dir_handle = FindFirstFile (name, &find_data);
203 if (dir_handle != INVALID_HANDLE_VALUE)
205 if ((len = strlen (find_data.cFileName)) < size)
206 memcpy (buf, find_data.cFileName, len + 1);
209 FindClose (dir_handle);
214 /* Get long name for file, if possible (assumed to be absolute). */
216 win32_get_long_filename (char * name, char * buf, int size)
221 char full[ MAX_PATH ];
228 /* Use local copy for destructive modification. */
229 memcpy (full, name, len+1);
230 unixtodos_filename (full);
232 /* Copy root part verbatim. */
233 len = _parse_root (full, &p);
234 memcpy (o, full, len);
241 p = strchr (q, '\\');
243 len = get_long_basename (full, o, size);
261 while (p != NULL && *p);
266 /* Map filename to a legal 8.3 name if necessary. */
268 map_win32_filename (const char * name, const char ** pPath)
270 static char shortname[MAX_PATH];
271 char * str = shortname;
274 const char * save_name = name;
276 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
278 register int left = 8; /* maximum number of chars in part */
279 register int extn = 0; /* extension added? */
280 register int dots = 2; /* maximum number of dots allowed */
283 *str++ = *name++; /* skip past UNC header */
285 while ((c = *name++))
292 extn = 0; /* reset extension flags */
293 dots = 2; /* max 2 dots */
294 left = 8; /* max length 8 for main part */
298 extn = 0; /* reset extension flags */
299 dots = 2; /* max 2 dots */
300 left = 8; /* max length 8 for main part */
305 /* Convert path components of the form .xxx to _xxx,
306 but leave . and .. as they are. This allows .emacs
307 to be read as _emacs, for example. */
326 extn = 1; /* we've got an extension */
327 left = 3; /* 3 chars in extension */
331 /* any embedded dots after the first are converted to _ */
336 case '#': /* don't lose these, they're important */
338 str[-1] = c; /* replace last character of part */
343 *str++ = tolower (c); /* map to lower case (looks nicer) */
345 dots = 0; /* started a path component */
354 strcpy (shortname, name);
355 unixtodos_filename (shortname);
359 *pPath = shortname + (path - save_name);