]> git.lyx.org Git - lyx.git/blobdiff - src/filedlg.C
More fixes to insettabular/text (and some missing features added).
[lyx.git] / src / filedlg.C
index 7572348a1a02aea349db7e768217ac290fc0a85d..2b6949034aca2fe0d77ff25169b6e593bbee7622 100644 (file)
@@ -1,35 +1,36 @@
 // -*- C++ -*-
 /* This file is part of
-* ======================================================
-* 
-*           LyX, The Document Processor
-*        
-*           Copyright (C) 1995 Matthias Ettrich
-*           Copyright (C) 1995-1998 The LyX Team.
-*
-*======================================================*/
+ * ====================================================== 
+ 
+ *           LyX, The Document Processor
+ *        
+ *           Copyright 1995 Matthias Ettrich
+ *           Copyright 1995-2000 The LyX Team.
+ *
+ * ====================================================== */
 
 #include <config.h>
 
-//     $Id: filedlg.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $   
-
-#if !defined(lint) && !defined(WITH_WARNINGS)
-static char vcid[] = "$Id: filedlg.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $";
-#endif /* lint */
-
 #include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdlib>
 #include <pwd.h>
 #include <grp.h>
-#include <string.h>
+#include <cstring>
+#include <map>
+#include <algorithm>
+
+using std::map;
+using std::max;
+using std::sort;
 
 #include "lyx_gui_misc.h" // CancelCloseCB
-#include "FileInfo.h"
+#include "support/FileInfo.h"
+#include "support/lyxlib.h"
 #include "gettext.h"
+#include "frontends/Dialogs.h"
 
 #ifdef HAVE_ERRNO_H
-#include <errno.h>
+#include <cerrno>
 #endif
 
 #if HAVE_DIRENT_H
@@ -51,188 +52,163 @@ static char vcid[] = "$Id: filedlg.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $";
 
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
-# include <time.h>
+# include <ctime>
 #else
 # if HAVE_SYS_TIME_H
 #  include <sys/time.h>
 # else
-#  include <time.h>
+#  include <ctime>
 # endif
 #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__
 #pragma implementation
 #endif
 
-#include "filetools.h"
+#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
+#ifdef SIGC_CXX_NAMESPACES
+using SigC::slot;
+#endif
+
+// 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(LString(),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 
 {
-       LString pszNewName;
-       struct passwd *pEntry;
-
+       string pszNewName;
+       struct passwd * pEntry;
+       
        // gets user name
        if ((pEntry = getpwuid(ID)))
                pszNewName = pEntry->pw_name;
        else {
-               pszNewName = LString() + int(ID); // We don't have int cast to LString
+               pszNewName = tostr(ID);
        }
-
+       
        // adds new node
-       return new UserCache(pszNewName, ID, pRoot);
-}
-
-
-UserCache::UserCache(LString 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 = NULL;
+       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
-LString UserCache::Find(uid_t ID)
+void GroupCache::add(gid_t ID) const 
 {
-       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(LString(),0,0);
-
-// Add: creates a new group entry
-GroupCache *GroupCache::Add(gid_t ID)
-{
-       LString pszNewName;
-       struct group *pEntry;
-
+       string pszNewName;
+       struct group * pEntry;
+       
        // gets user name
        if ((pEntry = getgrgid(ID))) pszNewName = pEntry->gr_name;
        else {
-               pszNewName = LString() + int(ID); // We don't have int cast to LString
+               pszNewName = tostr(ID);
        }
-
        // adds new node
-       return new GroupCache(pszNewName, ID, pRoot);
+       groups[ID] = pszNewName;
 }
 
 
-GroupCache::GroupCache(LString 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 = NULL;
-       }
+// static instances
+static UserCache lyxUserCache;
+static GroupCache lyxGroupCache;
 
-       // stores data
-       this->pszName = pszName;
-       this->ID = ID;
-}
 
+// 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 *);
 
-GroupCache::~GroupCache()
-{
-       if (pNext) delete pNext;
-}
-
-
-// Find: seeks group name from group ID
-LString 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 = r1->pszName.suffixIs('/'); 
-       bool r2d = r2->pszName.suffixIs('/');
-       if (r1d && !r2d) return -1;
-       if (!r1d && r2d) return 1;
-       return strcmp(r1->pszName.c_str(), r2->pszName.c_str());
-}
 
 // *** LyXFileDlg class implementation
 
 // static members
