]> git.lyx.org Git - lyx.git/blobdiff - src/filedlg.C
prepare for 1.1.6pre2
[lyx.git] / src / filedlg.C
index 6037454c905d89dbed2533549a8d922539385200..2240d9db56a69cc0a89797f9503b5287f42e7762 100644 (file)
@@ -1,25 +1,31 @@
 // -*- C++ -*-
 /* This file is part of
- * ======================================================
+ * ====================================================== 
  * 
  *           LyX, The Document Processor
  *        
  *           Copyright 1995 Matthias Ettrich
- *           Copyright 1995-1999 The LyX Team.
+ *           Copyright 1995-2000 The LyX Team.
  *
- * ======================================================*/
+ * ====================================================== */
 
 #include <config.h>
 
 #include <unistd.h>
-#include <cstdio>
 #include <cstdlib>
 #include <pwd.h>
 #include <grp.h>
 #include <cstring>
+#include <map>
+#include <algorithm>
+
+using std::map;
+using std::max;
+using std::sort;
 
 #include "lyx_gui_misc.h" // CancelCloseCB
 #include "support/FileInfo.h"
+#include "support/lyxlib.h"
 #include "gettext.h"
 
 #ifdef HAVE_ERRNO_H
@@ -55,8 +61,7 @@
 #endif
 
 #ifdef BROKEN_HEADERS
-extern "C" int gettimeofday(struct timeval *,struct timezone *);
-#define remove(a) unlink(a)      
+extern "C" int gettimeofday(struct timeval *, struct timezone *);
 #endif
 
 #ifdef __GNUG__
@@ -65,136 +70,118 @@ extern "C" int gettimeofday(struct timeval *,struct timezone *);
 
 #include "support/filetools.h"
 #include "filedlg.h"
-#include "definitions.h"
 
-static const long SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L; // six months, in seconds
+// six months, in seconds
+static const long SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L;
 static const long ONE_HOUR_SEC = 60L * 60L;
 
 // *** User cache class implementation
