Adds some convenience methods.
fl_filename_absolute can no generate a path using arbitrary source paths. Fl_Menu_ adds find_item_with_user_data and find_item_with_argument Fl_String adds find(string, start)
This commit is contained in:
parent
b2a41e08c3
commit
6bb5a81cee
@ -73,6 +73,8 @@ public:
|
||||
const Fl_Menu_Item* picked(const Fl_Menu_Item*);
|
||||
const Fl_Menu_Item* find_item(const char *name);
|
||||
const Fl_Menu_Item* find_item(Fl_Callback*);
|
||||
const Fl_Menu_Item* find_item_with_user_data(void*);
|
||||
const Fl_Menu_Item* find_item_with_argument(long);
|
||||
int find_index(const char *name) const;
|
||||
int find_index(const Fl_Menu_Item *item) const;
|
||||
int find_index(Fl_Callback *cb) const;
|
||||
|
||||
@ -113,6 +113,7 @@ public:
|
||||
Fl_String &operator+=(const char *src);
|
||||
Fl_String &operator+=(const Fl_String &src);
|
||||
Fl_String &operator+=(char c);
|
||||
int find(const Fl_String &needle, int start_pos=0) const;
|
||||
Fl_String &replace(int at, int n_del, const char *src, int n_ins=npos);
|
||||
Fl_String &replace(int at, int n_del, const Fl_String &src);
|
||||
Fl_String substr(int pos=0, int n=npos) const;
|
||||
|
||||
@ -63,7 +63,9 @@ FL_EXPORT Fl_String fl_filename_ext(const Fl_String &filename);
|
||||
FL_EXPORT Fl_String fl_filename_setext(const Fl_String &filename, const Fl_String &new_extension);
|
||||
FL_EXPORT Fl_String fl_filename_expand(const Fl_String &from);
|
||||
FL_EXPORT Fl_String fl_filename_absolute(const Fl_String &from);
|
||||
FL_EXPORT Fl_String fl_filename_absolute(const Fl_String &from, const Fl_String &base);
|
||||
FL_EXPORT Fl_String fl_filename_relative(const Fl_String &from);
|
||||
FL_EXPORT Fl_String fl_filename_relative(const Fl_String &from, const Fl_String &base);
|
||||
FL_EXPORT Fl_String fl_getcwd();
|
||||
|
||||
# endif
|
||||
@ -75,6 +77,7 @@ FL_EXPORT Fl_String fl_getcwd();
|
||||
|
||||
inline char *fl_filename_setext(char *to, const char *ext) { return fl_filename_setext(to, FL_PATH_MAX, ext); }
|
||||
inline int fl_filename_expand(char *to, const char *from) { return fl_filename_expand(to, FL_PATH_MAX, from); }
|
||||
FL_EXPORT int fl_filename_absolute(char *to, int tolen, const char *from, const char *cwd);
|
||||
inline int fl_filename_absolute(char *to, const char *from) { return fl_filename_absolute(to, FL_PATH_MAX, from); }
|
||||
FL_EXPORT int fl_filename_relative(char *to, int tolen, const char *from, const char *cwd);
|
||||
inline int fl_filename_relative(char *to, const char *from) { return fl_filename_relative(to, FL_PATH_MAX, from); }
|
||||
|
||||
@ -266,6 +266,40 @@ const Fl_Menu_Item * Fl_Menu_::find_item(Fl_Callback *cb) {
|
||||
return (const Fl_Menu_Item *)0;
|
||||
}
|
||||
|
||||
/**
|
||||
Find the menu item for the given user data \p v.
|
||||
|
||||
\param[in] v find the first item with this user data
|
||||
\returns The item found, or NULL if not found
|
||||
\see find_item(const char*)
|
||||
*/
|
||||
const Fl_Menu_Item* Fl_Menu_::find_item_with_user_data(void *v) {
|
||||
for ( int t=0; t < size(); t++ ) {
|
||||
const Fl_Menu_Item *m = menu_ + t;
|
||||
if (m->user_data_==v) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return (const Fl_Menu_Item *)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Find the menu item for the given user argument \p v.
|
||||
|
||||
\param[in] v find the first item with this user argument
|
||||
\returns The item found, or NULL if not found
|
||||
\see find_item(const char*)
|
||||
*/
|
||||
const Fl_Menu_Item* Fl_Menu_::find_item_with_argument(long v) {
|
||||
for ( int t=0; t < size(); t++ ) {
|
||||
const Fl_Menu_Item *m = menu_ + t;
|
||||
if (m->argument()==v) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return (const Fl_Menu_Item *)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
The value is the index into menu() of the last item chosen by
|
||||
the user. It is zero initially. You can set it as an integer, or set
|
||||
|
||||
@ -465,6 +465,21 @@ Fl_String &Fl_String::operator+=(char c) {
|
||||
return append(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Find a string inside this string.
|
||||
\param[in] needle find this string
|
||||
\param[in] start_pos start looking at this position
|
||||
\return the offset of the text inside this string, if it was found
|
||||
\return Fl_String::npos if the needle was not found
|
||||
*/
|
||||
int Fl_String::find(const Fl_String &needle, int start_pos) const {
|
||||
if ((start_pos < 0) || (start_pos >= size_)) return npos;
|
||||
const char *haystack = data() + start_pos;
|
||||
const char *found = strstr(haystack, needle.c_str());
|
||||
if (!found) return npos;
|
||||
return (int)(found - data());
|
||||
}
|
||||
|
||||
/**
|
||||
Replace part of the string with a C-style string or data.
|
||||
\param[in] at erase and insert at this index
|
||||
|
||||
@ -134,7 +134,7 @@ public:
|
||||
// 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);
|
||||
virtual int filename_absolute(char *to, int tolen, const char *from, const char *base);
|
||||
// the default implementation of filename_isdir() is in src/filename_isdir.cxx and may be enough
|
||||
virtual int filename_isdir(const char* n);
|
||||
// the default implementation of filename_isdir_quick() is in src/filename_isdir.cxx and may be enough
|
||||
|
||||
@ -74,7 +74,7 @@ public:
|
||||
char *errmsg=NULL, int errmsg_sz=0) FL_OVERRIDE;
|
||||
int filename_expand(char *to,int tolen, const char *from) FL_OVERRIDE;
|
||||
int filename_relative(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE;
|
||||
int filename_absolute(char *to, int tolen, const char *from) FL_OVERRIDE;
|
||||
int filename_absolute(char *to, int tolen, const char *from, const char *base) FL_OVERRIDE;
|
||||
int filename_isdir(const char *n) FL_OVERRIDE;
|
||||
int filename_isdir_quick(const char *n) FL_OVERRIDE;
|
||||
const char *filename_ext(const char *buf) FL_OVERRIDE;
|
||||
|
||||
@ -636,21 +636,17 @@ Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
|
||||
if (isdirsep(*from) || *from == '|' || from[1]==':') {
|
||||
int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) {
|
||||
if (isdirsep(*from) || *from == '|' || from[1]==':' || !base) {
|
||||
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;
|
||||
}
|
||||
strlcpy(temp, base, tolen);
|
||||
for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
|
||||
/* remove trailing '/' in current working directory */
|
||||
if (isdirsep(*(a-1))) a--;
|
||||
/* remove intermediate . and .. names: */
|
||||
while (*start == '.') {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Filename expansion routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2017 by Bill Spitzak and others.
|
||||
// Copyright 1998-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
static inline int isdirsep(char c) {return c == '/';}
|
||||
|
||||
/** Makes a filename absolute from a relative filename.
|
||||
/** Makes a filename absolute from a relative filename to the current working directory.
|
||||
\code
|
||||
#include <FL/filename.H>
|
||||
[..]
|
||||
@ -45,30 +45,46 @@ static inline int isdirsep(char c) {return c == '/';}
|
||||
\return 0 if no change, non zero otherwise
|
||||
*/
|
||||
int fl_filename_absolute(char *to, int tolen, const char *from) {
|
||||
return Fl::system_driver()->filename_absolute(to, tolen, from);
|
||||
char cwd_buf[FL_PATH_MAX]; // Current directory
|
||||
// get the current directory and return if we can't
|
||||
if (!fl_getcwd(cwd_buf, sizeof(cwd_buf))) {
|
||||
strlcpy(to, from, tolen);
|
||||
return 0;
|
||||
}
|
||||
return Fl::system_driver()->filename_absolute(to, tolen, from, cwd_buf);
|
||||
}
|
||||
|
||||
/** Concatenate the absolute path `base` with `from` to form the new absolute path in `to`.
|
||||
\code
|
||||
#include <FL/filename.H>
|
||||
char out[FL_PATH_MAX];
|
||||
fl_filename_absolute(out, sizeof(out), "../foo.txt", "/var/tmp"); // out="/var/foo.txt"
|
||||
fl_filename_absolute(out, sizeof(out), "../local/bin", "/usr/bin"); // out="/usr/local/bin"
|
||||
\endcode
|
||||
\param[out] to resulting absolute filename
|
||||
\param[in] tolen size of the absolute filename buffer
|
||||
\param[in] from relative filename
|
||||
\param[in] base `from` is relative to this absolute file path
|
||||
\return 0 if no change, non zero otherwise
|
||||
*/
|
||||
int fl_filename_absolute(char *to, int tolen, const char *from, const char *base) {
|
||||
return Fl::system_driver()->filename_absolute(to, tolen, from, base);
|
||||
}
|
||||
|
||||
/**
|
||||
\cond DriverDev
|
||||
\addtogroup DriverDeveloper
|
||||
\{
|
||||
*/
|
||||
|
||||
int Fl_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
|
||||
if (isdirsep(*from) || *from == '|') {
|
||||
int Fl_System_Driver::filename_absolute(char *to, int tolen, const char *from, const char *base) {
|
||||
if (isdirsep(*from) || *from == '|' || !base) {
|
||||
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;
|
||||
}
|
||||
strlcpy(temp, base, tolen);
|
||||
a = temp+strlen(temp);
|
||||
/* remove trailing '/' in current working directory */
|
||||
if (isdirsep(*(a-1))) a--;
|
||||
@ -125,10 +141,7 @@ int Fl_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
|
||||
\param[in] from absolute filename
|
||||
\return 0 if no change, non zero otherwise
|
||||
*/
|
||||
int // O - 0 if no change, 1 if changed
|
||||
fl_filename_relative(char *to, // O - Relative filename
|
||||
int tolen, // I - Size of "to" buffer
|
||||
const char *from) // I - Absolute filename
|
||||
int fl_filename_relative(char *to, int tolen, const char *from)
|
||||
{
|
||||
char cwd_buf[FL_PATH_MAX]; // Current directory
|
||||
// get the current directory and return if we can't
|
||||
@ -144,14 +157,10 @@ fl_filename_relative(char *to, // O - Relative filename
|
||||
\param[out] to resulting relative filename
|
||||
\param[in] tolen size of the relative filename buffer
|
||||
\param[in] from absolute filename
|
||||
\param[in] base relative to this absolute path
|
||||
\param[in] base generate filename relative to this absolute filename
|
||||
\return 0 if no change, non zero otherwise
|
||||
*/
|
||||
int // O - 0 if no change, 1 if changed
|
||||
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
|
||||
int fl_filename_relative(char *to, int tolen, const char *from, const char *base) {
|
||||
return Fl::system_driver()->filename_relative(to, tolen, from, base);
|
||||
}
|
||||
|
||||
@ -162,11 +171,7 @@ fl_filename_relative(char *to, // O - Relative filename
|
||||
\{
|
||||
*/
|
||||
|
||||
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
|
||||
int Fl_System_Driver::filename_relative(char *to, int tolen, const char *from, const char *base)
|
||||
{
|
||||
char *newslash; // Directory separator
|
||||
const char *slash; // Directory separator
|
||||
@ -314,6 +319,20 @@ Fl_String fl_filename_absolute(const Fl_String &from) {
|
||||
return Fl_String(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Append the relative filename `from` to the absolute filename `base` to form
|
||||
the new absolute path.
|
||||
\param[in] from relative filename
|
||||
\param[in] base `from` is relative to this absolute file path
|
||||
\return the new, absolute filename
|
||||
\see fl_filename_absolute(char *to, int tolen, const char *from, const char *base)
|
||||
*/
|
||||
Fl_String fl_filename_absolute(const Fl_String &from, const Fl_String &base) {
|
||||
char buffer[FL_PATH_MAX];
|
||||
fl_filename_absolute(buffer, FL_PATH_MAX, from.c_str(), base.c_str());
|
||||
return Fl_String(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Makes a filename relative to the current working directory.
|
||||
\param[in] from file path and name
|
||||
@ -326,6 +345,19 @@ Fl_String fl_filename_relative(const Fl_String &from) {
|
||||
return Fl_String(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
Makes a filename relative to any directory.
|
||||
\param[in] from file path and name
|
||||
\param[in] base relative to this absolute path
|
||||
\return the new, relative filename
|
||||
\see fl_filename_relative(char *to, int tolen, const char *from, const char *base)
|
||||
*/
|
||||
Fl_String fl_filename_relative(const Fl_String &from, const Fl_String &base) {
|
||||
char buffer[FL_PATH_MAX];
|
||||
fl_filename_relative(buffer, FL_PATH_MAX, from.c_str(), base.c_str());
|
||||
return Fl_String(buffer);
|
||||
}
|
||||
|
||||
/** Cross-platform function to get the current working directory
|
||||
as a UTF-8 encoded value in an Fl_String.
|
||||
\return the CWD encoded as UTF-8
|
||||
|
||||
@ -243,6 +243,56 @@ TEST(Fl_Preferences, Strings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(fl_filename, ext) {
|
||||
Fl_String r = fl_filename_ext("test.txt");
|
||||
EXPECT_STREQ(r.c_str(), ".txt");
|
||||
r = fl_filename_ext("test");
|
||||
EXPECT_STREQ(r.c_str(), "");
|
||||
r = fl_filename_ext("");
|
||||
EXPECT_STREQ(r.c_str(), "");
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(fl_filename, setext) {
|
||||
Fl_String r = fl_filename_setext(Fl_String("test.txt"), ".rtf");
|
||||
EXPECT_STREQ(r.c_str(), "test.rtf");
|
||||
r = fl_filename_setext(Fl_String("test"), ".rtf");
|
||||
EXPECT_STREQ(r.c_str(), "test.rtf");
|
||||
r = fl_filename_setext(Fl_String("test.txt"), "");
|
||||
EXPECT_STREQ(r.c_str(), "test");
|
||||
r = fl_filename_setext(Fl_String(""), ".rtf");
|
||||
EXPECT_STREQ(r.c_str(), ".rtf");
|
||||
r = fl_filename_setext(Fl_String("path/test"), ".rtf");
|
||||
EXPECT_STREQ(r.c_str(), "path/test.rtf");
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(fl_filename, relative) {
|
||||
Fl_String base = "/var/tmp/somedir";
|
||||
Fl_String r = fl_filename_relative("/var/tmp/somedir/foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "foo.txt");
|
||||
r = fl_filename_relative("/var/tmp/foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "../foo.txt");
|
||||
r = fl_filename_relative("./foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "./foo.txt");
|
||||
r = fl_filename_relative("../foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "../foo.txt");
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(fl_filename, absolute) {
|
||||
Fl_String base = "/var/tmp/somedir";
|
||||
Fl_String r = fl_filename_absolute("foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "/var/tmp/somedir/foo.txt");
|
||||
r = fl_filename_absolute("/var/tmp/foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "/var/tmp/foo.txt");
|
||||
r = fl_filename_absolute("./foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "/var/tmp/somedir/foo.txt");
|
||||
r = fl_filename_absolute("../foo.txt", base);
|
||||
EXPECT_STREQ(r.c_str(), "/var/tmp/foo.txt");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cb1a_ok = false, cb1b_ok = false, cb1c_ok = false;
|
||||
int cb1_alloc = 0;
|
||||
class MyString : public Fl_String {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user