home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / filedlg.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  18KB  |  764 lines

  1. // -*- C++ -*-
  2. /* This file is part of
  3. * ======================================================
  4. *           LyX, The Document Processor
  5. *        
  6. *           Copyright (C) 1995 Matthias Ettrich
  7. *           Copyright (C) 1995-1998 The LyX Team.
  8. *
  9. *======================================================*/
  10.  
  11. #include <config.h>
  12.  
  13. //     $Id: filedlg.C,v 1.1.1.1 1998/04/23 16:02:49 larsbj Exp $    
  14.  
  15. #if !defined(lint) && !defined(WITH_WARNINGS)
  16. static char vcid[] = "$Id: filedlg.C,v 1.1.1.1 1998/04/23 16:02:49 larsbj Exp $";
  17. #endif /* lint */
  18.  
  19. #include <unistd.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <pwd.h>
  23. #include <grp.h>
  24. #include <string.h>
  25.  
  26. #include "lyx_gui_misc.h" // CancelCloseCB
  27. #include "FileInfo.h"
  28. #include "gettext.h"
  29.  
  30. #ifdef HAVE_ERRNO_H
  31. #include <errno.h>
  32. #endif
  33.  
  34. #if HAVE_DIRENT_H
  35. # include <dirent.h>
  36. # define NAMLEN(dirent) strlen((dirent)->d_name)
  37. #else
  38. # define dirent direct
  39. # define NAMLEN(dirent) (dirent)->d_namlen
  40. # if HAVE_SYS_NDIR_H
  41. #  include <sys/ndir.h>
  42. # endif
  43. # if HAVE_SYS_DIR_H
  44. #  include <sys/dir.h>
  45. # endif
  46. # if HAVE_NDIR_H
  47. #  include <ndir.h>
  48. # endif
  49. #endif
  50.  
  51. #if TIME_WITH_SYS_TIME
  52. # include <sys/time.h>
  53. # include <time.h>
  54. #else
  55. # if HAVE_SYS_TIME_H
  56. #  include <sys/time.h>
  57. # else
  58. #  include <time.h>
  59. # endif
  60. #endif
  61.  
  62. #ifdef BROKEN_HEADERS
  63. extern "C" int gettimeofday(struct timeval *,struct timezone *);
  64. #define remove(a) unlink(a)      
  65. #endif
  66.  
  67. #ifdef __GNUG__
  68. #pragma implementation
  69. #endif
  70.  
  71. #include "filetools.h"
  72. #include "filedlg.h"
  73. #include "definitions.h"
  74.  
  75. static const long SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L; // six months, in seconds
  76. static const long ONE_HOUR_SEC = 60L * 60L;
  77.  
  78. // *** User cache class implementation
  79.  
  80. // global instance (user cache root)
  81. UserCache lyxUserCache = UserCache(LString(),0,0);
  82.  
  83.  
  84. // Add: creates a new user entry
  85. UserCache *UserCache::Add(uid_t ID)
  86. {
  87.     LString pszNewName;
  88.     struct passwd *pEntry;
  89.  
  90.     // gets user name
  91.     if ((pEntry = getpwuid(ID)))
  92.         pszNewName = pEntry->pw_name;
  93.     else {
  94.         pszNewName = LString() + int(ID); // We don't have int cast to LString
  95.     }
  96.  
  97.     // adds new node
  98.     return new UserCache(pszNewName, ID, pRoot);
  99. }
  100.  
  101.  
  102. UserCache::UserCache(LString const & pszName, uid_t ID, UserCache *pRoot)
  103. {
  104.     // links node
  105.     if (pRoot) {
  106.         this->pRoot = pRoot;
  107.         pNext = pRoot->pNext;
  108.         pRoot->pNext = this;
  109.     } else {
  110.         this->pRoot = this;
  111.         pNext = NULL;
  112.     }
  113.  
  114.     // stores data
  115.     this->pszName = pszName;
  116.     this->ID = ID;
  117. }
  118.  
  119.  
  120. UserCache::~UserCache()
  121. {
  122.     if (pNext) delete pNext;
  123. }
  124.  
  125.  
  126. // Find: seeks user name from user ID
  127. LString UserCache::Find(uid_t ID)
  128. {
  129.     if ((!pszName.empty()) && (this->ID == ID)) return pszName; 
  130.     if (pNext) return pNext->Find(ID);
  131.  
  132.     return pRoot->Add(ID)->pszName;
  133. }
  134.  
  135.  
  136. // *** Group cache class implementation
  137.  
  138. // global instance (group cache root)
  139. GroupCache lyxGroupCache = GroupCache(LString(),0,0);
  140.  
  141. // Add: creates a new group entry
  142. GroupCache *GroupCache::Add(gid_t ID)
  143. {
  144.     LString pszNewName;
  145.     struct group *pEntry;
  146.  
  147.     // gets user name
  148.     if ((pEntry = getgrgid(ID))) pszNewName = pEntry->gr_name;
  149.     else {
  150.         pszNewName = LString() + int(ID); // We don't have int cast to LString
  151.     }
  152.  
  153.     // adds new node
  154.     return new GroupCache(pszNewName, ID, pRoot);
  155. }
  156.  
  157.  
  158. GroupCache::GroupCache(LString const & pszName, gid_t ID, GroupCache *pRoot)
  159. {
  160.     // links node
  161.     if (pRoot) {
  162.         this->pRoot = pRoot;
  163.         pNext = pRoot->pNext;
  164.         pRoot->pNext = this;
  165.     } else {
  166.         this->pRoot = this;
  167.         pNext = NULL;
  168.     }
  169.  
  170.     // stores data
  171.     this->pszName = pszName;
  172.     this->ID = ID;
  173. }
  174.  
  175.  
  176. GroupCache::~GroupCache()
  177. {
  178.     if (pNext) delete pNext;
  179. }
  180.  
  181.  
  182. // Find: seeks group name from group ID
  183. LString GroupCache::Find(gid_t ID)
  184. {
  185.     if ((!pszName.empty()) && (this->ID == ID)) return pszName; 
  186.     if (pNext) return pNext->Find(ID);
  187.  
  188.     return pRoot->Add(ID)->pszName;
  189. }
  190.  
  191. // *** LyXDirEntry internal structure implementation
  192.  
  193. // ldeCompProc: compares two LyXDirEntry objects content (used for qsort)
  194. int LyXDirEntry::ldeCompProc(const LyXDirEntry *r1, 
  195.                  const LyXDirEntry *r2)
  196. {
  197.     bool r1d = r1->pszName.suffixIs('/'); 
  198.     bool r2d = r2->pszName.suffixIs('/');
  199.     if (r1d && !r2d) return -1;
  200.     if (!r1d && r2d) return 1;
  201.     return strcmp(r1->pszName.c_str(), r2->pszName.c_str());
  202. }
  203.  
  204. // *** LyXFileDlg class implementation
  205.  
  206. // static members
  207. FD_FileDlg *LyXFileDlg::pFileDlgForm = NULL;
  208. LyXFileDlg *LyXFileDlg::pCurrentDlg = NULL;
  209.  
  210.  
  211. // Reread: updates dialog list to match class directory
  212. void LyXFileDlg::Reread()
  213. {
  214.     int i;
  215.     DIR *pDirectory;
  216.     struct dirent *pDirEntry;
  217.     LString szFile;
  218.     char szBuffer[256], szMode[15], szTime[40];
  219.     FileInfo fileInfo;
  220.     
  221.     // Opens directory
  222.     pDirectory = opendir(pszDirectory.c_str());
  223.     if (!pDirectory) {
  224.         WriteFSAlert(_("Warning! Couldn't open directory."), 
  225.                  pszDirectory);
  226.         pszDirectory = GetCWD();
  227.         pDirectory = opendir(pszDirectory.c_str());
  228.     }
  229.  
  230.     // Clear the present namelist
  231.     if (pCurrentNames) {
  232.         delete [] pCurrentNames;
  233.         pCurrentNames = 0;
  234.     }
  235.  
  236.     // Updates display
  237.     fl_hide_object(pFileDlgForm->List);
  238.     fl_clear_browser(pFileDlgForm->List);
  239.     fl_set_input(pFileDlgForm->DirBox, pszDirectory.c_str());
  240.  
  241.     // Splits complete directory name into directories and compute depth
  242.     iDepth = 0;
  243.     LString line, Temp;
  244.     szFile = pszDirectory;
  245.     if (szFile != "/") {
  246.         szFile.split(Temp, '/');
  247.     }
  248.     while (!szFile.empty() || !Temp.empty()) {
  249.         LString dline = "@b"+line + Temp + '/';        
  250.         fl_add_browser_line(pFileDlgForm->List, dline.c_str());
  251.         szFile.split(Temp, '/');
  252.         line += ' ';
  253.         iDepth++;
  254.     }
  255.  
  256.     // Allocate names array
  257.     iNumNames = 0;
  258.     rewinddir(pDirectory);
  259.     while ((readdir(pDirectory))) ++iNumNames;
  260.     pCurrentNames = new LyXDirEntry[iNumNames];
  261.  
  262.     // Parses all entries of the given subdirectory
  263.     iNumNames = 0;
  264.     time_t curTime = time(NULL);
  265.     rewinddir(pDirectory);
  266.     while ((pDirEntry = readdir(pDirectory))) {
  267.  
  268.         bool isLink = false, isDir = false;
  269.  
  270.         // If the pattern doesn't start with a dot, skip hidden files
  271.         if (!pszMask.empty() && pszMask[0] != '.' && 
  272.             pDirEntry->d_name[0] == '.')
  273.                         continue;
  274.  
  275.         // Gets filename
  276.         LString fname = pDirEntry->d_name;
  277.  
  278.         // Under all circumstances, "." and ".." are not wanted
  279.         if (fname == "." || fname == "..")
  280.             continue;
  281.  
  282.         // gets file status
  283.         szFile = AddName(pszDirectory, fname);
  284.  
  285.         fileInfo.newFile(szFile, true);
  286.  
  287.         fileInfo.modeString(szMode);
  288.         unsigned int nlink = fileInfo.getNumberOfLinks();
  289.         LString user =    lyxUserCache.Find(fileInfo.getUid());
  290.         LString group = lyxGroupCache.Find(fileInfo.getGid());
  291.  
  292.         strcpy(szTime, ctime(&(fileInfo.getModificationTime())));
  293.         
  294.         if (curTime > fileInfo.getModificationTime() + SIX_MONTH_SEC
  295.             || curTime < fileInfo.getModificationTime()
  296.             + ONE_HOUR_SEC) {
  297.             // The file is fairly old or in the future. POSIX says
  298.             // the cutoff is 6 months old. Allow a 1 hour slop
  299.             // factor for what is considered "the future", to
  300.             // allow for NFS server/client clock disagreement.
  301.             // Show the year instead of the time of day.
  302.             strcpy(szTime+10, szTime+19);
  303.             szTime[15] = 0;
  304.         } else
  305.             szTime[16] = 0;
  306.         
  307.         sprintf(szBuffer, "%s %u %s %s %s ", szMode, 
  308.             nlink,
  309.             user.c_str(),
  310.             group.c_str(),
  311.             szTime + 4);
  312.  
  313.         strcat(szBuffer, pDirEntry->d_name);
  314.         strcat(szBuffer, fileInfo.typeIndicator());
  315.  
  316.         if ((isLink = fileInfo.isLink())) {
  317.             char *pszLinkBuffer;
  318.             char szTempLink[512];
  319.             int nRead;
  320.  
  321.             fileInfo.newFile(szFile);
  322.             
  323.             nRead = readlink(szFile.c_str(), 
  324.                      szTempLink, sizeof(szTempLink));
  325.             pszLinkBuffer = new char[nRead + 10];
  326.             strcat (szBuffer, " -> ");
  327.  
  328.             if (nRead > 0) strncpy(pszLinkBuffer, 
  329.                            szTempLink, nRead);
  330.             pszLinkBuffer[nRead] = 0;
  331.  
  332.             strcat(pszLinkBuffer, fileInfo.typeIndicator());
  333.             strcat(szBuffer, pszLinkBuffer);
  334.             
  335.             // frees link buffer
  336.             delete [] pszLinkBuffer;
  337.         }
  338.  
  339.         // filters files according to pattern and type
  340.         if (fileInfo.isRegular()
  341.             || fileInfo.isChar()
  342.             || fileInfo.isBlock()
  343.             || fileInfo.isFifo()) {
  344.             if (!fname.regexMatch(pszMask))
  345.                 continue;
  346.         } else if (!(isDir = fileInfo.isDir()))
  347.             continue;
  348.         
  349.         pCurrentNames[iNumNames].pszLsEntry = szBuffer;
  350.  
  351.         // creates used name
  352.         LString temp = fname;
  353.         if (isDir) temp += '/';
  354.         pCurrentNames[iNumNames].pszName = temp;
  355.  
  356.         // creates displayed name
  357.         temp = pDirEntry->d_name;
  358.         if (isLink)
  359.             temp += '@';
  360.         else
  361.             temp += fileInfo.typeIndicator();
  362.         
  363.         pCurrentNames[iNumNames++].pszDisplayed = temp;
  364.     }
  365.  
  366.     closedir(pDirectory);
  367.  
  368.     // Sort the names
  369.     qsort(pCurrentNames, iNumNames, sizeof(LyXDirEntry), 
  370.           (int (*)(const void *, const void *))LyXDirEntry::ldeCompProc);
  371.  
  372.     // Add them to directory box
  373.     for (i = 0; i < iNumNames; ++i) {
  374.         LString temp = line + pCurrentNames[i].pszDisplayed;
  375.         fl_add_browser_line(pFileDlgForm->List, temp.c_str());
  376.     }
  377.     fl_set_browser_topline(pFileDlgForm->List,iDepth);
  378.     fl_show_object(pFileDlgForm->List);
  379.     iLastSel = -1;
  380. }
  381.  
  382.  
  383. // SetDirectory: sets dialog current directory
  384. void LyXFileDlg::SetDirectory(LString const & Path)
  385. {
  386.     if (!pszDirectory.empty()) {
  387.         LString TempPath = ExpandPath(Path); // Expand ~/
  388.         TempPath = MakeAbsPath(TempPath, pszDirectory);
  389.         pszDirectory = MakeAbsPath(TempPath);
  390.     } else pszDirectory = MakeAbsPath(Path);
  391. }
  392.  
  393.  
  394. // SetMask: sets dialog file mask
  395. void LyXFileDlg::SetMask(LString const & NewMask)
  396. {
  397.     pszMask = NewMask;
  398.     fl_set_input(pFileDlgForm->PatBox, pszMask.c_str());
  399. }
  400.  
  401.  
  402. // SetInfoLine: sets dialog information line
  403. void LyXFileDlg::SetInfoLine(LString const & Line)
  404. {
  405.     pszInfoLine = Line;
  406.     fl_set_object_label(pFileDlgForm->FileInfo, pszInfoLine.c_str());
  407. }
  408.  
  409.  
  410. LyXFileDlg::LyXFileDlg()
  411. {
  412.     pCurrentNames = 0;
  413.     pszDirectory = MakeAbsPath(LString("."));
  414.     pszMask = '*';
  415.  
  416.     // Creates form if necessary. 
  417.     if (!pFileDlgForm) {
  418.         pFileDlgForm = create_form_FileDlg();
  419.         // Set callbacks. This means that we don't need a patch file
  420.         fl_set_object_callback(pFileDlgForm->DirBox,
  421.                        LyXFileDlg::FileDlgCB,0);
  422.         fl_set_object_callback(pFileDlgForm->PatBox,
  423.                        LyXFileDlg::FileDlgCB,1);
  424.         fl_set_object_callback(pFileDlgForm->List,
  425.                        LyXFileDlg::FileDlgCB,2);
  426.         fl_set_object_callback(pFileDlgForm->Filename,
  427.                        LyXFileDlg::FileDlgCB,3);
  428.         fl_set_object_callback(pFileDlgForm->Rescan,
  429.                        LyXFileDlg::FileDlgCB,10);
  430.         fl_set_object_callback(pFileDlgForm->Home,
  431.                        LyXFileDlg::FileDlgCB,11);
  432.         fl_set_object_callback(pFileDlgForm->User1,
  433.                        LyXFileDlg::FileDlgCB,12);
  434.         fl_set_object_callback(pFileDlgForm->User2,
  435.                        LyXFileDlg::FileDlgCB,13);
  436.         
  437.         // Make sure pressing the close box doesn't crash LyX. (RvdK)
  438.         fl_set_form_atclose(pFileDlgForm->FileDlg, CancelCB, NULL);
  439.            // Register doubleclick callback
  440.         fl_set_browser_dblclick_callback(pFileDlgForm->List,
  441.                          DoubleClickCB,0);
  442.     }
  443.     fl_hide_object(pFileDlgForm->User1);
  444.     fl_hide_object(pFileDlgForm->User2);
  445. }
  446.  
  447.  
  448. LyXFileDlg::~LyXFileDlg()
  449. {
  450.     // frees directory entries
  451.     if (pCurrentNames) {
  452.         delete [] pCurrentNames;
  453.     }
  454. }
  455.  
  456.  
  457. // SetButton: sets file selector user button action
  458. void LyXFileDlg::SetButton(int iIndex, LString const & pszName, 
  459.                LString const & pszPath)
  460. {
  461.     FL_OBJECT *pObject;
  462.     LString *pTemp;
  463.  
  464.     if (iIndex == 0) {
  465.         pObject = pFileDlgForm->User1;
  466.         pTemp = &pszUserPath1;
  467.     } else if (iIndex == 1) {            
  468.         pObject = pFileDlgForm->User2;
  469.         pTemp = &pszUserPath2;
  470.     } else return;
  471.  
  472.     if (!pszName.empty() && !pszPath.empty()) {
  473.         fl_set_object_label(pObject, pszName.c_str());
  474.         fl_show_object(pObject);
  475.         *pTemp = pszPath;
  476.     } else {
  477.         fl_hide_object(pObject);
  478.         *pTemp = LString();
  479.     }
  480. }
  481.  
  482.  
  483. // GetDirectory: gets last dialog directory
  484. LString LyXFileDlg::GetDirectory() 
  485. {
  486.     if (!pszDirectory.empty())
  487.         return pszDirectory;
  488.     else
  489.         return LString(".");
  490. }
  491.  
  492.  
  493. // RunDialog: handle dialog during file selection
  494. bool LyXFileDlg::RunDialog()
  495. {
  496.     force_cancel = false;
  497.     force_ok = false;
  498.     
  499.         // event loop
  500.         while(true) {
  501.  
  502.                 FL_OBJECT * pObject = fl_do_forms();
  503.  
  504.                 if (pObject == pFileDlgForm->Ready) {
  505.             if (HandleOK())
  506.                 return true;
  507.         } else if (pObject == pFileDlgForm->Cancel 
  508.                || force_cancel) 
  509.             return false;
  510.         else if (force_ok)
  511.             return true;
  512.     }
  513. }
  514.  
  515.  
  516. // XForms objects callback (static)
  517. void LyXFileDlg::FileDlgCB(FL_OBJECT *, long lArgument)
  518. {
  519.     if (!pCurrentDlg) return;
  520.  
  521.     switch (lArgument) {
  522.  
  523.     case 0: // get directory
  524.         pCurrentDlg->SetDirectory(fl_get_input(pFileDlgForm->DirBox));
  525.         pCurrentDlg->Reread();
  526.         break;
  527.  
  528.     case 1: // get mask
  529.         pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
  530.         pCurrentDlg->Reread();
  531.         break;
  532.  
  533.     case 2: // list
  534.         pCurrentDlg->HandleListHit();
  535.         break;    
  536.  
  537.     case 10: // rescan
  538.         pCurrentDlg->SetDirectory(fl_get_input(pFileDlgForm->DirBox));
  539.         pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
  540.         pCurrentDlg->Reread();
  541.         break;
  542.  
  543.     case 11: // home
  544.         pCurrentDlg->SetDirectory(getEnvPath("HOME"));
  545.         pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
  546.         pCurrentDlg->Reread();
  547.         break;
  548.  
  549.     case 12: // user button 1
  550.         if (!pCurrentDlg->pszUserPath1.empty()) {
  551.             pCurrentDlg->SetDirectory(pCurrentDlg->pszUserPath1);
  552.             pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
  553.             pCurrentDlg->Reread();
  554.         }
  555.         break;
  556.  
  557.     case 13: // user button 2
  558.         if (!pCurrentDlg->pszUserPath2.empty()) {
  559.             pCurrentDlg->SetDirectory(pCurrentDlg->pszUserPath2);
  560.             pCurrentDlg->SetMask(fl_get_input(pFileDlgForm->PatBox));
  561.             pCurrentDlg->Reread();
  562.         }
  563.         break;
  564.  
  565.     }
  566. }
  567.  
  568.  
  569. // Handle callback from list
  570. void LyXFileDlg::HandleListHit()
  571. {
  572.     // set info line
  573.     int iSelect = fl_get_browser(pFileDlgForm->List);
  574.     if (iSelect > iDepth)  {
  575.         SetInfoLine(pCurrentNames[iSelect - iDepth - 1].pszLsEntry);
  576.     } else {
  577.         SetInfoLine(LString());
  578.     }
  579. }
  580.  
  581.  
  582. // Callback for double click in list
  583. void LyXFileDlg::DoubleClickCB(FL_OBJECT *, long)
  584. {
  585.     if (pCurrentDlg->HandleDoubleClick())
  586.         // Simulate click on OK button
  587.         pCurrentDlg->Force(false);
  588. }
  589.  
  590.  
  591. // Handle double click from list
  592. bool LyXFileDlg::HandleDoubleClick()
  593. {
  594.     bool isDir;
  595.     LString pszTemp;
  596.     int iSelect;  
  597.  
  598.     // set info line
  599.     isDir = true;
  600.     iSelect = fl_get_browser(pFileDlgForm->List);
  601.     if (iSelect > iDepth)  {
  602.         pszTemp = pCurrentNames[iSelect - iDepth - 1].pszName;
  603.         SetInfoLine(pCurrentNames[iSelect - iDepth - 1].pszLsEntry);
  604.         if (!pszTemp.suffixIs('/')) {
  605.             isDir = false;
  606.             fl_set_input(pFileDlgForm->Filename, pszTemp.c_str());
  607.         }
  608.     } else if (iSelect !=0) {
  609.         SetInfoLine(LString());
  610.     } else
  611.         return true;
  612.  
  613.     // executes action
  614.     if (isDir) {
  615.  
  616.         int i;
  617.         LString Temp;
  618.  
  619.         // builds new directory name
  620.         if (iSelect > iDepth) {
  621.             // Directory deeper down
  622.             // First, get directory with trailing /
  623.             Temp = fl_get_input(pFileDlgForm->DirBox);
  624.             if (!Temp.suffixIs('/'))
  625.                 Temp += '/';
  626.             Temp += pszTemp;
  627.         } else {
  628.             // Directory higher up
  629.             Temp.erase();
  630.             for (i = 0; i < iSelect; ++i) {
  631.                 LString piece = fl_get_browser_line(pFileDlgForm->List, i+1);
  632.                 // The '+2' is here to count the '@b' (JMarc)
  633.                 Temp += piece.substring(i+2, piece.length()-1);
  634.             }
  635.         }
  636.  
  637.         // assigns it
  638.         SetDirectory(Temp);
  639.         Reread();
  640.         return false;
  641.     }
  642.     return true;
  643. }
  644.  
  645.  
  646. // Handle OK button call
  647. bool LyXFileDlg::HandleOK()
  648. {
  649.     LString pszTemp;
  650.  
  651.     // mask was changed
  652.     pszTemp = fl_get_input(pFileDlgForm->PatBox);
  653.     if (pszTemp!=pszMask) {
  654.         SetMask(pszTemp);
  655.         Reread();
  656.         return false;
  657.     }
  658.  
  659.     // directory was changed
  660.     pszTemp = fl_get_input(pFileDlgForm->DirBox);
  661.     if (pszTemp!=pszDirectory) {
  662.         SetDirectory(pszTemp);
  663.         Reread();
  664.         return false;
  665.     }
  666.     
  667.     // Handle return from list
  668.     int select = fl_get_browser(pFileDlgForm->List);
  669.     if (select > iDepth) {
  670.         LString temp = pCurrentNames[select - iDepth - 1].pszName;
  671.         if (!temp.suffixIs('/')) {
  672.             // If user didn't type anything, use browser
  673.             LString name = fl_get_input(pFileDlgForm->Filename);
  674.             if (name.empty()) {
  675.                 fl_set_input(pFileDlgForm->Filename, temp.c_str());
  676.             }
  677.             return true;
  678.         }
  679.     }
  680.     
  681.     // Emulate a doubleclick
  682.     return HandleDoubleClick();
  683. }
  684.  
  685.  
  686. // Handle Cancel CB from WM close
  687. int LyXFileDlg::CancelCB(FL_FORM *, void *)
  688. {
  689.     // Simulate a click on the cancel button
  690.     pCurrentDlg->Force(true);
  691.       return FL_IGNORE;
  692. }
  693.  
  694.  
  695. // Simulates a click on OK/Cancel
  696. void LyXFileDlg::Force(bool cancel)
  697. {
  698.     if (cancel) {
  699.         force_cancel = true;
  700.         fl_set_button(pFileDlgForm->Cancel, 1);
  701.     } else {
  702.         force_ok = true;
  703.         fl_set_button(pFileDlgForm->Ready, 1);
  704.     }
  705.     // Start timer to break fl_do_forms loop soon
  706.     fl_set_timer(pFileDlgForm->timer, 0.1);
  707. }
  708.  
  709.  
  710. // Select: launches dialog and returns selected file
  711. LString LyXFileDlg::Select(LString const & title, LString const & path, 
  712.                LString const & mask, LString const & suggested)
  713. {
  714.     bool isOk;
  715.  
  716.     // handles new mask and path
  717.     isOk = true;
  718.     if (!mask.empty()) {
  719.         SetMask(mask);
  720.         isOk = false;
  721.     }
  722.     if (!path.empty()) {
  723.         SetDirectory(path);
  724.         isOk = false;
  725.     }
  726.     if (!isOk) Reread();
  727.     else {
  728.         fl_select_browser_line(pFileDlgForm->List, 1);
  729.         fl_set_browser_topline(pFileDlgForm->List, 1);
  730.     }
  731.  
  732.     // checks whether dialog can be started
  733.     if (pCurrentDlg) return LString();
  734.     pCurrentDlg = this;
  735.  
  736.     // runs dialog
  737.     SetInfoLine (LString());
  738.     fl_set_input(pFileDlgForm->Filename, suggested.c_str());
  739.     fl_set_button(pFileDlgForm->Cancel, 0);
  740.     fl_set_button(pFileDlgForm->Ready, 0);
  741.     fl_set_focus_object(pFileDlgForm->FileDlg, pFileDlgForm->Filename);
  742.     fl_deactivate_all_forms();
  743.     fl_show_form(pFileDlgForm->FileDlg, FL_PLACE_MOUSE | FL_FREE_SIZE,
  744.              FL_FULLBORDER, title.c_str());
  745.  
  746.     isOk = RunDialog();
  747.  
  748.     fl_hide_form(pFileDlgForm->FileDlg);
  749.     fl_activate_all_forms();
  750.     pCurrentDlg = NULL;
  751.  
  752.     // Returns filename or LString() if no valid selection was made
  753.     if (!isOk || !fl_get_input(pFileDlgForm->Filename)[0]) return LString();
  754.  
  755.     pszFileName = fl_get_input(pFileDlgForm->Filename);
  756.  
  757.     if (!AbsolutePath(pszFileName)) {
  758.         pszFileName = AddName(fl_get_input(pFileDlgForm->DirBox), 
  759.                       pszFileName);
  760.     }
  761.     return pszFileName;
  762. }
  763.