-
-// global instance (user cache root)
-UserCache lyxUserCache = UserCache(string(),0,0);
+/// User cache class definition
+class UserCache {
+public:
+       /// seeks user name from group ID
+       string const & find(uid_t ID) const {
+               Users::const_iterator cit = users.find(ID);
+               if (cit == users.end()) {
+                       add(ID);
+                       return users[ID];
+               }
+               return (*cit).second;
+       }
+private:
+       ///
+       void add(uid_t ID) const;
+       ///
+       typedef map<uid_t, string> Users;
+       ///
+       mutable Users users;
+};
 
 
-// Add: creates a new user entry
-UserCache * UserCache::Add(uid_t ID)
+void UserCache::add(uid_t ID) const 
 {
        string pszNewName;
        struct passwd * pEntry;
-
+       
        // gets user name
        if ((pEntry = getpwuid(ID)))
                pszNewName = pEntry->pw_name;
        else {
                pszNewName = tostr(ID);
        }
-
+       
        // adds new node
-       return new UserCache(pszNewName, ID, pRoot);
-}
-
-
-UserCache::UserCache(string const & pszName, uid_t ID, UserCache * pRoot)
+       users[ID] = pszNewName;
+}      
+
+
+/// Group cache class definition
+class GroupCache {
+public:
+       /// seeks group name from group ID
+       string const & find(gid_t ID) const ;
+private:
+       ///
+       void add(gid_t ID) const;
+       ///
+       typedef map<gid_t, string> Groups;
+       ///
+       mutable Groups groups;
+};
+
+
+string const & GroupCache::find(gid_t ID) const 
 {
-       // links node
-       if (pRoot) {
-               this->pRoot = pRoot;
-               pNext = pRoot->pNext;
-               pRoot->pNext = this;
-       } else {
-               this->pRoot = this;
-               pNext = 0;
+       Groups::const_iterator cit = groups.find(ID);
+       if (cit == groups.end()) {
+               add(ID);
+               return groups[ID];
        }
-
-       // stores data
-       this->pszName = pszName;
-       this->ID = ID;
-}
-
-
-UserCache::~UserCache()
-{
-       if (pNext) delete pNext;
+       return (*cit).second;
 }
 
 
-// Find: seeks user name from user ID
-string UserCache::Find(uid_t ID)
-{
-       if ((!pszName.empty()) && (this->ID == ID)) return pszName; 
-       if (pNext) return pNext->Find(ID);
-
-       return pRoot->Add(ID)->pszName;
-}
-
-
-// *** Group cache class implementation
-
-// global instance (group cache root)
-GroupCache lyxGroupCache = GroupCache(string(),0,0);
-
-// Add: creates a new group entry
-GroupCache * GroupCache::Add(gid_t ID)
+void GroupCache::add(gid_t ID) const 
 {
        string pszNewName;
        struct group * pEntry;
-
+       
        // gets user name
        if ((pEntry = getgrgid(ID))) pszNewName = pEntry->gr_name;
        else {
                pszNewName = tostr(ID);
        }
-
        // adds new node
-       return new GroupCache(pszNewName, ID, pRoot);
+       groups[ID] = pszNewName;
 }
 
 
-GroupCache::GroupCache(string const & pszName, gid_t ID, GroupCache * pRoot)
-{
-       // links node
-       if (pRoot) {
-               this->pRoot = pRoot;
-               pNext = pRoot->pNext;
-               pRoot->pNext = this;
-       } else {
-               this->pRoot = this;
-               pNext = 0;
-       }
-
-       // stores data
-       this->pszName = pszName;
-       this->ID = ID;
-}
+// static instances
+static UserCache lyxUserCache;
+static GroupCache lyxGroupCache;
 
 
-GroupCache::~GroupCache()
-{
-       if (pNext) delete pNext;
-}
+// some "C" wrappers around callbacks
+extern "C" void C_LyXFileDlg_FileDlgCB(FL_OBJECT *, long lArgument);
+extern "C" void C_LyXFileDlg_DoubleClickCB(FL_OBJECT *, long);
+extern "C" int C_LyXFileDlg_CancelCB(FL_FORM *, void *);
 
 
-// Find: seeks group name from group ID
-string GroupCache::Find(gid_t ID)
-{
-       if ((!pszName.empty()) && (this->ID == ID)) return pszName; 
-       if (pNext) return pNext->Find(ID);
-
-       return pRoot->Add(ID)->pszName;
-}
-
-// *** LyXDirEntry internal structure implementation
+// compares two LyXDirEntry objects content (used for sort)
+class comp_direntry {
+public:
+       int operator()(LyXDirEntry const & r1,
+                      LyXDirEntry const & r2) const ;
+};
+       int comp_direntry::operator()(LyXDirEntry const & r1,
+                      LyXDirEntry const & r2) const {
+               bool r1d = suffixIs(r1.pszName, '/');
+               bool r2d = suffixIs(r2.pszName, '/');
+               if (r1d && !r2d) return 1;
+               if (!r1d && r2d) return 0;
+               return r1.pszName < r2.pszName;
+       }
 
-// ldeCompProc: compares two LyXDirEntry objects content (used for qsort)
-int LyXDirEntry::ldeCompProc(const LyXDirEntry * r1, 
-                            const LyXDirEntry * r2)
-{
-       bool r1d = suffixIs(r1->pszName, '/'); 
-       bool r2d = suffixIs(r2->pszName, '/');
-       if (r1d && !r2d) return -1;
-       if (!r1d && r2d) return 1;
-       return r1->pszName.compare(r2->pszName);
-}
 
 // *** LyXFileDlg class implementation
 
@@ -206,29 +193,17 @@ LyXFileDlg * LyXFileDlg::pCurrentDlg = 0;
 // Reread: updates dialog list to match class directory
 void LyXFileDlg::Reread()
 {
-       int i;
-       DIR * pDirectory;
-       struct dirent * pDirEntry;
-       string File;
-       string Buffer;
-       string Time;
-       char szMode[15];
-       FileInfo fileInfo;
-       
        // Opens directory
-       pDirectory = opendir(pszDirectory.c_str());
+       DIR * pDirectory = ::opendir(pszDirectory.c_str());
        if (!pDirectory) {
                WriteFSAlert(_("Warning! Couldn't open directory."), 
                             pszDirectory);
-               pszDirectory = GetCWD();
-               pDirectory = opendir(pszDirectory.c_str());
+               pszDirectory = lyx::getcwd();
+               pDirectory = ::opendir(pszDirectory.c_str());
        }
 
        // Clear the present namelist
-       if (pCurrentNames) {
-               delete [] pCurrentNames;
-               pCurrentNames = 0;
-       }
+       direntries.clear();
 
        // Updates display
        fl_hide_object(pFileDlgForm->List);
@@ -238,7 +213,9 @@ void LyXFileDlg::Reread()
        // Splits complete directory name into directories and compute depth
        iDepth = 0;
        string line, Temp;
-       File = pszDirectory;
+       char szMode[15];
+       FileInfo fileInfo;
+       string File = pszDirectory;
        if (File != "/") {
                File = split(File, Temp, '/');
        }
@@ -250,18 +227,11 @@ void LyXFileDlg::Reread()
                ++iDepth;
        }
 
-       // Allocate names array
-       iNumNames = 0;
-       rewinddir(pDirectory);
-       while ((readdir(pDirectory))) ++iNumNames;
-       pCurrentNames = new LyXDirEntry[iNumNames];
-
        // Parses all entries of the given subdirectory
-       iNumNames = 0;
        time_t curTime = time(0);
        rewinddir(pDirectory);
+       struct dirent * pDirEntry;
        while ((pDirEntry = readdir(pDirectory))) {
-
                bool isLink = false, isDir = false;
 
                // If the pattern doesn't start with a dot, skip hidden files
@@ -280,14 +250,13 @@ void LyXFileDlg::Reread()
                File = AddName(pszDirectory, fname);
 
                fileInfo.newFile(File, true);
-
                fileInfo.modeString(szMode);
                unsigned int nlink = fileInfo.getNumberOfLinks();
-               string user =   lyxUserCache.Find(fileInfo.getUid());
-               string group = lyxGroupCache.Find(fileInfo.getGid());
+               string user =   lyxUserCache.find(fileInfo.getUid());
+               string group = lyxGroupCache.find(fileInfo.getGid());
 
                time_t modtime = fileInfo.getModificationTime();
-               Time += ctime(&modtime);
+               string Time = ctime(&modtime);
                
                if (curTime > fileInfo.getModificationTime() + SIX_MONTH_SEC
                    || curTime < fileInfo.getModificationTime()
@@ -297,13 +266,14 @@ void LyXFileDlg::Reread()
                        // factor for what is considered "the future", to
                        // allow for NFS server/client clock disagreement.
                        // Show the year instead of the time of day.
-#warning fix!
-                       
                        Time.erase(10, 9);
+                       Time.erase(15, string::npos);
+               } else {
+                       Time.erase(16, string::npos);
                }
 
-               Buffer = szMode + ' ' +
-                       nlink + ' ' +
+               string Buffer = string(szMode) + ' ' +
+                       tostr(nlink) + ' ' +
                        user + ' ' +
                        group + ' ' +
                        Time.substr(4, string::npos) + ' ';
@@ -312,21 +282,21 @@ void LyXFileDlg::Reread()
                Buffer += fileInfo.typeIndicator();
 
                if ((isLink = fileInfo.isLink())) {
-                 string Link;
-
-                 if (LyXReadLink(File,Link)) {
-                      Buffer += " -> ";
-                      Buffer += Link;
-
-                      // This gives the FileType of the file that
-                      // is really pointed too after resolving all
-                      // symlinks. This is not necessarily the same
-                      // as the type of Link (which could again be a
-                      // link). Is that intended?
-                      //                              JV 199902
-                      fileInfo.newFile(File);
-                      Buffer += fileInfo.typeIndicator();
-                 }
+                       string Link;
+
+                       if (LyXReadLink(File, Link)) {
+                               Buffer += " -> ";
+                               Buffer += Link;
+
+                               // This gives the FileType of the file that
+                               // is really pointed too after resolving all
+                               // symlinks. This is not necessarily the same
+                               // as the type of Link (which could again be a
+                               // link). Is that intended?
+                               //                              JV 199902
+                               fileInfo.newFile(File);
+                               Buffer += fileInfo.typeIndicator();
+                       }
                }
 
                // filters files according to pattern and type
@@ -339,36 +309,38 @@ void LyXFileDlg::Reread()
                } else if (!(isDir = fileInfo.isDir()))
                        continue;
 
-               // Note pszLsEntry is an string!
-               pCurrentNames[iNumNames].pszLsEntry = Buffer;
+               LyXDirEntry tmp;
 
+               // Note pszLsEntry is an string!
+               tmp.pszLsEntry = Buffer;
                // creates used name
                string temp = fname;
                if (isDir) temp += '/';
-               pCurrentNames[iNumNames].pszName = temp;
 
+               tmp.pszName = temp;
                // creates displayed name
                temp = pDirEntry->d_name;
                if (isLink)
                        temp += '@';
                else
                        temp += fileInfo.typeIndicator();
-               
-               pCurrentNames[iNumNames++].pszDisplayed = temp;
+               tmp.pszDisplayed = temp;
+
+               direntries.push_back(tmp);
        }
 
        closedir(pDirectory);
 
        // Sort the names
