fix hex regex in SH
[nedit-bw.git] / relativeFileNormalization.diff
blobaaa1a844232aeba3fcb7bae9bfda8cc78160be1d
1 Allow NormalizePathname() and ParseFilename() to use windows path
3 Various operations require the extension of an incomplete file specification
4 to a full, absolute path. Before this patch, this completion uses the
5 current directory of the NEdit process as the base for relative file lookup.
6 However, this works against NEdit's file dialogs and shell processing which
7 start off in the directory of the current document, which may well not be
8 the same as the process' directory. Using "File > Open Selected" may not, in
9 this situation, find the file you would expect.
11 This patch alters NormalizePathname() and ParseFilename(), the utility
12 functions that perform the expansion so that the base for relative file
13 specifications can be passed, then changes all relevant calls to supply the
14 current window's file path value. It includes the nmReadWriteRelToWin.diff
15 adjustments to macro file functions read_file(), write_file() and
16 append_file() for this same behaviour, and adds a new one, full_file_name(),
17 which provides the macro writer with a way of obtaining the relative file
18 name from a relative file path.
20 ---
22 source/file.c | 6 +-
23 source/macro.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++--
24 source/menu.c | 2
25 source/nc.c | 4 -
26 source/nedit.c | 4 -
27 source/selection.c | 10 ++--
28 source/server.c | 2
29 source/tags.c | 22 +++++-----
30 util/fileUtils.c | 26 ++++++++---
31 util/fileUtils.h | 5 +-
32 util/getfiles.c | 2
33 11 files changed, 160 insertions(+), 38 deletions(-)
35 diff --quilt old/source/file.c new/source/file.c
36 --- old/source/file.c
37 +++ new/source/file.c
38 @@ -1076,20 +1076,20 @@ int SaveWindowAs(WindowInfo *window, con
39 } else
41 strcpy(fullname, newName);
44 - if (1 == NormalizePathname(fullname))
45 + if (1 == NormalizePathname(fullname, window->path))
47 return False;
50 /* Add newlines if requested */
51 if (addWrap)
52 addWrapNewlines(window);
54 - if (ParseFilename(fullname, filename, pathname) != 0) {
55 + if (ParseFilename(fullname, filename, pathname, window->path) != 0) {
56 return FALSE;
59 /* If the requested file is this file, just save it and return */
60 if (!strcmp(window->filename, filename) &&
61 @@ -1279,11 +1279,11 @@ static int doSave(WindowInfo *window)
62 /* free the text buffer copy returned from XmTextGetString */
63 XtFree(fileString);
65 #ifdef VMS
66 /* reflect the fact that NEdit is now editing a new version of the file */
67 - ParseFilename(fullname, window->filename, window->path);
68 + ParseFilename(fullname, window->filename, window->path, NULL);
69 #endif /*VMS*/
71 /* success, file was written */
72 SetWindowModified(window, FALSE);
74 diff --quilt old/source/macro.c new/source/macro.c
75 --- old/source/macro.c
76 +++ new/source/macro.c
77 @@ -182,10 +182,12 @@ static int validNumberMS(WindowInfo *win
78 DataValue *result, char **errMsg);
79 static int replaceInStringMS(WindowInfo *window, DataValue *argList, int nArgs,
80 DataValue *result, char **errMsg);
81 static int replaceSubstringMS(WindowInfo *window, DataValue *argList, int nArgs,
82 DataValue *result, char **errMsg);
83 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
84 + DataValue *result, char **errMsg);
85 static int readFileMS(WindowInfo *window, DataValue *argList, int nArgs,
86 DataValue *result, char **errMsg);
87 static int writeFileMS(WindowInfo *window, DataValue *argList, int nArgs,
88 DataValue *result, char **errMsg);
89 static int appendFileMS(WindowInfo *window, DataValue *argList, int nArgs,
90 @@ -527,10 +529,11 @@ static const BuiltInSubrName MacroSubrs[
91 { "to_column", toColumnMS },
92 { "set_window_title", setWindowTitleMS },
93 { "timer_add", timerAddMS },
94 { "timer_remove", timerRemoveMS },
95 { "escape_literal", escapeLiteralMS },
96 + { "full_file_name", fullFileNameMS },
97 { NULL, NULL } /* sentinel */
100 static const BuiltInSubrName SpecialVars[] = {
101 { "$cursor", cursorMV },
102 @@ -2070,11 +2073,11 @@ static int focusWindowMS(WindowInfo *win
104 /* didn't work? try normalizing the string passed in */
105 if (w == NULL) {
106 strncpy(normalizedString, string, MAXPATHLEN);
107 normalizedString[MAXPATHLEN-1] = '\0';
108 - if (1 == NormalizePathname(normalizedString)) {
109 + if (1 == NormalizePathname(normalizedString, window->path)) {
110 /* Something is broken with the input pathname. */
111 *errMsg = "Pathname too long in focus_window()";
112 return False;
114 for (w=WindowList; w != NULL; w = w->next) {
115 @@ -2506,10 +2509,112 @@ static int clipboardToStringMS(WindowInf
116 result->val.str.len = retLength;
118 return True;
122 +** Resolve the partial file path in name with respect to path.
123 +** (We don't use NormalizePathname() since this modifies its path in place.)
125 +static char *convFilePathToAbsolute(const char *path, char *name)
127 + static char *nameText = NULL, *ptr;
128 + static size_t nameTextLen = 0;
129 + size_t namelen, pathlen, len;
130 + Bool isRelative = False;
131 + size_t needSlash = 0;
133 + if (!path || !path[0] || strcmp(path, ".") == 0)
134 + path = GetCurrentDir();
136 +#ifdef VMS
137 + /* If path name is relative, make it refer to current window's directory;
138 + absolute paths start with a logical name ([\w$]+) followed by a colon,
139 + or with a non-relative path in brackets (not starting with . or -)
140 + */
141 + isRelative = ((strchr(name, ':') == NULL) && (strlen(name) > 1) &&
142 + !((name[0] == '[') && (name[1] != '-') &&
143 + (name[1] != '.')));
144 +#else
145 + /* UNIX-like:
146 + Any path starting without a "/" is considered relative; if the first
147 + character is "~", we really need the user's home directory */
148 + if (name[0] == '~' && name[1] == '/') {
149 + path = GetHomeDir();
150 + for (++name; *name == '/'; ++name)
151 + continue; /* skip slash(es) following initial tilde */
152 + isRelative = True;
154 + else
155 + isRelative = (name[0] != '/');
156 +#endif
158 + if (!isRelative)
159 + return name;
161 + namelen = strlen(name);
162 + pathlen = strlen(path);
164 +#ifndef VMS
165 + needSlash = (path && pathlen && path[pathlen - 1] != '/') ? 1 : 0;
166 +#endif
168 + /* make sure the buffer's big enough */
169 + len = namelen + pathlen + needSlash;
171 + if (nameTextLen < len) {
172 + ptr = realloc(nameText, len + 1);
173 + if (!ptr)
174 + return NULL;
175 + nameText = ptr;
176 + nameTextLen = len;
179 + /* copy in pieces */
180 + strcpy(nameText, path);
181 + if (needSlash)
182 + nameText[pathlen] = '/';
183 + strcpy(nameText + pathlen + needSlash, name);
185 + CompressPathname(nameText);
187 + return nameText;
191 +** Built-in macro subroutine for expanding a possibly partial file specification
192 +** to a full one, using the current window's directory as a base for relative
193 +** path specifications. It does not check for file/path validity.
195 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
196 + DataValue *result, char **errMsg)
198 + char stringStorage[TYPE_INT_STR_SIZE(int)], *name;
199 + size_t len;
201 + /* Validate arguments and convert to int */
202 + if (nArgs != 1)
203 + return wrongNArgsErr(errMsg);
204 + if (!readStringArg(argList[0], &name, stringStorage, errMsg))
205 + return False;
207 + name = convFilePathToAbsolute(window->path, name);
208 + len = strlen(name);
210 + if (name) {
211 + result->tag = STRING_TAG;
212 + AllocNString(&result->val.str, len + 1);
213 + strcpy(result->val.str.rep, name);
215 + else {
216 + result->tag = STRING_TAG;
217 + result->val.str.rep = PERM_ALLOC_STR("");
218 + result->val.str.len = 0;
221 + return True;
225 ** Built-in macro subroutine for reading the contents of a text file into
226 ** a string. On success, returns 1 in $readStatus, and the contents of the
227 ** file as a string in the subroutine return value. On failure, returns
228 @@ -2526,11 +2631,13 @@ static int readFileMS(WindowInfo *window
229 /* Validate arguments and convert to int */
230 if (nArgs != 1)
231 return wrongNArgsErr(errMsg);
232 if (!readStringArg(argList[0], &name, stringStorage, errMsg))
233 return False;
236 + name = convFilePathToAbsolute(window->path, name);
238 /* Read the whole file into an allocated string */
239 if ((fp = fopen(name, "r")) == NULL)
240 goto errorNoClose;
241 if (fstat(fileno(fp), &statbuf) != 0)
242 goto error;
243 @@ -2605,11 +2712,13 @@ static int writeOrAppendFile(int append,
244 return wrongNArgsErr(errMsg);
245 if (!readStringArg(argList[0], &string, stringStorage[1], errMsg))
246 return False;
247 if (!readStringArg(argList[1], &name, stringStorage[0], errMsg))
248 return False;
251 + name = convFilePathToAbsolute(window->path, name);
253 /* open the file */
254 if ((fp = fopen(name, append ? "a" : "w")) == NULL) {
255 result->tag = INT_TAG;
256 result->val.n = False;
257 return True;
258 diff --quilt old/source/menu.c new/source/menu.c
259 --- old/source/menu.c
260 +++ new/source/menu.c
261 @@ -2988,11 +2988,11 @@ static void openAP(Widget w, XEvent *eve
262 fileNameToOpen = resultDV.val.str.rep;
263 } else {
264 fileNameToOpen = args[0];
267 - if (0 != ParseFilename(fileNameToOpen, filename, pathname)
268 + if (0 != ParseFilename(fileNameToOpen, filename, pathname, window->path)
269 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
270 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
271 fileNameToOpen);
272 return;
274 diff --quilt old/source/nc.c new/source/nc.c
275 --- old/source/nc.c
276 +++ new/source/nc.c
277 @@ -712,11 +712,11 @@ static void parseCommandLine(int argc, c
278 newCommandString = XtMalloc(oldLength+length+1);
279 strncpy(newCommandString, commandString, oldLength);
280 XtFree(commandString);
281 commandString = newCommandString;
282 outPtr = newCommandString + oldLength;
283 - if (ParseFilename(nameList[j], name, path) != 0) {
284 + if (ParseFilename(nameList[j], name, path, NULL) != 0) {
285 /* An Error, most likely too long paths/strings given */
286 commandLine->serverRequest = NULL;
287 return;
289 strcat(path, name);
290 @@ -748,11 +748,11 @@ static void parseCommandLine(int argc, c
291 fileCount++;
293 if (nameList != NULL)
294 free(nameList);
295 #else
296 - if (ParseFilename(argv[i], name, path) != 0) {
297 + if (ParseFilename(argv[i], name, path, NULL) != 0) {
298 /* An Error, most likely too long paths/strings given */
299 commandLine->serverRequest = NULL;
300 return;
302 strcat(path, name);
303 diff --quilt old/source/nedit.c new/source/nedit.c
304 --- old/source/nedit.c
305 +++ new/source/nedit.c
306 @@ -664,11 +664,11 @@ int main(int argc, char **argv)
307 /* Use VMS's LIB$FILESCAN for filename in argv[i] to process */
308 /* wildcards and to obtain a full VMS file specification */
309 numFiles = VMSFileScan(argv[i], &nameList, NULL, INCLUDE_FNF);
310 /* for each expanded file name do: */
311 for (j = 0; j < numFiles; ++j) {
312 - if (ParseFilename(nameList[j], filename, pathname) == 0) {
313 + if (ParseFilename(nameList[j], filename, pathname, NULL) == 0) {
314 /* determine if file is to be openned in new tab, by
315 factoring the options -group, -tabbed & -untabbed */
316 if (group == 2) {
317 isTabbed = 0; /* start a new window for new group */
318 group = 1; /* next file will be within group */
319 @@ -719,11 +719,11 @@ int main(int argc, char **argv)
320 free(nameList[j]);
322 if (nameList != NULL)
323 free(nameList);
324 #else
325 - if (ParseFilename(argv[i], filename, pathname) == 0 ) {
326 + if (ParseFilename(argv[i], filename, pathname, NULL) == 0 ) {
327 /* determine if file is to be openned in new tab, by
328 factoring the options -group, -tabbed & -untabbed */
329 if (group == 2) {
330 isTabbed = 0; /* start a new window for new group */
331 group = 1; /* next file will be within group */
332 diff --quilt old/source/selection.c new/source/selection.c
333 --- old/source/selection.c
334 +++ new/source/selection.c
335 @@ -325,28 +325,29 @@ static void fileCB(Widget widget, Window
336 names, in these cases, either don't expand names, or try to use the
337 Motif internal parsing routine _XmOSGetDirEntries, which is not
338 guranteed to be available, but in practice is there and does work. */
339 #if defined(DONT_HAVE_GLOB) || defined(VMS)
340 /* Open the file */
341 - if (ParseFilename(nameText, filename, pathname) != 0) {
342 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
343 XBell(TheDisplay, 0);
344 return;
346 EditExistingFile(window, filename,
347 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(), False);
348 #elif defined(USE_MOTIF_GLOB)
349 { char **nameList = NULL;
350 int i, nFiles = 0, maxFiles = 30;
352 - if (ParseFilename(nameText, filename, pathname) != 0) {
353 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
354 XBell(TheDisplay, 0);
355 return;
357 _XmOSGetDirEntries(pathname, filename, XmFILE_ANY_TYPE, False, True,
358 &nameList, &nFiles, &maxFiles);
359 for (i=0; i<nFiles; i++) {
360 - if (ParseFilename(nameList[i], filename, pathname) != 0) {
361 + if (ParseFilename(nameList[i], filename, pathname,
362 + window->path) != 0) {
363 XBell(TheDisplay, 0);
365 else {
366 EditExistingFile(window, filename, pathname, 0,
367 NULL, False, NULL, GetPrefOpenInTab(), False);
368 @@ -378,11 +379,12 @@ static void fileCB(Widget widget, Window
369 fileNameToOpen = resultDV.val.str.rep;
370 } else {
371 fileNameToOpen = globbuf.gl_pathv[i];
374 - if (ParseFilename(fileNameToOpen, filename, pathname) != 0) {
375 + if (ParseFilename(fileNameToOpen, filename, pathname,
376 + window->path) != 0) {
377 XBell(TheDisplay, 0);
378 } else {
379 EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
380 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
381 False);
382 diff --quilt old/source/server.c new/source/server.c
383 --- old/source/server.c
384 +++ new/source/server.c
385 @@ -452,11 +452,11 @@ static void processServerCommandString(c
387 /* Process the filename by looking for the files in an
388 existing window, or opening if they don't exist */
389 editFlags = (readFlag ? PREF_READ_ONLY : 0) | CREATE |
390 (createFlag ? SUPPRESS_CREATE_WARN : 0);
391 - if (ParseFilename(fullname, filename, pathname) != 0) {
392 + if (ParseFilename(fullname, filename, pathname, NULL) != 0) {
393 fprintf(stderr, "NEdit: invalid file name\n");
394 deleteFileClosedProperty2(filename, pathname);
395 break;
398 diff --quilt old/source/tags.c new/source/tags.c
399 --- old/source/tags.c
400 +++ new/source/tags.c
401 @@ -253,22 +253,22 @@ static int addTag(const char *name, cons
402 if (*file == '/')
403 strcpy(newfile,file);
404 else
405 sprintf(newfile,"%s%s", path, file);
407 - NormalizePathname(newfile);
408 + NormalizePathname(newfile, NULL);
410 for (t = table[addr]; t; t = t->next) {
411 if (strcmp(name,t->name)) continue;
412 if (lang != t->language) continue;
413 if (strcmp(search,t->searchString)) continue;
414 if (posInf != t->posInf) continue;
415 if (*t->file == '/' && strcmp(newfile,t->file)) continue;
416 if (*t->file != '/') {
417 char tmpfile[MAXPATHLEN];
418 sprintf(tmpfile, "%s%s", t->path, t->file);
419 - NormalizePathname(tmpfile);
420 + NormalizePathname(tmpfile, NULL);
421 if (strcmp(newfile, tmpfile)) continue;
423 return 0;
426 @@ -364,11 +364,11 @@ int AddRelTagsFile(const char *tagSpec,
427 } else {
428 strcpy(pathName, GetCurrentDir());
430 strcat(pathName, "/");
431 strcat(pathName, filename);
432 - NormalizePathname(pathName);
433 + NormalizePathname(pathName, NULL);
435 for (t = FileList; t && strcmp(t->filename, pathName); t = t->next);
436 if (t) {
437 added=1;
438 continue;
439 @@ -432,11 +432,11 @@ int AddTagsFile(const char *tagSpec, int
440 strcat(pathName,"/");
441 strcat(pathName,filename);
442 } else {
443 strcpy(pathName,filename);
445 - NormalizePathname(pathName);
446 + NormalizePathname(pathName, NULL);
448 for (t = FileList; t && strcmp(t->filename,pathName); t = t->next);
449 if (t) {
450 /* This file is already in the list. It's easiest to just
451 refcount all tag/tip files even though we only actually care
452 @@ -503,11 +503,11 @@ int DeleteTagsFile(const char *tagSpec,
453 strcat(pathName,"/");
454 strcat(pathName,filename);
455 } else {
456 strcpy(pathName,filename);
458 - NormalizePathname(pathName);
459 + NormalizePathname(pathName, NULL);
461 for (last=NULL,t = FileList; t; last = t,t = t->next) {
462 if (strcmp(t->filename, pathName))
463 continue;
464 /* Don't unload tips files with nonzero refcounts unless forced */
465 @@ -733,11 +733,11 @@ static int loadTagsFile(const char *tags
466 /* Open the file */
467 if ((fp = fopen(resolvedTagsFile, "r")) == NULL) {
468 return 0;
471 - ParseFilename(resolvedTagsFile, NULL, tagPath);
472 + ParseFilename(resolvedTagsFile, NULL, tagPath, NULL);
474 /* Read the file and store its contents */
475 while (fgets(line, MAXLINE, fp)) {
477 /* This might take a while if you have a huge tags file (like I do)..
478 @@ -1147,11 +1147,11 @@ static int findAllMatches(WindowInfo *wi
479 strcpy(tagFiles[nMatches], fileToSearch);
480 else
481 sprintf(tagFiles[nMatches],"%s%s",tagPath,fileToSearch);
482 strcpy(tagSearch[nMatches],searchString);
483 tagPosInf[nMatches]=startPos;
484 - ParseFilename(tagFiles[nMatches], filename, pathname);
485 + ParseFilename(tagFiles[nMatches], filename, pathname, NULL);
486 /* Is this match in the current file? If so, use it! */
487 if (GetPrefSmartTags() && !strcmp(window->filename,filename)
488 && !strcmp(window->path,pathname) ) {
489 if (nMatches) {
490 strcpy(tagFiles[0],tagFiles[nMatches]);
491 @@ -1204,11 +1204,11 @@ static int findAllMatches(WindowInfo *wi
492 XBell(TheDisplay, 0);
493 return -1;
496 for (i=0; i<nMatches; i++) {
497 - ParseFilename(tagFiles[i], filename, pathname);
498 + ParseFilename(tagFiles[i], filename, pathname, NULL);
499 if ((i<nMatches-1 && !strcmp(tagFiles[i],tagFiles[i+1])) ||
500 (i>0 && !strcmp(tagFiles[i],tagFiles[i-1]))) {
501 if(*(tagSearch[i]) && (tagPosInf[i] != -1)) { /* etags */
502 sprintf(temp,"%2d. %s%s %8i %s", i+1, pathname,
503 filename, tagPosInf[i], tagSearch[i]);
504 @@ -1327,11 +1327,11 @@ static void showMatchingCalltip( Widget
505 FILE *fp;
506 struct stat statbuf;
507 char *message;
509 /* 1. Open the target file */
510 - NormalizePathname(tagFiles[i]);
511 + NormalizePathname(tagFiles[i], NULL);
512 fp = fopen(tagFiles[i], "r");
513 if (fp == NULL) {
514 DialogF(DF_ERR, parent, 1, "Error opening File", "Error opening %s",
515 "OK", tagFiles[i]);
516 return;
517 @@ -1446,11 +1446,11 @@ static void editTaggedLocation( Widget p
518 int startPos, endPos, lineNum, rows;
519 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
520 WindowInfo *windowToSearch;
521 WindowInfo *parentWindow = WidgetToWindow(parent);
523 - ParseFilename(tagFiles[i],filename,pathname);
524 + ParseFilename(tagFiles[i], filename, pathname, NULL);
525 /* open the file containing the definition */
526 EditExistingFile(parentWindow, filename, pathname, 0, NULL, False,
527 NULL, GetPrefOpenInTab(), False);
528 windowToSearch = FindWindowWithFile(filename, pathname);
529 if (windowToSearch == NULL) {
530 @@ -1993,11 +1993,11 @@ static int loadTipsFile(const char *tips
531 if(!ResolvePath(tipsFile, resolvedTipsFile))
532 return 0;
533 #endif
535 /* Get the path to the tips file */
536 - ParseFilename(resolvedTipsFile, NULL, tipPath);
537 + ParseFilename(resolvedTipsFile, NULL, tipPath, NULL);
539 /* Open the file */
540 if ((fp = fopen(resolvedTipsFile, "r")) == NULL)
541 return 0;
543 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
544 --- old/util/fileUtils.c
545 +++ new/util/fileUtils.c
546 @@ -86,12 +86,12 @@ static void copyThruSlash(char **toStrin
547 ** Return non-zero value if it fails, zero else.
548 ** For now we assume that filename and pathname are at
549 ** most MAXPATHLEN chars long.
550 ** To skip setting filename or pathname pass NULL for that argument.
552 -int
553 -ParseFilename(const char *fullname, char *filename, char *pathname)
554 +int ParseFilename(const char *fullname, char *filename, char *pathname,
555 + const char *relpath)
557 int fullLen = strlen(fullname);
558 int i, pathLen, fileLen;
560 #ifdef VMS
561 @@ -136,11 +136,11 @@ ParseFilename(const char *fullname, char
562 filename[fileLen] = 0;
565 #ifndef VMS /* UNIX specific... Modify at a later date for VMS */
566 if(pathname) {
567 - if (NormalizePathname(pathname)) {
568 + if (NormalizePathname(pathname, relpath)) {
569 return 1; /* pathname too long */
571 pathLen = strlen(pathname);
573 #endif
574 @@ -269,11 +269,11 @@ ResolvePath(const char * pathIn, char *
576 strcpy(pathEnd+1, resolveBuf);
577 } else {
578 strcpy(pathBuf, resolveBuf);
580 - NormalizePathname(pathBuf);
581 + NormalizePathname(pathBuf, NULL);
582 pathIn=pathBuf;
585 return FALSE;
586 #endif /* NO_READLINK */
587 @@ -285,27 +285,29 @@ ResolvePath(const char * pathIn, char *
588 ** Capable to handle arbitrary path length (>MAXPATHLEN)!
590 ** FIXME: Documentation
591 ** FIXME: Change return value to False and True.
593 -int NormalizePathname(char *pathname)
594 +int NormalizePathname(char *pathname, const char *relpath)
596 - /* if this is a relative pathname, prepend current directory */
597 + /* if this is a relative pathname, prepend relpath */
598 + /* if relpath is a relative path, prepend the current directory */
599 #ifdef __EMX__
600 /* OS/2, ...: welcome to the world of drive letters ... */
601 if (!_fnisabs(pathname)) {
602 #else
603 if (pathname[0] != '/') {
604 #endif
605 char *oldPathname;
606 size_t len;
607 + int useRelpath = (relpath && *relpath);
609 /* make a copy of pathname to work from */
610 oldPathname=(char *)malloc(strlen(pathname)+1);
611 strcpy(oldPathname, pathname);
612 /* get the working directory and prepend to the path */
613 - strcpy(pathname, GetCurrentDir());
614 + strcpy(pathname, useRelpath ? relpath : GetCurrentDir());
616 /* check for trailing slash, or pathname being root dir "/":
617 don't add a second '/' character as this may break things
618 on non-un*x systems */
619 len = strlen(pathname); /* GetCurrentDir() returns non-NULL value */
620 @@ -318,10 +320,18 @@ int NormalizePathname(char *pathname)
622 strcat(pathname, "/");
624 strcat(pathname, oldPathname);
625 free(oldPathname);
626 + if (useRelpath)
628 + /* make sure our relative path wasn't relative to start with */
629 + if (CompressPathname(pathname) == 0)
630 + return NormalizePathname(pathname, NULL);
631 + else
632 + return 1; /* some non-zero value */
636 /* compress out .. and . */
637 return CompressPathname(pathname);
639 @@ -470,11 +480,11 @@ copyThruSlash(char **toString, char **fr
643 ** Return 0 if everything's fine, 1 else.
645 -int NormalizePathname(char *pathname)
646 +int NormalizePathname(char *pathname, const char *relpath)
648 return 0;
652 diff --quilt old/util/fileUtils.h new/util/fileUtils.h
653 --- old/util/fileUtils.h
654 +++ new/util/fileUtils.h
655 @@ -28,15 +28,16 @@
656 #ifndef NEDIT_FILEUTILS_H_INCLUDED
657 #define NEDIT_FILEUTILS_H_INCLUDED
659 enum fileFormats {UNIX_FILE_FORMAT, DOS_FILE_FORMAT, MAC_FILE_FORMAT};
661 -int ParseFilename(const char *fullname, char *filename, char *pathname);
662 +int ParseFilename(const char *fullname, char *filename, char *pathname,
663 + const char *relpath);
664 int ExpandTilde(char *pathname);
665 const char* GetTrailingPathComponents(const char* path,
666 int noOfComponents);
667 -int NormalizePathname(char *pathname);
668 +int NormalizePathname(char *pathname, const char *relpath);
669 int CompressPathname(char *pathname);
670 int ResolvePath(const char * pathIn, char * pathResolved);
672 int FormatOfFile(const char *fileString);
673 void ConvertFromDosFileString(char *inString, int *length,
674 diff --quilt old/util/getfiles.c new/util/getfiles.c
675 --- old/util/getfiles.c
676 +++ new/util/getfiles.c
677 @@ -1401,11 +1401,11 @@ static void listCharEH(Widget w, XtPoint
678 /* compare them with the accumulated user keystrokes & decide the
679 appropriate line in the list widget to select */
680 selectPos = 0;
681 for (i=0; i<nItems; i++) {
682 XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &itemString);
683 - if (ParseFilename(itemString, name, path) != 0) {
684 + if (ParseFilename(itemString, name, path, NULL) != 0) {
685 XtFree(itemString);
686 return;
688 XtFree(itemString);
689 cmp = strncmp(name, keystrokes, nKeystrokes);