X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2FFormFiledialog.C;h=1c8aec402417cf13c4c52ed5313c3c84a7bed979;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=ad1093167a221916bda07ff2ab24981879e7e47f;hpb=add8d29c5f54f21560e50a8936233ec936b2dced;p=lyx.git diff --git a/src/frontends/xforms/FormFiledialog.C b/src/frontends/xforms/FormFiledialog.C index ad1093167a..1c8aec4024 100644 --- a/src/frontends/xforms/FormFiledialog.C +++ b/src/frontends/xforms/FormFiledialog.C @@ -20,17 +20,23 @@ #include "frontends/Dialogs.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 "support/lyxlib.h" #include "support/tostr.h" -#include "support/filetools.h" #include "lyx_forms.h" #include +#include +#include #include #include +#include + #include #include @@ -53,16 +59,59 @@ # 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; + using std::max; using std::sort; - +using std::ostringstream; +using std::string; using std::map; +using std::vector; -using namespace lyx::support; - +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 @@ -157,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 { @@ -171,7 +220,6 @@ public: } }; - } // namespace anon @@ -213,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()); @@ -224,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)) { @@ -290,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? @@ -308,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; @@ -374,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()); } @@ -393,7 +467,6 @@ void FileDialog::Private::SetInfoLine(string const & line) FileDialog::Private::Private() { directory_ = MakeAbsPath(string(".")); - mask_ = '*'; // Creates form if necessary. if (!file_dlg_form_) { @@ -529,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; @@ -539,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; @@ -643,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; } @@ -701,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; @@ -759,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(); @@ -782,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()) {