-       qsort(pCurrentNames, iNumNames, sizeof(LyXDirEntry), 
-             (int (*)(const void *, const void *))LyXDirEntry::ldeCompProc);
-
+       sort(direntries.begin(), direntries.end(), comp_direntry());
+       
        // Add them to directory box
-       for (i = 0; i < iNumNames; ++i) {
-               string temp = line + pCurrentNames[i].pszDisplayed;
+       for (DirEntries::const_iterator cit = direntries.begin();
+            cit != direntries.end(); ++cit) {
+               string const temp = line + (*cit).pszDisplayed;
                fl_add_browser_line(pFileDlgForm->List, temp.c_str());
        }
-       fl_set_browser_topline(pFileDlgForm->List,iDepth);
+       fl_set_browser_topline(pFileDlgForm->List, iDepth);
        fl_show_object(pFileDlgForm->List);
        iLastSel = -1;
 }
@@ -403,7 +375,6 @@ void LyXFileDlg::SetInfoLine(string const & Line)
 
 LyXFileDlg::LyXFileDlg()
 {
-       pCurrentNames = 0;
        pszDirectory = MakeAbsPath(string("."));
        pszMask = '*';
 
@@ -412,48 +383,41 @@ LyXFileDlg::LyXFileDlg()
                pFileDlgForm = create_form_FileDlg();
                // Set callbacks. This means that we don't need a patch file
                fl_set_object_callback(pFileDlgForm->DirBox,
-                                      LyXFileDlg::FileDlgCB,0);
+                                      C_LyXFileDlg_FileDlgCB, 0);
                fl_set_object_callback(pFileDlgForm->PatBox,
-                                      LyXFileDlg::FileDlgCB,1);
+                                      C_LyXFileDlg_FileDlgCB, 1);
                fl_set_object_callback(pFileDlgForm->List,
-                                      LyXFileDlg::FileDlgCB,2);
+                                      C_LyXFileDlg_FileDlgCB, 2);
                fl_set_object_callback(pFileDlgForm->Filename,
-                                      LyXFileDlg::FileDlgCB,3);
+                                      C_LyXFileDlg_FileDlgCB, 3);
                fl_set_object_callback(pFileDlgForm->Rescan,
-                                      LyXFileDlg::FileDlgCB,10);
+                                      C_LyXFileDlg_FileDlgCB, 10);
                fl_set_object_callback(pFileDlgForm->Home,
-                                      LyXFileDlg::FileDlgCB,11);
+                                      C_LyXFileDlg_FileDlgCB, 11);
                fl_set_object_callback(pFileDlgForm->User1,
-                                      LyXFileDlg::FileDlgCB,12);
+                                      C_LyXFileDlg_FileDlgCB, 12);
                fl_set_object_callback(pFileDlgForm->User2,
-                                      LyXFileDlg::FileDlgCB,13);
+                                      C_LyXFileDlg_FileDlgCB, 13);
                
                // Make sure pressing the close box doesn't crash LyX. (RvdK)