-FD_FileDlg *LyXFileDlg::pFileDlgForm = NULL;
-LyXFileDlg *LyXFileDlg::pCurrentDlg = NULL;
+FD_FileDlg * LyXFileDlg::pFileDlgForm = 0;
+LyXFileDlg * LyXFileDlg::pCurrentDlg = 0;
 
 
 // Reread: updates dialog list to match class directory
 void LyXFileDlg::Reread()
 {
-       int i;
-       DIR *pDirectory;
-       struct dirent *pDirEntry;
-       LString File, Buffer;   
-       char szMode[15], szTime[40];
-       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);
@@ -241,31 +217,26 @@ void LyXFileDlg::Reread()
 
        // Splits complete directory name into directories and compute depth
        iDepth = 0;
-       LString line, Temp;
-       File = pszDirectory;
+       string line, Temp;
+       char szMode[15];
+       FileInfo fileInfo;
+       string File = pszDirectory;
        if (File != "/") {
-               File.split(Temp, '/');
+               File = split(File, Temp, '/');
        }
        while (!File.empty() || !Temp.empty()) {
-               LString dline = "@b"+line + Temp + '/';         
+               string dline = "@b"+line + Temp + '/';          
                fl_add_browser_line(pFileDlgForm->List, dline.c_str());
-               File.split(Temp, '/');
+               File = split(File, Temp, '/');
                line += ' ';
-               iDepth++;
+               ++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(NULL);
+       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
@@ -274,7 +245,7 @@ void LyXFileDlg::Reread()
                         continue;
 
                // Gets filename
-               LString fname = pDirEntry->d_name;
+               string fname = pDirEntry->d_name;
 
                // Under all circumstances, "." and ".." are not wanted
                if (fname == "." || fname == "..")
@@ -284,14 +255,13 @@ void LyXFileDlg::Reread()
                File = AddName(pszDirectory, fname);
 
                fileInfo.newFile(File, true);
-
                fileInfo.modeString(szMode);
                unsigned int nlink = fileInfo.getNumberOfLinks();
-               LString user =  lyxUserCache.Find(fileInfo.getUid());
-               LString group = lyxGroupCache.Find(fileInfo.getGid());
+               string user =   lyxUserCache.find(fileInfo.getUid());
+               string group = lyxGroupCache.find(fileInfo.getGid());
 
                time_t modtime = fileInfo.getModificationTime();
-               strcpy(szTime, ctime(&modtime));
+               string Time = ctime(&modtime);
                
                if (curTime > fileInfo.getModificationTime() + SIX_MONTH_SEC
                    || curTime < fileInfo.getModificationTime()
@@ -301,38 +271,37 @@ 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.
-                       strcpy(szTime+10, szTime+19);
-                       szTime[15] = 0;
-               } else
-                       szTime[16] = 0;
-               
-               char szHeadBuf[128];              
-               sprintf(szHeadBuf, "%s %u %s %s %s ", szMode, 
-                       nlink,
-                       user.c_str(),
-                       group.c_str(),
-                       szTime + 4);            
-               Buffer = szHeadBuf;
+                       Time.erase(10, 9);
+                       Time.erase(15, string::npos);
+               } else {
+                       Time.erase(16, string::npos);
+               }
+
+               string Buffer = string(szMode) + ' ' +
+                       tostr(nlink) + ' ' +
+                       user + ' ' +
+                       group + ' ' +
+                       Time.substr(4, string::npos) + ' ';
 
                Buffer += pDirEntry->d_name;
                Buffer += fileInfo.typeIndicator();
 
                if ((isLink = fileInfo.isLink())) {
-                 LString 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
@@ -340,51 +309,53 @@ void LyXFileDlg::Reread()
                    || fileInfo.isChar()
                    || fileInfo.isBlock()
                    || fileInfo.isFifo()) {
-                       if (!fname.regexMatch(pszMask))
+                       if (!regexMatch(fname, pszMask))
                                continue;
                } else if (!(isDir = fileInfo.isDir()))
                        continue;
 
