1 // $Id: Flu_File_Chooser.h,v 1.63 2004/10/18 15:14:58 jbryan Exp $
2 
3 /***************************************************************
4  *                FLU - FLTK Utility Widgets
5  *  Copyright (C) 2002 Ohio Supercomputer Center, Ohio State University
6  *
7  * This file and its content is protected by a software license.
8  * You should have received a copy of this license with this file.
9  * If not, please contact the Ohio Supercomputer Center immediately:
10  * Attn: Jason Bryan Re: FLU 1224 Kinnear Rd, Columbus, Ohio 43212
11  *
12  ***************************************************************/
13 
14 
15 
16 #ifndef _FLU_FILE_CHOOSER_H
17 #define _FLU_FILE_CHOOSER_H
18 
19 #include <FL/Fl_Double_Window.H>
20 #include <FL/Fl_Input.H>
21 #include <FL/Fl_Menu_Button.H>
22 #include <FL/Fl_Tile.H>
23 #include <FL/Fl_Pack.H>
24 #include <FL/Fl_Scroll.H>
25 #include <FL/Fl_Check_Button.H>
26 
27 #include "Flu_Button.h"
28 #include "Flu_Return_Button.h"
29 #include "Flu_Wrap_Group.h"
30 #include "Flu_Combo_Tree.h"
31 #include "Flu_Combo_List.h"
32 #include "flu_export.h"
33 #include "FluSimpleString.h"
34 #include "FluVectorClass.h"
35 
36 FluMakeVectorClass( FluSimpleString, FluStringVector );
37 
38 FLU_EXPORT const char* flu_file_chooser( const char *message, const char *pattern, const char *filename );
39 FLU_EXPORT int flu_multi_file_chooser( const char *message, const char *pattern, const char *filename, FluStringVector *filelist );
40 FLU_EXPORT const char* flu_save_chooser( const char *message, const char *pattern, const char *filename );
41 FLU_EXPORT const char* flu_dir_chooser( const char *message, const char *filename );
42 FLU_EXPORT const char* flu_dir_chooser( const char *message, const char *filename, bool showFiles );
43 FLU_EXPORT const char* flu_file_and_dir_chooser( const char *message, const char *filename );
44 
45 //! A file and directory choosing widget that looks and acts similar to the stock Windows file chooser
46 class FLU_EXPORT Flu_File_Chooser : public Fl_Double_Window
47 {
48 
49   friend class FileInput;
50   class FileInput : public Fl_Input
51     {
52     public:
53       FileInput( int x, int y, int w, int h, const char *l, Flu_File_Chooser *c );
54       ~FileInput();
55 
56       int handle( int event );
57     protected:
58       Flu_File_Chooser *chooser;
59     };
60 
61  public:
62 
63   //! strings to be set by a programmer to the correct phrase or name for their language
64   /*! (they are in english by default)   */
65   static FluSimpleString favoritesTxt;
66   static FluSimpleString desktopTxt;
67   static FluSimpleString myComputerTxt;
68   static FluSimpleString myDocumentsTxt;
69 
70   static FluSimpleString filenameTxt;
71   static FluSimpleString okTxt;
72   static FluSimpleString cancelTxt;
73   static FluSimpleString locationTxt;
74   static FluSimpleString showHiddenTxt;
75   static FluSimpleString fileTypesTxt;
76   static FluSimpleString directoryTxt;
77   static FluSimpleString allFilesTxt;
78   static FluSimpleString defaultFolderNameTxt;
79 
80   static FluSimpleString backTTxt;
81   static FluSimpleString forwardTTxt;
82   static FluSimpleString upTTxt;
83   static FluSimpleString reloadTTxt;
84   static FluSimpleString trashTTxt;
85   static FluSimpleString newDirTTxt;
86   static FluSimpleString addFavoriteTTxt;
87   static FluSimpleString previewTTxt;
88   static FluSimpleString listTTxt;
89   static FluSimpleString wideListTTxt;
90   static FluSimpleString detailTTxt;
91 
92   static FluSimpleString detailTxt[4];
93   static FluSimpleString contextMenuTxt[3];
94   static FluSimpleString diskTypesTxt[6];
95 
96   static FluSimpleString createFolderErrTxt;
97   static FluSimpleString deleteFileErrTxt;
98   static FluSimpleString fileExistsErrTxt;
99   static FluSimpleString renameErrTxt;
100 
101   //! This class must be derived from to create a "preview" widget.
102   /*! Simply derive from this class and overload Fl_Group's methods to create a widget
103     able to preview whatever file type you want. Register it with Flu_File_Chooser::add_preview_handler()
104     When a file is previewed, all registered handlers are visited until the preview() virtual function
105     for one of them returns nonzero. When preview() is called, the absolute path of the file is passed in,
106     and the widget should determine whether it can preview the file and update itself accordingly. If
107     it can preview the file, it should return nonzero, else it should return zero.
108    */
109   class FLU_EXPORT PreviewWidgetBase : public Fl_Group
110     {
111     public:
112       PreviewWidgetBase();
113       virtual ~PreviewWidgetBase();
114       virtual int preview( const char *filename ) = 0;
115     };
116 
117   //! File entry type
118   enum {
119     ENTRY_NONE = 1,         /*!< An empty (or non-existant) entry */
120     ENTRY_DIR = 2,          /*!< A directory entry */
121     ENTRY_FILE = 4,         /*!< A file entry */
122     ENTRY_FAVORITE = 8,     /*!< A favorite entry */
123     ENTRY_DRIVE = 16,       /*!< An entry that refers to a disk drive */
124     ENTRY_MYDOCUMENTS = 32, /*!< The entry referring to the current user's documents */
125     ENTRY_MYCOMPUTER = 64   /*!< The entry referring to "My Computer" in Windows */
126   };
127 
128   //! Chooser type
129   enum {
130     SINGLE = 0,            /*!< Choose a single file or directory */
131     MULTI = 1,             /*!< Choose multiple files or directories */
132     DIRECTORY = 4,         /*!< Choose directories (choosing files is implicit if this bit is clear) */
133     DEACTIVATE_FILES = 8,  /*!< When choosing directories, also show the files in a deactivated state */
134     SAVING = 16,           /*!< When choosing files, whether to keep the current filename always in the input area */
135     STDFILE = 32           /*!< Choose both files and directories at the same time */
136   };
137 
138   //! Structure holding the info needed for custom file types
139   struct FileTypeInfo
140   {
141     Fl_Image *icon;
142     FluSimpleString extensions;
143     FluSimpleString type, shortType;
144   };
145 
146   //! Constructor opening a file chooser with title \b title visiting directory \b path with files filtered according to \b pattern. \b type is a logical OR of Flu_File_Chooser::SINGLE, Flu_File_Chooser::MULTI, and Flu_File_Chooser::DIRECTORY
147   Flu_File_Chooser( const char *path, const char *pattern, int type, const char *title );
148 
149   //! Destructor
150   ~Flu_File_Chooser();
151 
152   //! Add a custom callback that is called when the user right-clicks on an entry
153   /*! \param type is the type of entry to handle (i.e. a logical OR of \c ENTRY_NONE, \c ENTRY_DIR, \c ENTRY_FILE, \c ENTRY_FAVORITE, \c ENTRY_DRIVE, \c ENTRY_MYDOCUMENTS, \c ENTRY_MYCOMPUTER). To add a "nothing" handler (when the user right-clicks on nothing), use ENTRY_NONE
154     \param ext is the extension of the file that will cause this handler to be added to the popup menu
155     \param name is the name that will appear in the popup menu for this handler
156    */
157   static void add_context_handler( int type, const char *ext, const char *name,
158 				   void (*cb)(const char*,int,void*), void *cbd );
159 
160   //! Add a "preview" widget (derived from class Flu_File_Chooser::PreviewWidgetBase) that will handle custom previewing of files
161   static void add_preview_handler( PreviewWidgetBase *w );
162 
163   //! Add descriptive information and an icon for a file type
164   /*! \param extensions is a space- or comma-delimited list of file extensions, or \c NULL for directories. e.g. "zip,tgz,rar"
165     \param short_description is a short description (!) of the file type. e.g. "Compressed Archive"
166     \param icon is an optional custom icon to use for this file type
167    */
168   static void add_type( const char *extensions, const char *short_description, Fl_Image *icon = NULL );
169 
170   //! deprecated - do not use - right click to change filenames
allow_file_editing(bool b)171   inline void allow_file_editing( bool b )
172     { fileEditing = b; }
173 
174   //! deprecated - do not use - right click to change filenames
allow_file_editing()175   inline bool allow_file_editing() const
176     { return fileEditing; }
177 
178   //! Set whether file sorting is case insensitive. Default value is case-insensitive for windows, case-sensitive for everything else
case_insensitive_sort(bool b)179   inline void case_insensitive_sort( bool b )
180     { caseSort = !b; }
181 
182   //! Get whether file sorting is case insensitive
case_insensitive_sort()183   inline bool case_insensitive_sort() const
184     { return !caseSort; }
185 
186   //! Change the current directory the chooser is browsing to \b path
187   void cd( const char *path );
188 
189   //! Clear the history of which directories have been visited
190   void clear_history();
191 
192   //! \return how many files are selected
193   int count();
194 
195   //! Set the default icon to use for all files for which no other icon has been specified
default_file_icon(Fl_Image * i)196   inline void default_file_icon( Fl_Image* i )
197     { defaultFileIcon = i; }
198 
199   //! Alias for cd()
directory(const char * d)200   inline void directory( const char *d )
201     { cd( d ); }
202 
203   //! Alias for pattern()
filter(const char * p)204   inline void filter( const char *p )
205     { pattern( p ); }
206 
207   //! Alias for pattern()
filter()208   inline const char* filter() const
209     { return pattern(); }
210 
211   //! \return a pointer to a FileTypeInfo structure for files with type \b extension
212   static FileTypeInfo *find_type( const char *extension );
213 
214   //! \return the current directory that the browser is visiting
get_current_directory()215   inline const char* get_current_directory() const
216     { return currentDir.c_str(); }
217 
218   //! Override of Fl_Double_Window::handle()
219   int handle( int event );
220 
221   //! Change the file filter pattern to \b p
222   void pattern( const char *p );
223 
224   //! Get the current file filter pattern
pattern()225   inline const char* pattern() const
226     { return rawPattern.c_str(); }
227 
228   //! Set the state of the preview button
preview(bool b)229   inline void preview( bool b )
230     { previewBtn->value(b); previewBtn->do_callback(); }
231 
232   //! Get the state of the preview button
preview()233   inline int preview() const
234     { return previewBtn->value(); }
235 
236   //! Refresh the current directory
rescan()237   inline void rescan() { reloadCB(); }
238 
239   //! Override of Fl_Double_Window::resize()
240   void resize( int x, int y, int w, int h );
241 
242   //! Select all entries (only valid for multiple-selections)
243   void select_all();
244 
245   //! Set a custom sorting function for sorting entries based on filename
set_sort_function(int (* cb)(const char *,const char *))246   inline void set_sort_function( int (*cb)(const char*,const char*) )
247     { customSort = cb; rescan(); }
248 
249   //! Set the type of the chooser (see constructor)
type(int t)250   inline void type( int t )
251     { selectionType = t; rescan(); }
252 
253   //! Get the type of the chooser
type(int)254   inline int type( int /*t*/ ) const
255     { return selectionType; }
256 
257   //! Unselect all entries
258   void unselect_all();
259 
260   //! Set the current file the chooser is selecting
261   void value( const char *v );
262 
263   //! Get the current file the chooser is selecting
264   const char *value();
265 
266   //! For MULTI file queries, get selected file \b n (base 1 - i.e. 1 returns the first file, 2 the second, etc)
267   const char *value( int n );
268 
269   FileInput filename;
270   // the <Enter> key behavior is not correct for versions before 1.1.4rc2
271 #if FL_MAJOR_VERSION >= 1 && FL_MINOR_VERSION >= 1 && FL_PATCH_VERSION >= 4
272   Flu_Return_Button ok;
273 #else
274   Flu_Button ok;
275 #endif
276   Flu_Button cancel;
277 
278   // apparently there is a bug in VC6 that prevents friend classes from accessing
279   // non-public members. stupid windows
280   // several other compilers were reported to have a problem with this too, so
281   // i'm just making the whole class public to eliminate potential problems.
282   // bad c++ - i know...
283   //#ifndef WIN32
284   //protected:
285   //#endif
286 
287   class ContextHandler
288     {
289     public:
290       FluSimpleString ext, name;
291       int type;
292       void (*callback)(const char*,int,void*);
293       void *callbackData;
294       inline ContextHandler& operator =( const ContextHandler &c )
295       { ext = c.ext; name = c.name; type = c.type; callback = c.callback; callbackData = c.callbackData; return *this; }
296     };
297   FluMakeVectorClass( ContextHandler, ContextHandlerVector );
298   static ContextHandlerVector contextHandlers;
299 
300   typedef PreviewWidgetBase* pPreviewWidgetBase;
301   FluMakeVectorClass( pPreviewWidgetBase, PreviewHandlerVector );
302   static PreviewHandlerVector previewHandlers;
303 
304   Fl_Check_Button *hiddenFiles;
305   Flu_Combo_Tree *location;
306 
_backCB(Fl_Widget *,void * arg)307   inline static void _backCB( Fl_Widget * /*w*/, void *arg )
308     { ((Flu_File_Chooser*)arg)->backCB(); }
309   void backCB();
310 
_forwardCB(Fl_Widget *,void * arg)311   inline static void _forwardCB( Fl_Widget * /*w*/, void *arg )
312     { ((Flu_File_Chooser*)arg)->forwardCB(); }
313   void forwardCB();
314 
_sortCB(Fl_Widget * w,void * arg)315   inline static void _sortCB( Fl_Widget *w, void *arg )
316     { ((Flu_File_Chooser*)arg)->sortCB( w ); }
317   void sortCB( Fl_Widget *w );
318 
_previewCB(Fl_Widget *,void * arg)319   inline static void _previewCB( Fl_Widget*, void *arg )
320     { ((Flu_File_Chooser*)arg)->previewCB(); }
321   void previewCB();
322 
_listModeCB(Fl_Widget *,void * arg)323   inline static void _listModeCB( Fl_Widget * /*w*/, void *arg )
324     { ((Flu_File_Chooser*)arg)->listModeCB(); }
325   void listModeCB();
326 
_filenameCB(Fl_Widget *,void * arg)327   inline static void _filenameCB( Fl_Widget * /*w*/, void *arg )
328     { ((Flu_File_Chooser*)arg)->filenameCB(); }
329   void filenameCB();
330 
_locationCB(Fl_Widget * w,void * arg)331   inline static void _locationCB( Fl_Widget *w, void *arg )
332     { ((Flu_File_Chooser*)arg)->locationCB( ((Flu_Combo_Tree*)w)->value() ); }
333   void locationCB( const char *path );
334 
_locationQJCB(Fl_Widget * w,void * arg)335   inline static void _locationQJCB( Fl_Widget *w, void *arg )
336     { ((Flu_File_Chooser*)arg)->cd( ((Fl_Button*)w)->label() ); }
337 
delayedCdCB(void * arg)338   inline static void delayedCdCB( void *arg )
339     { ((Flu_File_Chooser*)arg)->cd( ((Flu_File_Chooser*)arg)->delayedCd.c_str() ); }
340 
selectCB(void * arg)341   inline static void selectCB( void *arg )
342     { ((Flu_File_Chooser*)arg)->okCB(); }
343 
_cancelCB(Fl_Widget *,void * arg)344   inline static void _cancelCB( Fl_Widget*, void *arg )
345     { ((Flu_File_Chooser*)arg)->cancelCB(); }
346   void cancelCB();
347 
_okCB(Fl_Widget *,void * arg)348   inline static void _okCB( Fl_Widget*, void *arg )
349     { ((Flu_File_Chooser*)arg)->okCB(); }
350   void okCB();
351 
_trashCB(Fl_Widget *,void * arg)352   inline static void _trashCB( Fl_Widget*, void *arg )
353     { ((Flu_File_Chooser*)arg)->trashCB(); }
354   void trashCB( bool recycle = true );
355 
_newFolderCB(Fl_Widget *,void * arg)356   inline static void _newFolderCB( Fl_Widget*, void *arg )
357     { ((Flu_File_Chooser*)arg)->newFolderCB(); }
358   void newFolderCB();
359 
upDirCB(Fl_Widget *,void * arg)360   inline static void upDirCB( Fl_Widget*, void *arg )
361     { ((Flu_File_Chooser*)arg)->cd( "../" ); }
362 
reloadCB(Fl_Widget *,void * arg)363   inline static void reloadCB( Fl_Widget*, void *arg )
364     { ((Flu_File_Chooser*)arg)->reloadCB(); }
365   void reloadCB();
366 
_homeCB(Fl_Widget *,void * arg)367   inline static void _homeCB( Fl_Widget*, void *arg )
368     { ((Flu_File_Chooser*)arg)->homeCB(); }
369   void homeCB();
370 
_desktopCB(Fl_Widget *,void * arg)371   inline static void _desktopCB( Fl_Widget*, void *arg )
372     { ((Flu_File_Chooser*)arg)->desktopCB(); }
373   void desktopCB();
374 
_favoritesCB(Fl_Widget *,void * arg)375   inline static void _favoritesCB( Fl_Widget*, void *arg )
376     { ((Flu_File_Chooser*)arg)->favoritesCB(); }
377   void favoritesCB();
378 
_myComputerCB(Fl_Widget *,void * arg)379   inline static void _myComputerCB( Fl_Widget*, void *arg )
380     { ((Flu_File_Chooser*)arg)->myComputerCB(); }
381   void myComputerCB();
382 
_addToFavoritesCB(Fl_Widget *,void * arg)383   inline static void _addToFavoritesCB( Fl_Widget*, void *arg )
384     { ((Flu_File_Chooser*)arg)->addToFavoritesCB(); }
385   void addToFavoritesCB();
386 
_documentsCB(Fl_Widget *,void * arg)387   inline static void _documentsCB( Fl_Widget*, void *arg )
388     { ((Flu_File_Chooser*)arg)->documentsCB(); }
389   void documentsCB();
390 
_hideCB(Fl_Widget *,void * arg)391   inline static void _hideCB( Fl_Widget*, void *arg )
392     { ((Flu_File_Chooser*)arg)->hideCB(); }
393   void hideCB();
394   void do_callback();
395 
396   enum {
397     SORT_NAME = 1,
398     SORT_SIZE = 2,
399     SORT_TYPE = 4,
400     SORT_DATE = 8,
401     SORT_REVERSE = 16
402   };
403   static void _qSort( int how, bool caseSort, Fl_Widget **array, int low, int high );
404 
405   friend class Entry;
406   class Entry : public Fl_Input
407     {
408     public:
409       Entry( const char* name, int t, bool d, Flu_File_Chooser *c );
410       ~Entry();
411 
412       int handle( int event );
413       void draw();
414 
415       void updateSize();
416       void updateIcon();
417 
418       FluSimpleString filename, date, filesize, shortname,
419 	description, shortDescription, toolTip, altname;
420       //FluSimpleString permissions;
421       //unsigned char pU, pG, pO; // 3-bit unix style permissions
422       unsigned int type, idate;
423       unsigned long isize;
424       bool selected;
425       int editMode;
426       Flu_File_Chooser *chooser;
427       Fl_Image *icon;
428 
429       int nameW, typeW, sizeW, dateW;
430       bool details;
431 
_inputCB(Fl_Widget *,void * arg)432       inline static void _inputCB( Fl_Widget * /*w*/, void *arg )
433 	{ ((Entry*)arg)->inputCB(); }
434       void inputCB();
435 
_editCB(void * arg)436       inline static void _editCB( void *arg )
437 	{ ((Entry*)arg)->editCB(); }
438       void editCB();
439     };
440 
441   friend class FileList;
442   class FileList : public Flu_Wrap_Group
443     {
444     public:
445       FileList( int x, int y, int w, int h, Flu_File_Chooser *c );
446       ~FileList();
447 
448       int handle( int event );
449       void sort( int numDirs = -1 );
450 
child(int n)451       inline Fl_Widget *child(int n) const
452 	{ return Flu_Wrap_Group::child(n); }
453 
children()454       inline int children() const
455 	{ return Flu_Wrap_Group::children(); }
456 
457       int numDirs;
458       Flu_File_Chooser *chooser;
459     };
460 
461   friend class FileDetails;
462   class FileDetails : public Fl_Pack
463     {
464     public:
465       FileDetails( int x, int y, int w, int h, Flu_File_Chooser *c );
466       ~FileDetails();
467 
468       int handle( int event );
469       void sort( int numDirs = -1 );
470 
471       void scroll_to( Fl_Widget *w );
472       Fl_Widget* next( Fl_Widget* w );
473       Fl_Widget* previous( Fl_Widget* w );
474 
475       int numDirs;
476       Flu_File_Chooser *chooser;
477     };
478 
479   friend class CBTile;
480   class CBTile : public Fl_Tile
481     {
482     public:
483       CBTile( int x, int y, int w, int h, Flu_File_Chooser *c );
484       int handle( int event );
485       Flu_File_Chooser *chooser;
486     };
487 
488   friend class FileColumns;
489   class FileColumns : public Fl_Tile
490     {
491     public:
492       FileColumns( int x, int y, int w, int h, Flu_File_Chooser *c );
493       ~FileColumns();
494 
495       int handle( int event );
496       void resize( int x, int y, int w, int h );
497       Flu_File_Chooser *chooser;
498       int W1, W2, W3, W4;
499     };
500 
501   friend class PreviewTile;
502   class PreviewTile : public Fl_Tile
503     {
504     public:
505       PreviewTile( int x, int y, int w, int h, Flu_File_Chooser *c );
506       int handle( int event );
507       Flu_File_Chooser *chooser;
508       int last;
509     };
510 
511   class ImgTxtPreview : public PreviewWidgetBase
512     {
513     public:
514       int preview( const char *filename );
515       unsigned char previewTxt[1024];
516     };
517 
518   friend class PreviewGroup;
519   class PreviewGroup : public Fl_Group
520     {
521     public:
522       PreviewGroup( int x, int y, int w, int h, Flu_File_Chooser *c );
523       void draw();
524       Flu_File_Chooser *chooser;
525       FluSimpleString lastFile, file;
526       PreviewWidgetBase* handled;
527     };
528 
529   Fl_Group *getEntryGroup();
530   Fl_Group *getEntryContainer();
531 
532   void win2unix( FluSimpleString &s );
533 
534   void cleanupPath( FluSimpleString &s );
535 
536   bool correctPath( FluSimpleString &path );
537 
538   void updateEntrySizes();
539 
540   void buildLocationCombo();
541 
542   void updateLocationQJ();
543 
544   void addToHistory();
545 
546   FluSimpleString formatDate( const char *d );
547 
548   void recursiveScan( const char *dir, FluStringVector *files );
549 
550   bool stripPatterns( FluSimpleString s, FluStringVector* patterns );
551 
552   int popupContextMenu( Entry *entry );
553 
554   FluSimpleString commonStr();
555 
556   static ImgTxtPreview *imgTxtPreview;
557 
558   static int (*customSort)(const char*,const char*);
559 
560   PreviewGroup *previewGroup;
561   PreviewTile *previewTile;
562   Fl_Group *fileGroup, *locationQuickJump;
563   Fl_Menu_Button entryPopup;
564   Fl_Image *defaultFileIcon;
565   Entry *lastSelected;
566   FileList *filelist;
567   FileColumns *filecolumns;
568   Fl_Group *fileDetailsGroup;
569   Fl_Scroll *filescroll;
570   FileDetails *filedetails;
571   Flu_Button *detailNameBtn, *detailTypeBtn, *detailSizeBtn, *detailDateBtn;
572   FluSimpleString currentDir, delayedCd, rawPattern;
573   FluSimpleString configFilename;
574   FluSimpleString userHome, userDesktop, userDocs;
575   FluSimpleString drives[26];
576   Fl_Pixmap* driveIcons[26];
577   Flu_Button *fileListBtn, *fileListWideBtn, *fileDetailsBtn, *backBtn, *forwardBtn, *upDirBtn, *trashBtn,
578     *newDirBtn, *addFavoriteBtn, *reloadBtn, *previewBtn;
579   Fl_Browser *favoritesList;
580   Flu_Combo_List *filePattern;
581   int selectionType;
582   bool filenameEnterCallback, filenameTabCallback, walkingHistory, caseSort, fileEditing;
583   int sortMethod;
584 
585   FluStringVector patterns;
586 
587   static FileTypeInfo *types;
588   static int numTypes;
589   static int typeArraySize;
590 
591   static FluSimpleString dArrow[4];
592   static FluSimpleString uArrow[4];
593 
594 #ifdef WIN32
595   unsigned int driveMask;
596   unsigned int driveTypes[26];
597   FluSimpleString volumeNames[26];
598   bool refreshDrives;
599 #endif
600 
601   class History
602   {
603   public:
History()604     History() { last = next = NULL; }
605     FluSimpleString path;
606     History *last, *next;
607   };
608 
609   History *history, *currentHist;
610 
611   Fl_Callback *_callback;
612   void *_userdata;
613 
614 };
615 
616 #endif
617