X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fxforms%2FFormFiledialog.C;h=1c8aec402417cf13c4c52ed5313c3c84a7bed979;hb=37e82a546392d43f787826b85481a11f2a27af15;hp=3d9d5b05c4c0d608a058e826fb99f0790237c248;hpb=05347e410191c930106a14d4ae9039ffaf28a7c4;p=lyx.git diff --git a/src/frontends/xforms/FormFiledialog.C b/src/frontends/xforms/FormFiledialog.C index 3d9d5b05c4..1c8aec4024 100644 --- a/src/frontends/xforms/FormFiledialog.C +++ b/src/frontends/xforms/FormFiledialog.C @@ -20,18 +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 @@ -57,6 +62,7 @@ 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; @@ -70,12 +76,42 @@ 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::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 @@ -170,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 { @@ -184,7 +220,6 @@ public: } }; - } // namespace anon @@ -198,31 +233,6 @@ int FileDialog::Private::minw_ = 0; int FileDialog::Private::minh_ = 0; -namespace { - -boost::regex getRegex(string const & pat) -{ - // We massage the pattern a bit so that the usual - // shell pattern we all are used to will work. - // One nice thing about using a real regex is that - // things like "*.*[^~]" will work also. - // build the regex string. - string pattern = subst(pat, ".", "\\."); - pattern = subst(pattern, "*", ".*"); - - boost::regex reg(pattern); - return reg; -} - - -bool globMatch(string const & a, boost::regex const & reg) -{ - return boost::regex_match(a, reg); -} - -} // namespace anon - - // Reread: updates dialog list to match class directory void FileDialog::Private::Reread() { @@ -251,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()); @@ -262,8 +272,7 @@ void FileDialog::Private::Reread() ++depth_; } - // Parses all entries of the given subdirectory - boost::regex reg = getRegex(mask_); + vector const glob_matches = expand_globs(mask_, directory_); time_t curTime = time(0); rewinddir(dir); @@ -330,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? @@ -348,7 +357,10 @@ void FileDialog::Private::Reread() || fileInfo.isChar() || fileInfo.isBlock() || fileInfo.isFifo()) { - if (!globMatch(fname, reg)) + 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; @@ -414,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) { - mask_ = newmask; + SetFilters(FileFilterList(mask)); +} + + +void FileDialog::Private::SetFilters(FileFilterList const & filters) +{ + 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()); } @@ -433,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_) { @@ -569,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; @@ -579,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; @@ -683,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; } @@ -741,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; @@ -799,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(); @@ -822,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()) {