-               // Note pszLsEntry is an LString!
-               pCurrentNames[iNumNames].pszLsEntry = Buffer;
+               LyXDirEntry tmp;
 
+               // Note pszLsEntry is an string!
+               tmp.pszLsEntry = Buffer;
                // creates used name
-               LString temp = fname;
+               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) {
-               LString 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;
 }
 
 
 // SetDirectory: sets dialog current directory
-void LyXFileDlg::SetDirectory(LString const & Path)
+void LyXFileDlg::SetDirectory(string const & Path)
 {
        if (!pszDirectory.empty()) {
-               LString TempPath = ExpandPath(Path); // Expand ~/
+               string TempPath = ExpandPath(Path); // Expand ~/
                TempPath = MakeAbsPath(TempPath, pszDirectory);
                pszDirectory = MakeAbsPath(TempPath);
        } else pszDirectory = MakeAbsPath(Path);
@@ -392,7 +363,7 @@ void LyXFileDlg::SetDirectory(LString const & Path)
 
 
 // SetMask: sets dialog file mask
-void LyXFileDlg::SetMask(LString const & NewMask)
+void LyXFileDlg::SetMask(string const & NewMask)
 {
        pszMask = NewMask;
        fl_set_input(pFileDlgForm->PatBox, pszMask.c_str());
@@ -400,7 +371,7 @@ void LyXFileDlg::SetMask(LString const & NewMask)
 
 
 // SetInfoLine: sets dialog information line
-void LyXFileDlg::SetInfoLine(LString const & Line)
+void LyXFileDlg::SetInfoLine(string const & Line)
 {
        pszInfoLine = Line;
        fl_set_object_label(pFileDlgForm->FileInfo, pszInfoLine.c_str());
@@ -409,8 +380,7 @@ void LyXFileDlg::SetInfoLine(LString const & Line)
 
 LyXFileDlg::LyXFileDlg()
 {
-       pCurrentNames = 0;
-       pszDirectory = MakeAbsPath(LString('.'));
+       pszDirectory = MakeAbsPath(string("."));
        pszMask = '*';
 
        // Creates form if necessary. 
@@ -418,48 +388,56 @@ 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, NULL);
+               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);
+
+       r_ = Dialogs::redrawGUI.connect(slot(this, &LyXFileDlg::redraw));
 }
 
 
 LyXFileDlg::~LyXFileDlg()
 {
-       // frees directory entries
-       if (pCurrentNames) {
-               delete [] pCurrentNames;
-       }
+       r_.disconnect();
+}
+
+
+void LyXFileDlg::redraw()
+{
+       if (pFileDlgForm->FileDlg && pFileDlgForm->FileDlg->visible)
+               fl_redraw_form(pFileDlgForm->FileDlg);
 }
 
 
 // SetButton: sets file selector user button action
-void LyXFileDlg::SetButton(int iIndex, LString const & pszName, 
-                          LString const & pszPath)
+void LyXFileDlg::SetButton(int iIndex, string const & pszName, 
+                          string const & pszPath)
 {
-       FL_OBJECT *pObject;
-       LString *pTemp;
+       FL_OBJECT * pObject;
+       string * pTemp;
 
        if (iIndex == 0) {
                pObject = pFileDlgForm->User1;
@@ -475,18 +453,18 @@ void LyXFileDlg::SetButton(int iIndex, LString const & pszName,
                *pTemp = pszPath;
        } else {
                fl_hide_object(pObject);
-               *pTemp = LString();
+               (*pTemp).erase();
        }
 }
 
 
 // GetDirectory: gets last dialog directory
-LString LyXFileDlg::GetDirectory() 
+string const LyXFileDlg::GetDirectory() const
 {
        if (!pszDirectory.empty())
                return pszDirectory;
        else
-               return LString('.');
+               return string(".");
 }
 
 
@@ -498,7 +476,6 @@ bool LyXFileDlg::RunDialog()
        
         // event loop
         while(true) {
-
                 FL_OBJECT * pObject = fl_do_forms();
 
                 if (pObject == pFileDlgForm->Ready) {
@@ -541,7 +518,7 @@ void LyXFileDlg::FileDlgCB(FL_OBJECT *, long lArgument)
                break;
 
        case 11: // home
-               pCurrentDlg->SetDirectory(getEnvPath("HOME"));
+               pCurrentDlg->SetDirectory(GetEnvPath("HOME"));
                pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
                pCurrentDlg->Reread();
                break;
@@ -549,7 +526,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;
@@ -557,7 +535,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;
@@ -566,15 +545,21 @@ 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(LString());
+               SetInfoLine(string());
        }
 }
 
@@ -588,49 +573,51 @@ 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;
-       LString pszTemp;
-       int iSelect;  
+       string pszTemp;
 
        // 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);
-               if (!pszTemp.suffixIs('/')) {
+               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) {
-               SetInfoLine(LString());
+       } else if (iSelect != 0) {
+               SetInfoLine(string());
        } else
                return true;
 
        // executes action
        if (isDir) {
-
-               int i;
-               LString Temp;
+               string Temp;
 
                // builds new directory name
                if (iSelect > iDepth) {
                        // Directory deeper down
                        // First, get directory with trailing /
                        Temp = fl_get_input(pFileDlgForm->DirBox);
-                       if (!Temp.suffixIs('/'))
+                       if (!suffixIs(Temp, '/'))
                                Temp += '/';
                        Temp += pszTemp;
                } else {
                        // Directory higher up
-                       Temp.clean();
-                       for (i = 0; i < iSelect; ++i) {
-                               LString piece = fl_get_browser_line(pFileDlgForm->List, i+1);
+                       Temp.erase();
+                       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.substring(i+2, piece.length()-1);
+                               Temp += piece.substr(i + 2);
                        }
                }
 
@@ -646,11 +633,9 @@ bool LyXFileDlg::HandleDoubleClick()
 // Handle OK button call
 bool LyXFileDlg::HandleOK()
 {
-       LString 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;
@@ -658,26 +643,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) {
-               LString temp = pCurrentNames[select - iDepth - 1].pszName;
-               if (!temp.suffixIs('/')) {
+               string const temp = direntries[select - iDepth - 1].pszName;
+               if (!suffixIs(temp, '/')) {
                        // If user didn't type anything, use browser
-                       LString 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();
 }
@@ -692,6 +678,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)
 {
@@ -708,13 +700,11 @@ void LyXFileDlg::Force(bool cancel)
 
 
 // Select: launches dialog and returns selected file
-LString LyXFileDlg::Select(LString const & title, LString const & path, 
-                          LString const & mask, LString 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;
@@ -724,33 +714,50 @@ LString LyXFileDlg::Select(LString const & title, LString 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 LString();
+       if (pCurrentDlg) return string();
        pCurrentDlg = this;
 
        // runs dialog
-       SetInfoLine (LString());
+       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 = NULL;
+       pCurrentDlg = 0;
 
-       // Returns filename or LString() if no valid selection was made
-       if (!isOk || !fl_get_input(pFileDlgForm->Filename)[0]) return LString();
+       // Returns filename or string() if no valid selection was made
+       if (!isOk || !fl_get_input(pFileDlgForm->Filename)[0]) return string();
 
        pszFileName = fl_get_input(pFileDlgForm->Filename);