-               fl_set_form_atclose(pFileDlgForm->FileDlg, CancelCB, 0);
+               fl_set_form_atclose(pFileDlgForm->FileDlg, 
+                                   C_LyXFileDlg_CancelCB, 0);
                // Register doubleclick callback
                fl_set_browser_dblclick_callback(pFileDlgForm->List,
-                                                DoubleClickCB,0);
+                                                C_LyXFileDlg_DoubleClickCB,
+                                                0);
        }
        fl_hide_object(pFileDlgForm->User1);
        fl_hide_object(pFileDlgForm->User2);
 }
 
 
-LyXFileDlg::~LyXFileDlg()
-{
-       // frees directory entries
-       if (pCurrentNames) {
-               delete [] pCurrentNames;
-       }
-}
-
-
 // SetButton: sets file selector user button action
 void LyXFileDlg::SetButton(int iIndex, string const & pszName, 
                           string const & pszPath)
 {
-       FL_OBJECT *pObject;
-       string *pTemp;
+       FL_OBJECT * pObject;
+       string * pTemp;
 
        if (iIndex == 0) {
                pObject = pFileDlgForm->User1;
@@ -475,7 +439,7 @@ void LyXFileDlg::SetButton(int iIndex, string const & pszName,
 
 
 // GetDirectory: gets last dialog directory
-string LyXFileDlg::GetDirectory() 
+string const LyXFileDlg::GetDirectory() const
 {
        if (!pszDirectory.empty())
                return pszDirectory;
@@ -492,7 +456,6 @@ bool LyXFileDlg::RunDialog()
        
         // event loop
         while(true) {
-
                 FL_OBJECT * pObject = fl_do_forms();
 
                 if (pObject == pFileDlgForm->Ready) {
@@ -543,7 +506,8 @@ void LyXFileDlg::FileDlgCB(FL_OBJECT *, long lArgument)
        case 12: // user button 1
                if (!pCurrentDlg->pszUserPath1.empty()) {
                        pCurrentDlg->SetDirectory(pCurrentDlg->pszUserPath1);
-                       pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
+                       pCurrentDlg->SetMask(fl_get_input(pFileDlgForm
+                                                         ->PatBox));
                        pCurrentDlg->Reread();
                }
                break;
@@ -551,7 +515,8 @@ void LyXFileDlg::FileDlgCB(FL_OBJECT *, long lArgument)
        case 13: // user button 2
                if (!pCurrentDlg->pszUserPath2.empty()) {
                        pCurrentDlg->SetDirectory(pCurrentDlg->pszUserPath2);
-                       pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
+                       pCurrentDlg->SetMask(fl_get_input(pFileDlgForm
+                                                         ->PatBox));
                        pCurrentDlg->Reread();
                }
                break;
@@ -560,13 +525,19 @@ void LyXFileDlg::FileDlgCB(FL_OBJECT *, long lArgument)
 }
 
 
+extern "C" void C_LyXFileDlg_FileDlgCB(FL_OBJECT * ob, long data) 
+{
+       LyXFileDlg::FileDlgCB(ob, data);
+}
+
+
 // Handle callback from list
 void LyXFileDlg::HandleListHit()
 {
        // set info line
-       int iSelect = fl_get_browser(pFileDlgForm->List);
+       int const iSelect = fl_get_browser(pFileDlgForm->List);
        if (iSelect > iDepth)  {
-               SetInfoLine(pCurrentNames[iSelect - iDepth - 1].pszLsEntry);
+               SetInfoLine(direntries[iSelect - iDepth - 1].pszLsEntry);
        } else {
                SetInfoLine(string());
        }
@@ -582,32 +553,34 @@ void LyXFileDlg::DoubleClickCB(FL_OBJECT *, long)
 }
 
 
+extern "C" void C_LyXFileDlg_DoubleClickCB(FL_OBJECT * ob, long data)
+{
+       LyXFileDlg::DoubleClickCB(ob, data);
+}
+
+
 // Handle double click from list
 bool LyXFileDlg::HandleDoubleClick()
 {
-       bool isDir;
        string pszTemp;
-       int iSelect;  
 
        // set info line
-       isDir = true;
-       iSelect = fl_get_browser(pFileDlgForm->List);
+       bool isDir = true;
+       int const iSelect = fl_get_browser(pFileDlgForm->List);
        if (iSelect > iDepth)  {
-               pszTemp = pCurrentNames[iSelect - iDepth - 1].pszName;
-               SetInfoLine(pCurrentNames[iSelect - iDepth - 1].pszLsEntry);
+               pszTemp = direntries[iSelect - iDepth - 1].pszName;
+               SetInfoLine(direntries[iSelect - iDepth - 1].pszLsEntry);
                if (!suffixIs(pszTemp, '/')) {
                        isDir = false;
                        fl_set_input(pFileDlgForm->Filename, pszTemp.c_str());
                }
-       } else if (iSelect !=0) {
+       } else if (iSelect != 0) {
                SetInfoLine(string());
        } else
                return true;
 
        // executes action
        if (isDir) {
-
-               int i;
                string Temp;
 
                // builds new directory name
@@ -621,7 +594,7 @@ bool LyXFileDlg::HandleDoubleClick()
                } else {
                        // Directory higher up
                        Temp.erase();
-                       for (i = 0; i < iSelect; ++i) {
+                       for (int i = 0; i < iSelect; ++i) {
                                string piece = fl_get_browser_line(pFileDlgForm->List, i+1);
                                // The '+2' is here to count the '@b' (JMarc)
                                Temp += piece.substr(i + 2);
@@ -640,11 +613,9 @@ bool LyXFileDlg::HandleDoubleClick()
 // Handle OK button call
 bool LyXFileDlg::HandleOK()
 {
-       string pszTemp;
-
        // mask was changed
-       pszTemp = fl_get_input(pFileDlgForm->PatBox);
-       if (pszTemp!=pszMask) {
+       string pszTemp = fl_get_input(pFileDlgForm->PatBox);
+       if (pszTemp != pszMask) {
                SetMask(pszTemp);
                Reread();
                return false;
@@ -652,26 +623,27 @@ bool LyXFileDlg::HandleOK()
 
        // directory was changed
        pszTemp = fl_get_input(pFileDlgForm->DirBox);
-       if (pszTemp!=pszDirectory) {
+       if (pszTemp!= pszDirectory) {
                SetDirectory(pszTemp);
                Reread();
                return false;
        }
        
        // Handle return from list
-       int select = fl_get_browser(pFileDlgForm->List);
+       int const select = fl_get_browser(pFileDlgForm->List);
        if (select > iDepth) {
-               string temp = pCurrentNames[select - iDepth - 1].pszName;
+               string const temp = direntries[select - iDepth - 1].pszName;
                if (!suffixIs(temp, '/')) {
                        // If user didn't type anything, use browser
-                       string name = fl_get_input(pFileDlgForm->Filename);
+                       string const name =
+                               fl_get_input(pFileDlgForm->Filename);
                        if (name.empty()) {
                                fl_set_input(pFileDlgForm->Filename, temp.c_str());
                        }
                        return true;
                }
        }
-       
+
        // Emulate a doubleclick
        return HandleDoubleClick();
 }
@@ -686,6 +658,12 @@ int LyXFileDlg::CancelCB(FL_FORM *, void *)
 }
 
 
+extern "C" int C_LyXFileDlg_CancelCB(FL_FORM *fl, void *xev)
+{
+       return LyXFileDlg::CancelCB(fl, xev);
+}
+
+
 // Simulates a click on OK/Cancel
 void LyXFileDlg::Force(bool cancel)
 {
@@ -702,13 +680,11 @@ void LyXFileDlg::Force(bool cancel)
 
 
 // Select: launches dialog and returns selected file
-string LyXFileDlg::Select(string const & title, string const & path, 
-                          string const & mask, string const & suggested)
+string const LyXFileDlg::Select(string const & title, string const & path, 
+                               string const & mask, string const & suggested)
 {
-       bool isOk;
-
        // handles new mask and path
-       isOk = true;
+       bool isOk = true;
        if (!mask.empty()) {
                SetMask(mask);
                isOk = false;
@@ -718,27 +694,44 @@ string LyXFileDlg::Select(string const & title, string const & path,
                isOk = false;
        }
        if (!isOk) Reread();
-       else {
-               fl_select_browser_line(pFileDlgForm->List, 1);
-               fl_set_browser_topline(pFileDlgForm->List, 1);
+
+       // highlight the suggested file in the browser, if it exists.
+       int sel = 0;
+       string const filename = OnlyFilename(suggested);
+       if (!filename.empty()) {
+               for (int i = 0; 
+                    i < fl_get_browser_maxline(pFileDlgForm->List); ++i) {
+                       string s =
+                               fl_get_browser_line(pFileDlgForm->List, i + 1);
+                       s = strip(frontStrip(s));
+                       if (s == filename) {
+                               sel = i + 1;
+                               break;
+                       }
+               }
        }
+       
+       if (sel != 0) fl_select_browser_line(pFileDlgForm->List, sel);
+       int const top = max(sel - 5, 1);
+       fl_set_browser_topline(pFileDlgForm->List, top);
 
        // checks whether dialog can be started
        if (pCurrentDlg) return string();
        pCurrentDlg = this;
 
        // runs dialog
-       SetInfoLine (string());
+       SetInfoLine(string());
        fl_set_input(pFileDlgForm->Filename, suggested.c_str());
        fl_set_button(pFileDlgForm->Cancel, 0);
        fl_set_button(pFileDlgForm->Ready, 0);
        fl_set_focus_object(pFileDlgForm->FileDlg, pFileDlgForm->Filename);
        fl_deactivate_all_forms();
-       fl_show_form(pFileDlgForm->FileDlg, FL_PLACE_MOUSE | FL_FREE_SIZE,
-                    FL_FULLBORDER, title.c_str());
+       fl_show_form(pFileDlgForm->FileDlg, 
+                    FL_PLACE_MOUSE | FL_FREE_SIZE, FL_TRANSIENT,
+                    title.c_str());
 
        isOk = RunDialog();
-
+       
        fl_hide_form(pFileDlgForm->FileDlg);
        fl_activate_all_forms();
        pCurrentDlg = 0;