summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2016-04-08 15:17:39 +0000
committerManolo Gouy <Manolo>2016-04-08 15:17:39 +0000
commit62952ea2952768d922e2c93bcaa67e05c419f5a3 (patch)
tree3dcd142b3e57409079e86a3535c16a68567addc4
parent19b98e40de481349f88c02883a2330ed19ccd316 (diff)
Rewrite filename_absolute.cxx for the driver model.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11554 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--FL/Fl_System_Driver.H6
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.H2
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx128
-rw-r--r--src/filename_absolute.cxx113
4 files changed, 166 insertions, 83 deletions
diff --git a/FL/Fl_System_Driver.H b/FL/Fl_System_Driver.H
index 12e0f5f1d..03364e2f4 100644
--- a/FL/Fl_System_Driver.H
+++ b/FL/Fl_System_Driver.H
@@ -98,10 +98,14 @@ public:
virtual int get_key(int k) {return 0;}
// implement scandir-like function
virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {return -1;}
- // the default implementation of filename_expand may be enough
+ // the default implementation of filename_expand() may be enough
virtual int filename_expand(char *to, int tolen, const char *from);
// to implement
virtual const char *getpwnam(const char *login) {return NULL;}
+ // the default implementation of filename_relative() is in src/filename_absolute.cxx and may be enough
+ virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
+ // the default implementation of filename_absolute() is in src/filename_absolute.cxx and may be enough
+ virtual int filename_absolute(char *to, int tolen, const char *from);
};
#endif // FL_SYSTEM_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
index 75fdbc860..cd7e03c50 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.H
@@ -70,6 +70,8 @@ public:
virtual int get_key(int k);
virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
virtual int filename_expand(char *to,int tolen, const char *from);
+ virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
+ virtual int filename_absolute(char *to, int tolen, const char *from);
};
#endif // FL_WINAPI_SYSTEM_DRIVER_H
diff --git a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
index cbd5f9081..6d32b4f6b 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_System_Driver.cxx
@@ -486,6 +486,134 @@ int Fl_WinAPI_System_Driver::filename_expand(char *to,int tolen, const char *fro
return ret;
}
+int // O - 0 if no change, 1 if changed
+Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename
+ int tolen, // I - Size of "to" buffer
+ const char *from, // I - Absolute filename
+ const char *base) // I - Find path relative to this path
+{
+ char *newslash; // Directory separator
+ const char *slash; // Directory separator
+ char *cwd = 0L, *cwd_buf = 0L;
+ if (base) cwd = cwd_buf = strdup(base);
+
+ // return if "from" is not an absolute path
+ if (from[0] == '\0' ||
+ (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' &&
+ !isdirsep(from[2]))) {
+ strlcpy(to, from, tolen);
+ if (cwd_buf) free(cwd_buf);
+ return 0;
+ }
+
+ // return if "cwd" is not an absolute path
+ if (!cwd || cwd[0] == '\0' ||
+ (!isdirsep(*cwd) && !isalpha(*cwd) && cwd[1] != ':' &&
+ !isdirsep(cwd[2]))) {
+ strlcpy(to, from, tolen);
+ if (cwd_buf) free(cwd_buf);
+ return 0;
+ }
+
+ // convert all backslashes into forward slashes
+ for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\'))
+ *newslash = '/';
+
+ // test for the exact same string and return "." if so
+ if (!strcasecmp(from, cwd)) {
+ strlcpy(to, ".", tolen);
+ free(cwd_buf);
+ return (1);
+ }
+
+ // test for the same drive. Return the absolute path if not
+ if (tolower(*from & 255) != tolower(*cwd & 255)) {
+ // Not the same drive...
+ strlcpy(to, from, tolen);
+ free(cwd_buf);
+ return 0;
+ }
+
+ // compare the path name without the drive prefix
+ from += 2; cwd += 2;
+
+ // compare both path names until we find a difference
+ for (slash = from, newslash = cwd;
+ *slash != '\0' && *newslash != '\0';
+ slash ++, newslash ++)
+ if (isdirsep(*slash) && isdirsep(*newslash)) continue;
+ else if (tolower(*slash & 255) != tolower(*newslash & 255)) break;
+
+ // skip over trailing slashes
+ if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash)
+ &&(newslash==cwd || !isdirsep(newslash[-1])) )
+ newslash--;
+
+ // now go back to the first character of the first differing paths segment
+ while (!isdirsep(*slash) && slash > from) slash --;
+ if (isdirsep(*slash)) slash ++;
+
+ // do the same for the current dir
+ if (isdirsep(*newslash)) newslash --;
+ if (*newslash != '\0')
+ while (!isdirsep(*newslash) && newslash > cwd) newslash --;
+
+ // prepare the destination buffer
+ to[0] = '\0';
+ to[tolen - 1] = '\0';
+
+ // now add a "previous dir" sequence for every following slash in the cwd
+ while (*newslash != '\0') {
+ if (isdirsep(*newslash)) strlcat(to, "../", tolen);
+ newslash ++;
+ }
+
+ // finally add the differing path from "from"
+ strlcat(to, slash, tolen);
+
+ free(cwd_buf);
+ return 1;
+}
+
+int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
+ if (isdirsep(*from) || *from == '|' || from[1]==':') {
+ strlcpy(to, from, tolen);
+ return 0;
+ }
+ char *a;
+ char *temp = new char[tolen];
+ const char *start = from;
+ a = getcwd(temp, tolen);
+ if (!a) {
+ strlcpy(to, from, tolen);
+ delete[] temp;
+ return 0;
+ }
+ for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
+ if (isdirsep(*(a-1))) a--;
+ /* remove intermediate . and .. names: */
+ while (*start == '.') {
+ if (start[1]=='.' && isdirsep(start[2])) {
+ char *b;
+ for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/}
+ if (b < temp) break;
+ a = b;
+ start += 3;
+ } else if (isdirsep(start[1])) {
+ start += 2;
+ } else if (!start[1]) {
+ start ++; // Skip lone "."
+ break;
+ } else
+ break;
+ }
+ *a++ = '/';
+ strlcpy(a,start,tolen - (a - temp));
+ strlcpy(to, temp, tolen);
+ delete[] temp;
+ return 1;
+}
+
//
// End of "$Id$".
//
diff --git a/src/filename_absolute.cxx b/src/filename_absolute.cxx
index be1bb0888..7d96c6cbc 100644
--- a/src/filename_absolute.cxx
+++ b/src/filename_absolute.cxx
@@ -23,21 +23,12 @@
*/
#include <FL/filename.H>
-#include <FL/fl_utf8.h>
+#include <FL/Fl.H>
+#include <FL/Fl_System_Driver.H>
#include <stdlib.h>
#include "flstring.h"
-#include <ctype.h>
-#if defined(WIN32) && !defined(__CYGWIN__)
-# include <direct.h>
-#else
-# include <unistd.h>
-#endif
-#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
-inline int isdirsep(char c) {return c=='/' || c=='\\';}
-#else
-#define isdirsep(c) ((c)=='/')
-#endif
+inline int isdirsep(char c) {return c == '/';}
/** Makes a filename absolute from a relative filename.
\code
@@ -54,30 +45,25 @@ inline int isdirsep(char c) {return c=='/' || c=='\\';}
\return 0 if no change, non zero otherwise
*/
int fl_filename_absolute(char *to, int tolen, const char *from) {
- if (isdirsep(*from) || *from == '|'
-#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
- || from[1]==':'
-#endif
- ) {
+ return Fl::system_driver()->filename_absolute(to, tolen, from);
+}
+
+
+int Fl_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
+ if (isdirsep(*from) || *from == '|') {
strlcpy(to, from, tolen);
return 0;
}
-
char *a;
char *temp = new char[tolen];
const char *start = from;
-
a = fl_getcwd(temp, tolen);
if (!a) {
strlcpy(to, from, tolen);
delete[] temp;
return 0;
}
-#if defined(WIN32) || defined(__EMX__) && !defined(__CYGWIN__)
- for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
-#else
a = temp+strlen(temp);
-#endif
if (isdirsep(*(a-1))) a--;
/* remove intermediate . and .. names: */
while (*start == '.') {
@@ -95,14 +81,10 @@ int fl_filename_absolute(char *to, int tolen, const char *from) {
} else
break;
}
-
*a++ = '/';
strlcpy(a,start,tolen - (a - temp));
-
strlcpy(to, temp, tolen);
-
delete[] temp;
-
return 1;
}
@@ -151,113 +133,80 @@ fl_filename_relative(char *to, // O - Relative filename
int tolen, // I - Size of "to" buffer
const char *from, // I - Absolute filename
const char *base) { // I - Find path relative to this path
-
+ return Fl::system_driver()->filename_relative(to, tolen, from, base);
+}
+
+int // O - 0 if no change, 1 if changed
+Fl_System_Driver::filename_relative(char *to, // O - Relative filename
+ int tolen, // I - Size of "to" buffer
+ const char *from, // I - Absolute filename
+ const char *base) // I - Find path relative to this path
+{
char *newslash; // Directory separator
const char *slash; // Directory separator
char *cwd = 0L, *cwd_buf = 0L;
if (base) cwd = cwd_buf = strdup(base);
// return if "from" is not an absolute path
-#if defined(WIN32) || defined(__EMX__)
- if (from[0] == '\0' ||
- (!isdirsep(*from) && !isalpha(*from) && from[1] != ':' &&
- !isdirsep(from[2]))) {
-#else
if (from[0] == '\0' || !isdirsep(*from)) {
-#endif // WIN32 || __EMX__
strlcpy(to, from, tolen);
if (cwd_buf) free(cwd_buf);
return 0;
}
-
+
// return if "cwd" is not an absolute path
-#if defined(WIN32) || defined(__EMX__)
- if (!cwd || cwd[0] == '\0' ||
- (!isdirsep(*cwd) && !isalpha(*cwd) && cwd[1] != ':' &&
- !isdirsep(cwd[2]))) {
-#else
if (!cwd || cwd[0] == '\0' || !isdirsep(*cwd)) {
-#endif // WIN32 || __EMX__
strlcpy(to, from, tolen);
if (cwd_buf) free(cwd_buf);
return 0;
}
-
-#if defined(WIN32) || defined(__EMX__)
- // convert all backslashes into forward slashes
- for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\'))
- *newslash = '/';
-
- // test for the exact same string and return "." if so
- if (!strcasecmp(from, cwd)) {
- strlcpy(to, ".", tolen);
- free(cwd_buf);
- return (1);
- }
-
- // test for the same drive. Return the absolute path if not
- if (tolower(*from & 255) != tolower(*cwd & 255)) {
- // Not the same drive...
- strlcpy(to, from, tolen);
- free(cwd_buf);
- return 0;
- }
-
- // compare the path name without the drive prefix
- from += 2; cwd += 2;
-#else
+
// test for the exact same string and return "." if so
if (!strcmp(from, cwd)) {
strlcpy(to, ".", tolen);
free(cwd_buf);
return (1);
}
-#endif // WIN32 || __EMX__
-
+
// compare both path names until we find a difference
for (slash = from, newslash = cwd;
- *slash != '\0' && *newslash != '\0';
+ *slash != '\0' && *newslash != '\0';
slash ++, newslash ++)
if (isdirsep(*slash) && isdirsep(*newslash)) continue;
-#if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) // PORTME: Fl_System_Driver - filename stuff
- else if (tolower(*slash & 255) != tolower(*newslash & 255)) break;
-#else
else if (*slash != *newslash) break;
-#endif // WIN32 || __EMX__ || __APPLE__ // PORTME: Fl_System_Driver - filename stuff
-
+
// skip over trailing slashes
if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash)
- &&(newslash==cwd || !isdirsep(newslash[-1])) )
+ &&(newslash==cwd || !isdirsep(newslash[-1])) )
newslash--;
-
+
// now go back to the first character of the first differing paths segment
while (!isdirsep(*slash) && slash > from) slash --;
if (isdirsep(*slash)) slash ++;
-
+
// do the same for the current dir
if (isdirsep(*newslash)) newslash --;
if (*newslash != '\0')
while (!isdirsep(*newslash) && newslash > cwd) newslash --;
-
+
// prepare the destination buffer
to[0] = '\0';
to[tolen - 1] = '\0';
-
+
// now add a "previous dir" sequence for every following slash in the cwd
while (*newslash != '\0') {
if (isdirsep(*newslash)) strlcat(to, "../", tolen);
-
+
newslash ++;
}
-
+
// finally add the differing path from "from"
strlcat(to, slash, tolen);
-
+
free(cwd_buf);
return 1;
}
-
//
// End of "$Id$".
//