X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2FFormFiledialog.C;h=1c8aec402417cf13c4c52ed5313c3c84a7bed979;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=2fea4dae905af39446da34f631d0b26e680bfb1b;hpb=99d1627a471b92f403598d03dfc861ddc3c11be0;p=lyx.git diff --git a/src/frontends/xforms/FormFiledialog.C b/src/frontends/xforms/FormFiledialog.C index 2fea4dae90..1c8aec4024 100644 --- a/src/frontends/xforms/FormFiledialog.C +++ b/src/frontends/xforms/FormFiledialog.C @@ -6,32 +6,39 @@ * \author unknown * \author John Levon * - * Full author contact details are available in file CREDITS + * Full author contact details are available in file CREDITS. */ #include -#include -#include -#include -#include -#include -#include +#include "FormFiledialog.h" +#include "forms/form_filedialog.h" -using std::map; -using std::max; -using std::sort; +#include "forms_gettext.h" +#include "xforms_helpers.h" + +#include "frontends/Dialogs.h" -#include "frontends/Alert.h" #include "support/FileInfo.h" -#include "support/lyxlib.h" +#include "support/filefilterlist.h" +#include "support/filetools.h" +#include "support/globbing.h" #include "support/lstrings.h" -#include "gettext.h" -#include "frontends/Dialogs.h" -#include "forms_gettext.h" -#include "xforms_helpers.h" +#include "support/lyxlib.h" +#include "support/tostr.h" + +#include "lyx_forms.h" #include +#include +#include + +#include +#include +#include + +#include +#include //#ifdef HAVE_ERRNO_H //#include @@ -52,14 +59,59 @@ using std::sort; # endif #endif +using lyx::support::AbsolutePath; +using lyx::support::AddName; +using lyx::support::ExpandPath; +using lyx::support::FileFilterList; +using lyx::support::FileInfo; +using lyx::support::getcwd; +using lyx::support::GetEnvPath; +using lyx::support::LyXReadLink; +using lyx::support::MakeAbsPath; +using lyx::support::OnlyFilename; +using lyx::support::split; +using lyx::support::subst; +using lyx::support::suffixIs; +using lyx::support::trim; -#include "support/filetools.h" -#include "FormFiledialog.h" -#include "forms/form_filedialog.h" -#include FORMS_H_LOCATION +using std::max; +using std::sort; +using std::ostringstream; +using std::string; +using std::map; +using std::vector; + +using namespace lyx::frontend; namespace { +/** Given a string " ", expand each glob in turn. + * Any glob that cannot be expanded is ignored silently. + * Invokes \c convert_brace_glob and \c glob internally, so use only + * on systems supporting the Posix function 'glob'. + * \param mask the string " ". + * \param directory the current working directory from + * which \c glob is invoked. + * \returns a vector of all matching file names. + */ +vector const expand_globs(string const & mask, + string const & directory) +{ + // Split into individual globs and then call 'glob' on each one. + typedef boost::tokenizer > Tokenizer; + boost::char_separator const separator(" "); + + vector matches; + Tokenizer const tokens(mask, separator); + Tokenizer::const_iterator it = tokens.begin(); + Tokenizer::const_iterator const end = tokens.end(); + for (; it != end; ++it) + lyx::support::glob(matches, *it, directory); + + return matches; +} + + // six months, in seconds long const SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L; //static @@ -113,7 +165,7 @@ private: void UserCache::add(uid_t ID) const { struct passwd const * entry = getpwuid(ID); - users[ID] = entry ? entry->pw_name : tostr(ID); + users[ID] = entry ? entry->pw_name : tostr(int(ID)); } @@ -146,7 +198,7 @@ string const & GroupCache::find(gid_t ID) const void GroupCache::add(gid_t ID) const { struct group const * entry = getgrgid(ID); - groups[ID] = entry ? entry->gr_name : tostr(ID); + groups[ID] = entry ? entry->gr_name : tostr(int(ID)); } // local instances @@ -154,7 +206,7 @@ UserCache lyxUserCache; GroupCache lyxGroupCache; // compares two LyXDirEntry objects content (used for sort) -class comp_direntry { +class comp_direntry : public std::binary_function { public: bool operator()(DirEntry const & r1, DirEntry const & r2) const { @@ -168,7 +220,6 @@ public: } }; - } // namespace anon @@ -188,9 +239,12 @@ void FileDialog::Private::Reread() // Opens directory DIR * dir = ::opendir(directory_.c_str()); if (!dir) { +// FIXME: re-add ... +#if 0 Alert::err_alert(_("Warning! Couldn't open directory."), directory_); - directory_ = lyx::getcwd(); +#endif + directory_ = getcwd(); dir = ::opendir(directory_.c_str()); } @@ -207,9 +261,9 @@ void FileDialog::Private::Reread() string line, Temp; string mode; string File = directory_; - if (File != "/") { + if (File != "/") File = split(File, Temp, '/'); - } + while (!File.empty() || !Temp.empty()) { string dline = "@b" + line + Temp + '/'; fl_add_browser_line(file_dlg_form_->List, dline.c_str()); @@ -218,7 +272,8 @@ void FileDialog::Private::Reread() ++depth_; } - // Parses all entries of the given subdirectory + vector const glob_matches = expand_globs(mask_, directory_); + time_t curTime = time(0); rewinddir(dir); while (dirent * entry = readdir(dir)) { @@ -284,7 +339,7 @@ void FileDialog::Private::Reread() buffer += Link; // This gives the FileType of the file that - // is really pointed too after resolving all + // is really pointed to after resolving all // symlinks. This is not necessarily the same // as the type of Link (which could again be a // link). Is that intended? @@ -302,7 +357,10 @@ void FileDialog::Private::Reread() || fileInfo.isChar() || fileInfo.isBlock() || fileInfo.isFifo()) { - if (!regexMatch(fname, mask_)) + typedef vector::const_iterator viterator; + viterator gbegin = glob_matches.begin(); + viterator const gend = glob_matches.end(); + if (std::find(gbegin, gend, fname) == gend) continue; } else if (!(isDir = fileInfo.isDir())) continue; @@ -350,14 +408,17 @@ void FileDialog::Private::SetDirectory(string const & path) { string tmp; if (path.empty()) - tmp = lyx::getcwd(); + tmp = getcwd(); else tmp = MakeAbsPath(ExpandPath(path), directory_); // must check the directory exists DIR * dir = ::opendir(tmp.c_str()); if (!dir) { +// FIXME: re-add ... +#if 0 Alert::err_alert(_("Warning! Couldn't open directory."), tmp); +#endif } else { ::closedir(dir); directory_ = tmp; @@ -365,10 +426,32 @@ void FileDialog::Private::SetDirectory(string const & path) } -// SetMask: sets dialog file mask -void FileDialog::Private::SetMask(string const & newmask) +void FileDialog::Private::SetFilters(string const & mask) +{ + SetFilters(FileFilterList(mask)); +} + + +void FileDialog::Private::SetFilters(FileFilterList const & filters) { - mask_ = newmask; + if (filters.empty()) + return; + + // Just take the first one for now. + typedef FileFilterList::Filter::glob_iterator glob_iterator; + glob_iterator const begin = filters[0].begin(); + glob_iterator const end = filters[0].end(); + if (begin == end) + return; + + ostringstream ss; + for (glob_iterator it = begin; it != end; ++it) { + if (it != begin) + ss << ' '; + ss << *it; + } + + mask_ = ss.str(); fl_set_input(file_dlg_form_->PatBox, mask_.c_str()); } @@ -381,10 +464,9 @@ void FileDialog::Private::SetInfoLine(string const & line) } -FileDialog::Private::Private(Dialogs & dia) +FileDialog::Private::Private() { directory_ = MakeAbsPath(string(".")); - mask_ = '*'; // Creates form if necessary. if (!file_dlg_form_) { @@ -420,7 +502,7 @@ FileDialog::Private::Private(Dialogs & dia) fl_hide_object(file_dlg_form_->User1); fl_hide_object(file_dlg_form_->User2); - r_ = dia.redrawGUI().connect(boost::bind(&FileDialog::Private::redraw, this)); + r_ = Dialogs::redrawGUI().connect(boost::bind(&FileDialog::Private::redraw, this)); } @@ -520,7 +602,7 @@ void FileDialog::Private::FileDlgCB(FL_OBJECT *, long arg) break; case 1: // get mask - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; @@ -530,25 +612,25 @@ void FileDialog::Private::FileDlgCB(FL_OBJECT *, long arg) case 10: // rescan current_dlg_->SetDirectory(fl_get_input(file_dlg_form_->DirBox)); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 11: // home current_dlg_->SetDirectory(GetEnvPath("HOME")); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 12: // user button 1 current_dlg_->SetDirectory(current_dlg_->user_path1_); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; case 13: // user button 2 current_dlg_->SetDirectory(current_dlg_->user_path2_); - current_dlg_->SetMask(fl_get_input(file_dlg_form_->PatBox)); + current_dlg_->SetFilters(fl_get_input(file_dlg_form_->PatBox)); current_dlg_->Reread(); break; @@ -634,7 +716,7 @@ bool FileDialog::Private::HandleOK() // mask was changed string tmp = fl_get_input(file_dlg_form_->PatBox); if (tmp != mask_) { - SetMask(tmp); + SetFilters(tmp); Reread(); return false; } @@ -692,21 +774,13 @@ void FileDialog::Private::Force(bool cancel) // Select: launches dialog and returns selected file string const FileDialog::Private::Select(string const & title, string const & path, - string const & mask, + FileFilterList const & filters, string const & suggested) { // handles new mask and path - bool isOk = true; - if (!mask.empty()) { - SetMask(mask); - isOk = false; - } - if (!path.empty()) { - SetDirectory(path); - isOk = false; - } - if (!isOk) - Reread(); + SetFilters(filters); + SetDirectory(path); + Reread(); // highlight the suggested file in the browser, if it exists. int sel = 0; @@ -750,7 +824,7 @@ string const FileDialog::Private::Select(string const & title, FL_PLACE_MOUSE | FL_FREE_SIZE, 0, title.c_str()); - isOk = RunDialog(); + bool const isOk = RunDialog(); fl_hide_form(file_dlg_form_->form); fl_activate_all_forms(); @@ -773,7 +847,7 @@ string const FileDialog::Private::SelectDir(string const & title, string const & path, string const & suggested) { - SetMask("*/"); + SetFilters("*/"); // handles new path bool isOk = true; if (!path.empty()) {