fix syntax error
[nedit-bw.git] / relativeFileNormalization.diff
blobc7623817413b7f4e547e6de9fc75d201b7f8088c
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 | 8 +--
23 source/macro.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++--
24 source/menu.c | 6 +-
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, 164 insertions(+), 42 deletions(-)
35 diff --quilt old/source/file.c new/source/file.c
36 --- old/source/file.c
37 +++ new/source/file.c
38 @@ -1067,20 +1067,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 @@ -1161,11 +1161,11 @@ static int doSave(WindowInfo *window)
62 /* call the "pre_save_hook", if the macro returns a string, interpret this
63 as the new filename */
64 success = MacroApplyHook(window, "pre_save_hook", 0, NULL, &hookResult);
65 if (success && hookResult.tag == STRING_TAG) {
66 if (ParseFilename(hookResult.val.str.rep,
67 - window->filename, window->path)) {
68 + window->filename, window->path, window->path)) {
69 return FALSE;
73 /* Get the full name of the file */
74 @@ -1281,11 +1281,11 @@ static int doSave(WindowInfo *window)
75 /* free the text buffer copy returned from XmTextGetString */
76 XtFree(fileString);
78 #ifdef VMS
79 /* reflect the fact that NEdit is now editing a new version of the file */
80 - ParseFilename(fullname, window->filename, window->path);
81 + ParseFilename(fullname, window->filename, window->path, NULL);
82 #endif /*VMS*/
84 /* success, file was written */
85 SetWindowModified(window, FALSE);
87 diff --quilt old/source/macro.c new/source/macro.c
88 --- old/source/macro.c
89 +++ new/source/macro.c
90 @@ -181,10 +181,12 @@ static int validNumberMS(WindowInfo *win
91 DataValue *result, char **errMsg);
92 static int replaceInStringMS(WindowInfo *window, DataValue *argList, int nArgs,
93 DataValue *result, char **errMsg);
94 static int replaceSubstringMS(WindowInfo *window, DataValue *argList, int nArgs,
95 DataValue *result, char **errMsg);
96 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
97 + DataValue *result, char **errMsg);
98 static int readFileMS(WindowInfo *window, DataValue *argList, int nArgs,
99 DataValue *result, char **errMsg);
100 static int writeFileMS(WindowInfo *window, DataValue *argList, int nArgs,
101 DataValue *result, char **errMsg);
102 static int appendFileMS(WindowInfo *window, DataValue *argList, int nArgs,
103 @@ -526,10 +528,11 @@ static const BuiltInSubrName MacroSubrs[
104 { "to_column", toColumnMS },
105 { "set_window_title", setWindowTitleMS },
106 { "timer_add", timerAddMS },
107 { "timer_remove", timerRemoveMS },
108 { "escape_literal", escapeLiteralMS },
109 + { "full_file_name", fullFileNameMS },
110 { NULL, NULL } /* sentinel */
113 static const BuiltInSubrName SpecialVars[] = {
114 { "$cursor", cursorMV },
115 @@ -2069,11 +2072,11 @@ static int focusWindowMS(WindowInfo *win
117 /* didn't work? try normalizing the string passed in */
118 if (w == NULL) {
119 strncpy(normalizedString, string, MAXPATHLEN);
120 normalizedString[MAXPATHLEN-1] = '\0';
121 - if (1 == NormalizePathname(normalizedString)) {
122 + if (1 == NormalizePathname(normalizedString, window->path)) {
123 /* Something is broken with the input pathname. */
124 *errMsg = "Pathname too long in focus_window()";
125 return False;
127 for (w=WindowList; w != NULL; w = w->next) {
128 @@ -2505,10 +2508,112 @@ static int clipboardToStringMS(WindowInf
129 result->val.str.len = retLength;
131 return True;
135 +** Resolve the partial file path in name with respect to path.
136 +** (We don't use NormalizePathname() since this modifies its path in place.)
138 +static char *convFilePathToAbsolute(const char *path, char *name)
140 + static char *nameText = NULL, *ptr;
141 + static size_t nameTextLen = 0;
142 + size_t namelen, pathlen, len;
143 + Bool isRelative = False;
144 + size_t needSlash = 0;
146 + if (!path || !path[0] || strcmp(path, ".") == 0)
147 + path = GetCurrentDir();
149 +#ifdef VMS
150 + /* If path name is relative, make it refer to current window's directory;
151 + absolute paths start with a logical name ([\w$]+) followed by a colon,
152 + or with a non-relative path in brackets (not starting with . or -)
153 + */
154 + isRelative = ((strchr(name, ':') == NULL) && (strlen(name) > 1) &&
155 + !((name[0] == '[') && (name[1] != '-') &&
156 + (name[1] != '.')));
157 +#else
158 + /* UNIX-like:
159 + Any path starting without a "/" is considered relative; if the first
160 + character is "~", we really need the user's home directory */
161 + if (name[0] == '~' && name[1] == '/') {
162 + path = GetHomeDir();
163 + for (++name; *name == '/'; ++name)
164 + continue; /* skip slash(es) following initial tilde */
165 + isRelative = True;
167 + else
168 + isRelative = (name[0] != '/');
169 +#endif
171 + if (!isRelative)
172 + return name;
174 + namelen = strlen(name);
175 + pathlen = strlen(path);
177 +#ifndef VMS
178 + needSlash = (path && pathlen && path[pathlen - 1] != '/') ? 1 : 0;
179 +#endif
181 + /* make sure the buffer's big enough */
182 + len = namelen + pathlen + needSlash;
184 + if (nameTextLen < len) {
185 + ptr = realloc(nameText, len + 1);
186 + if (!ptr)
187 + return NULL;
188 + nameText = ptr;
189 + nameTextLen = len;
192 + /* copy in pieces */
193 + strcpy(nameText, path);
194 + if (needSlash)
195 + nameText[pathlen] = '/';
196 + strcpy(nameText + pathlen + needSlash, name);
198 + CompressPathname(nameText);
200 + return nameText;
204 +** Built-in macro subroutine for expanding a possibly partial file specification
205 +** to a full one, using the current window's directory as a base for relative
206 +** path specifications. It does not check for file/path validity.
208 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
209 + DataValue *result, char **errMsg)
211 + char stringStorage[TYPE_INT_STR_SIZE(int)], *name;
212 + size_t len;
214 + /* Validate arguments and convert to int */
215 + if (nArgs != 1)
216 + return wrongNArgsErr(errMsg);
217 + if (!readStringArg(argList[0], &name, stringStorage, errMsg))
218 + return False;
220 + name = convFilePathToAbsolute(window->path, name);
221 + len = strlen(name);
223 + if (name) {
224 + result->tag = STRING_TAG;
225 + AllocNString(&result->val.str, len + 1);
226 + strcpy(result->val.str.rep, name);
228 + else {
229 + result->tag = STRING_TAG;
230 + result->val.str.rep = PERM_ALLOC_STR("");
231 + result->val.str.len = 0;
234 + return True;
238 ** Built-in macro subroutine for reading the contents of a text file into
239 ** a string. On success, returns 1 in $readStatus, and the contents of the
240 ** file as a string in the subroutine return value. On failure, returns
241 @@ -2525,11 +2630,13 @@ static int readFileMS(WindowInfo *window
242 /* Validate arguments and convert to int */
243 if (nArgs != 1)
244 return wrongNArgsErr(errMsg);
245 if (!readStringArg(argList[0], &name, stringStorage, errMsg))
246 return False;
249 + name = convFilePathToAbsolute(window->path, name);
251 /* Read the whole file into an allocated string */
252 if ((fp = fopen(name, "r")) == NULL)
253 goto errorNoClose;
254 if (fstat(fileno(fp), &statbuf) != 0)
255 goto error;
256 @@ -2604,11 +2711,13 @@ static int writeOrAppendFile(int append,
257 return wrongNArgsErr(errMsg);
258 if (!readStringArg(argList[0], &string, stringStorage[1], errMsg))
259 return False;
260 if (!readStringArg(argList[1], &name, stringStorage[0], errMsg))
261 return False;
264 + name = convFilePathToAbsolute(window->path, name);
266 /* open the file */
267 if ((fp = fopen(name, append ? "a" : "w")) == NULL) {
268 result->tag = INT_TAG;
269 result->val.n = False;
270 return True;
271 @@ -5285,11 +5394,11 @@ static int neditHomeMV(WindowInfo *windo
272 DataValue *result, char **errMsg)
274 const char *neditRCName = GetRCFileName(NEDIT_RC);
275 char neditHome[MAXPATHLEN];
277 - if (0 != ParseFilename(neditRCName, NULL, neditHome)) {
278 + if (0 != ParseFilename(neditRCName, NULL, neditHome, NULL)) {
279 M_FAILURE("Unable to parse path of nedit.rc in %s");
282 result->tag = STRING_TAG;
283 AllocNStringCpy(&result->val.str, neditHome);
284 diff --quilt old/source/menu.c new/source/menu.c
285 --- old/source/menu.c
286 +++ new/source/menu.c
287 @@ -2974,11 +2974,11 @@ static void openAP(Widget w, XEvent *eve
288 fileNameToOpen = resultDV.val.str.rep;
289 } else {
290 fileNameToOpen = args[0];
293 - if (0 != ParseFilename(fileNameToOpen, filename, pathname)
294 + if (0 != ParseFilename(fileNameToOpen, filename, pathname, window->path)
295 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
296 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
297 fileNameToOpen);
298 return;
300 @@ -5025,11 +5025,11 @@ static void updatePrevOpenMenu(WindowInf
301 if (index >= NPrevOpen) {
302 /* unmanaging before destroying stops parent from displaying */
303 XtUnmanageChild(items[n]);
304 XtDestroyWidget(items[n]);
305 } else {
306 - ParseFilename(prevOpenSorted[index], filename, pathname);
307 + ParseFilename(prevOpenSorted[index], filename, pathname, NULL);
308 fileIsOpen = !!FindWindowWithFile(filename, pathname);
309 XtVaSetValues(items[n],
310 XmNlabelString, st1=XmStringCreateSimple(prevOpenSorted[index]),
311 XmNset, fileIsOpen,
312 NULL);
313 @@ -5041,11 +5041,11 @@ static void updatePrevOpenMenu(WindowInf
317 /* Add new items for the remaining file names to the menu */
318 for (; index<NPrevOpen; index++) {
319 - ParseFilename(prevOpenSorted[index], filename, pathname);
320 + ParseFilename(prevOpenSorted[index], filename, pathname, NULL);
321 fileIsOpen = !!FindWindowWithFile(filename, pathname);
322 btn = XtVaCreateManagedWidget("win", xmToggleButtonWidgetClass,
323 window->prevOpenMenuPane,
324 XmNlabelString, st1=XmStringCreateSimple(prevOpenSorted[index]),
325 XmNmarginHeight, 0,
326 diff --quilt old/source/nc.c new/source/nc.c
327 --- old/source/nc.c
328 +++ new/source/nc.c
329 @@ -712,11 +712,11 @@ static void parseCommandLine(int argc, c
330 newCommandString = XtMalloc(oldLength+length+1);
331 strncpy(newCommandString, commandString, oldLength);
332 XtFree(commandString);
333 commandString = newCommandString;
334 outPtr = newCommandString + oldLength;
335 - if (ParseFilename(nameList[j], name, path) != 0) {
336 + if (ParseFilename(nameList[j], name, path, NULL) != 0) {
337 /* An Error, most likely too long paths/strings given */
338 commandLine->serverRequest = NULL;
339 return;
341 strcat(path, name);
342 @@ -748,11 +748,11 @@ static void parseCommandLine(int argc, c
343 fileCount++;
345 if (nameList != NULL)
346 free(nameList);
347 #else
348 - if (ParseFilename(argv[i], name, path) != 0) {
349 + if (ParseFilename(argv[i], name, path, NULL) != 0) {
350 /* An Error, most likely too long paths/strings given */
351 commandLine->serverRequest = NULL;
352 return;
354 strcat(path, name);
355 diff --quilt old/source/nedit.c new/source/nedit.c
356 --- old/source/nedit.c
357 +++ new/source/nedit.c
358 @@ -658,11 +658,11 @@ int main(int argc, char **argv)
359 /* Use VMS's LIB$FILESCAN for filename in argv[i] to process */
360 /* wildcards and to obtain a full VMS file specification */
361 numFiles = VMSFileScan(argv[i], &nameList, NULL, INCLUDE_FNF);
362 /* for each expanded file name do: */
363 for (j = 0; j < numFiles; ++j) {
364 - if (ParseFilename(nameList[j], filename, pathname) == 0) {
365 + if (ParseFilename(nameList[j], filename, pathname, NULL) == 0) {
366 /* determine if file is to be openned in new tab, by
367 factoring the options -group, -tabbed & -untabbed */
368 if (group == 2) {
369 isTabbed = 0; /* start a new window for new group */
370 group = 1; /* next file will be within group */
371 @@ -713,11 +713,11 @@ int main(int argc, char **argv)
372 free(nameList[j]);
374 if (nameList != NULL)
375 free(nameList);
376 #else
377 - if (ParseFilename(argv[i], filename, pathname) == 0 ) {
378 + if (ParseFilename(argv[i], filename, pathname, NULL) == 0 ) {
379 /* determine if file is to be openned in new tab, by
380 factoring the options -group, -tabbed & -untabbed */
381 if (group == 2) {
382 isTabbed = 0; /* start a new window for new group */
383 group = 1; /* next file will be within group */
384 diff --quilt old/source/selection.c new/source/selection.c
385 --- old/source/selection.c
386 +++ new/source/selection.c
387 @@ -326,21 +326,21 @@ static void fileCB(Widget widget, Window
388 names, in these cases, either don't expand names, or try to use the
389 Motif internal parsing routine _XmOSGetDirEntries, which is not
390 guranteed to be available, but in practice is there and does work. */
391 #if defined(DONT_HAVE_GLOB) || defined(VMS)
392 /* Open the file */
393 - if (ParseFilename(nameText, filename, pathname) != 0) {
394 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
395 XBell(TheDisplay, 0);
396 return;
398 EditExistingFile(window, filename,
399 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(), False);
400 #elif defined(USE_MOTIF_GLOB)
401 { char **nameList = NULL;
402 int i, nFiles = 0, maxFiles = 30;
404 - if (ParseFilename(nameText, filename, pathname) != 0) {
405 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
406 XBell(TheDisplay, 0);
407 return;
409 _XmOSGetDirEntries(pathname, filename, XmFILE_ANY_TYPE, False, True,
410 &nameList, &nFiles, &maxFiles);
411 @@ -360,11 +360,12 @@ static void fileCB(Widget widget, Window
412 fileNameToOpen = resultDV.val.str.rep;
413 } else {
414 fileNameToOpen = nameList[i];
417 - if (ParseFilename(fileNameToOpen, filename, pathname) != 0) {
418 + if (ParseFilename(fileNameToOpen, filename, pathname,
419 + window->path) != 0) {
420 XBell(TheDisplay, 0);
421 } else {
422 EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
423 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
424 False);
425 @@ -397,11 +398,12 @@ static void fileCB(Widget widget, Window
426 fileNameToOpen = resultDV.val.str.rep;
427 } else {
428 fileNameToOpen = globbuf.gl_pathv[i];
431 - if (ParseFilename(fileNameToOpen, filename, pathname) != 0) {
432 + if (ParseFilename(fileNameToOpen, filename, pathname,
433 + window->path) != 0) {
434 XBell(TheDisplay, 0);
435 } else {
436 EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
437 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
438 False);
439 diff --quilt old/source/server.c new/source/server.c
440 --- old/source/server.c
441 +++ new/source/server.c
442 @@ -454,11 +454,11 @@ static void processServerCommandString(c
444 /* Process the filename by looking for the files in an
445 existing window, or opening if they don't exist */
446 editFlags = (readFlag ? PREF_READ_ONLY : 0) | CREATE |
447 (createFlag ? SUPPRESS_CREATE_WARN : 0);
448 - if (ParseFilename(fullname, filename, pathname) != 0) {
449 + if (ParseFilename(fullname, filename, pathname, NULL) != 0) {
450 fprintf(stderr, "NEdit: invalid file name\n");
451 deleteFileClosedProperty2(filename, pathname);
452 break;
455 diff --quilt old/source/tags.c new/source/tags.c
456 --- old/source/tags.c
457 +++ new/source/tags.c
458 @@ -253,22 +253,22 @@ static int addTag(const char *name, cons
459 if (*file == '/')
460 strcpy(newfile,file);
461 else
462 sprintf(newfile,"%s%s", path, file);
464 - NormalizePathname(newfile);
465 + NormalizePathname(newfile, NULL);
467 for (t = table[addr]; t; t = t->next) {
468 if (strcmp(name,t->name)) continue;
469 if (lang != t->language) continue;
470 if (strcmp(search,t->searchString)) continue;
471 if (posInf != t->posInf) continue;
472 if (*t->file == '/' && strcmp(newfile,t->file)) continue;
473 if (*t->file != '/') {
474 char tmpfile[MAXPATHLEN];
475 sprintf(tmpfile, "%s%s", t->path, t->file);
476 - NormalizePathname(tmpfile);
477 + NormalizePathname(tmpfile, NULL);
478 if (strcmp(newfile, tmpfile)) continue;
480 return 0;
483 @@ -364,11 +364,11 @@ int AddRelTagsFile(const char *tagSpec,
484 } else {
485 strcpy(pathName, GetCurrentDir());
487 strcat(pathName, "/");
488 strcat(pathName, filename);
489 - NormalizePathname(pathName);
490 + NormalizePathname(pathName, NULL);
492 for (t = FileList; t && strcmp(t->filename, pathName); t = t->next);
493 if (t) {
494 added=1;
495 continue;
496 @@ -432,11 +432,11 @@ int AddTagsFile(const char *tagSpec, int
497 strcat(pathName,"/");
498 strcat(pathName,filename);
499 } else {
500 strcpy(pathName,filename);
502 - NormalizePathname(pathName);
503 + NormalizePathname(pathName, NULL);
505 for (t = FileList; t && strcmp(t->filename,pathName); t = t->next);
506 if (t) {
507 /* This file is already in the list. It's easiest to just
508 refcount all tag/tip files even though we only actually care
509 @@ -503,11 +503,11 @@ int DeleteTagsFile(const char *tagSpec,
510 strcat(pathName,"/");
511 strcat(pathName,filename);
512 } else {
513 strcpy(pathName,filename);
515 - NormalizePathname(pathName);
516 + NormalizePathname(pathName, NULL);
518 for (last=NULL,t = FileList; t; last = t,t = t->next) {
519 if (strcmp(t->filename, pathName))
520 continue;
521 /* Don't unload tips files with nonzero refcounts unless forced */
522 @@ -733,11 +733,11 @@ static int loadTagsFile(const char *tags
523 /* Open the file */
524 if ((fp = fopen(resolvedTagsFile, "r")) == NULL) {
525 return 0;
528 - ParseFilename(resolvedTagsFile, NULL, tagPath);
529 + ParseFilename(resolvedTagsFile, NULL, tagPath, NULL);
531 /* Read the file and store its contents */
532 while (fgets(line, MAXLINE, fp)) {
534 /* This might take a while if you have a huge tags file (like I do)..
535 @@ -1147,11 +1147,11 @@ static int findAllMatches(WindowInfo *wi
536 strcpy(tagFiles[nMatches], fileToSearch);
537 else
538 sprintf(tagFiles[nMatches],"%s%s",tagPath,fileToSearch);
539 strcpy(tagSearch[nMatches],searchString);
540 tagPosInf[nMatches]=startPos;
541 - ParseFilename(tagFiles[nMatches], filename, pathname);
542 + ParseFilename(tagFiles[nMatches], filename, pathname, NULL);
543 /* Is this match in the current file? If so, use it! */
544 if (GetPrefSmartTags() && !strcmp(window->filename,filename)
545 && !strcmp(window->path,pathname) ) {
546 if (nMatches) {
547 strcpy(tagFiles[0],tagFiles[nMatches]);
548 @@ -1204,11 +1204,11 @@ static int findAllMatches(WindowInfo *wi
549 XBell(TheDisplay, 0);
550 return -1;
553 for (i=0; i<nMatches; i++) {
554 - ParseFilename(tagFiles[i], filename, pathname);
555 + ParseFilename(tagFiles[i], filename, pathname, NULL);
556 if ((i<nMatches-1 && !strcmp(tagFiles[i],tagFiles[i+1])) ||
557 (i>0 && !strcmp(tagFiles[i],tagFiles[i-1]))) {
558 if(*(tagSearch[i]) && (tagPosInf[i] != -1)) { /* etags */
559 sprintf(temp,"%2d. %s%s %8i %s", i+1, pathname,
560 filename, tagPosInf[i], tagSearch[i]);
561 @@ -1326,11 +1326,11 @@ static void showMatchingCalltip( Widget
562 FILE *fp;
563 struct stat statbuf;
564 char *message;
566 /* 1. Open the target file */
567 - NormalizePathname(tagFiles[i]);
568 + NormalizePathname(tagFiles[i], NULL);
569 fp = fopen(tagFiles[i], "r");
570 if (fp == NULL) {
571 DialogF(DF_ERR, parent, 1, "Error opening File", "Error opening %s",
572 "OK", tagFiles[i]);
573 return;
574 @@ -1445,11 +1445,11 @@ static void editTaggedLocation( Widget p
575 int startPos, endPos, lineNum, rows;
576 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
577 WindowInfo *windowToSearch;
578 WindowInfo *parentWindow = WidgetToWindow(parent);
580 - ParseFilename(tagFiles[i],filename,pathname);
581 + ParseFilename(tagFiles[i], filename, pathname, NULL);
582 /* open the file containing the definition */
583 EditExistingFile(parentWindow, filename, pathname, 0, NULL, False,
584 NULL, GetPrefOpenInTab(), False);
585 windowToSearch = FindWindowWithFile(filename, pathname);
586 if (windowToSearch == NULL) {
587 @@ -1992,11 +1992,11 @@ static int loadTipsFile(const char *tips
588 if(!ResolvePath(tipsFile, resolvedTipsFile))
589 return 0;
590 #endif
592 /* Get the path to the tips file */
593 - ParseFilename(resolvedTipsFile, NULL, tipPath);
594 + ParseFilename(resolvedTipsFile, NULL, tipPath, NULL);
596 /* Open the file */
597 if ((fp = fopen(resolvedTipsFile, "r")) == NULL)
598 return 0;
600 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
601 --- old/util/fileUtils.c
602 +++ new/util/fileUtils.c
603 @@ -86,12 +86,12 @@ static void copyThruSlash(char **toStrin
604 ** Return non-zero value if it fails, zero else.
605 ** For now we assume that filename and pathname are at
606 ** least MAXPATHLEN chars long.
607 ** To skip setting filename or pathname pass NULL for that argument.
609 -int
610 -ParseFilename(const char *fullname, char *filename, char *pathname)
611 +int ParseFilename(const char *fullname, char *filename, char *pathname,
612 + const char *relpath)
614 int fullLen = strlen(fullname);
615 int i, pathLen, fileLen;
617 #ifdef VMS
618 @@ -136,11 +136,11 @@ ParseFilename(const char *fullname, char
619 filename[fileLen] = 0;
622 #ifndef VMS /* UNIX specific... Modify at a later date for VMS */
623 if(pathname) {
624 - if (NormalizePathname(pathname)) {
625 + if (NormalizePathname(pathname, relpath)) {
626 return 1; /* pathname too long */
628 pathLen = strlen(pathname);
630 #endif
631 @@ -269,11 +269,11 @@ ResolvePath(const char * pathIn, char *
633 strcpy(pathEnd+1, resolveBuf);
634 } else {
635 strcpy(pathBuf, resolveBuf);
637 - NormalizePathname(pathBuf);
638 + NormalizePathname(pathBuf, NULL);
639 pathIn=pathBuf;
642 return FALSE;
643 #endif /* NO_READLINK */
644 @@ -285,27 +285,29 @@ ResolvePath(const char * pathIn, char *
645 ** Capable to handle arbitrary path length (>MAXPATHLEN)!
647 ** FIXME: Documentation
648 ** FIXME: Change return value to False and True.
650 -int NormalizePathname(char *pathname)
651 +int NormalizePathname(char *pathname, const char *relpath)
653 - /* if this is a relative pathname, prepend current directory */
654 + /* if this is a relative pathname, prepend relpath */
655 + /* if relpath is a relative path, prepend the current directory */
656 #ifdef __EMX__
657 /* OS/2, ...: welcome to the world of drive letters ... */
658 if (!_fnisabs(pathname)) {
659 #else
660 if (pathname[0] != '/') {
661 #endif
662 char *oldPathname;
663 size_t len;
664 + int useRelpath = (relpath && *relpath);
666 /* make a copy of pathname to work from */
667 oldPathname=(char *)malloc(strlen(pathname)+1);
668 strcpy(oldPathname, pathname);
669 /* get the working directory and prepend to the path */
670 - strcpy(pathname, GetCurrentDir());
671 + strcpy(pathname, useRelpath ? relpath : GetCurrentDir());
673 /* check for trailing slash, or pathname being root dir "/":
674 don't add a second '/' character as this may break things
675 on non-un*x systems */
676 len = strlen(pathname); /* GetCurrentDir() returns non-NULL value */
677 @@ -318,10 +320,18 @@ int NormalizePathname(char *pathname)
679 strcat(pathname, "/");
681 strcat(pathname, oldPathname);
682 free(oldPathname);
683 + if (useRelpath)
685 + /* make sure our relative path wasn't relative to start with */
686 + if (CompressPathname(pathname) == 0)
687 + return NormalizePathname(pathname, NULL);
688 + else
689 + return 1; /* some non-zero value */
693 /* compress out .. and . */
694 return CompressPathname(pathname);
696 @@ -470,11 +480,11 @@ copyThruSlash(char **toString, char **fr
700 ** Return 0 if everything's fine, 1 else.
702 -int NormalizePathname(char *pathname)
703 +int NormalizePathname(char *pathname, const char *relpath)
705 return 0;
709 diff --quilt old/util/fileUtils.h new/util/fileUtils.h
710 --- old/util/fileUtils.h
711 +++ new/util/fileUtils.h
712 @@ -28,15 +28,16 @@
713 #ifndef NEDIT_FILEUTILS_H_INCLUDED
714 #define NEDIT_FILEUTILS_H_INCLUDED
716 enum fileFormats {UNIX_FILE_FORMAT, DOS_FILE_FORMAT, MAC_FILE_FORMAT};
718 -int ParseFilename(const char *fullname, char *filename, char *pathname);
719 +int ParseFilename(const char *fullname, char *filename, char *pathname,
720 + const char *relpath);
721 int ExpandTilde(char *pathname);
722 const char* GetTrailingPathComponents(const char* path,
723 int noOfComponents);
724 -int NormalizePathname(char *pathname);
725 +int NormalizePathname(char *pathname, const char *relpath);
726 int CompressPathname(char *pathname);
727 int ResolvePath(const char * pathIn, char * pathResolved);
729 int FormatOfFile(const char *fileString);
730 void ConvertFromDosFileString(char *inString, int *length,
731 diff --quilt old/util/getfiles.c new/util/getfiles.c
732 --- old/util/getfiles.c
733 +++ new/util/getfiles.c
734 @@ -1022,11 +1022,11 @@ static void listCharEH(Widget w, XtPoint
735 /* compare them with the accumulated user keystrokes & decide the
736 appropriate line in the list widget to select */
737 selectPos = 0;
738 for (i=0; i<nItems; i++) {
739 XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &itemString);
740 - if (ParseFilename(itemString, name, path) != 0) {
741 + if (ParseFilename(itemString, name, path, NULL) != 0) {
742 XtFree(itemString);
743 return;
745 XtFree(itemString);
746 cmp = strncmp(name, keystrokes, nKeystrokes);