Program memory leaks
[nedit-bw.git] / relativeFileNormalization.diff
blob0a2f8e75c4dee2060e6f8a7d1fb79479ffbee645
1 From: Tony Balinski <ajbj@free.fr>
2 Subject: Allow NormalizePathname() and ParseFilename() to use windows path
4 Various operations require the extension of an incomplete file specification
5 to a full, absolute path. Before this patch, this completion uses the
6 current directory of the NEdit process as the base for relative file lookup.
7 However, this works against NEdit's file dialogs and shell processing which
8 start off in the directory of the current document, which may well not be
9 the same as the process' directory. Using "File > Open Selected" may not, in
10 this situation, find the file you would expect.
12 This patch alters NormalizePathname() and ParseFilename(), the utility
13 functions that perform the expansion so that the base for relative file
14 specifications can be passed, then changes all relevant calls to supply the
15 current window's file path value. It includes the nmReadWriteRelToWin.diff
16 adjustments to macro file functions read_file(), write_file() and
17 append_file() for this same behaviour, and adds a new one, full_file_name(),
18 which provides the macro writer with a way of obtaining the relative file
19 name from a relative file path.
21 ---
23 source/file.c | 8 +--
24 source/macro.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++--
25 source/menu.c | 6 +-
26 source/nc.c | 4 -
27 source/nedit.c | 4 -
28 source/selection.c | 10 ++--
29 source/server.c | 2
30 source/tags.c | 22 ++++-----
31 util/fileUtils.c | 26 ++++++++---
32 util/fileUtils.h | 5 +-
33 util/getfiles.c | 2
34 11 files changed, 164 insertions(+), 42 deletions(-)
36 diff --quilt old/source/file.c new/source/file.c
37 --- old/source/file.c
38 +++ new/source/file.c
39 @@ -1089,20 +1089,20 @@ int SaveWindowAs(WindowInfo *window, con
40 } else
42 strcpy(fullname, newName);
45 - if (1 == NormalizePathname(fullname))
46 + if (1 == NormalizePathname(fullname, window->path))
48 return False;
51 /* Add newlines if requested */
52 if (addWrap)
53 addWrapNewlines(window);
55 - if (ParseFilename(fullname, filename, pathname) != 0) {
56 + if (ParseFilename(fullname, filename, pathname, window->path) != 0) {
57 return FALSE;
60 /* If the requested file is this file, just save it and return */
61 if (!strcmp(window->filename, filename) &&
62 @@ -1183,11 +1183,11 @@ static int doSave(WindowInfo *window)
63 /* call the "pre_save_hook", if the macro returns a string, interpret this
64 as the new filename */
65 success = MacroApplyHook(window, "pre_save_hook", 0, NULL, &hookResult);
66 if (success && hookResult.tag == STRING_TAG) {
67 if (ParseFilename(hookResult.val.str.rep,
68 - window->filename, window->path)) {
69 + window->filename, window->path, window->path)) {
70 return FALSE;
74 /* Get the full name of the file */
75 @@ -1303,11 +1303,11 @@ static int doSave(WindowInfo *window)
76 /* free the text buffer copy returned from XmTextGetString */
77 XtFree(fileString);
79 #ifdef VMS
80 /* reflect the fact that NEdit is now editing a new version of the file */
81 - ParseFilename(fullname, window->filename, window->path);
82 + ParseFilename(fullname, window->filename, window->path, NULL);
83 #endif /*VMS*/
85 /* success, file was written */
86 SetWindowModified(window, FALSE);
88 diff --quilt old/source/macro.c new/source/macro.c
89 --- old/source/macro.c
90 +++ new/source/macro.c
91 @@ -192,10 +192,12 @@ static int validNumberMS(WindowInfo *win
92 DataValue *result, char **errMsg);
93 static int replaceInStringMS(WindowInfo *window, DataValue *argList, int nArgs,
94 DataValue *result, char **errMsg);
95 static int replaceSubstringMS(WindowInfo *window, DataValue *argList, int nArgs,
96 DataValue *result, char **errMsg);
97 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
98 + DataValue *result, char **errMsg);
99 static int readFileMS(WindowInfo *window, DataValue *argList, int nArgs,
100 DataValue *result, char **errMsg);
101 static int writeFileMS(WindowInfo *window, DataValue *argList, int nArgs,
102 DataValue *result, char **errMsg);
103 static int appendFileMS(WindowInfo *window, DataValue *argList, int nArgs,
104 @@ -537,10 +539,11 @@ static const BuiltInSubrName MacroSubrs[
105 { "to_column", toColumnMS },
106 { "set_window_title", setWindowTitleMS },
107 { "timer_add", timerAddMS },
108 { "timer_remove", timerRemoveMS },
109 { "escape_literal", escapeLiteralMS },
110 + { "full_file_name", fullFileNameMS },
111 { NULL, NULL } /* sentinel */
114 static const BuiltInSubrName SpecialVars[] = {
115 { "$cursor", cursorMV },
116 @@ -1969,11 +1972,11 @@ static int focusWindowMS(WindowInfo *win
118 /* didn't work? try normalizing the string passed in */
119 if (w == NULL) {
120 strncpy(normalizedString, string, MAXPATHLEN);
121 normalizedString[MAXPATHLEN-1] = '\0';
122 - if (1 == NormalizePathname(normalizedString)) {
123 + if (1 == NormalizePathname(normalizedString, window->path)) {
124 /* Something is broken with the input pathname. */
125 *errMsg = "Pathname too long in focus_window()";
126 return False;
128 for (w=WindowList; w != NULL; w = w->next) {
129 @@ -2405,10 +2408,112 @@ static int clipboardToStringMS(WindowInf
130 result->val.str.len = retLength;
132 return True;
136 +** Resolve the partial file path in name with respect to path.
137 +** (We don't use NormalizePathname() since this modifies its path in place.)
139 +static char *convFilePathToAbsolute(const char *path, char *name)
141 + static char *nameText = NULL, *ptr;
142 + static size_t nameTextLen = 0;
143 + size_t namelen, pathlen, len;
144 + Bool isRelative = False;
145 + size_t needSlash = 0;
147 + if (!path || !path[0] || strcmp(path, ".") == 0)
148 + path = GetCurrentDir();
150 +#ifdef VMS
151 + /* If path name is relative, make it refer to current window's directory;
152 + absolute paths start with a logical name ([\w$]+) followed by a colon,
153 + or with a non-relative path in brackets (not starting with . or -)
154 + */
155 + isRelative = ((strchr(name, ':') == NULL) && (strlen(name) > 1) &&
156 + !((name[0] == '[') && (name[1] != '-') &&
157 + (name[1] != '.')));
158 +#else
159 + /* UNIX-like:
160 + Any path starting without a "/" is considered relative; if the first
161 + character is "~", we really need the user's home directory */
162 + if (name[0] == '~' && name[1] == '/') {
163 + path = GetHomeDir();
164 + for (++name; *name == '/'; ++name)
165 + continue; /* skip slash(es) following initial tilde */
166 + isRelative = True;
168 + else
169 + isRelative = (name[0] != '/');
170 +#endif
172 + if (!isRelative)
173 + return name;
175 + namelen = strlen(name);
176 + pathlen = strlen(path);
178 +#ifndef VMS
179 + needSlash = (path && pathlen && path[pathlen - 1] != '/') ? 1 : 0;
180 +#endif
182 + /* make sure the buffer's big enough */
183 + len = namelen + pathlen + needSlash;
185 + if (nameTextLen < len) {
186 + ptr = realloc(nameText, len + 1);
187 + if (!ptr)
188 + return NULL;
189 + nameText = ptr;
190 + nameTextLen = len;
193 + /* copy in pieces */
194 + strcpy(nameText, path);
195 + if (needSlash)
196 + nameText[pathlen] = '/';
197 + strcpy(nameText + pathlen + needSlash, name);
199 + CompressPathname(nameText);
201 + return nameText;
205 +** Built-in macro subroutine for expanding a possibly partial file specification
206 +** to a full one, using the current window's directory as a base for relative
207 +** path specifications. It does not check for file/path validity.
209 +static int fullFileNameMS(WindowInfo *window, DataValue *argList, int nArgs,
210 + DataValue *result, char **errMsg)
212 + char stringStorage[TYPE_INT_STR_SIZE(int)], *name;
213 + size_t len;
215 + /* Validate arguments and convert to int */
216 + if (nArgs != 1)
217 + return wrongNArgsErr(errMsg);
218 + if (!readStringArg(argList[0], &name, stringStorage, errMsg))
219 + return False;
221 + name = convFilePathToAbsolute(window->path, name);
222 + len = strlen(name);
224 + if (name) {
225 + result->tag = STRING_TAG;
226 + AllocNString(&result->val.str, len + 1);
227 + strcpy(result->val.str.rep, name);
229 + else {
230 + result->tag = STRING_TAG;
231 + result->val.str.rep = PERM_ALLOC_STR("");
232 + result->val.str.len = 0;
235 + return True;
239 ** Built-in macro subroutine for reading the contents of a text file into
240 ** a string. On success, returns 1 in $readStatus, and the contents of the
241 ** file as a string in the subroutine return value. On failure, returns
242 @@ -2425,11 +2530,13 @@ static int readFileMS(WindowInfo *window
243 /* Validate arguments and convert to int */
244 if (nArgs != 1)
245 return wrongNArgsErr(errMsg);
246 if (!readStringArg(argList[0], &name, stringStorage, errMsg))
247 return False;
250 + name = convFilePathToAbsolute(window->path, name);
252 /* Read the whole file into an allocated string */
253 if ((fp = fopen(name, "r")) == NULL)
254 goto errorNoClose;
255 if (fstat(fileno(fp), &statbuf) != 0)
256 goto error;
257 @@ -2504,11 +2611,13 @@ static int writeOrAppendFile(int append,
258 return wrongNArgsErr(errMsg);
259 if (!readStringArg(argList[0], &string, stringStorage[1], errMsg))
260 return False;
261 if (!readStringArg(argList[1], &name, stringStorage[0], errMsg))
262 return False;
265 + name = convFilePathToAbsolute(window->path, name);
267 /* open the file */
268 if ((fp = fopen(name, append ? "a" : "w")) == NULL) {
269 result->tag = INT_TAG;
270 result->val.n = False;
271 return True;
272 @@ -5183,11 +5292,11 @@ static int neditHomeMV(WindowInfo *windo
273 DataValue *result, char **errMsg)
275 const char *neditRCName = GetRCFileName(NEDIT_RC);
276 char neditHome[MAXPATHLEN];
278 - if (0 != ParseFilename(neditRCName, NULL, neditHome)) {
279 + if (0 != ParseFilename(neditRCName, NULL, neditHome, NULL)) {
280 M_FAILURE("Unable to parse path of nedit.rc in %s");
283 result->tag = STRING_TAG;
284 AllocNStringCpy(&result->val.str, neditHome);
285 diff --quilt old/source/menu.c new/source/menu.c
286 --- old/source/menu.c
287 +++ new/source/menu.c
288 @@ -2974,11 +2974,11 @@ static void openAP(Widget w, XEvent *eve
289 fileNameToOpen = resultDV.val.str.rep;
290 } else {
291 fileNameToOpen = args[0];
294 - if (0 != ParseFilename(fileNameToOpen, filename, pathname)
295 + if (0 != ParseFilename(fileNameToOpen, filename, pathname, window->path)
296 || strlen(filename) + strlen(pathname) > MAXPATHLEN - 1) {
297 fprintf(stderr, "nedit: invalid file name for open action: %s\n",
298 fileNameToOpen);
299 return;
301 @@ -5025,11 +5025,11 @@ static void updatePrevOpenMenu(WindowInf
302 if (index >= NPrevOpen) {
303 /* unmanaging before destroying stops parent from displaying */
304 XtUnmanageChild(items[n]);
305 XtDestroyWidget(items[n]);
306 } else {
307 - ParseFilename(prevOpenSorted[index], filename, pathname);
308 + ParseFilename(prevOpenSorted[index], filename, pathname, NULL);
309 fileIsOpen = !!FindWindowWithFile(filename, pathname);
310 XtVaSetValues(items[n],
311 XmNlabelString, st1=XmStringCreateSimple(prevOpenSorted[index]),
312 XmNset, fileIsOpen,
313 NULL);
314 @@ -5041,11 +5041,11 @@ static void updatePrevOpenMenu(WindowInf
318 /* Add new items for the remaining file names to the menu */
319 for (; index<NPrevOpen; index++) {
320 - ParseFilename(prevOpenSorted[index], filename, pathname);
321 + ParseFilename(prevOpenSorted[index], filename, pathname, NULL);
322 fileIsOpen = !!FindWindowWithFile(filename, pathname);
323 btn = XtVaCreateManagedWidget("win", xmToggleButtonWidgetClass,
324 window->prevOpenMenuPane,
325 XmNlabelString, st1=XmStringCreateSimple(prevOpenSorted[index]),
326 XmNmarginHeight, 0,
327 diff --quilt old/source/nc.c new/source/nc.c
328 --- old/source/nc.c
329 +++ new/source/nc.c
330 @@ -712,11 +712,11 @@ static void parseCommandLine(int argc, c
331 newCommandString = XtMalloc(oldLength+length+1);
332 strncpy(newCommandString, commandString, oldLength);
333 XtFree(commandString);
334 commandString = newCommandString;
335 outPtr = newCommandString + oldLength;
336 - if (ParseFilename(nameList[j], name, path) != 0) {
337 + if (ParseFilename(nameList[j], name, path, NULL) != 0) {
338 /* An Error, most likely too long paths/strings given */
339 commandLine->serverRequest = NULL;
340 return;
342 strcat(path, name);
343 @@ -748,11 +748,11 @@ static void parseCommandLine(int argc, c
344 fileCount++;
346 if (nameList != NULL)
347 free(nameList);
348 #else
349 - if (ParseFilename(argv[i], name, path) != 0) {
350 + if (ParseFilename(argv[i], name, path, NULL) != 0) {
351 /* An Error, most likely too long paths/strings given */
352 commandLine->serverRequest = NULL;
353 return;
355 strcat(path, name);
356 diff --quilt old/source/nedit.c new/source/nedit.c
357 --- old/source/nedit.c
358 +++ new/source/nedit.c
359 @@ -658,11 +658,11 @@ int main(int argc, char **argv)
360 /* Use VMS's LIB$FILESCAN for filename in argv[i] to process */
361 /* wildcards and to obtain a full VMS file specification */
362 numFiles = VMSFileScan(argv[i], &nameList, NULL, INCLUDE_FNF);
363 /* for each expanded file name do: */
364 for (j = 0; j < numFiles; ++j) {
365 - if (ParseFilename(nameList[j], filename, pathname) == 0) {
366 + if (ParseFilename(nameList[j], filename, pathname, NULL) == 0) {
367 /* determine if file is to be openned in new tab, by
368 factoring the options -group, -tabbed & -untabbed */
369 if (group == 2) {
370 isTabbed = 0; /* start a new window for new group */
371 group = 1; /* next file will be within group */
372 @@ -713,11 +713,11 @@ int main(int argc, char **argv)
373 free(nameList[j]);
375 if (nameList != NULL)
376 free(nameList);
377 #else
378 - if (ParseFilename(argv[i], filename, pathname) == 0 ) {
379 + if (ParseFilename(argv[i], filename, pathname, NULL) == 0 ) {
380 /* determine if file is to be openned in new tab, by
381 factoring the options -group, -tabbed & -untabbed */
382 if (group == 2) {
383 isTabbed = 0; /* start a new window for new group */
384 group = 1; /* next file will be within group */
385 diff --quilt old/source/selection.c new/source/selection.c
386 --- old/source/selection.c
387 +++ new/source/selection.c
388 @@ -326,21 +326,21 @@ static void fileCB(Widget widget, Window
389 names, in these cases, either don't expand names, or try to use the
390 Motif internal parsing routine _XmOSGetDirEntries, which is not
391 guranteed to be available, but in practice is there and does work. */
392 #if defined(DONT_HAVE_GLOB) || defined(VMS)
393 /* Open the file */
394 - if (ParseFilename(nameText, filename, pathname) != 0) {
395 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
396 XBell(TheDisplay, 0);
397 return;
399 EditExistingFile(window, filename,
400 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(), False);
401 #elif defined(USE_MOTIF_GLOB)
402 { char **nameList = NULL;
403 int i, nFiles = 0, maxFiles = 30;
405 - if (ParseFilename(nameText, filename, pathname) != 0) {
406 + if (ParseFilename(nameText, filename, pathname, window->path) != 0) {
407 XBell(TheDisplay, 0);
408 return;
410 _XmOSGetDirEntries(pathname, filename, XmFILE_ANY_TYPE, False, True,
411 &nameList, &nFiles, &maxFiles);
412 @@ -360,11 +360,12 @@ static void fileCB(Widget widget, Window
413 fileNameToOpen = resultDV.val.str.rep;
414 } else {
415 fileNameToOpen = nameList[i];
418 - if (ParseFilename(fileNameToOpen, filename, pathname) != 0) {
419 + if (ParseFilename(fileNameToOpen, filename, pathname,
420 + window->path) != 0) {
421 XBell(TheDisplay, 0);
422 } else {
423 EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
424 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
425 False);
426 @@ -397,11 +398,12 @@ static void fileCB(Widget widget, Window
427 fileNameToOpen = resultDV.val.str.rep;
428 } else {
429 fileNameToOpen = globbuf.gl_pathv[i];
432 - if (ParseFilename(fileNameToOpen, filename, pathname) != 0) {
433 + if (ParseFilename(fileNameToOpen, filename, pathname,
434 + window->path) != 0) {
435 XBell(TheDisplay, 0);
436 } else {
437 EditExistingFile(GetPrefOpenInTab() ? window : NULL, filename,
438 pathname, 0, NULL, False, NULL, GetPrefOpenInTab(),
439 False);
440 diff --quilt old/source/server.c new/source/server.c
441 --- old/source/server.c
442 +++ new/source/server.c
443 @@ -454,11 +454,11 @@ static void processServerCommandString(c
445 /* Process the filename by looking for the files in an
446 existing window, or opening if they don't exist */
447 editFlags = (readFlag ? PREF_READ_ONLY : 0) | CREATE |
448 (createFlag ? SUPPRESS_CREATE_WARN : 0);
449 - if (ParseFilename(fullname, filename, pathname) != 0) {
450 + if (ParseFilename(fullname, filename, pathname, NULL) != 0) {
451 fprintf(stderr, "NEdit: invalid file name\n");
452 deleteFileClosedProperty2(filename, pathname);
453 break;
456 diff --quilt old/source/tags.c new/source/tags.c
457 --- old/source/tags.c
458 +++ new/source/tags.c
459 @@ -252,22 +252,22 @@ static int addTag(const char *name, cons
460 if (*file == '/')
461 strcpy(newfile,file);
462 else
463 sprintf(newfile,"%s%s", path, file);
465 - NormalizePathname(newfile);
466 + NormalizePathname(newfile, NULL);
468 for (t = table[addr]; t; t = t->next) {
469 if (strcmp(name,t->name)) continue;
470 if (lang != t->language) continue;
471 if (strcmp(search,t->searchString)) continue;
472 if (posInf != t->posInf) continue;
473 if (*t->file == '/' && strcmp(newfile,t->file)) continue;
474 if (*t->file != '/') {
475 char tmpfile[MAXPATHLEN];
476 sprintf(tmpfile, "%s%s", t->path, t->file);
477 - NormalizePathname(tmpfile);
478 + NormalizePathname(tmpfile, NULL);
479 if (strcmp(newfile, tmpfile)) continue;
481 return 0;
484 @@ -363,11 +363,11 @@ int AddRelTagsFile(const char *tagSpec,
485 } else {
486 strcpy(pathName, GetCurrentDir());
488 strcat(pathName, "/");
489 strcat(pathName, filename);
490 - NormalizePathname(pathName);
491 + NormalizePathname(pathName, NULL);
493 for (t = FileList; t && strcmp(t->filename, pathName); t = t->next);
494 if (t) {
495 added=1;
496 continue;
497 @@ -431,11 +431,11 @@ int AddTagsFile(const char *tagSpec, int
498 strcat(pathName,"/");
499 strcat(pathName,filename);
500 } else {
501 strcpy(pathName,filename);
503 - NormalizePathname(pathName);
504 + NormalizePathname(pathName, NULL);
506 for (t = FileList; t && strcmp(t->filename,pathName); t = t->next);
507 if (t) {
508 /* This file is already in the list. It's easiest to just
509 refcount all tag/tip files even though we only actually care
510 @@ -502,11 +502,11 @@ int DeleteTagsFile(const char *tagSpec,
511 strcat(pathName,"/");
512 strcat(pathName,filename);
513 } else {
514 strcpy(pathName,filename);
516 - NormalizePathname(pathName);
517 + NormalizePathname(pathName, NULL);
519 for (last=NULL,t = FileList; t; last = t,t = t->next) {
520 if (strcmp(t->filename, pathName))
521 continue;
522 /* Don't unload tips files with nonzero refcounts unless forced */
523 @@ -732,11 +732,11 @@ static int loadTagsFile(const char *tags
524 /* Open the file */
525 if ((fp = fopen(resolvedTagsFile, "r")) == NULL) {
526 return 0;
529 - ParseFilename(resolvedTagsFile, NULL, tagPath);
530 + ParseFilename(resolvedTagsFile, NULL, tagPath, NULL);
532 /* Read the file and store its contents */
533 while (fgets(line, MAXLINE, fp)) {
535 /* This might take a while if you have a huge tags file (like I do)..
536 @@ -1145,11 +1145,11 @@ static int findAllMatches(WindowInfo *wi
537 strcpy(tagFiles[nMatches], fileToSearch);
538 else
539 sprintf(tagFiles[nMatches],"%s%s",tagPath,fileToSearch);
540 strcpy(tagSearch[nMatches],searchString);
541 tagPosInf[nMatches]=startPos;
542 - ParseFilename(tagFiles[nMatches], filename, pathname);
543 + ParseFilename(tagFiles[nMatches], filename, pathname, NULL);
544 /* Is this match in the current file? If so, use it! */
545 if (GetPrefSmartTags() && !strcmp(window->filename,filename)
546 && !strcmp(window->path,pathname) ) {
547 if (nMatches) {
548 strcpy(tagFiles[0],tagFiles[nMatches]);
549 @@ -1202,11 +1202,11 @@ static int findAllMatches(WindowInfo *wi
550 XBell(TheDisplay, 0);
551 return -1;
554 for (i=0; i<nMatches; i++) {
555 - ParseFilename(tagFiles[i], filename, pathname);
556 + ParseFilename(tagFiles[i], filename, pathname, NULL);
557 if ((i<nMatches-1 && !strcmp(tagFiles[i],tagFiles[i+1])) ||
558 (i>0 && !strcmp(tagFiles[i],tagFiles[i-1]))) {
559 if(*(tagSearch[i]) && (tagPosInf[i] != -1)) { /* etags */
560 sprintf(temp,"%2d. %s%s %8i %s", i+1, pathname,
561 filename, tagPosInf[i], tagSearch[i]);
562 @@ -1324,11 +1324,11 @@ static void showMatchingCalltip( Widget
563 FILE *fp;
564 struct stat statbuf;
565 char *message;
567 /* 1. Open the target file */
568 - NormalizePathname(tagFiles[i]);
569 + NormalizePathname(tagFiles[i], NULL);
570 fp = fopen(tagFiles[i], "r");
571 if (fp == NULL) {
572 DialogF(DF_ERR, parent, 1, "Error opening File", "Error opening %s",
573 "OK", tagFiles[i]);
574 return;
575 @@ -1443,11 +1443,11 @@ static void editTaggedLocation( Widget p
576 int startPos, endPos, lineNum, rows;
577 char filename[MAXPATHLEN], pathname[MAXPATHLEN];
578 WindowInfo *windowToSearch;
579 WindowInfo *parentWindow = WidgetToWindow(parent);
581 - ParseFilename(tagFiles[i],filename,pathname);
582 + ParseFilename(tagFiles[i], filename, pathname, NULL);
583 /* open the file containing the definition */
584 EditExistingFile(parentWindow, filename, pathname, 0, NULL, False,
585 NULL, GetPrefOpenInTab(), False);
586 windowToSearch = FindWindowWithFile(filename, pathname);
587 if (windowToSearch == NULL) {
588 @@ -1990,11 +1990,11 @@ static int loadTipsFile(const char *tips
589 if(!ResolvePath(tipsFile, resolvedTipsFile))
590 return 0;
591 #endif
593 /* Get the path to the tips file */
594 - ParseFilename(resolvedTipsFile, NULL, tipPath);
595 + ParseFilename(resolvedTipsFile, NULL, tipPath, NULL);
597 /* Open the file */
598 if ((fp = fopen(resolvedTipsFile, "r")) == NULL)
599 return 0;
601 diff --quilt old/util/fileUtils.c new/util/fileUtils.c
602 --- old/util/fileUtils.c
603 +++ new/util/fileUtils.c
604 @@ -86,12 +86,12 @@ static void copyThruSlash(char **toStrin
605 ** Return non-zero value if it fails, zero else.
606 ** For now we assume that filename and pathname are at
607 ** least MAXPATHLEN chars long.
608 ** To skip setting filename or pathname pass NULL for that argument.
610 -int
611 -ParseFilename(const char *fullname, char *filename, char *pathname)
612 +int ParseFilename(const char *fullname, char *filename, char *pathname,
613 + const char *relpath)
615 int fullLen = strlen(fullname);
616 int i, pathLen, fileLen;
618 #ifdef VMS
619 @@ -136,11 +136,11 @@ ParseFilename(const char *fullname, char
620 filename[fileLen] = 0;
623 #ifndef VMS /* UNIX specific... Modify at a later date for VMS */
624 if(pathname) {
625 - if (NormalizePathname(pathname)) {
626 + if (NormalizePathname(pathname, relpath)) {
627 return 1; /* pathname too long */
629 pathLen = strlen(pathname);
631 #endif
632 @@ -269,11 +269,11 @@ ResolvePath(const char * pathIn, char *
634 strcpy(pathEnd+1, resolveBuf);
635 } else {
636 strcpy(pathBuf, resolveBuf);
638 - NormalizePathname(pathBuf);
639 + NormalizePathname(pathBuf, NULL);
640 pathIn=pathBuf;
643 return FALSE;
644 #endif /* NO_READLINK */
645 @@ -285,27 +285,29 @@ ResolvePath(const char * pathIn, char *
646 ** Capable to handle arbitrary path length (>MAXPATHLEN)!
648 ** FIXME: Documentation
649 ** FIXME: Change return value to False and True.
651 -int NormalizePathname(char *pathname)
652 +int NormalizePathname(char *pathname, const char *relpath)
654 - /* if this is a relative pathname, prepend current directory */
655 + /* if this is a relative pathname, prepend relpath */
656 + /* if relpath is a relative path, prepend the current directory */
657 #ifdef __EMX__
658 /* OS/2, ...: welcome to the world of drive letters ... */
659 if (!_fnisabs(pathname)) {
660 #else
661 if (pathname[0] != '/') {
662 #endif
663 char *oldPathname;
664 size_t len;
665 + int useRelpath = (relpath && *relpath);
667 /* make a copy of pathname to work from */
668 oldPathname=(char *)malloc(strlen(pathname)+1);
669 strcpy(oldPathname, pathname);
670 /* get the working directory and prepend to the path */
671 - strcpy(pathname, GetCurrentDir());
672 + strcpy(pathname, useRelpath ? relpath : GetCurrentDir());
674 /* check for trailing slash, or pathname being root dir "/":
675 don't add a second '/' character as this may break things
676 on non-un*x systems */
677 len = strlen(pathname); /* GetCurrentDir() returns non-NULL value */
678 @@ -318,10 +320,18 @@ int NormalizePathname(char *pathname)
680 strcat(pathname, "/");
682 strcat(pathname, oldPathname);
683 free(oldPathname);
684 + if (useRelpath)
686 + /* make sure our relative path wasn't relative to start with */
687 + if (CompressPathname(pathname) == 0)
688 + return NormalizePathname(pathname, NULL);
689 + else
690 + return 1; /* some non-zero value */
694 /* compress out .. and . */
695 return CompressPathname(pathname);
697 @@ -470,11 +480,11 @@ copyThruSlash(char **toString, char **fr
701 ** Return 0 if everything's fine, 1 else.
703 -int NormalizePathname(char *pathname)
704 +int NormalizePathname(char *pathname, const char *relpath)
706 return 0;
710 diff --quilt old/util/fileUtils.h new/util/fileUtils.h
711 --- old/util/fileUtils.h
712 +++ new/util/fileUtils.h
713 @@ -28,15 +28,16 @@
714 #ifndef NEDIT_FILEUTILS_H_INCLUDED
715 #define NEDIT_FILEUTILS_H_INCLUDED
717 enum fileFormats {UNIX_FILE_FORMAT, DOS_FILE_FORMAT, MAC_FILE_FORMAT};
719 -int ParseFilename(const char *fullname, char *filename, char *pathname);
720 +int ParseFilename(const char *fullname, char *filename, char *pathname,
721 + const char *relpath);
722 int ExpandTilde(char *pathname);
723 const char* GetTrailingPathComponents(const char* path,
724 int noOfComponents);
725 -int NormalizePathname(char *pathname);
726 +int NormalizePathname(char *pathname, const char *relpath);
727 int CompressPathname(char *pathname);
728 int ResolvePath(const char * pathIn, char * pathResolved);
730 int FormatOfFile(const char *fileString);
731 void ConvertFromDosFileString(char *inString, int *length,
732 diff --quilt old/util/getfiles.c new/util/getfiles.c
733 --- old/util/getfiles.c
734 +++ new/util/getfiles.c
735 @@ -1022,11 +1022,11 @@ static void listCharEH(Widget w, XtPoint
736 /* compare them with the accumulated user keystrokes & decide the
737 appropriate line in the list widget to select */
738 selectPos = 0;
739 for (i=0; i<nItems; i++) {
740 XmStringGetLtoR(items[i], XmSTRING_DEFAULT_CHARSET, &itemString);
741 - if (ParseFilename(itemString, name, path) != 0) {
742 + if (ParseFilename(itemString, name, path, NULL) != 0) {
743 XtFree(itemString);
744 return;
746 XtFree(itemString);
747 cmp = strncmp(name, keystrokes, nKeystrokes);