Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

glui_dialogs.C

Go to the documentation of this file.
00001 #include "std/support.H"
00002 #include "glew/glew.H"
00003 
00004 #include "glut_winsys.H" 
00005 #include "glui_dialogs.H" 
00006 #include "tty_glut.H"
00007 #include "glui/glui.h"
00008 #include "std/file.H"
00009 #include "widgets/alert_box_icon_exclaim.H"
00010 #include "widgets/alert_box_icon_question.H"
00011 #include "widgets/alert_box_icon_warn.H"
00012 #include "widgets/alert_box_icon_info.H"
00013 #include "widgets/alert_box_icon_jot.H"
00014 #include "widgets/file_select_icon_arrow_down.H"
00015 #include "widgets/file_select_icon_arrow_up.H"
00016 #include "widgets/file_select_icon_scroll.H"
00017 #include "widgets/file_select_icon_doc.H"
00018 #include "widgets/file_select_icon_doc_x.H"
00019 #include "widgets/file_select_icon_doc_r.H"
00020 #include "widgets/file_select_icon_blank.H"
00021 #include "widgets/file_select_icon_drive.H"
00022 #include "widgets/file_select_icon_folder.H"
00023 #include "widgets/file_select_icon_folder_r.H"
00024 #include "widgets/file_select_icon_folder_x.H"
00025 #include "widgets/file_select_icon_folder_up.H"
00026 #include "widgets/file_select_icon_folder_dot.H"
00027 #include "widgets/file_select_icon_folder_plus.H"
00028 #include "widgets/file_select_icon_jot.H"
00029 #include "widgets/file_select_icon_disc.H"
00030 #include "widgets/file_select_icon_disc_save.H"
00031 #include "widgets/file_select_icon_disc_load.H"
00032 
00033 /*****************************************************************
00034  * GLUIPopUp
00035  *****************************************************************/
00036 
00037 //////////////////////////////////////////////////////
00038 // Static Variables Initialization
00039 //////////////////////////////////////////////////////
00040 ARRAY<GLUIPopUp*>    GLUIPopUp::_ui;
00041 
00042 //////////////////////////////////////////////////////
00043 // Constructor
00044 //////////////////////////////////////////////////////
00045 GLUIPopUp::GLUIPopUp(GLUT_WINSYS *w) :
00046    _glut_winsys(w),
00047    _glui(NULL),
00048    _blocking(true)
00049 {
00050    _ui += this;
00051    _id = (_ui.num()-1);
00052 }
00053 
00054 //////////////////////////////////////////////////////
00055 // Destructor
00056 //////////////////////////////////////////////////////
00057 GLUIPopUp::~GLUIPopUp()
00058 {
00059    cerr << "GLUIPopUp::~GLUIPopUp - Error!!! Destructor not implemented.\n";
00060 }
00061 
00062 //////////////////////////////////////////////////////
00063 // show_glui()
00064 //////////////////////////////////////////////////////
00065 bool     
00066 GLUIPopUp::show_glui(bool blocking)
00067 {
00068    assert(!_glui);
00069 
00070    _blocking = blocking;
00071 
00072    if (_blocking)
00073    {
00074       GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00075 
00076       if (mgr->get_blocker())
00077       {
00078          cerr << "GLUIPopUp::show_glui() - *ERROR* Another PopUp is already blocking!\n";
00079          return false;
00080       }
00081 
00082       mgr->set_blocker(_glut_winsys);
00083    }
00084 
00085    build_glui(); 
00086    
00087    assert(_glui);
00088 
00089    _glui->show();
00090 
00091    return true;
00092 }
00093 
00094 
00095 //////////////////////////////////////////////////////
00096 // build_glui()
00097 //////////////////////////////////////////////////////
00098 void     
00099 GLUIPopUp::build_glui()
00100 {
00101    int root_x, root_y, root_w, root_h;
00102 
00103    _glut_winsys->size(root_w,root_h);
00104    _glut_winsys->position(root_x,root_y);
00105 
00106    _glui = GLUI_Master.create_glui("PopUp", 0, root_x + root_w/2, root_y + root_h/2);
00107 
00108    assert(_glui);
00109 
00110    _glui->set_main_gfx_window(_glut_winsys->id());
00111 
00112    //Sub-classes do stuff here...
00113 
00114 }
00115 
00116 //////////////////////////////////////////////////////
00117 // unbuild_glui()
00118 //////////////////////////////////////////////////////
00119 void     
00120 GLUIPopUp::unbuild_glui()
00121 {
00122    //Sub-classes do stuff here...
00123 
00124    assert(_glui);
00125 
00126    _panel.clear(); 
00127    _button.clear();
00128    _slider.clear();
00129    _listbox.clear();
00130    _rollout.clear();
00131    _edittext.clear();
00132    _bitmapbox.clear();
00133    _checkbox.clear();
00134    _statictext.clear();
00135    _activetext.clear();
00136    _radiogroup.clear();
00137    _radiobutton.clear();
00138 
00139    _glui->set_cursor(GLUT_CURSOR_WAIT);
00140 
00141    _glui->close();
00142 
00143    _glui = NULL;
00144 
00145 }
00146 
00147 //////////////////////////////////////////////////////
00148 // hide_glui()
00149 //////////////////////////////////////////////////////
00150 bool
00151 GLUIPopUp::hide_glui()
00152 {
00153    assert(_glui);
00154 
00155    unbuild_glui();
00156 
00157    if (_blocking)
00158    {
00159       GLUT_MANAGER *mgr = (GLUT_MANAGER *)FD_MANAGER::mgr(); assert(mgr);
00160 
00161       assert(mgr->get_blocker());
00162 
00163       mgr->clear_blocker(_glut_winsys);
00164    }
00165 
00166    return true;
00167 }
00168 
00169 //////////////////////////////////////////////////////
00170 // slider_cbs()
00171 //////////////////////////////////////////////////////
00172 void
00173 GLUIPopUp::slider_cbs(int id)
00174 {
00175    assert((id >> ID_SHIFT) < _ui.num());
00176    _ui[id >> ID_SHIFT]->slider_cb(id&ID_MASK);
00177 }
00178 
00179 //////////////////////////////////////////////////////
00180 // button_cbs()
00181 //////////////////////////////////////////////////////
00182 void
00183 GLUIPopUp::button_cbs(int id)
00184 {
00185    assert((id >> ID_SHIFT) < _ui.num());
00186    _ui[id >> ID_SHIFT]->button_cb(id&ID_MASK);
00187 }
00188 
00189 //////////////////////////////////////////////////////
00190 // activetext_cbs()
00191 //////////////////////////////////////////////////////
00192 void
00193 GLUIPopUp::activetext_cbs(int id)
00194 {
00195    assert((id >> ID_SHIFT) < _ui.num());
00196    _ui[id >> ID_SHIFT]->activetext_cb(id&ID_MASK);
00197 }
00198 
00199 //////////////////////////////////////////////////////
00200 // listbox_cbs()
00201 //////////////////////////////////////////////////////
00202 void
00203 GLUIPopUp::listbox_cbs(int id)
00204 {
00205    assert((id >> ID_SHIFT) < _ui.num());
00206    _ui[id >> ID_SHIFT]->listbox_cb(id&ID_MASK);
00207 }
00208 
00209 //////////////////////////////////////////////////////
00210 // edittext_cbs()
00211 //////////////////////////////////////////////////////
00212 void
00213 GLUIPopUp::edittext_cbs(int id)
00214 {
00215    assert((id >> ID_SHIFT) < _ui.num());
00216    _ui[id >> ID_SHIFT]->edittext_cb(id&ID_MASK);
00217 }
00218 
00219 //////////////////////////////////////////////////////
00220 // checkbox_cbs()
00221 //////////////////////////////////////////////////////
00222 void
00223 GLUIPopUp::checkbox_cbs(int id)
00224 {
00225    assert((id >> ID_SHIFT) < _ui.num());
00226    _ui[id >> ID_SHIFT]->checkbox_cb(id&ID_MASK);
00227 }
00228 
00229 //////////////////////////////////////////////////////
00230 // bitmapbox_cbs()
00231 //////////////////////////////////////////////////////
00232 void
00233 GLUIPopUp::bitmapbox_cbs(int id)
00234 {
00235    assert((id >> ID_SHIFT) < _ui.num());
00236    _ui[id >> ID_SHIFT]->bitmapbox_cb(id&ID_MASK);
00237 }
00238 
00239 //////////////////////////////////////////////////////
00240 // radiogroup_cbs()
00241 //////////////////////////////////////////////////////
00242 void
00243 GLUIPopUp::radiogroup_cbs(int id)
00244 {
00245    assert((id >> ID_SHIFT) < _ui.num());
00246    _ui[id >> ID_SHIFT]->radiogroup_cb(id&ID_MASK);
00247 }
00248 
00249 /*****************************************************************
00250  * GLUIAlertBox
00251  *****************************************************************/
00252 
00253 //////////////////////////////////////////////////////
00254 // Static Variables Initialization
00255 //////////////////////////////////////////////////////
00256 
00257 bool                       GLUIAlertBox::_icon_init = false;
00258 GLUIAlertBox::IconBitmap   GLUIAlertBox::_icons[ICON_NUM];
00259 
00260 //////////////////////////////////////////////////////
00261 // Constructor
00262 //////////////////////////////////////////////////////
00263 GLUIAlertBox::GLUIAlertBox(GLUT_WINSYS *w) :
00264    GLUIPopUp(w),
00265       _cb(NULL),
00266       _vp(NULL),
00267       _vpd(NULL),
00268       _idx(-1)
00269 {
00270    if (!_icon_init)
00271    {
00272       _icons[JOT_ICON].set(alert_box_jot_icon);
00273       _icons[INFO_ICON].set(alert_box_info_icon);
00274       _icons[QUESTION_ICON].set(alert_box_question_icon);
00275       _icons[EXCLAMATION_ICON].set(alert_box_exclaim_icon);
00276       _icons[WARNING_ICON].set(alert_box_warn_icon);
00277       _icon_init = true;
00278    }
00279 }
00280 
00281 //////////////////////////////////////////////////////
00282 // Destructor
00283 //////////////////////////////////////////////////////
00284 GLUIAlertBox::~GLUIAlertBox()
00285 {
00286 
00287 }
00288 
00289 //////////////////////////////////////////////////////
00290 // is_displaying()
00291 //////////////////////////////////////////////////////
00292 bool 
00293 GLUIAlertBox::is_displaying()  
00294 { 
00295    return is_showing();
00296 }
00297 
00298 //////////////////////////////////////////////////////
00299 // display()
00300 //////////////////////////////////////////////////////
00301 bool 
00302 GLUIAlertBox::display(bool blocking, alert_cb_t cb, void *vp, void *vpd, int idx)  
00303 { 
00304 
00305    if (is_displaying())
00306    {
00307       cerr << "GLUIAlertBox::display - *ERROR* It's already displaying!\n";
00308       return false;
00309    }
00310 
00311    if (_buttons.num() == 0)
00312    {
00313       cerr << "GLUIAlertBox::display - *ERROR* No buttons defined!\n";
00314       return false;
00315    }
00316 
00317    assert(_cb == NULL);
00318    assert(_vp == NULL);
00319    assert(_vpd == NULL);
00320    assert(_idx == -1);
00321 
00322    if (!show_glui(blocking))
00323    {
00324       cerr << "GLUIAlertBox::display - *ERROR* Couldn't show GLUI window!\n";
00325       return false;
00326    }
00327 
00328    assert(is_displaying());
00329 
00330    _cb = cb; 
00331    _vp = vp; 
00332    _vpd = vpd; 
00333    _idx = idx;
00334 
00335    return true; 
00336 }
00337 
00338 //////////////////////////////////////////////////////
00339 // undisplay()
00340 //////////////////////////////////////////////////////
00341 bool
00342 GLUIAlertBox::undisplay(int button) 
00343 { 
00344    assert(is_displaying());
00345    
00346    if (!hide_glui())
00347    {
00348       cerr << "GLUIAlertBox::undisplay - *ERROR* Couldn't hide GLUI window!\n";
00349       return false;
00350    }
00351   
00352    assert(!is_displaying());
00353 
00354    clear_title();
00355    clear_icon();
00356    clear_default();
00357    clear_buttons();
00358    clear_text();
00359 
00360    alert_cb_t   cb  = _cb;
00361    void        *vp  = _vp;
00362    void        *vpd = _vpd;
00363    int         idx  = _idx;
00364 
00365    _cb  = NULL;
00366    _vp  = NULL;
00367    _vpd = NULL;
00368    _idx = -1;
00369 
00370    if (cb)
00371    {
00372       cb(vp, vpd, idx, button);
00373    }
00374 
00375    return true;
00376 }
00377 
00378 //////////////////////////////////////////////////////
00379 // build_glui()
00380 //////////////////////////////////////////////////////
00381 void     
00382 GLUIAlertBox::build_glui()
00383 {
00384    GLUIPopUp::build_glui();
00385 
00386    int i;
00387 
00388    int id = _id << ID_SHIFT;
00389 
00390    _glui->rename(**_title);
00391 
00392    assert(_panel.num()==0);        for (i=0; i<PANEL_NUM; i++)          _panel.add(0);
00393    assert(_bitmapbox.num()==0);    for (i=0; i<BITMAPBOX_NUM; i++)      _bitmapbox.add(0);
00394    assert(_button.num()==0);       for (i=0; i<_buttons.num(); i++)     _button.add(0);
00395    assert(_statictext.num()==0);   for (i=0; i<max(1,_text.num()); i++) _statictext.add(0);
00396    
00397    if ((_icon != NO_ICON) || _text.num())
00398    {
00399       _panel[PANEL_TEXT] = _glui->add_panel("",GLUI_PANEL_RAISED);
00400       assert(_panel[PANEL_TEXT]);           
00401 
00402       if (_icon != NO_ICON)
00403       {
00404          _bitmapbox[BITMAPBOX_ICON] = _glui->add_bitmapbox_to_panel(
00405             _panel[PANEL_TEXT],"", 
00406             id+BITMAPBOX_ICON, bitmapbox_cbs,false);
00407          assert(_bitmapbox[BITMAPBOX_ICON]);
00408       
00409          _bitmapbox[BITMAPBOX_ICON]->set_border(0);
00410          _bitmapbox[BITMAPBOX_ICON]->set_margin(4);
00411          _bitmapbox[BITMAPBOX_ICON]->set_img_size(_icons[_icon]._width,_icons[_icon]._height);
00412          _bitmapbox[BITMAPBOX_ICON]->copy_img(_icons[_icon]._data,_icons[_icon]._width,_icons[_icon]._height,3);
00413       }
00414 
00415       _glui->add_column_to_panel(_panel[PANEL_TEXT],false);   
00416 
00417       for (i=0; i<max(1,_text.num()); i++)
00418       {
00419          _statictext[i] = _glui->add_statictext_to_panel(
00420             _panel[PANEL_TEXT], (char*)
00421             ((!_text.num())?(" "):(**_text[i])));
00422          assert(_statictext[i]);
00423          _statictext[i]->set_alignment(GLUI_ALIGN_LEFT);
00424          _statictext[i]->set_h(16);
00425       }
00426 
00427       _glui->add_column_to_panel(_panel[PANEL_TEXT],false);   
00428    }
00429 
00430    _panel[PANEL_BUTTONS] = _glui->add_panel("",GLUI_PANEL_NONE);
00431    assert(_panel[PANEL_BUTTONS]);           
00432 
00433    for (i=0; i<_buttons.num(); i++)
00434    {
00435       _button[i] = _glui->add_button_to_panel(
00436          _panel[PANEL_BUTTONS], **_buttons[i], 
00437          id+i, button_cbs);
00438       assert(_button[i]);
00439       
00440       _button[i]->set_w(75);
00441 
00442       if (i != _buttons.num()-1) 
00443          _glui->add_column_to_panel(_panel[PANEL_BUTTONS],false);   
00444    }
00445    
00446    _panel[PANEL_BUTTONS]->set_alignment(GLUI_ALIGN_RIGHT);
00447 
00448    //Fix up sizes...
00449    int delta; 
00450    
00451    if (_panel[PANEL_TEXT] && ((delta = _panel[PANEL_BUTTONS]->get_w() - _panel[PANEL_TEXT]->get_w()) > 0))
00452    {
00453       _statictext[0]->set_w(_statictext[0]->get_w() + delta);
00454    }
00455 
00456    //Center the window
00457 
00458    int root_x, root_y, root_w, root_h, x, y;
00459 
00460    _glut_winsys->size(root_w,root_h);
00461    _glut_winsys->position(root_x,root_y);
00462 
00463    x = root_x + (root_w - _glui->get_w())/2;
00464    y = root_y + (root_h - _glui->get_h())/2;
00465 
00466    _glui->reposition(max(x,root_x),max(y,root_y));
00467 
00468    //Set default button
00469    if (_default >= 0)
00470    {
00471       assert(_default < _button.num());
00472       _glui->activate_control(_button[_default],GLUI_ACTIVATE_DEFAULT);
00473    }
00474 }
00475 
00476 //////////////////////////////////////////////////////
00477 // unbuild_glui()
00478 //////////////////////////////////////////////////////
00479 void     
00480 GLUIAlertBox::unbuild_glui()
00481 {
00482    //Clean up...
00483    
00484    GLUIPopUp::unbuild_glui();
00485 }
00486 
00487 //////////////////////////////////////////////////////
00488 // button_cb()
00489 //////////////////////////////////////////////////////
00490 void
00491 GLUIAlertBox::button_cb(int id)
00492 {
00493    undisplay(id);
00494 }
00495 
00496    
00497 /*****************************************************************
00498  * GLUIFileSelect
00499  *****************************************************************/
00500 
00501 #define GLUI_FILE_SELECT_NUM_FILES        10
00502 #define GLUI_FILE_SELECT_NUM_RECENT       5
00503 #define GLUI_FILE_SELECT_PATH_WIDTH       330
00504 #define GLUI_FILE_SELECT_NAME_WIDTH       260
00505 #define GLUI_FILE_SELECT_SIZE_WIDTH       85
00506 #define GLUI_FILE_SELECT_DATE_WIDTH       135
00507 //#define GLUI_FILE_SELECT_FILTER_WIDTH     455
00508 #define GLUI_FILE_SELECT_FILTER_WIDTH     425
00509 #define GLUI_FILE_SELECT_ACTION_WIDTH     85
00510 #define GLUI_FILE_SELECT_HEADING_GAP      4
00511 #define GLUI_FILE_SELECT_SCROLL_MIN       20
00512 #define GLUI_FILE_SELECT_DOUBLECLICK_TIME 0.65
00513 
00514 //////////////////////////////////////////////////////
00515 // Static Variables Initialization
00516 //////////////////////////////////////////////////////
00517 
00518 bool                       GLUIFileSelect::_icon_init = false;
00519 GLUIFileSelect::IconBitmap GLUIFileSelect::_icons[ICON_NUM];
00520 
00521 bool                       GLUIFileSelect::_bitmap_init = false;
00522 GLUIFileSelect::IconBitmap GLUIFileSelect::_bitmaps[BITMAP_NUM];
00523 
00524 //////////////////////////////////////////////////////
00525 // Constructor
00526 //////////////////////////////////////////////////////
00527 GLUIFileSelect::GLUIFileSelect(GLUT_WINSYS *w) :
00528    GLUIPopUp(w),
00529       _cb(NULL),
00530       _vp(NULL),
00531       _idx(-1),
00532       _current_path(NULL),
00533       _current_mode(MODE_NORMAL),
00534       _current_sort(SORT_NAME_UP),
00535       _current_selection(-1),
00536       _current_selection_time(0.0),
00537       _current_scroll(0),
00538       _current_scrollbar_wheel(false),
00539       _current_scrollbar_wheel_position(-1),
00540       _current_scrollbar_wheel_index(-1),
00541       _current_scrollbar_state(BAR_STATE_NONE),
00542       _current_scrollbar_state_inside(false),
00543       _current_scrollbar_state_pixel_position(0),
00544       _current_scrollbar_state_index_position(0),
00545       _current_scrollbar_state_above_ratio(0.0),
00546       _current_scrollbar_state_below_ratio(0.0)
00547 {
00548    if (!_icon_init)
00549    {
00550       _icons[LOAD_ICON].set(file_select_disc_load_icon);
00551       _icons[SAVE_ICON].set(file_select_disc_save_icon);
00552       _icons[DISC_ICON].set(file_select_disc_icon);
00553       _icons[JOT_ICON].set(file_select_jot_icon);
00554       _icon_init = true;
00555    }
00556    if (!_bitmap_init)
00557    {
00558       _bitmaps[BITMAP_X].set(file_select_doc_x_icon);
00559       _bitmaps[BITMAP_R].set(file_select_doc_r_icon);
00560       _bitmaps[BITMAP_UP].set(file_select_folder_up_icon);
00561       _bitmaps[BITMAP_DOT].set(file_select_folder_dot_icon);
00562       _bitmaps[BITMAP_PLUS].set(file_select_folder_plus_icon);
00563       _bitmaps[BITMAP_UPARROW].set(file_select_arrow_up_icon);
00564       _bitmaps[BITMAP_DOWNARROW].set(file_select_arrow_down_icon);
00565       _bitmaps[BITMAP_SCROLL].set(file_select_scroll_icon);
00566       _bitmaps[BITMAP_DRIVE].set(file_select_drive_icon);
00567       _bitmaps[BITMAP_FOLDER].set(file_select_folder_icon);
00568       _bitmaps[BITMAP_DOC].set(file_select_doc_icon);
00569       _bitmaps[BITMAP_BLANK].set(file_select_blank_icon);
00570       _bitmap_init = true;
00571    }
00572 }
00573 
00574 //////////////////////////////////////////////////////
00575 // Destructor
00576 //////////////////////////////////////////////////////
00577 GLUIFileSelect::~GLUIFileSelect()
00578 {
00579 
00580 }
00581 
00582 //////////////////////////////////////////////////////
00583 // is_displaying()
00584 //////////////////////////////////////////////////////
00585 bool 
00586 GLUIFileSelect::is_displaying()  
00587 { 
00588    return is_showing(); 
00589 }
00590 
00591 //////////////////////////////////////////////////////
00592 // display()
00593 //////////////////////////////////////////////////////
00594 bool 
00595 GLUIFileSelect::display(bool blocking, file_cb_t cb, void *vp, int idx) 
00596 { 
00597    if (is_displaying())
00598    {
00599       cerr << "GLUIFileSelect::display - *ERROR* It's already displaying!\n";
00600       return false;
00601    }
00602 
00603    assert(_cb == NULL);
00604    assert(_vp == NULL);
00605    assert(_idx == -1);
00606 
00607    if (!show_glui(blocking))
00608    {
00609       cerr << "GLUIFileSelect::display - *ERROR* Couldn't show GLUI window!\n";
00610       return false;
00611    }
00612 
00613    assert(is_displaying());
00614 
00615    _cb = cb; 
00616    _vp = vp; 
00617    _idx = idx;
00618 
00619    return true; 
00620 }
00621 
00622 //////////////////////////////////////////////////////
00623 // undisplay()
00624 //////////////////////////////////////////////////////
00625 bool
00626 GLUIFileSelect::undisplay(int button, str_ptr path, str_ptr file)
00627 { 
00628    assert(is_displaying());
00629    
00630    if (!hide_glui())
00631    {
00632       cerr << "GLUIFileSelect::undisplay - *ERROR* Couldn't hide GLUI window!\n";
00633       return false;
00634    }
00635   
00636    assert(!is_displaying());
00637 
00638    _path = path;
00639    _file = file;
00640 
00641    if (button == OK_ACTION)
00642    {
00643       _current_recent_paths.add_uniquely(_path);
00644       while(_current_recent_paths.num() > GLUI_FILE_SELECT_NUM_RECENT) 
00645       {
00646          _current_recent_paths.pull_index(0);
00647       }
00648    }
00649 
00650    clear_title();
00651    clear_action();
00652    clear_icon();
00653    //clear_path();
00654    clear_file();
00655    clear_filter();
00656    //clear_filters();
00657 
00658    file_cb_t    cb = _cb;
00659    void        *vp = _vp;
00660    int         idx = _idx;
00661 
00662    _cb = NULL;
00663    _vp = NULL;
00664    _idx = -1;
00665 
00666    if (cb)
00667    {
00668       cb(vp, idx, button, path, file);
00669    }
00670 
00671    return true;
00672 }
00673 
00674 //////////////////////////////////////////////////////
00675 // build_glui()
00676 //////////////////////////////////////////////////////
00677 void     
00678 GLUIFileSelect::build_glui()
00679 {
00680    GLUIPopUp::build_glui();
00681 
00682    int i,spacer;
00683 
00684    int id = _id << ID_SHIFT;
00685 
00686    _glui->rename(**_title);
00687 
00688    assert(_panel.num()==0);        for (i=0; i<PANEL_NUM; i++)       _panel.add(0);
00689    assert(_button.num()==0);       for (i=0; i<BUT_NUM; i++)         _button.add(0);
00690    assert(_edittext.num()==0);     for (i=0; i<EDITTEXT_NUM; i++)    _edittext.add(0);
00691    assert(_checkbox.num()==0);     for (i=0; i<CHECKBOX_NUM; i++)    _checkbox.add(0);
00692    assert(_listbox.num()==0);      for (i=0; i<LIST_NUM; i++)        _listbox.add(0);
00693    assert(_bitmapbox.num()==0);    for (i=0; i<BITMAPBOX_NUM  +   GLUI_FILE_SELECT_NUM_FILES; i++)   _bitmapbox.add(0);
00694    assert(_statictext.num()==0);   for (i=0; i<STATICTEXT_NUM + 2*GLUI_FILE_SELECT_NUM_FILES; i++)  _statictext.add(0);
00695    assert(_activetext.num()==0);   for (i=0; i<ACTIVETEXT_NUM +   GLUI_FILE_SELECT_NUM_FILES; i++)  _activetext.add(0);
00696 
00697    //Controls
00698 
00699    _panel[PANEL_PATH] = _glui->add_panel("",GLUI_PANEL_RAISED/*,GLUI_PANEL_NONE*/);
00700    assert(_panel[PANEL_PATH]);           
00701 
00702    if (_icon != NO_ICON)
00703    {
00704       _bitmapbox[BITMAPBOX_ICON] = _glui->add_bitmapbox_to_panel(
00705          _panel[PANEL_PATH],"", 
00706          id+BITMAPBOX_ICON, bitmapbox_cbs,false);
00707       assert(_bitmapbox[BITMAPBOX_ICON]);
00708    
00709       _bitmapbox[BITMAPBOX_ICON]->set_border(0);
00710       _bitmapbox[BITMAPBOX_ICON]->set_margin(0);
00711       _bitmapbox[BITMAPBOX_ICON]->set_img_size(_icons[_icon]._width,_icons[_icon]._height);
00712       _bitmapbox[BITMAPBOX_ICON]->copy_img(_icons[_icon]._data,_icons[_icon]._width,_icons[_icon]._height,3);
00713    }
00714 
00715    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00716 
00717    //Spacer
00718    _statictext[STATICTEXT_SPACER_PATH] = _glui->add_statictext_to_panel(
00719       _panel[PANEL_PATH],
00720       "");
00721    assert(_statictext[STATICTEXT_SPACER_PATH]);
00722 
00723    //Path
00724    _listbox[LIST_PATH] = _glui->add_listbox_to_panel(
00725       _panel[PANEL_PATH], 
00726       "Path ", NULL,
00727       id+LIST_PATH, listbox_cbs);
00728    assert(_listbox[LIST_PATH]);
00729    _listbox[LIST_PATH]->set_w(GLUI_FILE_SELECT_PATH_WIDTH);
00730    _listbox[LIST_PATH]->set_alignment(GLUI_ALIGN_RIGHT);
00731 
00732    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00733 
00734 /*
00735    //Margin Spacer
00736    _statictext[STATICTEXT_SPACER_PATH_MARGIN1] = _glui->add_statictext_to_panel(
00737       _panel[PANEL_PATH],
00738       "");
00739    assert(_statictext[STATICTEXT_SPACER_PATH_MARGIN1]);
00740    _statictext[STATICTEXT_SPACER_PATH_MARGIN1]->set_w(0); 
00741    _statictext[STATICTEXT_SPACER_PATH_MARGIN1]->set_h(0); 
00742 
00743    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00744 */
00745    //Spacer
00746    _statictext[STATICTEXT_SPACER_UP] = _glui->add_statictext_to_panel(
00747       _panel[PANEL_PATH],
00748       "");
00749    assert(_statictext[STATICTEXT_SPACER_UP]);
00750 
00751    //Up
00752    _bitmapbox[BITMAPBOX_UP] = _glui->add_bitmapbox_to_panel(
00753       _panel[PANEL_PATH],"", 
00754       id+BITMAPBOX_UP, bitmapbox_cbs);
00755    assert(_bitmapbox[BITMAPBOX_UP]);
00756 
00757    _bitmapbox[BITMAPBOX_UP]->set_border(0);
00758    _bitmapbox[BITMAPBOX_UP]->set_margin(2);
00759    _bitmapbox[BITMAPBOX_UP]->set_depressable(true);
00760    _bitmapbox[BITMAPBOX_UP]->set_img_size(_bitmaps[BITMAP_UP]._width,_bitmaps[BITMAP_UP]._height);
00761    _bitmapbox[BITMAPBOX_UP]->copy_img(_bitmaps[BITMAP_UP]._data,_bitmaps[BITMAP_UP]._width,_bitmaps[BITMAP_UP]._height,3);
00762 
00763    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00764 
00765    //Spacer
00766    _statictext[STATICTEXT_SPACER_DOT] = _glui->add_statictext_to_panel(
00767       _panel[PANEL_PATH],
00768       "");
00769    assert(_statictext[STATICTEXT_SPACER_DOT]);
00770 
00771    //Dot
00772 
00773    _bitmapbox[BITMAPBOX_DOT] = _glui->add_bitmapbox_to_panel(
00774       _panel[PANEL_PATH],"", 
00775       id+BITMAPBOX_DOT, bitmapbox_cbs);
00776    assert(_bitmapbox[BITMAPBOX_DOT]);
00777 
00778    _bitmapbox[BITMAPBOX_DOT]->set_border(0);
00779    _bitmapbox[BITMAPBOX_DOT]->set_margin(2);
00780    _bitmapbox[BITMAPBOX_DOT]->set_depressable(true);
00781    _bitmapbox[BITMAPBOX_DOT]->set_img_size(_bitmaps[BITMAP_DOT]._width,_bitmaps[BITMAP_DOT]._height);
00782    _bitmapbox[BITMAPBOX_DOT]->copy_img(_bitmaps[BITMAP_DOT]._data,_bitmaps[BITMAP_DOT]._width,_bitmaps[BITMAP_DOT]._height,3);
00783 
00784    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00785 
00786    //Spacer
00787    _statictext[STATICTEXT_SPACER_PLUS] = _glui->add_statictext_to_panel(
00788       _panel[PANEL_PATH],
00789       "");
00790    assert(_statictext[STATICTEXT_SPACER_PLUS]);
00791 
00792    //Plus
00793 
00794    _bitmapbox[BITMAPBOX_PLUS] = _glui->add_bitmapbox_to_panel(
00795       _panel[PANEL_PATH],"", 
00796       id+BITMAPBOX_PLUS, bitmapbox_cbs);
00797    assert(_bitmapbox[BITMAPBOX_PLUS]);
00798 
00799    _bitmapbox[BITMAPBOX_PLUS]->set_border(0);
00800    _bitmapbox[BITMAPBOX_PLUS]->set_margin(2);
00801    _bitmapbox[BITMAPBOX_PLUS]->set_depressable(true);
00802    _bitmapbox[BITMAPBOX_PLUS]->set_img_size(_bitmaps[BITMAP_PLUS]._width,_bitmaps[BITMAP_PLUS]._height);
00803    _bitmapbox[BITMAPBOX_PLUS]->copy_img(_bitmaps[BITMAP_PLUS]._data,_bitmaps[BITMAP_PLUS]._width,_bitmaps[BITMAP_PLUS]._height,3);
00804 
00805    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00806 
00807    //Spacer
00808    _statictext[STATICTEXT_SPACER_R] = _glui->add_statictext_to_panel(
00809       _panel[PANEL_PATH],
00810       "");
00811    assert(_statictext[STATICTEXT_SPACER_R]);
00812 
00813    //R
00814 
00815    _bitmapbox[BITMAPBOX_R] = _glui->add_bitmapbox_to_panel(
00816       _panel[PANEL_PATH],"", 
00817       id+BITMAPBOX_R, bitmapbox_cbs);
00818    assert(_bitmapbox[BITMAPBOX_R]);
00819 
00820    _bitmapbox[BITMAPBOX_R]->set_border(0);
00821    _bitmapbox[BITMAPBOX_R]->set_margin(2);
00822    _bitmapbox[BITMAPBOX_R]->set_depressable(true);
00823    _bitmapbox[BITMAPBOX_R]->set_img_size(_bitmaps[BITMAP_R]._width,_bitmaps[BITMAP_R]._height);
00824    _bitmapbox[BITMAPBOX_R]->copy_img(_bitmaps[BITMAP_R]._data,_bitmaps[BITMAP_R]._width,_bitmaps[BITMAP_R]._height,3);
00825 
00826    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00827 
00828    //Spacer
00829    _statictext[STATICTEXT_SPACER_X] = _glui->add_statictext_to_panel(
00830       _panel[PANEL_PATH],
00831       "");
00832    assert(_statictext[STATICTEXT_SPACER_X]);
00833 
00834    //X
00835 
00836    _bitmapbox[BITMAPBOX_X] = _glui->add_bitmapbox_to_panel(
00837       _panel[PANEL_PATH],"", 
00838       id+BITMAPBOX_X, bitmapbox_cbs);
00839    assert(_bitmapbox[BITMAPBOX_X]);
00840 
00841    _bitmapbox[BITMAPBOX_X]->set_border(0);
00842    _bitmapbox[BITMAPBOX_X]->set_margin(2);
00843    _bitmapbox[BITMAPBOX_X]->set_depressable(true);
00844    _bitmapbox[BITMAPBOX_X]->set_img_size(_bitmaps[BITMAP_X]._width,_bitmaps[BITMAP_X]._height);
00845    _bitmapbox[BITMAPBOX_X]->copy_img(_bitmaps[BITMAP_X]._data,_bitmaps[BITMAP_X]._width,_bitmaps[BITMAP_X]._height,3);
00846 
00847    _glui->add_column_to_panel(_panel[PANEL_PATH],false);   
00848 
00849    //Margin Spacer
00850    _statictext[STATICTEXT_SPACER_PATH_MARGIN2] = _glui->add_statictext_to_panel(
00851       _panel[PANEL_PATH],
00852       "");
00853    assert(_statictext[STATICTEXT_SPACER_PATH_MARGIN2]);
00854    _statictext[STATICTEXT_SPACER_PATH_MARGIN2]->set_w(0); 
00855    _statictext[STATICTEXT_SPACER_PATH_MARGIN2]->set_h(0); 
00856 
00857 
00858    //Files
00859 
00860    _panel[PANEL_FILES] = _glui->add_panel("",GLUI_PANEL_NONE/*,GLUI_PANEL_RAISED*/);
00861    assert(_panel[PANEL_FILES]);           
00862 
00863    //Types
00864 
00865    //Spacer
00866 
00867    _button[BUT_HEADING_TYPE] = _glui->add_button_to_panel(
00868       _panel[PANEL_FILES],
00869       "",
00870       id+BUT_HEADING_TYPE, button_cbs);
00871    assert(_button[BUT_HEADING_TYPE]);
00872    _button[BUT_HEADING_TYPE]->set_alignment(GLUI_ALIGN_CENTER);
00873    _button[BUT_HEADING_TYPE]->disable();
00874    //_button[BUT_HEADING_TYPE]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
00875 
00876    //Spacer
00877    _statictext[STATICTEXT_SPACER_FILES_TYPE] = _glui->add_statictext_to_panel(
00878       _panel[PANEL_FILES],
00879       "");
00880    assert(_statictext[STATICTEXT_SPACER_FILES_TYPE]);
00881    _statictext[STATICTEXT_SPACER_FILES_TYPE]->set_w(0);
00882    _statictext[STATICTEXT_SPACER_FILES_TYPE]->set_alignment(GLUI_ALIGN_CENTER);
00883    
00884    for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
00885    {
00886       _bitmapbox[BITMAPBOX_NUM + i] = _glui->add_bitmapbox_to_panel(
00887          _panel[PANEL_FILES],"", 
00888          id+BITMAPBOX_NUM + i, bitmapbox_cbs, false);
00889       assert(_bitmapbox[BITMAPBOX_NUM + i]);
00890    
00891       _bitmapbox[BITMAPBOX_NUM + i]->set_border(0);
00892       _bitmapbox[BITMAPBOX_NUM + i]->set_margin(0);
00893       _bitmapbox[BITMAPBOX_NUM + i]->set_alignment(GLUI_ALIGN_RIGHT);
00894       _bitmapbox[BITMAPBOX_NUM + i]->set_img_size(_bitmaps[BITMAP_FOLDER]._width,_bitmaps[BITMAP_FOLDER]._height);
00895       _bitmapbox[BITMAPBOX_NUM + i]->copy_img(_bitmaps[BITMAP_FOLDER]._data,_bitmaps[BITMAP_FOLDER]._width,_bitmaps[BITMAP_FOLDER]._height,3);
00896    }
00897 
00898    //Names
00899 
00900    _glui->add_column_to_panel(_panel[PANEL_FILES],false);      
00901 
00902    _button[BUT_HEADING_NAME] = _glui->add_button_to_panel(
00903       _panel[PANEL_FILES],
00904       "Name",
00905       id+BUT_HEADING_NAME, button_cbs);
00906    assert(_button[BUT_HEADING_NAME]);
00907    _button[BUT_HEADING_NAME]->set_alignment(GLUI_ALIGN_LEFT);
00908    _button[BUT_HEADING_NAME]->set_w(GLUI_FILE_SELECT_NAME_WIDTH-1);
00909 
00910    //Spacer
00911    _statictext[STATICTEXT_SPACER_FILES_NAME] = _glui->add_statictext_to_panel(
00912       _panel[PANEL_FILES],
00913       "");
00914    assert(_statictext[STATICTEXT_SPACER_FILES_NAME]);
00915    _statictext[STATICTEXT_SPACER_FILES_NAME]->set_w(0); 
00916 
00917    for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
00918    {
00919       _activetext[ACTIVETEXT_NUM + i] = _glui->add_activetext_to_panel(
00920          _panel[PANEL_FILES],
00921          **(str_ptr("Filename #") + str_ptr(i)),
00922          id+ACTIVETEXT_NUM + i, activetext_cbs);
00923       assert(_activetext[ACTIVETEXT_NUM + i]);
00924       _activetext[ACTIVETEXT_NUM + i]->set_alignment(GLUI_ALIGN_LEFT);
00925       _activetext[ACTIVETEXT_NUM + i]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
00926    }
00927 
00928    //Sizes
00929 
00930    _glui->add_column_to_panel(_panel[PANEL_FILES],false);      
00931 
00932    _button[BUT_HEADING_SIZE] = _glui->add_button_to_panel(
00933       _panel[PANEL_FILES],
00934       "Size",
00935       id+BUT_HEADING_SIZE, button_cbs);
00936    assert(_button[BUT_HEADING_SIZE]);
00937    _button[BUT_HEADING_SIZE]->set_alignment(GLUI_ALIGN_LEFT);
00938    _button[BUT_HEADING_SIZE]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
00939 
00940    //Spacer
00941    _statictext[STATICTEXT_SPACER_FILES_SIZE] = _glui->add_statictext_to_panel(
00942       _panel[PANEL_FILES],
00943       "");
00944    assert(_statictext[STATICTEXT_SPACER_FILES_SIZE]);
00945    _statictext[STATICTEXT_SPACER_FILES_SIZE]->set_w(0); 
00946 
00947    for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
00948    {
00949       _statictext[STATICTEXT_NUM + 2*i] = _glui->add_statictext_to_panel(
00950          _panel[PANEL_FILES],
00951          " X.XXX KB");
00952       assert(_statictext[STATICTEXT_NUM + 2*i]);
00953       _statictext[STATICTEXT_NUM + 2*i]->set_alignment(GLUI_ALIGN_RIGHT);
00954       _statictext[STATICTEXT_NUM + 2*i]->set_right_justify(true);
00955       _statictext[STATICTEXT_NUM + 2*i]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
00956       //_statictext[STATICTEXT_NUM + 2*i]->set_w(0);
00957    }
00958 
00959    //Dates
00960    
00961    _glui->add_column_to_panel(_panel[PANEL_FILES],false);      
00962    
00963    _button[BUT_HEADING_DATE] = _glui->add_button_to_panel(
00964       _panel[PANEL_FILES],
00965       "Date",
00966       id+BUT_HEADING_DATE, button_cbs);
00967    assert(_button[BUT_HEADING_DATE]);
00968    _button[BUT_HEADING_DATE]->set_alignment(GLUI_ALIGN_LEFT);
00969    _button[BUT_HEADING_DATE]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);
00970 
00971    //Spacer
00972    _statictext[STATICTEXT_SPACER_FILES_DATE] = _glui->add_statictext_to_panel(
00973       _panel[PANEL_FILES],
00974       "");
00975    assert(_statictext[STATICTEXT_SPACER_FILES_DATE]);
00976    _statictext[STATICTEXT_SPACER_FILES_DATE]->set_w(0); 
00977 
00978    for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
00979    {
00980       _statictext[STATICTEXT_NUM + 2*i + 1] = _glui->add_statictext_to_panel(
00981          _panel[PANEL_FILES],
00982          " DD/MM/YY HH:MM");
00983       assert(_statictext[STATICTEXT_NUM + 2*i + 1]);
00984       _statictext[STATICTEXT_NUM + 2*i + 1]->set_alignment(GLUI_ALIGN_RIGHT);
00985       _statictext[STATICTEXT_NUM + 2*i + 1]->set_right_justify(true);
00986       _statictext[STATICTEXT_NUM + 2*i + 1]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);
00987       //_statictext[STATICTEXT_NUM + 2*i + 1]->set_w(0);
00988    }
00989 
00990    //Scrolling
00991 
00992    _glui->add_column_to_panel(_panel[PANEL_FILES],false);      
00993 
00994    //Spacer
00995    _button[BUT_HEADING_SCROLL] = _glui->add_button_to_panel(
00996       _panel[PANEL_FILES],
00997       "",
00998       id+BUT_HEADING_SCROLL, button_cbs);
00999    assert(_button[BUT_HEADING_SCROLL]);
01000    _button[BUT_HEADING_SCROLL]->set_alignment(GLUI_ALIGN_LEFT);
01001    _button[BUT_HEADING_SCROLL]->disable();
01002    //_button[BUT_HEADING_TYPE]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
01003 
01004    //Spacer
01005    _statictext[STATICTEXT_SPACER_FILES_SCROLL] = _glui->add_statictext_to_panel(
01006       _panel[PANEL_FILES],
01007       "");
01008    assert(_statictext[STATICTEXT_SPACER_FILES_SCROLL]);
01009    _statictext[STATICTEXT_SPACER_FILES_SCROLL]->set_w(0); 
01010 
01011    _bitmapbox[BITMAPBOX_UP_FILE] = _glui->add_bitmapbox_to_panel(
01012       _panel[PANEL_FILES],"", 
01013       id+BITMAPBOX_UP_FILE, bitmapbox_cbs,true);
01014    assert(_bitmapbox[BITMAPBOX_UP_FILE]);
01015 
01016    _bitmapbox[BITMAPBOX_UP_FILE]->set_border(0);
01017    _bitmapbox[BITMAPBOX_UP_FILE]->set_margin(2);
01018    _bitmapbox[BITMAPBOX_UP_FILE]->set_depressable(true);
01019    _bitmapbox[BITMAPBOX_UP_FILE]->set_alignment(GLUI_ALIGN_LEFT);
01020    _bitmapbox[BITMAPBOX_UP_FILE]->set_img_size(_bitmaps[BITMAP_UPARROW]._width,_bitmaps[BITMAP_UPARROW]._height);
01021    _bitmapbox[BITMAPBOX_UP_FILE]->copy_img(_bitmaps[BITMAP_UPARROW]._data,_bitmaps[BITMAP_UPARROW]._width,_bitmaps[BITMAP_UPARROW]._height,3);
01022 
01023 
01024    _bitmapbox[BITMAPBOX_SCROLL_FILE] = _glui->add_bitmapbox_to_panel(
01025       _panel[PANEL_FILES],"", 
01026       id+BITMAPBOX_SCROLL_FILE, bitmapbox_cbs,true);
01027    assert(_bitmapbox[BITMAPBOX_SCROLL_FILE]);
01028 
01029    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_border(0);
01030    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_margin(2);
01031    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_depressable(true);
01032    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_alignment(GLUI_ALIGN_LEFT);
01033    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_img_size(_bitmaps[BITMAP_SCROLL]._width,_bitmaps[BITMAP_SCROLL]._height);
01034    _bitmapbox[BITMAPBOX_SCROLL_FILE]->copy_img(_bitmaps[BITMAP_SCROLL]._data,_bitmaps[BITMAP_SCROLL]._width,_bitmaps[BITMAP_SCROLL]._height,3);
01035 
01036    _bitmapbox[BITMAPBOX_DOWN_FILE] = _glui->add_bitmapbox_to_panel(
01037       _panel[PANEL_FILES],"", 
01038       id+BITMAPBOX_DOWN_FILE, bitmapbox_cbs,true);
01039    assert(_bitmapbox[BITMAPBOX_DOWN_FILE]);
01040 
01041    _bitmapbox[BITMAPBOX_DOWN_FILE]->set_border(0);
01042    _bitmapbox[BITMAPBOX_DOWN_FILE]->set_margin(2);
01043    _bitmapbox[BITMAPBOX_DOWN_FILE]->set_depressable(true);
01044    _bitmapbox[BITMAPBOX_DOWN_FILE]->set_alignment(GLUI_ALIGN_LEFT);
01045    _bitmapbox[BITMAPBOX_DOWN_FILE]->set_img_size(_bitmaps[BITMAP_DOWNARROW]._width,_bitmaps[BITMAP_DOWNARROW]._height);
01046    _bitmapbox[BITMAPBOX_DOWN_FILE]->copy_img(_bitmaps[BITMAP_DOWNARROW]._data,_bitmaps[BITMAP_DOWNARROW]._width,_bitmaps[BITMAP_DOWNARROW]._height,3);
01047 
01048 
01049    //Adjust scroller
01050 
01051    _bitmapbox[BITMAPBOX_SCROLL_FILE]->set_img_size(_bitmapbox[BITMAPBOX_SCROLL_FILE]->get_image_w(), 
01052                                                     (GLUI_FILE_SELECT_NUM_FILES) * (_bitmapbox[BITMAPBOX_NUM]->get_h()) 
01053                                                       + (GLUI_FILE_SELECT_NUM_FILES-1) * 3 - 3
01054                                                          - _bitmapbox[BITMAPBOX_UP_FILE]->get_h() 
01055                                                          - _bitmapbox[BITMAPBOX_DOWN_FILE]->get_h() 
01056                                                          - 3);
01057 
01058    //Actions
01059    
01060    _panel[PANEL_ACTION] = _glui->add_panel("",GLUI_PANEL_RAISED);
01061    assert(_panel[PANEL_ACTION]);           
01062 
01063    _glui->add_column_to_panel(_panel[PANEL_ACTION],false);   
01064 
01065    _edittext[EDITTEXT_FILE] = _glui->add_edittext_to_panel(
01066       _panel[PANEL_ACTION], "Filename ", 
01067       GLUI_EDITTEXT_TEXT, NULL, 
01068       id+EDITTEXT_FILE, edittext_cbs);
01069    assert(_edittext[EDITTEXT_FILE]);
01070    _edittext[EDITTEXT_FILE]->set_alignment(GLUI_ALIGN_RIGHT);
01071    //_edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
01072 
01073    _listbox[LIST_FILTER] = _glui->add_listbox_to_panel(
01074       _panel[PANEL_ACTION], 
01075       "Filter Mask ", NULL,
01076       id+LIST_FILTER, listbox_cbs);
01077    assert(_listbox[LIST_FILTER]);
01078    _listbox[LIST_FILTER]->set_alignment(GLUI_ALIGN_RIGHT);
01079    _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
01080 
01081    _glui->add_column_to_panel(_panel[PANEL_ACTION],false);   
01082 
01083    _statictext[STATICTEXT_LABEL_DOT] = _glui->add_statictext_to_panel(
01084       _panel[PANEL_ACTION],
01085       "Dot");
01086    assert(_statictext[STATICTEXT_LABEL_DOT]);
01087    _statictext[STATICTEXT_LABEL_DOT]->set_w(0); 
01088    _statictext[STATICTEXT_LABEL_DOT]->set_w(_statictext[STATICTEXT_LABEL_DOT]->get_w()+3); 
01089    _statictext[STATICTEXT_LABEL_DOT]->set_alignment(GLUI_ALIGN_LEFT);
01090 
01091    _checkbox[CHECKBOX_DOT] = _glui->add_checkbox_to_panel(
01092       _panel[PANEL_ACTION], "", NULL,
01093       id+CHECKBOX_DOT, checkbox_cbs);
01094    assert(_checkbox[CHECKBOX_DOT]);
01095    _checkbox[CHECKBOX_DOT]->set_show_name(false);  
01096    _checkbox[CHECKBOX_DOT]->set_w(0);
01097    _checkbox[CHECKBOX_DOT]->set_alignment(GLUI_ALIGN_CENTER);
01098 
01099    //Fix size (should always have shorter name...)
01100    _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
01101                                  (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
01102                                           _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
01103 /*   
01104    _glui->add_column_to_panel(_panel[PANEL_ACTION],false);   
01105    
01106    //Margin spacer
01107    _statictext[STATICTEXT_SPACER_ACTION_MARGIN1] = _glui->add_statictext_to_panel(
01108       _panel[PANEL_ACTION],
01109       "");
01110    assert(_statictext[STATICTEXT_SPACER_ACTION_MARGIN1]);
01111    _statictext[STATICTEXT_SPACER_ACTION_MARGIN1]->set_w(0); 
01112    _statictext[STATICTEXT_SPACER_ACTION_MARGIN1]->set_h(0); 
01113 */
01114    _glui->add_column_to_panel(_panel[PANEL_ACTION],false);      
01115    
01116    _button[BUT_ACTION] = _glui->add_button_to_panel(
01117       _panel[PANEL_ACTION], **_action, 
01118       id+BUT_ACTION, button_cbs);
01119    assert(_button[BUT_ACTION]);
01120    _button[BUT_ACTION]->set_w(GLUI_FILE_SELECT_ACTION_WIDTH);
01121 
01122    _button[BUT_CANCEL] = _glui->add_button_to_panel(
01123       _panel[PANEL_ACTION], "Cancel", 
01124       id+BUT_CANCEL, button_cbs);
01125    assert(_button[BUT_CANCEL]);
01126    _button[BUT_CANCEL]->set_w(GLUI_FILE_SELECT_ACTION_WIDTH);
01127 /*
01128    _glui->add_column_to_panel(_panel[PANEL_ACTION],false);  
01129 
01130    //Margin spacer
01131    _statictext[STATICTEXT_SPACER_ACTION_MARGIN2] = _glui->add_statictext_to_panel(
01132       _panel[PANEL_ACTION],
01133       "");
01134    assert(_statictext[STATICTEXT_SPACER_ACTION_MARGIN2]);
01135    _statictext[STATICTEXT_SPACER_ACTION_MARGIN2]->set_w(0); 
01136    _statictext[STATICTEXT_SPACER_ACTION_MARGIN2]->set_h(0); 
01137 */
01138    //Adjust file spacers
01139    _statictext[STATICTEXT_SPACER_FILES_TYPE]->set_h(GLUI_FILE_SELECT_HEADING_GAP);
01140    _statictext[STATICTEXT_SPACER_FILES_NAME]->set_h(GLUI_FILE_SELECT_HEADING_GAP);
01141    _statictext[STATICTEXT_SPACER_FILES_SIZE]->set_h(GLUI_FILE_SELECT_HEADING_GAP);
01142    _statictext[STATICTEXT_SPACER_FILES_DATE]->set_h(GLUI_FILE_SELECT_HEADING_GAP);
01143    _statictext[STATICTEXT_SPACER_FILES_SCROLL]->set_h(GLUI_FILE_SELECT_HEADING_GAP);
01144 
01145    _button[BUT_HEADING_TYPE]->set_w(_bitmapbox[BITMAPBOX_NUM]->get_w()+2);
01146    _button[BUT_HEADING_SCROLL]->set_w(_bitmapbox[BITMAPBOX_SCROLL_FILE]->get_w()-1);
01147 
01148    
01149    //Adjust path spacers
01150    spacer = ((_icon != NO_ICON) ? 
01151                      (_bitmapbox[BITMAPBOX_ICON]->get_h()) : 
01152                      (_bitmapbox[BITMAPBOX_UP]->get_h())) 
01153                                     - _listbox[LIST_PATH]->get_h() - 6;
01154    spacer = max(0,spacer);
01155    _statictext[STATICTEXT_SPACER_PATH]->set_h(spacer);
01156    _statictext[STATICTEXT_SPACER_PATH]->set_w(0);
01157 
01158    spacer = ((_icon != NO_ICON) ? 
01159                      (_bitmapbox[BITMAPBOX_ICON]->get_h()) : 
01160                      (_listbox[LIST_PATH]->get_h())) 
01161                                     - _bitmapbox[BITMAPBOX_UP]->get_h() - 4;
01162    spacer = max(0,spacer);
01163 
01164    _statictext[STATICTEXT_SPACER_UP]->set_h(spacer);
01165    _statictext[STATICTEXT_SPACER_UP]->set_w(0);
01166    _statictext[STATICTEXT_SPACER_DOT]->set_h(spacer);
01167    _statictext[STATICTEXT_SPACER_DOT]->set_w(0);
01168    _statictext[STATICTEXT_SPACER_PLUS]->set_h(spacer);
01169    _statictext[STATICTEXT_SPACER_PLUS]->set_w(0);
01170    _statictext[STATICTEXT_SPACER_R]->set_h(spacer);
01171    _statictext[STATICTEXT_SPACER_R]->set_w(0);
01172    _statictext[STATICTEXT_SPACER_X]->set_h(spacer);
01173    _statictext[STATICTEXT_SPACER_X]->set_w(0);
01174 
01175    spacer = max(0, _panel[PANEL_FILES]->get_w() - _panel[PANEL_PATH]->get_w());
01176    //_statictext[STATICTEXT_SPACER_PATH_MARGIN1]->set_w(spacer/2);
01177    //_statictext[STATICTEXT_SPACER_PATH_MARGIN2]->set_w(spacer/2);
01178    _statictext[STATICTEXT_SPACER_PATH_MARGIN2]->set_w(spacer);
01179 
01180    //Adjust action spacers
01181 /*
01182    spacer = _panel[PANEL_FILES]->get_w() - _panel[PANEL_ACTION]->get_w();
01183    _statictext[STATICTEXT_SPACER_ACTION_MARGIN1]->set_w(spacer/2);
01184    _statictext[STATICTEXT_SPACER_ACTION_MARGIN2]->set_w(spacer/2);
01185 */
01186    spacer = _panel[PANEL_FILES]->get_w() - _panel[PANEL_ACTION]->get_w();
01187    _button[BUT_ACTION]->set_w(_button[BUT_ACTION]->get_w() + spacer);
01188    _button[BUT_CANCEL]->set_w(_button[BUT_CANCEL]->get_w() + spacer);
01189 
01190    //Center the window
01191    int root_x, root_y, root_w, root_h, x, y;
01192 
01193    _glut_winsys->size(root_w,root_h);
01194    _glut_winsys->position(root_x,root_y);
01195 
01196    x = root_x + (root_w - _glui->get_w())/2;
01197    y = root_y + (root_h - _glui->get_h())/2;
01198 
01199    _glui->reposition(max(x,root_x),max(y,root_y));
01200 
01201    init();
01202 
01203    // Send unhandled middle button events to the scroller
01204    // WIN32 GLUT's been hacked to turn mouse wheel events into
01205    // small middle button drag events...
01206    _glui->set_default_middle_handler(_bitmapbox[BITMAPBOX_SCROLL_FILE]);
01207 
01208    _glui->activate_control(_edittext[EDITTEXT_FILE],GLUI_ACTIVATE_DEFAULT);
01209 
01210 }
01211 
01212 //////////////////////////////////////////////////////
01213 // unbuild_glui()
01214 //////////////////////////////////////////////////////
01215 void     
01216 GLUIFileSelect::unbuild_glui()
01217 {
01218    //Clean up...
01219    GLUIPopUp::unbuild_glui();
01220 }
01221 
01222 /*
01223 //////////////////////////////////////////////////////
01224 // rename_()
01225 //////////////////////////////////////////////////////
01226 bool     
01227 GLUIFileSelect::rename_(Cstr_ptr &old_name, Cstr_ptr &new_name)
01228 {   
01229    int ret;
01230 
01231 #ifdef WIN32
01232    ret = rename(**old_name, **new_name);
01233 #else
01234    //XXX - Untested
01235    ret = rename(**old_name, **new_name);
01236 #endif
01237    
01238    if (ret != 0)
01239    {
01240       cerr << "GLUIFileSelect::rename_() - ERROR!! Couldn't rename: '" << old_name << "' to: '" << new_name << "'\n";
01241       return false;
01242    }
01243    else
01244    {
01245       return true;
01246    }
01247 }
01248 
01249 //////////////////////////////////////////////////////
01250 // remove_()
01251 //////////////////////////////////////////////////////
01252 bool     
01253 GLUIFileSelect::remove_(Cstr_ptr &file)
01254 {   
01255    int ret;
01256 
01257 #ifdef WIN32
01258    ret = remove(**file);
01259 #else
01260    //XXX - Untested
01261    ret = remove(**file);
01262 #endif
01263    
01264    if (ret != 0)
01265    {
01266       cerr << "GLUIFileSelect::remove_() - ERROR!! Couldn't remove: '" << file << "'\n";
01267       return false;
01268    }
01269    else
01270    {
01271       return true;
01272    }
01273 }
01274 
01275 //////////////////////////////////////////////////////
01276 // rmdir_()
01277 //////////////////////////////////////////////////////
01278 bool     
01279 GLUIFileSelect::rmdir_(Cstr_ptr &dir)
01280 {   
01281    int ret;
01282 
01283 #ifdef WIN32
01284    ret = _rmdir(**dir);
01285 #else
01286    //XXX - Untested
01287    ret = rmdir(**dir);
01288 #endif
01289    
01290    if (ret != 0)
01291    {
01292       cerr << "GLUIFileSelect::rmdir_() - ERROR!! Couldn't rmdir: '" << dir << "'\n";
01293       return false;
01294    }
01295    else
01296    {
01297       return true;
01298    }
01299 }
01300 
01301 //////////////////////////////////////////////////////
01302 // mkdir_()
01303 //////////////////////////////////////////////////////
01304 bool     
01305 GLUIFileSelect::mkdir_(Cstr_ptr &dir)
01306 {   
01307    int ret;
01308 
01309 #ifdef WIN32
01310    ret = _mkdir(**dir);
01311 #else
01312    //XXX - Untested
01313    ret = mkdir(**dir, S_IRUSR  | S_IWUSR  | S_IXUSR |
01314                       S_IRGRP  |            S_IXGRP |
01315                       S_IROTH  |            S_IXOTH );
01316 // ret = mkdir(**dir, S_IRUSR  | S_IWUSR  | S_IXUSR |
01317 //                    S_IRGRP  | S_IWGRP  | S_IXGRP |
01318 //                    S_IROTH  | S_IWOTH  | S_IXOTH );
01319 
01320 #endif
01321    
01322    if (ret != 0)
01323    {
01324       cerr << "GLUIFileSelect::mkdir_() - ERROR!! Couldn't mkdir: '" << dir << "'\n";
01325       return false;
01326    }
01327    else
01328    {
01329       return true;
01330    }
01331 }
01332 
01333 //////////////////////////////////////////////////////
01334 // chdir_()
01335 //////////////////////////////////////////////////////
01336 bool     
01337 GLUIFileSelect::chdir_(Cstr_ptr &new_dir)
01338 {   
01339    int ret;
01340 
01341 #ifdef WIN32
01342    ret = _chdir(**new_dir);
01343 #else
01344    ret = chdir(**new_dir);
01345 #endif
01346    
01347    if (ret != 0)
01348    {
01349       cerr << "GLUIFileSelect::chdir_() - ERROR!! Couldn't CHDIR to: '" << new_dir << "'\n";
01350       return false;
01351    }
01352    else
01353    {
01354       return true;
01355    }
01356 }
01357 
01358 #define CWD_BUF 1024
01359 //////////////////////////////////////////////////////
01360 // getcwd_()
01361 //////////////////////////////////////////////////////
01362 str_ptr
01363 GLUIFileSelect::getcwd_()
01364 {
01365    char *ret, cwd[CWD_BUF];
01366 
01367 #ifdef WIN32
01368    ret = _getcwd(cwd,CWD_BUF);
01369 #else
01370    ret = getcwd(cwd,CWD_BUF);
01371 #endif
01372    
01373    if (!ret)
01374    {
01375       cerr << "GLUIFileSelect::getcwd_() - ERROR!! Couldn't retreive CWD!\n";
01376       return NULL_STR;
01377    }
01378    else
01379    {
01380       return cwd;
01381    }
01382 }
01383 */
01384 //////////////////////////////////////////////////////
01385 // readdir_()
01386 //////////////////////////////////////////////////////
01387 str_list 
01388 GLUIFileSelect::readdir_(Cstr_ptr &path, Cstr_ptr &filter)
01389 {
01390    str_list list;
01391    static Cstr_ptr dot("."), dotdot("..");
01392    bool hide_leading_dot = _checkbox[CHECKBOX_DOT]->get_int_val() == 0;
01393 #ifdef WIN32
01394    WIN32_FIND_DATA file;
01395    HANDLE hFile;
01396    
01397    assert(filter != NULL_STR);
01398    
01399    //General filter only applies to files, and not directories... so use '*' filter
01400    if ((hFile = FindFirstFile(**(path + "/" + "*"), &file)) != INVALID_HANDLE_VALUE) 
01401    {
01402       while (1) 
01403       {
01404          str_ptr fname(file.cFileName); assert(int(fname.len())>0);
01405          
01406          if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
01407          {
01408             //However the leading '.' filter checkbox still applies!
01409             if ( (( hide_leading_dot) && (fname[0] != '.'))  ||
01410                  ((!hide_leading_dot) && (fname!=dot)&&(fname!=dotdot))  )
01411             {
01412                list += fname;
01413             }
01414 
01415          }
01416          if (!FindNextFile(hFile, &file)) break;
01417       }
01418       FindClose(hFile);
01419    }
01420 
01421    //General filter applies to files
01422    if ((hFile = FindFirstFile(**(path + "/" + filter), &file)) != INVALID_HANDLE_VALUE) 
01423    {
01424       while (1) 
01425       {
01426          str_ptr fname(file.cFileName); assert(int(fname.len())>0);
01427 
01428          if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
01429          {
01430             //However the leading '.' filter checkbox also applies!
01431             if (!(hide_leading_dot && fname[0]=='.'))
01432             {
01433                list += fname;
01434             }
01435          }
01436          if (!FindNextFile(hFile, &file)) break;
01437       }
01438       FindClose(hFile);
01439    }
01440 #else
01441    DIR *dir = 0;
01442    struct dirent *direntry;
01443 
01444    if ((dir = opendir(**path))!=NULL)
01445    {
01446       struct stat statbuf;
01447       while ((direntry = readdir(dir))!=NULL)
01448       {
01449          str_ptr file(direntry->d_name), full_path = path + "/" + file;
01450          
01451          if (!stat(**full_path, &statbuf))
01452          {
01453             //General filter only applies to files, not directories...
01454             if ((statbuf.st_mode&S_IFMT)==S_IFDIR) 
01455             {
01456                //But the '.' filter checkbox still applies
01457                if ( ( hide_leading_dot && file[0]!='.')             ||
01458                     (!hide_leading_dot && file!=dot && file!=dotdot)  )
01459                {
01460                   list += file;
01461                }
01462             } 
01463             else if (((statbuf.st_mode&S_IFMT)!=S_IFDIR) && !fnmatch(**filter, **file, FNM_PATHNAME & FNM_PERIOD)) 
01464             {
01465                //However the leading '.' filter checkbox also applies!
01466                if (!(hide_leading_dot && file[0]=='.'))
01467                {
01468                   list += file;
01469                }
01470             }
01471          }
01472       }
01473       closedir(dir);
01474    }
01475 #endif
01476    return list;
01477 }
01478 
01479 //////////////////////////////////////////////////////
01480 // stat_()
01481 //////////////////////////////////////////////////////
01482 bool
01483 GLUIFileSelect::stat_(Cstr_ptr &cpath, DIR_ENTRYptr &ret)
01484 {
01485    assert(cpath != NULL_STR);
01486 
01487    str_ptr path = cpath;
01488 
01489    ret->clear();
01490 
01491 #ifdef WIN32
01492    
01493    struct _stat buf;
01494 
01495    char   buf_drv[_MAX_DRIVE], buf_dir[_MAX_DIR];
01496    char buf_fname[_MAX_FNAME], buf_ext[_MAX_EXT];
01497 
01498    _splitpath(**path, buf_drv, buf_dir, buf_fname, buf_ext);
01499 
01500    str_ptr s_drv(buf_drv); 
01501    str_ptr s_dir(buf_dir); 
01502    str_ptr s_fname(buf_fname);
01503 
01504    //Roll fname and extension together and make sure
01505    //it's non-null only for real file/folder names (not dot)
01506    s_fname = s_fname + buf_ext;
01507 
01508    //If fname points to a directory via a '.', then drop the
01509    if (s_fname == ".")
01510    {
01511       s_fname = NULL_STR;
01512    }
01513 
01514    //Full paths must start with a drive
01515    if (s_drv == NULL_STR)
01516    {
01517       cerr << "GLUIFileSelect::stat_() - Not a full path with drive prefix: '" << path << "'\n";
01518       return false;
01519    }
01520    //Path must point to a literal entity
01521    else if (s_fname == "..")
01522    {
01523       cerr << "GLUIFileSelect::stat_() - Relative paths not allowed: '" << path << "'\n";
01524       return false;
01525    }
01526    //No file or directory indicates a drive's root dir
01527    else if ( ((s_dir == "/")  ||  (s_dir == "\\") || (s_dir == NULL_STR)) && 
01528              (s_fname == NULL_STR) )
01529    {
01530       //Clean up path...
01531       path = s_drv + "\\";
01532 
01533       str_ptr drive_type_name;
01534       ULARGE_INTEGER total_space, free_space;
01535       uint drive_type = GetDriveType(**path);
01536 
01537       switch (drive_type)
01538       {
01539          case DRIVE_REMOVABLE:   drive_type_name = "[Floppy Drive]"; break;
01540          case DRIVE_FIXED:       drive_type_name = "[Hard Drive]"; break;
01541          case DRIVE_REMOTE:      drive_type_name = "[Network Drive]"; break;
01542          case DRIVE_CDROM:       drive_type_name = "[Disc Drive]"; break;
01543          case DRIVE_RAMDISK:     drive_type_name = "[RAM Drive]"; break;
01544          case DRIVE_UNKNOWN:     drive_type_name = "[*UNKNOWN TYPE*]"; break;
01545          case DRIVE_NO_ROOT_DIR: drive_type_name = "[*NO ROOT DIRECTORY*]"; break;
01546          default: assert(0); break;
01547       }
01548 
01549       ret->_type = DIR_ENTRY::DIR_ENTRY_DRIVE;
01550       ret->_full_path = path;
01551       ret->_name = drive_type_name;
01552 
01553       //Ignores error if media not present to avoid the pop-up prompt to insert disc...
01554       unsigned int old_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); 
01555       //XXX - Floppy seek is so slow, it really chokes... Forget it.
01556       if ((drive_type != DRIVE_REMOVABLE) && (GetDiskFreeSpaceEx(**path,&free_space,&total_space,NULL)))
01557 //      if (GetDiskFreeSpaceEx(**path,&free_space,&total_space,NULL))
01558       {
01559          ret->_size = (LONGLONG)(total_space.QuadPart-free_space.QuadPart);
01560       }
01561       SetErrorMode(old_mode);
01562    }
01563    else
01564    {
01565       //Fix up paths with trailing slashes because
01566       //they don't end with a file/folder name, 
01567       //otherwise _stat will fail out...
01568 
01569       //s_drv looks like "X:"
01570       //s_dir looks like "/some/folders/with/trailing/slash/"
01571       //s_fname looks like "name.extension" (could be a folder or file)
01572       if (s_fname == NULL_STR)
01573       {
01574          //We're not just a drive, so s_dir must
01575          //contain folder(s) and we'll just lop off the trailing slash
01576          //so path points to the foldername...
01577          
01578          //XXX - use strcpy instead...
01579          if ( (s_dir[(int)s_dir.len()-1] != '/') && (s_dir[(int)s_dir.len()-1] != '\\') )
01580             
01581          {
01582             cerr << "GLUIFileSelect::stat_() - Error. Something is malformed about path. Trailing slash expected: '" << path << "'\n";
01583             return false;
01584          }
01585 
01586          path = s_drv; for (int i=0; i< (int)s_dir.len()-1; i++) path = path + str_ptr(s_dir[i]);
01587       }
01588       else
01589       {
01590          path = s_drv + s_dir + s_fname;
01591       }
01592 
01593 
01594       if (_stat(**path, &buf) != 0)
01595       {
01596          cerr << "GLUIFileSelect::stat_() - Failed to get information on target: '" << path << "'\n";
01597          return false;
01598       }
01599 
01600       switch (buf.st_mode & _S_IFMT)
01601       {
01602          case _S_IFREG:
01603             ret->_type = DIR_ENTRY::DIR_ENTRY_FILE;
01604             ret->_full_path = path;
01605             ret->_size = buf.st_size;  
01606             ret->_date = buf.st_mtime;
01607          break;
01608          case _S_IFDIR:
01609             ret->_type = DIR_ENTRY::DIR_ENTRY_DIRECTORY;
01610             ret->_full_path = path;
01611             //ret->_size = buf.st_size;  
01612             ret->_date = buf.st_mtime;
01613          break;
01614          default:
01615             ret->_type = DIR_ENTRY::DIR_ENTRY_UNKNOWN;
01616          break;
01617       }
01618    }
01619 #else
01620    struct stat buf;
01621  
01622    //Path must start with a '/'
01623    if (path[0] != '/')
01624    {
01625       cerr << "GLUIFileSelect::stat_() - Not a full path beginning with a '/': '" << path << "'\n";
01626       return false;
01627    }
01628    //Path must point to a literal entity
01629    if (path[(int)path.len()-1] == '.')
01630    {
01631       cerr << "GLUIFileSelect::stat_() - Relative paths with .'s not allowed: '" << path << "'\n";
01632       return false;
01633    }
01634    else
01635    {
01636       //Treat root directory like a win32 'drive'
01637       if ((int)path.len() == 1)
01638       {
01639 
01640          assert(path == "/");
01641 
01642          if (stat("/.", &buf) != 0)
01643          {
01644             cerr << "GLUIFileSelect::stat_() - Failed to get information on target: '/.'\n";
01645             return false;
01646          }
01647 
01648          switch (buf.st_mode & S_IFMT)
01649          {
01650             case S_IFDIR:
01651                ret->_full_path = "/";
01652                ret->_type =      DIR_ENTRY::DIR_ENTRY_DRIVE;
01653                ret->_name =      "[Root]";  
01654                //ret->_size =    buf.st_size;  
01655                ret->_date =      buf.st_mtime;
01656             break;
01657             default:
01658                cerr << "GLUIFileSelect::stat_() - Target: '/.' claims not to be a directory!!\n";
01659                return false;
01660             break;
01661          }  
01662       }
01663       else
01664       {
01665          //Fix up paths with trailing slashes because
01666          //they don't end with a file/folder name, 
01667          //otherwise _stat will fail out...
01668          if (path[(int)path.len()-1] == '/')
01669          {
01670             //We'll just lop off the trailing slash
01671             //so path points to the foldername...
01672             //XXX - use strcpy instead...
01673             str_ptr new_path;
01674             for (int i=0; i< (int)path.len()-1; i++) new_path = new_path + str_ptr(path[i]);
01675             path = new_path;
01676          }
01677 
01678          if (stat(**path, &buf) != 0)
01679          {
01680             cerr << "GLUIFileSelect::stat_() - Failed to get information on target: '" << path << "'\n";
01681             return false;
01682          }
01683 
01684          switch (buf.st_mode & S_IFMT)
01685          {
01686             case S_IFDIR:
01687                ret->_type =      DIR_ENTRY::DIR_ENTRY_DIRECTORY;
01688                ret->_full_path = path;
01689                //ret->_size =    buf.st_size;  
01690                ret->_date =      buf.st_mtime;
01691             break;
01692             case S_IFREG:
01693                ret->_type =      DIR_ENTRY::DIR_ENTRY_FILE;
01694                ret->_full_path = path;
01695                ret->_size =      buf.st_size;  
01696                ret->_date =      buf.st_mtime;
01697             break;
01698             default:
01699                ret->_type = DIR_ENTRY::DIR_ENTRY_UNKNOWN;
01700             break;
01701          }  
01702       }
01703    }
01704 #endif
01705    
01706    return true;
01707 
01708 }
01709 
01710 
01711 
01712 /////////////////////////////////////////////////////
01713 // generate_dir_contents()
01714 //////////////////////////////////////////////////////
01715 bool
01716 GLUIFileSelect::generate_dir_contents(DIR_ENTRYptr &dir)
01717 {
01718    int i;
01719 
01720    assert((dir->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY) ||
01721           (dir->_type == DIR_ENTRY::DIR_ENTRY_DRIVE) ||
01722           (dir->_type == DIR_ENTRY::DIR_ENTRY_ROOT) );
01723 
01724    dir->_contents.clear();
01725 
01726    if (dir->_type != DIR_ENTRY::DIR_ENTRY_ROOT)
01727    {
01728       assert(_filter < _filters.num());
01729       //readdir wants a path pointing to a dir...
01730       //_full_path already has trailing slashes removed
01731       //for directories, but not for 'drives' i.e. root directories...
01732       //so add the . back in that case....
01733       str_list entries = readdir_(dir->_full_path + 
01734                                     ((dir->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?("."):(NULL_STR)),
01735                                           _filters[_filter]);
01736 
01737       for (i=0; i<entries.num(); i++)
01738       {  
01739          // Careful about assembling paths, /'s and filenames
01740          // Don't need trailing slashes for root direntories a.k.a. 'drives'...
01741          DIR_ENTRYptr e = generate_dir_entry(
01742             dir->_full_path + 
01743                ((dir->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?(NULL_STR):("/")) + 
01744                   entries[i], entries[i]);
01745 
01746          if (  (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY) ||
01747                (e->_type == DIR_ENTRY::DIR_ENTRY_FILE) )
01748          {
01749             dir->_contents += e;
01750          }
01751          else if (e->_type == DIR_ENTRY::DIR_ENTRY_UNKNOWN)
01752          {
01753             cerr << "GLUIFileSelect::generate_dir_contents() - WARNING!! Unknown directory entry: '" << e->_full_path << "'\n";
01754          }
01755          else
01756          {
01757             assert(e->_type != DIR_ENTRY::DIR_ENTRY_DRIVE);
01758             assert(e->_type != DIR_ENTRY::DIR_ENTRY_ROOT);
01759          }
01760       }
01761    }
01762    else
01763    {
01764       DIR_ENTRYptr e;
01765 #ifdef WIN32
01766       // XXX - Should this be more forgiving under failure? Nah
01767       DWORD drives = GetLogicalDrives();
01768 
01769       assert(drives != 0);
01770 
01771       for (i=0; i < 26; i++)
01772       {
01773          if (drives & 1<<i)
01774          {
01775             str_ptr drv((char)('A'+i));
01776             e = generate_dir_entry(drv + ":\\", drv + ": ");
01777             assert((e != NULL) && (e->_type == DIR_ENTRY::DIR_ENTRY_DRIVE));
01778             dir->_contents += e;
01779          }
01780       }
01781 #else
01782       // XXX - Should this be more forgiving under failure? Nah
01783       e = generate_dir_entry("/", "/ ");
01784       assert( (e != NULL) && (e->_type == DIR_ENTRY::DIR_ENTRY_DRIVE));
01785       dir->_contents += e;
01786 #endif
01787 
01788       //Verify this path... 
01789       //Save the CWD before mucking about...
01790       str_ptr old_cwd = getcwd_(), jotroot_cwd;
01791 
01792       if (chdir_(Config::JOT_ROOT()))
01793       {
01794          if ((jotroot_cwd = getcwd_()) != NULL_STR)
01795          {
01796             e = generate_dir_entry(jotroot_cwd, NULL_STR);
01797             if ((e != NULL) && (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
01798             {
01799                dir->_contents += e;
01800             }
01801          }
01802       }
01803       if (old_cwd != NULL_STR) chdir_(old_cwd);
01804 
01805       //These paths have been 'tested' by chdiring to them,
01806       //and reading back the getcwd... They're 'safe'
01807       for (i=0; i<_current_recent_paths.num(); i++)
01808       {
01809          e = generate_dir_entry(_current_recent_paths[i], NULL_STR);
01810          if ((e != NULL) && (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
01811          {
01812             dir->_contents += e;
01813          }
01814       }
01815    }
01816 
01817    return true;
01818 }
01819 
01820 
01821 //////////////////////////////////////////////////////
01822 // sort_dir_contents()
01823 //////////////////////////////////////////////////////
01824 
01825 static int sort_name(const void* va, const void* vb)
01826 #ifdef WIN32
01827 //Case-sensitive string comparison...
01828 //{ return strcmp(      **(*((DIR_ENTRYptr *)va))->_name, **(*((DIR_ENTRYptr *)vb))->_name);   }
01829 //Case-INsensitive version...
01830 { return _stricmp(      **(*((DIR_ENTRYptr *)va))->_name, **(*((DIR_ENTRYptr *)vb))->_name);   }
01831 #else
01832 //Case-sensitive string comparison...
01833 //{ return strcmp(      **(*((DIR_ENTRYptr *)va))->_name, **(*((DIR_ENTRYptr *)vb))->_name);   }
01834 //Case-INsensitive version...
01835 { return strcasecmp(      **(*((DIR_ENTRYptr *)va))->_name, **(*((DIR_ENTRYptr *)vb))->_name);   }
01836 #endif
01837 
01838 static int sort_type(const void* va, const void* vb)
01839 { return                (*((DIR_ENTRYptr *)va))->_type -  (*((DIR_ENTRYptr *)vb))->_type;    }
01840 static int sort_size(const void* va, const void* vb)
01841 { return Sign2(         (*((DIR_ENTRYptr *)va))->_size -  (*((DIR_ENTRYptr *)vb))->_size);   }
01842 static int sort_date(const void* va, const void* vb)
01843 { return Sign2(difftime((*((DIR_ENTRYptr *)va))->_date,   (*((DIR_ENTRYptr *)vb))->_date));  }
01844 
01845 
01846 static int sort_by_name_up(const void* va, const void* vb)
01847 { int ret; if (!(ret = sort_type(va,vb))) if (!(ret = sort_name(va,vb))) ret = sort_date(va,vb); return ret; }
01848 static int sort_by_date_up(const void* va, const void* vb)
01849 { int ret; if (!(ret = sort_type(va,vb))) if (!(ret = sort_date(va,vb))) ret = sort_name(va,vb); return ret; }
01850 static int sort_by_size_up(const void* va, const void* vb)
01851 { int ret; if (!(ret = sort_type(va,vb))) if (!(ret = sort_size(va,vb))) ret = sort_name(va,vb); return ret; }
01852 
01853 static int sort_by_name_down(const void* va, const void* vb) { return sort_by_name_up(vb,va);   }
01854 static int sort_by_date_down(const void* va, const void* vb) { return sort_by_date_up(vb,va); }
01855 static int sort_by_size_down(const void* va, const void* vb) { return sort_by_size_up(vb,va); }
01856 
01857 void
01858 GLUIFileSelect::sort_dir_contents(DIR_ENTRYptr &dir, sort_t sort)
01859 {
01860    assert(dir != NULL);
01861 
01862    compare_func_t func;
01863 
01864    switch(sort)
01865    {
01866       case SORT_NAME_UP:   func = sort_by_name_up;    break;
01867       case SORT_NAME_DOWN: func = sort_by_name_down;  break;
01868       case SORT_DATE_UP:   func = sort_by_date_up;    break;
01869       case SORT_DATE_DOWN: func = sort_by_date_down;  break;
01870       case SORT_SIZE_UP:   func = sort_by_size_up;    break;
01871       case SORT_SIZE_DOWN: func = sort_by_size_down;  break;
01872       default: assert(0); break;
01873    }
01874 
01875    if (dir->_type != DIR_ENTRY::DIR_ENTRY_ROOT)
01876    {
01877       dir->_contents.sort(func);
01878    }
01879 }
01880 
01881 //////////////////////////////////////////////////////
01882 // get_selected_entry()
01883 //////////////////////////////////////////////////////
01884 DIR_ENTRYptr
01885 GLUIFileSelect::get_selected_entry()
01886 {
01887    if (_current_selection == -1) return NULL;
01888 
01889    assert(_current_path != NULL);
01890    assert( (_current_scroll + _current_selection) < _current_path->_contents.num());
01891 
01892    return _current_path->_contents[_current_scroll + _current_selection];
01893 }
01894 
01895 //////////////////////////////////////////////////////
01896 // set_selected_entry()
01897 //////////////////////////////////////////////////////
01898 void
01899 GLUIFileSelect::set_selected_entry(DIR_ENTRYptr e)
01900 {
01901    if (e == NULL)
01902    {
01903       _current_selection = -1;
01904    }
01905    else
01906    {
01907       assert(_current_path != NULL);
01908 
01909       int ind = _current_path->_contents.get_index(e);
01910 
01911       assert(ind != BAD_IND);
01912 
01913       ind -= _current_scroll;
01914 
01915       if ((ind >= 0) && (ind < GLUI_FILE_SELECT_NUM_FILES))
01916       {
01917          _current_selection = ind;
01918       }
01919       else
01920       {
01921          _current_selection = -1;
01922       }
01923    }
01924 }
01925 
01926 //////////////////////////////////////////////////////
01927 // do_scroll_delta()
01928 //////////////////////////////////////////////////////
01929 void
01930 GLUIFileSelect::do_scroll_delta(int delta)
01931 {
01932    do_scroll_set(_current_scroll + delta);
01933 }
01934 
01935 //////////////////////////////////////////////////////
01936 // do_scroll_set()
01937 //////////////////////////////////////////////////////
01938 void
01939 GLUIFileSelect::do_scroll_set(int scroll)
01940 {
01941    assert(_current_path != NULL);
01942    assert((_current_scroll >= 0) &&
01943           (_current_scroll <= max(0,_current_path->_contents.num() - GLUI_FILE_SELECT_NUM_FILES + 1)));
01944 
01945    DIR_ENTRYptr selected_entry = get_selected_entry();
01946 
01947    _current_scroll = scroll;
01948 
01949    _current_scroll = max(_current_scroll,0);
01950 
01951    _current_scroll = min(_current_scroll,max(0,_current_path->_contents.num() - GLUI_FILE_SELECT_NUM_FILES + 1));
01952 
01953    set_selected_entry(selected_entry);
01954    
01955    update();   
01956 }
01957 
01958 
01959 //////////////////////////////////////////////////////
01960 // do_scrollbar()
01961 //////////////////////////////////////////////////////
01962 
01963 void
01964 GLUIFileSelect::do_scrollbar(int e, int x, int y, int i, int k, int m)
01965 {
01966    //Middle and Right mouse button callbacks go through disabled controls...
01967    if (!_bitmapbox[BITMAPBOX_SCROLL_FILE]->enabled) return;
01968 
01969    //int w = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_image_w();
01970    int h = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_image_h();
01971 
01972    int n_delta, p_delta;
01973 
01974    int pix_below, pix_showing, pix_above;
01975    int num_below, num_showing, num_above;
01976 
01977    compute_scroll_geometry(h, pix_below, pix_showing, pix_above, num_below, num_showing, num_above);
01978 
01979    switch (e)
01980    {
01981 
01982       case GLUI_BITMAPBOX_EVENT_MOUSE_DOWN:
01983          // Cancel any pending wheel stuff...
01984          _current_scrollbar_wheel = false;
01985 
01986          // Clicked above scroller -- page up
01987          if ( y < pix_below )
01988          {
01989             _current_scrollbar_state = BAR_STATE_LOWER_DOWN;
01990             _current_scrollbar_state_inside = i!=0;
01991             update_scroll();
01992          }
01993          // Clicked above scroller -- page down
01994          else if ( y >= h - pix_above )
01995          {
01996             _current_scrollbar_state = BAR_STATE_UPPER_DOWN;
01997             _current_scrollbar_state_inside = i!=0;
01998             update_scroll();
01999          }
02000          // Start dragging scroller...
02001          else
02002          {
02003             _current_scrollbar_state = BAR_STATE_SCROLL_DOWN;
02004             _current_scrollbar_state_inside = i!=0;
02005             _current_scrollbar_state_pixel_position = y;
02006             _current_scrollbar_state_index_position = _current_scroll;
02007             _current_scrollbar_state_above_ratio = (double)num_above/(double)pix_above;
02008             _current_scrollbar_state_below_ratio = (double)num_below/(double)pix_below;
02009             update_scroll();
02010          }
02011       break;
02012       case GLUI_BITMAPBOX_EVENT_MOUSE_MOVE:
02013 
02014          // If we're dragging the scroller...
02015          if (_current_scrollbar_state == BAR_STATE_SCROLL_DOWN)
02016          {
02017             p_delta = _current_scrollbar_state_pixel_position - y;
02018 
02019             if (p_delta > 0)
02020             {
02021                n_delta = int((double)(p_delta) * _current_scrollbar_state_below_ratio + 0.5);
02022             }
02023             else if (p_delta < 0)
02024             {
02025                n_delta = int((double)(p_delta) * _current_scrollbar_state_above_ratio + 0.5);
02026             }
02027             else
02028             {
02029                n_delta = 0;
02030             }
02031             _current_scrollbar_state_inside = i!=0;
02032 
02033             do_scroll_set(_current_scrollbar_state_index_position + n_delta);
02034          }
02035          else if (_current_scrollbar_state == BAR_STATE_LOWER_DOWN)
02036          {
02037             bool old_i = _current_scrollbar_state_inside;
02038             _current_scrollbar_state_inside = i!=0;
02039             if ((i!=0)!=old_i) update_scroll();
02040          }
02041          else if (_current_scrollbar_state == BAR_STATE_UPPER_DOWN)
02042          {
02043             bool old_i = _current_scrollbar_state_inside;
02044             _current_scrollbar_state_inside = i!=0;
02045             if ((i!=0)!=old_i) update_scroll();
02046          }
02047       break;
02048       case GLUI_BITMAPBOX_EVENT_MOUSE_UP:
02049 
02050          // If we're dragging the scroller...
02051          if (_current_scrollbar_state == BAR_STATE_SCROLL_DOWN)
02052          {
02053             p_delta = _current_scrollbar_state_pixel_position - y;
02054 
02055             if (p_delta > 0)
02056             {
02057                n_delta = int((double)(p_delta) * _current_scrollbar_state_below_ratio + 0.5);
02058             }
02059             else if (p_delta < 0)
02060             {
02061                n_delta = int((double)(p_delta) * _current_scrollbar_state_above_ratio + 0.5);
02062             }
02063             else
02064             {
02065                n_delta = 0;
02066             }
02067 
02068             _current_scrollbar_state_inside = i!=0;
02069             _current_scrollbar_state = BAR_STATE_NONE;
02070             do_scroll_set(_current_scrollbar_state_index_position + n_delta);
02071          }
02072          else
02073          {
02074             if (i && _current_scrollbar_state == BAR_STATE_LOWER_DOWN)
02075             {
02076                n_delta = num_showing;
02077             }
02078             else if (i && _current_scrollbar_state == BAR_STATE_UPPER_DOWN)
02079             {
02080                n_delta = -num_showing;
02081             }
02082             else
02083             {
02084                n_delta = 0;            
02085             }
02086 
02087             _current_scrollbar_state_inside = i!=0;
02088             _current_scrollbar_state = BAR_STATE_NONE;
02089             do_scroll_delta(n_delta);
02090          }
02091          
02092       break;
02093       case GLUI_BITMAPBOX_EVENT_KEY:
02094          switch(k)
02095          {
02096             case 103: //down arrow
02097                do_scroll_delta(+1);
02098             break;
02099             case 101: //up arrow
02100                do_scroll_delta(-1);
02101             break;
02102             case 105: //page down
02103                do_scroll_delta(+num_showing);
02104             break;
02105             case 104: //page up
02106                do_scroll_delta(-num_showing);
02107             break;
02108             case 107: //end
02109                do_scroll_set(_current_scroll + num_showing + num_below);
02110             break;
02111             case 106: //home
02112                do_scroll_set(0);
02113             break;
02114             default:
02115 
02116             break;
02117          }
02118       break;
02119       case GLUI_BITMAPBOX_EVENT_MIDDLE_DOWN:
02120          if (_current_scrollbar_state == BAR_STATE_NONE)
02121          {
02122             _current_scrollbar_wheel = true;
02123             _current_scrollbar_wheel_index = _current_scroll;
02124             _current_scrollbar_wheel_position = y;   
02125 
02126             for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
02127             {
02128                //If a file was the active control, deactivate it.
02129                //Looks wired to see the files scrolling by, 
02130                //with a fixed file slot active...
02131                if (_activetext[ACTIVETEXT_NUM + i]->active)
02132                {
02133                   _glui->disactivate_current_control();
02134                   _glui->activate_control(_bitmapbox[BITMAPBOX_SCROLL_FILE], GLUI_ACTIVATE_MOUSE);
02135                }
02136             }
02137          }
02138       break;
02139       case GLUI_BITMAPBOX_EVENT_MIDDLE_MOVE:
02140          if (_current_scrollbar_wheel == true)
02141          {
02142             p_delta = _current_scrollbar_wheel_position - y;
02143 
02144             if (p_delta > 0)
02145             {
02146                n_delta = int((double)(p_delta) / 10.0);
02147             }
02148             else if (p_delta < 0)
02149             {
02150                n_delta = int((double)(p_delta) / 10.0);
02151             }
02152             else
02153             {
02154                n_delta = 0;
02155             }
02156             do_scroll_set(_current_scrollbar_wheel_index + n_delta);
02157          }
02158       break;
02159       case GLUI_BITMAPBOX_EVENT_MIDDLE_UP:
02160          if (_current_scrollbar_wheel == true)
02161          {
02162 /*
02163             p_delta = _current_scrollbar_wheel_position - y;
02164 
02165             if (p_delta > 0)
02166             {
02167                n_delta = int((double)(p_delta) / 10.0);
02168             }
02169             else if (p_delta < 0)
02170             {
02171                n_delta = int((double)(p_delta) / 10.0);
02172             }
02173             else
02174             {
02175                n_delta = 0;
02176             }
02177             do_scroll_set(_current_scrollbar_wheel_index + n_delta);
02178 */
02179             _current_scrollbar_wheel = false;
02180          }
02181       break;
02182       case GLUI_BITMAPBOX_EVENT_RIGHT_DOWN:
02183       case GLUI_BITMAPBOX_EVENT_RIGHT_MOVE:
02184       case GLUI_BITMAPBOX_EVENT_RIGHT_UP:
02185       case GLUI_BITMAPBOX_EVENT_NONE:
02186       break;
02187       default:
02188          assert(0);
02189       break;
02190    }
02191 
02192 }
02193 
02194 //////////////////////////////////////////////////////
02195 // do_up_directory()
02196 //////////////////////////////////////////////////////
02197 void
02198 GLUIFileSelect::do_up_directory()
02199 {
02200    bool ret = do_directory_change(_current_path->_parent->_full_path); assert(ret);
02201 }
02202 
02203 //////////////////////////////////////////////////////
02204 // do_refresh()
02205 //////////////////////////////////////////////////////
02206 void
02207 GLUIFileSelect::do_refresh()
02208 {
02209    bool ret = do_directory_change(_current_path->_full_path); assert(ret);
02210 }
02211 
02212 //////////////////////////////////////////////////////
02213 // do_delete_mode()
02214 //////////////////////////////////////////////////////
02215 void
02216 GLUIFileSelect::do_delete_mode()
02217 {
02218    DIR_ENTRYptr e = get_selected_entry(); 
02219    
02220    assert(e != NULL);
02221    assert((e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY) ||
02222           (e->_type == DIR_ENTRY::DIR_ENTRY_FILE) );
02223 
02224    _current_mode_saved_file = _edittext[EDITTEXT_FILE]->get_text();
02225 
02226    if (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY)
02227    {
02228       _edittext[EDITTEXT_FILE]->set_text(**(str_ptr("Delete directory ") + e->_full_path + " ?"));
02229    }
02230    else
02231    {
02232       _edittext[EDITTEXT_FILE]->set_text(**(str_ptr("Delete file ") + e->_full_path + " ?"));
02233    }
02234    
02235 
02236    _current_mode = MODE_DELETE;
02237 
02238    update();
02239 }
02240 
02241 //////////////////////////////////////////////////////
02242 // do_rename_mode()
02243 //////////////////////////////////////////////////////
02244 void
02245 GLUIFileSelect::do_rename_mode()
02246 {
02247    DIR_ENTRYptr e = get_selected_entry(); 
02248 
02249    assert(e != NULL);
02250    assert((e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY) ||
02251           (e->_type == DIR_ENTRY::DIR_ENTRY_FILE) );
02252 
02253    _current_mode_saved_file = _edittext[EDITTEXT_FILE]->get_text();
02254 
02255    _edittext[EDITTEXT_FILE]->set_text(**e->_name);
02256 
02257    _current_mode = MODE_RENAME;
02258 
02259    update();
02260 
02261 }
02262 
02263 //////////////////////////////////////////////////////
02264 // do_add_mode()
02265 //////////////////////////////////////////////////////
02266 void
02267 GLUIFileSelect::do_add_mode()
02268 {
02269    assert(_current_path != NULL);
02270    assert(_current_path->_type != DIR_ENTRY::DIR_ENTRY_ROOT);
02271 
02272    _current_mode_saved_file = _edittext[EDITTEXT_FILE]->get_text();
02273 
02274    _edittext[EDITTEXT_FILE]->set_text("NewFolder");
02275 
02276    _current_mode = MODE_ADD;
02277 
02278    update();
02279 
02280 }
02281 
02282 //////////////////////////////////////////////////////
02283 // do_delete_action()
02284 //////////////////////////////////////////////////////
02285 void
02286 GLUIFileSelect::do_delete_action()
02287 {
02288    DIR_ENTRYptr e = get_selected_entry();   assert(e != NULL);
02289 
02290    if (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY)
02291    {
02292       if (!rmdir_(**e->_full_path))
02293       {
02294          cerr << "GLUIFileSelect::do_delete_action() - **FAILED**\n";
02295       }
02296    }
02297    else if (e->_type == DIR_ENTRY::DIR_ENTRY_FILE)
02298    {
02299       if (!remove_(**e->_full_path))
02300       {
02301          cerr << "GLUIFileSelect::do_delete_action() - **FAILED**\n";
02302       }
02303    }
02304    else
02305    {
02306       assert(0); 
02307    }
02308 
02309    //_edittext[EDITTEXT_FILE]->set_text(**_current_mode_saved_file);
02310    _edittext[EDITTEXT_FILE]->set_text("");
02311    _current_mode = MODE_NORMAL;
02312 
02313    do_refresh();
02314 }
02315 
02316 //////////////////////////////////////////////////////
02317 // do_rename_action()
02318 //////////////////////////////////////////////////////
02319 void
02320 GLUIFileSelect::do_rename_action()
02321 {
02322    assert(_current_path != NULL);
02323 
02324    DIR_ENTRYptr e = get_selected_entry();   assert(e != NULL);
02325 
02326    str_ptr new_name = _current_path->_full_path + 
02327                            ((_current_path->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?(NULL_STR):("/")) + 
02328                               _edittext[EDITTEXT_FILE]->get_text();
02329 
02330 
02331    if (!rename_(e->_full_path , new_name))
02332    {
02333       cerr << "GLUIFileSelect::do_rename_action() - **FAILED**\n";
02334    }
02335 
02336    //_edittext[EDITTEXT_FILE]->set_text(**_current_mode_saved_file);
02337    _edittext[EDITTEXT_FILE]->set_text("");
02338    _current_mode = MODE_NORMAL;
02339 
02340    do_refresh();
02341 }
02342 
02343 
02344 //////////////////////////////////////////////////////
02345 // do_add_action()
02346 //////////////////////////////////////////////////////
02347 void
02348 GLUIFileSelect::do_add_action()
02349 {
02350    assert(_current_path != NULL);
02351 
02352    str_ptr new_folder = _current_path->_full_path + 
02353                            ((_current_path->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?(NULL_STR):("/")) + 
02354                               _edittext[EDITTEXT_FILE]->get_text();
02355 
02356    if (!mkdir_(new_folder))
02357    {
02358       cerr << "GLUIFileSelect::do_add_action() - Failed to create directory: '" << new_folder << "'\n";
02359    }
02360 
02361    _edittext[EDITTEXT_FILE]->set_text(**_current_mode_saved_file);
02362    _current_mode = MODE_NORMAL;
02363 
02364    do_refresh();
02365 }
02366 
02367 //////////////////////////////////////////////////////
02368 // do_cancel_action()
02369 //////////////////////////////////////////////////////
02370 void
02371 GLUIFileSelect::do_cancel_action()
02372 {
02373    _edittext[EDITTEXT_FILE]->set_text(**_current_mode_saved_file);
02374    _current_mode = MODE_NORMAL;
02375    update();
02376 }
02377 
02378 
02379 //////////////////////////////////////////////////////
02380 // do_path_listbox()
02381 //////////////////////////////////////////////////////
02382 void
02383 GLUIFileSelect::do_path_listbox()
02384 {
02385    int chosen_ind = _listbox[LIST_PATH]->get_int_val();
02386 
02387    if (chosen_ind == -1) 
02388    {
02389       _listbox[LIST_PATH]->set_int_val(0);
02390    }
02391    else
02392    {
02393       DIR_ENTRYptr  dir = _current_path;
02394       DIR_ENTRYlist dirs;
02395 
02396       //To avoid flicking, don't actually let the 
02397       //listbox change to the selected item...
02398       //Let that happen when the directory change
02399       //re-fills the listbox and selects the right item...
02400       _listbox[LIST_PATH]->set_int_val(0);
02401 
02402       //Compile recursion of current path
02403       while (dir->_type != DIR_ENTRY::DIR_ENTRY_ROOT)
02404       {
02405          dirs.add(dir);
02406          dir = dir->_parent;
02407       }
02408 
02409       DIR_ENTRYptr chosen_dir;
02410 
02411       if (chosen_ind < dirs.num())
02412       {
02413          chosen_dir = dirs[chosen_ind];
02414       }
02415       else if (chosen_ind == dirs.num())
02416       {
02417          chosen_dir = dir;
02418       }
02419       else
02420       {
02421          chosen_dir = dir->_contents[chosen_ind - 1 - dirs.num()];
02422       }
02423       do_directory_change(chosen_dir->_full_path);
02424    }
02425 }
02426 
02427 
02428 //////////////////////////////////////////////////////
02429 // do_edittext_event()
02430 //////////////////////////////////////////////////////
02431 void
02432 GLUIFileSelect::do_edittext_event() 
02433 {
02434    int reason = _edittext[EDITTEXT_FILE]->get_event_key();
02435 
02436    if ( (_current_mode == MODE_RENAME) ||
02437         (_current_mode == MODE_DELETE) ||
02438         (_current_mode == MODE_ADD) ) 
02439    {
02440       switch(reason)
02441       {
02442          case 13: //enter
02443             button_cb(BUT_ACTION);
02444          break;
02445          case 27: //esc
02446             button_cb(BUT_CANCEL);
02447          break;
02448          default: //tabbed or moused to another control
02449             //chill out
02450          break;
02451       }
02452    }
02453    else
02454    {
02455       assert(_current_mode == MODE_NORMAL);
02456 
02457       switch(reason)
02458       {
02459          case 13: //enter
02460             button_cb(BUT_ACTION);
02461          break;
02462          case 27: //esc
02463             button_cb(BUT_CANCEL);
02464          break;
02465          default: //tabbed or moused to another control
02466             //chill out
02467          break;
02468       }
02469    }
02470 
02471 }
02472 
02473 //////////////////////////////////////////////////////
02474 // do_entry_select()
02475 //////////////////////////////////////////////////////
02476 void
02477 GLUIFileSelect::do_entry_select(int ind)
02478 {
02479    DIR_ENTRYptr e;
02480 
02481    assert(ind >= -1);
02482    assert(ind < GLUI_FILE_SELECT_NUM_FILES);
02483 
02484    
02485    if (_current_selection == -1)
02486    {
02487 
02488       _current_selection = ind;      
02489       e = get_selected_entry();
02490 
02491       if (e == NULL)
02492       {
02493          _current_selection_time = 0.0;
02494       }
02495       else if ((e->_type == DIR_ENTRY::DIR_ENTRY_DRIVE) ||
02496                (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
02497 
02498       {
02499          _current_selection_time = the_time();         
02500          update();
02501       }
02502       else if (e->_type == DIR_ENTRY::DIR_ENTRY_FILE)
02503       {
02504          _current_selection_time = the_time();         
02505          _edittext[EDITTEXT_FILE]->set_text(**e->_name);
02506          update();
02507       }
02508       else
02509       {
02510          assert(0);
02511       }
02512    }
02513    else if (_current_selection != ind)
02514    {
02515       _current_selection = ind;      
02516       e = get_selected_entry();
02517 
02518       if (e == NULL)
02519       {
02520          _current_selection_time = 0.0;
02521          update();
02522       }
02523       else if ((e->_type == DIR_ENTRY::DIR_ENTRY_DRIVE) ||
02524                (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
02525 
02526       {
02527          _current_selection_time = the_time();         
02528          update();
02529       }
02530       else if (e->_type == DIR_ENTRY::DIR_ENTRY_FILE)
02531       {
02532          _current_selection_time = the_time();         
02533          _edittext[EDITTEXT_FILE]->set_text(**e->_name);
02534          update();
02535       }
02536       else
02537       {
02538          assert(0);
02539       }
02540    }
02541    else
02542    {
02543       _current_selection = ind;      
02544       e = get_selected_entry();
02545 
02546       if (e == NULL)
02547       {
02548          _current_selection_time = 0.0;
02549       }
02550       else if ((e->_type == DIR_ENTRY::DIR_ENTRY_DRIVE) ||
02551                (e->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
02552 
02553       {
02554          double new_time = the_time();
02555          double delta_time = new_time - _current_selection_time;
02556 
02557          if (delta_time < GLUI_FILE_SELECT_DOUBLECLICK_TIME)
02558          {
02559             do_directory_change(e->_full_path);
02560          }
02561          else
02562          {
02563             _current_selection_time = new_time;
02564             //update();
02565          }
02566       }
02567       else if (e->_type == DIR_ENTRY::DIR_ENTRY_FILE)
02568       {
02569          double new_time = the_time();
02570          double delta_time = new_time - _current_selection_time;
02571 
02572          if (delta_time < GLUI_FILE_SELECT_DOUBLECLICK_TIME)
02573          {
02574             //double clicked a file -- see if the file name matches
02575             //the current name in the edittext box first...
02576             if (e->_name == str_ptr(_edittext[EDITTEXT_FILE]->get_text()))
02577             {
02578                undisplay(OK_ACTION, 
02579                   _current_path->_full_path +
02580                      ((_current_path->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?(NULL_STR):("/")), 
02581                         _edittext[EDITTEXT_FILE]->get_text());
02582             }
02583             //if not, just set the edittext to the clicked file's name
02584             else
02585             {
02586                _current_selection_time = new_time;
02587                _edittext[EDITTEXT_FILE]->set_text(**e->_name);
02588                update();
02589             }
02590          }
02591          else
02592          {
02593             _current_selection_time = new_time;
02594             _edittext[EDITTEXT_FILE]->set_text(**e->_name);
02595             update();
02596          }
02597       }
02598       else
02599       {
02600          assert(0);
02601       }
02602    }
02603    
02604 }
02605 
02606 //////////////////////////////////////////////////////
02607 // do_sort_toggle()
02608 //////////////////////////////////////////////////////
02609 void
02610 GLUIFileSelect::do_sort_toggle(int button)
02611 {
02612    DIR_ENTRYptr selected_entry = get_selected_entry();
02613 
02614    switch(button)
02615    {
02616       case BUT_HEADING_NAME:
02617          if (_current_sort == SORT_NAME_UP) 
02618             _current_sort = SORT_NAME_DOWN;
02619          else 
02620             _current_sort = SORT_NAME_UP;
02621       break;
02622       case BUT_HEADING_SIZE:
02623          if (_current_sort == SORT_SIZE_UP) 
02624             _current_sort = SORT_SIZE_DOWN;
02625          else 
02626             _current_sort = SORT_SIZE_UP;
02627       break;
02628       case BUT_HEADING_DATE:
02629          if (_current_sort == SORT_DATE_UP) 
02630             _current_sort = SORT_DATE_DOWN;
02631          else 
02632             _current_sort = SORT_DATE_UP;
02633       break;
02634       default:
02635          assert(0);
02636       break;
02637    }
02638 
02639    assert(_current_path != NULL);
02640 
02641    sort_dir_contents(_current_path,_current_sort);
02642    
02643    set_selected_entry(selected_entry);
02644 
02645    assert(_current_scroll < _current_path->_contents.num());
02646 
02647    update();
02648 }
02649 
02650 //////////////////////////////////////////////////////
02651 // generate_dir_entry()
02652 //////////////////////////////////////////////////////
02653 DIR_ENTRYptr
02654 GLUIFileSelect::generate_dir_entry(Cstr_ptr &full_path, Cstr_ptr &name)
02655 {
02656    DIR_ENTRYptr ret = new DIR_ENTRY;
02657 
02658    if (full_path == NULL_STR)
02659    {
02660       ret->_type = DIR_ENTRY::DIR_ENTRY_ROOT;
02661       ret->_full_path = NULL_STR;
02662    }
02663    else
02664    {
02665       if (!stat_(full_path,ret))
02666       {
02667          ret = NULL;
02668       }
02669    }
02670 
02671    if (ret != NULL)
02672    {
02673       //Assign the given name and append with
02674       //any existing name...
02675       if (name != NULL_STR)
02676       {
02677          ret->_name = name + ret->_name;
02678       }
02679       //Assign path name to name by default...
02680       else
02681       {
02682          ret->_name = ret->_full_path;
02683       }
02684    }
02685 
02686    return ret;
02687 }
02688 
02689 //////////////////////////////////////////////////////
02690 // init()
02691 //////////////////////////////////////////////////////
02692 void     
02693 GLUIFileSelect::init()
02694 {
02695    bool ret;
02696 
02697    ret = do_directory_change(_path);  assert(ret);
02698 
02699    _edittext[EDITTEXT_FILE]->set_text(**_file);
02700 
02701    //Maintain persistent setting
02702    //_current_sort = SORT_NAME_UP;
02703 
02704    //Update path?
02705    //_path = _current_path->_full_path;
02706 
02707 }
02708 
02709 //////////////////////////////////////////////////////
02710 // do_directory_change()
02711 //////////////////////////////////////////////////////
02712 bool
02713 GLUIFileSelect::do_directory_change(Cstr_ptr &dir)
02714 {
02715    bool ret;
02716  
02717    int old_cursor = _glui->get_cursor();
02718    _glui->set_cursor(GLUT_CURSOR_WAIT);
02719 
02720    DIR_ENTRYptr new_path = generate_dir_tree(dir);
02721 
02722    if (new_path == NULL)
02723    {
02724       new_path = generate_dir_tree("");
02725       assert(new_path != NULL);
02726       cerr << "GLUIFileSelect::do_directory_change() - Failed to open: '" << dir << 
02727                   "'. Falling back to '" << new_path->_name << "'\n";
02728       ret = false;
02729    }
02730    else
02731    {
02732       ret = true;
02733    }
02734 
02735    _current_selection = -1;
02736 
02737    _current_scroll = 0;
02738 
02739    _current_path = new_path;
02740 
02741    sort_dir_contents(_current_path,_current_sort);
02742 
02743    update();
02744 
02745    _glui->set_cursor(old_cursor);
02746 
02747    return ret;
02748 }
02749 
02750 
02751 //////////////////////////////////////////////////////
02752 // generate_dir_tree()
02753 //////////////////////////////////////////////////////
02754 DIR_ENTRYptr
02755 GLUIFileSelect::generate_dir_tree(Cstr_ptr &new_path)
02756 {
02757    bool foo;
02758 
02759    //Return value
02760    DIR_ENTRYptr cur_entry, ret_entry;
02761 
02762    //Save the CWD before mucking about...
02763    str_ptr old_cwd = getcwd_();
02764 
02765    if (old_cwd == NULL_STR)
02766    {
02767       cerr << "GLUIFileSelect::generate_dir_tree() - ERROR!! Couldn't retreive old CWD!\n";
02768    }
02769 
02770    if (new_path == NULL_STR)
02771    {
02772       ret_entry = generate_dir_entry(NULL_STR, "Entire File System");
02773       foo = generate_dir_contents(ret_entry); assert(foo);
02774    }
02775    else if (chdir_(new_path))
02776    {
02777       str_ptr tmp_cwd, cur_cwd;
02778 
02779       cur_cwd   = getcwd_();                                assert(cur_cwd != NULL_STR);
02780       ret_entry = generate_dir_entry(cur_cwd, NULL_STR);    assert(ret_entry != NULL); 
02781       cur_entry = ret_entry;
02782 
02783       while (1)
02784       {
02785          foo = chdir_("..");   assert(foo);
02786          tmp_cwd = getcwd_();  assert(tmp_cwd != NULL_STR);
02787 
02788          if (tmp_cwd == cur_cwd) break;
02789 
02790          cur_entry->_parent = generate_dir_entry(tmp_cwd, NULL_STR); assert(cur_entry->_parent != NULL);
02791 
02792          cur_entry = cur_entry->_parent;
02793          cur_cwd = tmp_cwd;
02794       }
02795 
02796       //Create ROOT entry
02797       cur_entry->_parent = generate_dir_entry(NULL_STR, "Entire File System");
02798       cur_entry = cur_entry->_parent;
02799 
02800       //Get listing
02801       foo = generate_dir_contents(ret_entry); assert(foo);
02802 
02803       //Add favorites and drives (root's listing)
02804       foo = generate_dir_contents(cur_entry); assert(foo);
02805 
02806    }
02807    else
02808    {
02809       ret_entry = NULL;
02810    }
02811 
02812 
02813    if (old_cwd != NULL_STR)
02814    {
02815       if (!chdir_(old_cwd))
02816       {
02817          cerr << "GLUIFileSelect::generate_dir_tree() - Failed restoring old CWD...\n";
02818       }
02819    }
02820 
02821    return ret_entry;
02822 }
02823 
02824 
02825 
02826 //////////////////////////////////////////////////////
02827 // update()
02828 //////////////////////////////////////////////////////
02829 void     
02830 GLUIFileSelect::update()
02831 {
02832    update_paths();
02833    update_files();
02834    update_actions();
02835    
02836 }
02837 
02838 //////////////////////////////////////////////////////
02839 // update_paths()
02840 //////////////////////////////////////////////////////
02841 void     
02842 GLUIFileSelect::update_paths()
02843 {
02844    update_pathlist();
02845    update_icons();
02846 }
02847 
02848 //////////////////////////////////////////////////////
02849 // update_pathlist()
02850 //////////////////////////////////////////////////////
02851 void     
02852 GLUIFileSelect::update_pathlist()
02853 {
02854    str_ptr foo,bar;
02855 
02856    int i,j;
02857 
02858    if ( (_current_mode == MODE_RENAME) ||
02859         (_current_mode == MODE_DELETE) ||
02860         (_current_mode == MODE_ADD) ) 
02861    {
02862       _listbox[LIST_PATH]->disable();
02863       _listbox[LIST_PATH]->set_w(GLUI_FILE_SELECT_PATH_WIDTH);
02864    }
02865    else
02866    {
02867       assert(_current_mode == MODE_NORMAL);
02868 
02869       // Fill up the listbox
02870       _listbox[LIST_PATH]->enable();
02871       _listbox[LIST_PATH]->set_w(GLUI_FILE_SELECT_PATH_WIDTH);
02872 
02873       DIR_ENTRYlist dirs;
02874       DIR_ENTRYptr  dir = _current_path;
02875 
02876       //Compile recursion of current path
02877       while (dir->_type != DIR_ENTRY::DIR_ENTRY_ROOT)
02878       {
02879          dirs.add(dir);
02880          dir = dir->_parent;
02881       }
02882 
02883       //Clear it out
02884       while (_listbox[LIST_PATH]->delete_item(-1)) {}
02885       for (i=0; _listbox[LIST_PATH]->delete_item(i); i++) {}
02886 
02887       //Add this placeholder for final selection
02888       //to avoid flickering...
02889       foo = _current_path->_name; 
02890       bar=foo;j=foo.len();while(!_listbox[LIST_PATH]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
02891       _listbox[LIST_PATH]->add_item(-2, **bar);  
02892 
02893       //Master root 
02894       _listbox[LIST_PATH]->add_item(-1,         "--File Systems----------------");
02895       foo = dir->_name; 
02896       bar=foo;j=foo.len();while(!_listbox[LIST_PATH]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
02897       _listbox[LIST_PATH]->add_item(dirs.num(), **bar);  
02898 
02899       assert(dir->_contents.num() > 0); //At least holds JOT_ROOT and drives (WIN32) or root directoy (Unix)
02900 
02901       i = 0;
02902 
02903       //Drives
02904       if (dir->_contents[i]->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)
02905       {
02906          _listbox[LIST_PATH]->add_item(-1,         "--Drives-----------------------");
02907          while ( (i < dir->_contents.num()) && (dir->_contents[i]->_type == DIR_ENTRY::DIR_ENTRY_DRIVE))
02908          {
02909             foo = dir->_contents[i]->_name; 
02910             bar=foo;j=foo.len();while(!_listbox[LIST_PATH]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
02911             _listbox[LIST_PATH]->add_item(dirs.num() + 1 + i, **bar);
02912             i++;
02913          }
02914       }
02915 
02916       //Recent
02917       if (dir->_contents[i]->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY)
02918       {
02919          _listbox[LIST_PATH]->add_item(-1,         "--Recent-----------------------");
02920          while (i < dir->_contents.num())
02921          {
02922             assert(dir->_contents[i]->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY);
02923             foo = dir->_contents[i]->_name; 
02924             bar=foo;j=foo.len();while(!_listbox[LIST_PATH]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
02925             _listbox[LIST_PATH]->add_item(dirs.num() + 1 + i, **bar);
02926             i++;
02927          }
02928       }
02929 
02930       assert(i == dir->_contents.num());
02931 
02932       //Current
02933       if (dirs.num() > 0)
02934       {
02935          _listbox[LIST_PATH]->add_item(-1,         "--Current---------------------");
02936 
02937          for (i=dirs.num()-1; i>=0 ; i--)
02938          {
02939             foo = dirs[i]->_name; 
02940             bar=foo;j=foo.len();while(!_listbox[LIST_PATH]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
02941             _listbox[LIST_PATH]->add_item(i, **bar);
02942          }
02943       }
02944       
02945       _listbox[LIST_PATH]->set_int_val(0);
02946 
02947       //Remove placeholder
02948       _listbox[LIST_PATH]->delete_item(-2);
02949    }
02950 }
02951 
02952 //////////////////////////////////////////////////////
02953 // update_icons()
02954 //////////////////////////////////////////////////////
02955 void     
02956 GLUIFileSelect::update_icons()
02957 {
02958    if ( (_current_mode == MODE_RENAME) ||
02959         (_current_mode == MODE_DELETE) ||
02960         (_current_mode == MODE_ADD) ) 
02961    {
02962       _bitmapbox[BITMAPBOX_DOT]->disable();
02963       _bitmapbox[BITMAPBOX_UP]->disable();
02964       _bitmapbox[BITMAPBOX_PLUS]->disable();
02965       _bitmapbox[BITMAPBOX_R]->disable();
02966       _bitmapbox[BITMAPBOX_X]->disable();
02967    }
02968    else
02969    {
02970       assert(_current_mode == MODE_NORMAL);
02971 
02972       // -refresh
02973       _bitmapbox[BITMAPBOX_DOT]->enable();
02974       
02975       assert(_current_path != NULL);
02976       // -up dir
02977       if (_current_path->_parent != NULL)
02978       {
02979          assert(_current_path->_type != DIR_ENTRY::DIR_ENTRY_ROOT);
02980          _bitmapbox[BITMAPBOX_UP]->enable();
02981       }
02982       else
02983       {
02984          _bitmapbox[BITMAPBOX_UP]->disable();
02985       }
02986    
02987       // -new dir
02988       if ((_current_path->_type == DIR_ENTRY::DIR_ENTRY_DRIVE) ||
02989           (_current_path->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY))
02990       {
02991          _bitmapbox[BITMAPBOX_PLUS]->enable();
02992       }
02993       else
02994       {
02995          _bitmapbox[BITMAPBOX_PLUS]->disable();
02996       }
02997 
02998       // -rename/-delete
02999       DIR_ENTRYptr selected_entry = get_selected_entry();
03000       if ((selected_entry != NULL) &&
03001           (_current_path->_type != DIR_ENTRY::DIR_ENTRY_ROOT) &&
03002             ( (selected_entry->_type == DIR_ENTRY::DIR_ENTRY_DIRECTORY) ||
03003               (selected_entry->_type == DIR_ENTRY::DIR_ENTRY_FILE)))
03004       {
03005          _bitmapbox[BITMAPBOX_R]->enable();
03006          _bitmapbox[BITMAPBOX_X]->enable();
03007       }
03008       else
03009       {
03010          _bitmapbox[BITMAPBOX_R]->disable();
03011          _bitmapbox[BITMAPBOX_X]->disable();
03012       }
03013    }
03014 }
03015 
03016 
03017 //////////////////////////////////////////////////////
03018 // update_files()
03019 //////////////////////////////////////////////////////
03020 void     
03021 GLUIFileSelect::update_files()
03022 {
03023    update_headings();
03024    update_listing();
03025    update_scroll();
03026 }
03027 
03028 
03029 //////////////////////////////////////////////////////
03030 // update_headings()
03031 //////////////////////////////////////////////////////
03032 void     
03033 GLUIFileSelect::update_headings()
03034 {
03035    if ( (_current_mode == MODE_RENAME) ||
03036         (_current_mode == MODE_DELETE) ||
03037         (_current_mode == MODE_ADD) ) 
03038    {
03039       _button[BUT_HEADING_NAME]->disable();
03040       _button[BUT_HEADING_SIZE]->disable();
03041       _button[BUT_HEADING_DATE]->disable();
03042    }
03043    else
03044    {
03045       assert(_current_mode == MODE_NORMAL);
03046 
03047       //Re-set button labels
03048       assert(_current_path != NULL);
03049 
03050       _button[BUT_HEADING_NAME]->set_name("Name");
03051       _button[BUT_HEADING_SIZE]->set_name("Size");
03052       _button[BUT_HEADING_DATE]->set_name("Date");
03053 
03054       if (_current_path->_type == DIR_ENTRY::DIR_ENTRY_ROOT)
03055       {
03056          _button[BUT_HEADING_NAME]->disable();
03057          _button[BUT_HEADING_SIZE]->disable();
03058          _button[BUT_HEADING_DATE]->disable();
03059       }
03060       else
03061       {
03062          _button[BUT_HEADING_NAME]->enable();
03063          _button[BUT_HEADING_SIZE]->enable();
03064          _button[BUT_HEADING_DATE]->enable();
03065 
03066          switch(_current_sort)
03067          {
03068             case SORT_NAME_UP:
03069                _button[BUT_HEADING_NAME]->set_name("Name [^]");
03070             break;
03071             case SORT_NAME_DOWN:
03072                _button[BUT_HEADING_NAME]->set_name("Name [v]");
03073             break;
03074             case SORT_DATE_UP:
03075                _button[BUT_HEADING_DATE]->set_name("Date [^]");
03076             break;
03077             case SORT_DATE_DOWN:
03078                _button[BUT_HEADING_DATE]->set_name("Date [v]");
03079             break;
03080             case SORT_SIZE_UP:
03081                _button[BUT_HEADING_SIZE]->set_name("Size [^]");
03082             break;
03083             case SORT_SIZE_DOWN:
03084                _button[BUT_HEADING_SIZE]->set_name("Size [v]");
03085             break;
03086             default:
03087                assert(0);
03088          }
03089       }
03090    }
03091 }
03092 
03093 //////////////////////////////////////////////////////
03094 // shorten_string()
03095 //////////////////////////////////////////////////////
03096 str_ptr
03097 GLUIFileSelect::shorten_string(int new_len, Cstr_ptr &string)
03098 {
03099    str_ptr ret;
03100 
03101    int len = string.len();
03102 
03103    assert( (new_len >= 0) && (new_len < len) );
03104 
03105    //Return only new_len characters from string, chop
03106    //extra from the middle, and replace with elipses...
03107 
03108    int starting_len   = new_len/2;
03109    int finishing_len  = new_len - starting_len;
03110 
03111    char *starting  = new char[starting_len+1]; assert(starting);
03112    
03113    strncpy(starting,**string,starting_len); starting[starting_len] = 0;
03114 
03115    ret = str_ptr(starting) + "..." + &(**string)[len-finishing_len];
03116 
03117    delete[] starting;
03118 
03119    return ret;
03120 }
03121 
03122 //////////////////////////////////////////////////////
03123 // update_listing()
03124 //////////////////////////////////////////////////////
03125 #define CHR_BUF_SIZE 1024
03126 void     
03127 GLUIFileSelect::update_listing()
03128 {
03129    int i,j;
03130 
03131    if ( (_current_mode == MODE_RENAME) ||
03132         (_current_mode == MODE_DELETE) ||
03133         (_current_mode == MODE_ADD) ) 
03134    {
03135       for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
03136       {
03137          _bitmapbox[BITMAPBOX_NUM + i]->disable();
03138          _activetext[ACTIVETEXT_NUM + i]->disable();
03139          _activetext[ACTIVETEXT_NUM + i]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
03140          _statictext[STATICTEXT_NUM + 2*i]->disable();
03141          _statictext[STATICTEXT_NUM + 2*i]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
03142          _statictext[STATICTEXT_NUM + 2*i + 1]->disable();
03143          _statictext[STATICTEXT_NUM + 2*i + 1]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);      
03144       }
03145    }
03146    else
03147    {
03148       assert(_current_mode == MODE_NORMAL);
03149 
03150       for (i=0;i<GLUI_FILE_SELECT_NUM_FILES;i++)
03151       {
03152          if ( (_current_path != NULL) && 
03153               (_current_scroll+i < _current_path->_contents.num()) )
03154          {
03155             int         ret;
03156             char        chr_buf[CHR_BUF_SIZE];
03157             str_ptr     foo, bar;
03158             IconBitmap  *bm;
03159             DIR_ENTRYptr e = _current_path->_contents[_current_scroll+i]; assert(e != NULL);
03160 
03161 
03162 
03163             switch(e->_type)
03164             {
03165                case DIR_ENTRY::DIR_ENTRY_DRIVE:       bm = &_bitmaps[BITMAP_DRIVE];   break;
03166                case DIR_ENTRY::DIR_ENTRY_DIRECTORY:   bm = &_bitmaps[BITMAP_FOLDER];  break;
03167                case DIR_ENTRY::DIR_ENTRY_FILE:        bm = &_bitmaps[BITMAP_DOC];     break;
03168                default: assert(0); break;
03169             }
03170             _bitmapbox[BITMAPBOX_NUM + i]->enable();
03171             _bitmapbox[BITMAPBOX_NUM + i]->set_img_size(bm->_width, bm->_height);
03172             _bitmapbox[BITMAPBOX_NUM + i]->copy_img(bm->_data, bm->_width, bm->_height, 3);
03173 
03174             _activetext[ACTIVETEXT_NUM + i]->enable();
03175             _activetext[ACTIVETEXT_NUM + i]->set_name(" ");
03176             _activetext[ACTIVETEXT_NUM + i]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
03177             foo = e->_name; 
03178             bar=foo;j=foo.len();while(!_activetext[ACTIVETEXT_NUM + i]->check_fit(**bar)) bar=shorten_string(--j,foo);
03179             _activetext[ACTIVETEXT_NUM + i]->set_text(**bar);
03180             _activetext[ACTIVETEXT_NUM + i]->set_highlighted(i == _current_selection);
03181 
03182             //XXX - Truncate...
03183             if      (e->_size >= 1e13) sprintf(chr_buf,"%3.f TB", e->_size/1e12);
03184             else if (e->_size >= 1e10) sprintf(chr_buf,"%3.f GB", e->_size/1e9);
03185             else if (e->_size >= 1e7)  sprintf(chr_buf,"%3.f MB", e->_size/1e6);
03186             else if (e->_size >= 1e3)  sprintf(chr_buf,"%3.f KB", e->_size/1e3);
03187             else if (e->_size >= 0)    sprintf(chr_buf,"%3.f B",  e->_size);
03188             else                       chr_buf[0]=0;
03189 
03190             _statictext[STATICTEXT_NUM + 2*i]->enable();
03191             _statictext[STATICTEXT_NUM + 2*i]->set_name(" ");
03192             _statictext[STATICTEXT_NUM + 2*i]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
03193             foo = chr_buf; 
03194             bar=foo;j=foo.len();while(!_statictext[STATICTEXT_NUM + 2*i]->check_fit(**bar)) bar=shorten_string(--j,foo);
03195             _statictext[STATICTEXT_NUM + 2*i]->set_text(**bar);         
03196 
03197             //XXX - Truncate...
03198             if (e->_date > 0)
03199             {
03200                ret = strftime(chr_buf, CHR_BUF_SIZE, "%m/%d/%Y %I:%M %p", localtime(&e->_date)); assert(ret != 0);
03201             }
03202             else
03203             {
03204                chr_buf[0] = 0;
03205             }
03206             _statictext[STATICTEXT_NUM + 2*i + 1]->enable();
03207             _statictext[STATICTEXT_NUM + 2*i + 1]->set_name(" ");
03208             _statictext[STATICTEXT_NUM + 2*i + 1]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);      
03209             foo = chr_buf; 
03210             bar=foo;j=foo.len();while(!_statictext[STATICTEXT_NUM + 2*i + 1]->check_fit(**bar)) bar=shorten_string(--j,foo);
03211             _statictext[STATICTEXT_NUM + 2*i + 1]->set_text(**bar);
03212          }
03213          else
03214          {
03215             IconBitmap *bm = &_bitmaps[BITMAP_BLANK];
03216             
03217             if ( (_current_path->_contents.num() == 0) && (i==0) )
03218             {
03219                _bitmapbox[BITMAPBOX_NUM + i]->enable();
03220                _bitmapbox[BITMAPBOX_NUM + i]->set_img_size(bm->_width, bm->_height);
03221                _bitmapbox[BITMAPBOX_NUM + i]->copy_img(bm->_data, bm->_width, bm->_height, 3);
03222          
03223                _activetext[ACTIVETEXT_NUM + i]->disable();
03224                _activetext[ACTIVETEXT_NUM + i]->set_text("Empty");
03225                _activetext[ACTIVETEXT_NUM + i]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
03226                _activetext[ACTIVETEXT_NUM + i]->set_highlighted(false);
03227                assert(i != _current_selection);
03228 
03229                _statictext[STATICTEXT_NUM + 2*i]->disable();
03230                _statictext[STATICTEXT_NUM + 2*i]->set_text("");
03231                _statictext[STATICTEXT_NUM + 2*i]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
03232          
03233                _statictext[STATICTEXT_NUM + 2*i + 1]->disable();
03234                _statictext[STATICTEXT_NUM + 2*i + 1]->set_text("");
03235                _statictext[STATICTEXT_NUM + 2*i + 1]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);   
03236             }
03237             else
03238             {
03239                _bitmapbox[BITMAPBOX_NUM + i]->enable();
03240                _bitmapbox[BITMAPBOX_NUM + i]->set_img_size(bm->_width, bm->_height);
03241                _bitmapbox[BITMAPBOX_NUM + i]->copy_img(bm->_data, bm->_width, bm->_height, 3);
03242          
03243                _activetext[ACTIVETEXT_NUM + i]->disable();
03244                _activetext[ACTIVETEXT_NUM + i]->set_text("");
03245                _activetext[ACTIVETEXT_NUM + i]->set_w(GLUI_FILE_SELECT_NAME_WIDTH);
03246                _activetext[ACTIVETEXT_NUM + i]->set_highlighted(false);
03247                assert(i != _current_selection);
03248 
03249                _statictext[STATICTEXT_NUM + 2*i]->disable();
03250                _statictext[STATICTEXT_NUM + 2*i]->set_text("");
03251                _statictext[STATICTEXT_NUM + 2*i]->set_w(GLUI_FILE_SELECT_SIZE_WIDTH);
03252          
03253                _statictext[STATICTEXT_NUM + 2*i + 1]->disable();
03254                _statictext[STATICTEXT_NUM + 2*i + 1]->set_text("");
03255                _statictext[STATICTEXT_NUM + 2*i + 1]->set_w(GLUI_FILE_SELECT_DATE_WIDTH);   
03256             }
03257          }
03258       }
03259    }
03260 }
03261 
03262 //////////////////////////////////////////////////////
03263 // update_scroll()
03264 //////////////////////////////////////////////////////
03265 void     
03266 GLUIFileSelect::update_scroll()
03267 {
03268    int i,j;
03269 
03270    if ( (_current_mode == MODE_RENAME) ||
03271         (_current_mode == MODE_DELETE) ||
03272         (_current_mode == MODE_ADD) ) 
03273    {
03274       _bitmapbox[BITMAPBOX_DOWN_FILE]->disable();
03275       _bitmapbox[BITMAPBOX_UP_FILE]->disable();
03276       _bitmapbox[BITMAPBOX_SCROLL_FILE]->disable();
03277    }
03278    else
03279    {
03280       assert(_current_mode == MODE_NORMAL);
03281 
03282       //Otherwise...
03283 
03284       int w = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_image_w();
03285       int h = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_image_h();
03286 
03287       int pix_below, pix_showing, pix_above;
03288       int num_below, num_showing, num_above;
03289 
03290       IconBitmap  slider(w,h);
03291       IconBitmap *proto = &_bitmaps[BITMAP_SCROLL];  
03292       assert(proto && (proto->_width == w));
03293 
03294       compute_scroll_geometry(h, pix_below, pix_showing, pix_above, num_below, num_showing, num_above);
03295 
03296       i=0;
03297 
03298       if (pix_below)
03299       {
03300          slider.copy(0, 5, proto, 0, i, w, 1); i++;
03301          if ((_current_scrollbar_state == BAR_STATE_LOWER_DOWN) && _current_scrollbar_state_inside)
03302          {
03303             for (j=1; j<pix_below; j++)      { slider.copy(0, 5, proto, 0, i, w, 1); i++; }
03304          }
03305          else
03306          {
03307             for (j=1; j<pix_below; j++)      { slider.copy(0, 6, proto, 0, i, w, 1); i++; }
03308          }
03309       }
03310    
03311       slider.copy(0, 0, proto, 0, i, w, 2); i+=2;
03312       for (j=2; j<(pix_showing-2); j++)   { slider.copy(0, 2, proto, 0, i, w, 1); i++; }
03313       slider.copy(0, 3, proto, 0, i, w, 2); i+=2;
03314 
03315       if (pix_above)
03316       {
03317          if ((_current_scrollbar_state == BAR_STATE_UPPER_DOWN) && _current_scrollbar_state_inside)
03318          {
03319             for (j=0; j<(pix_above-1); j++)  { slider.copy(0, 7, proto, 0, i, w, 1); i++; }
03320          }
03321          else
03322          {
03323             for (j=0; j<(pix_above-1); j++)  { slider.copy(0, 6, proto, 0, i, w, 1); i++; }
03324          }
03325          slider.copy(0, 7, proto, 0, i, w, 1); i++;
03326       }
03327 
03328       assert(i==h);
03329 
03330       _bitmapbox[BITMAPBOX_SCROLL_FILE]->copy_img(slider._data, slider._width, slider._height ,3);
03331 
03332 
03333       if (pix_below)
03334       {
03335          _bitmapbox[BITMAPBOX_DOWN_FILE]->enable();
03336       }
03337       else
03338       {
03339          _bitmapbox[BITMAPBOX_DOWN_FILE]->disable();
03340       }
03341 
03342       if (pix_above)
03343       {
03344          _bitmapbox[BITMAPBOX_UP_FILE]->enable();
03345       }
03346       else
03347       {
03348          _bitmapbox[BITMAPBOX_UP_FILE]->disable();
03349       }
03350 
03351       if (pix_above || pix_below)
03352       {
03353          _bitmapbox[BITMAPBOX_SCROLL_FILE]->enable();
03354       }
03355       else
03356       {
03357          _bitmapbox[BITMAPBOX_SCROLL_FILE]->disable();
03358       }
03359    }
03360 }
03361 
03362 //////////////////////////////////////////////////////
03363 // compute_scroll_geometry()
03364 //////////////////////////////////////////////////////
03365 void     
03366 GLUIFileSelect::compute_scroll_geometry(int h, int &pix_below, int &pix_showing, int &pix_above,
03367                                                int &num_below, int &num_showing, int &num_above)
03368 {
03369    assert(_current_path != NULL);
03370    assert((_current_scroll >= 0) &&
03371           (_current_scroll <= max(0,_current_path->_contents.num() - GLUI_FILE_SELECT_NUM_FILES + 1)));
03372 
03373    double n = _current_path->_contents.num();
03374 
03375    double n_above    = _current_scroll;
03376    double n_showing  = min(n - n_above , GLUI_FILE_SELECT_NUM_FILES - 1.0);
03377    double n_below    = n - n_above - n_showing;
03378 
03379    double n_ab       = n_above + n_below;
03380 
03381    double p_showing = max((double)GLUI_FILE_SELECT_SCROLL_MIN, h * ((n>0.0)?(1.0 - n_above/n - n_below/n):(0.0)));
03382    double p_above = (h-p_showing) * ((n_ab>0.0)?(n_above/n_ab):(0.0));
03383    double p_below = (h-p_showing) * ((n_ab>0.0)?(n_below/n_ab):(0.0));
03384 
03385    num_above   = int(n_above);
03386    num_showing = int(n_showing);
03387    num_below   = int(n_below);
03388 
03389    pix_showing = int(p_showing);
03390    pix_above   = int(p_above);
03391    pix_below   = int(p_below);
03392 
03393    int leftover = h - (pix_below + pix_above + pix_showing);
03394 
03395    if (leftover)
03396    {
03397       if ((pix_below < pix_above) && (num_below))
03398       {
03399          pix_below += leftover;
03400       }
03401       else if (num_above)
03402       {
03403          pix_above += leftover;
03404       }
03405       else
03406       {
03407          pix_showing += leftover;
03408       }
03409    }
03410 
03411 }
03412 
03413 //////////////////////////////////////////////////////
03414 // update_actions()
03415 //////////////////////////////////////////////////////
03416 void     
03417 GLUIFileSelect::update_actions()
03418 {
03419    int i,j;
03420 
03421    if (_current_mode == MODE_RENAME)
03422    {
03423       _listbox[LIST_FILTER]->disable();
03424       _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
03425 
03426       _statictext[STATICTEXT_LABEL_DOT]->disable();
03427       _checkbox[CHECKBOX_DOT]->disable();
03428 
03429       _edittext[EDITTEXT_FILE]->set_name("Rename ");
03430       _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
03431                                     (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
03432                                              _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
03433       _edittext[EDITTEXT_FILE]->enable();
03434       _glui->activate_control(_edittext[EDITTEXT_FILE],GLUI_ACTIVATE_DEFAULT);
03435 
03436       _button[BUT_ACTION]->set_name("RENAME");
03437       _button[BUT_ACTION]->enable();
03438 
03439       _button[BUT_CANCEL]->set_name("Cancel");
03440       _button[BUT_CANCEL]->enable();
03441    }
03442    else if (_current_mode == MODE_DELETE)
03443    {
03444       _listbox[LIST_FILTER]->disable();
03445       _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
03446 
03447       _statictext[STATICTEXT_LABEL_DOT]->disable();
03448       _checkbox[CHECKBOX_DOT]->disable();
03449 
03450       _edittext[EDITTEXT_FILE]->set_name(" ");
03451       _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
03452                                     (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
03453                                              _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
03454       _edittext[EDITTEXT_FILE]->disable();
03455 
03456       _button[BUT_ACTION]->set_name("DELETE");
03457       _button[BUT_ACTION]->enable();
03458 
03459       _button[BUT_CANCEL]->set_name("Cancel");
03460       _button[BUT_CANCEL]->enable();
03461       _glui->activate_control(_button[BUT_CANCEL],GLUI_ACTIVATE_DEFAULT);
03462    }
03463    else if (_current_mode == MODE_ADD) 
03464    {
03465       _listbox[LIST_FILTER]->disable();
03466       _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
03467 
03468       _statictext[STATICTEXT_LABEL_DOT]->disable();
03469       _checkbox[CHECKBOX_DOT]->disable();
03470 
03471       _edittext[EDITTEXT_FILE]->set_name("Create ");
03472       _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
03473                                     (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
03474                                              _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
03475       _edittext[EDITTEXT_FILE]->enable();
03476       _glui->activate_control(_edittext[EDITTEXT_FILE],GLUI_ACTIVATE_DEFAULT);
03477 
03478       _button[BUT_ACTION]->set_name("CREATE");
03479       _button[BUT_ACTION]->enable();
03480 
03481       _button[BUT_CANCEL]->set_name("Cancel");
03482       _button[BUT_CANCEL]->enable();
03483    }
03484    else
03485    {
03486       assert(_current_mode == MODE_NORMAL);
03487 
03488       assert(_current_path != NULL);
03489 
03490       if (_current_path->_type == DIR_ENTRY::DIR_ENTRY_ROOT)
03491       {
03492          _listbox[LIST_FILTER]->disable();
03493          _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
03494 
03495          _statictext[STATICTEXT_LABEL_DOT]->disable();
03496          _checkbox[CHECKBOX_DOT]->disable();
03497 
03498          _button[BUT_ACTION]->disable();
03499          _button[BUT_ACTION]->set_name(**_action);
03500 
03501          _button[BUT_CANCEL]->enable();
03502          _button[BUT_CANCEL]->set_name("Cancel");
03503 
03504          _edittext[EDITTEXT_FILE]->disable();
03505          _edittext[EDITTEXT_FILE]->set_name("Filename ");
03506          _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
03507                                        (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
03508                                                 _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
03509       }
03510       else
03511       {
03512          str_ptr foo, bar;
03513 
03514          assert(_filter < _filters.num());
03515 
03516          _listbox[LIST_FILTER]->enable();
03517          _listbox[LIST_FILTER]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH);
03518 
03519          _statictext[STATICTEXT_LABEL_DOT]->enable();
03520          _checkbox[CHECKBOX_DOT]->enable();
03521 
03522          //Clear it out
03523          for (i=0; _listbox[LIST_FILTER]->delete_item(i); i++) {}
03524 
03525          //Add this placeholder for final selection to avoid flickering...
03526          foo = _filters[_filter]; 
03527          bar=foo;j=foo.len();while(!_listbox[LIST_FILTER]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
03528          _listbox[LIST_FILTER]->add_item(-1, **bar);
03529 
03530          for (i=0; i < _filters.num(); i++) 
03531          {
03532             foo = _filters[i]; 
03533             bar=foo;j=foo.len();while(!_listbox[LIST_FILTER]->check_item_fit(**bar)) bar=shorten_string(--j,foo);
03534             _listbox[LIST_FILTER]->add_item(i, **bar);
03535          }
03536 
03537          _listbox[LIST_FILTER]->set_int_val(_filter);
03538 
03539          //Remove placeholder
03540          _listbox[LIST_FILTER]->delete_item(-1);
03541 
03542          _button[BUT_ACTION]->enable();
03543          _button[BUT_ACTION]->set_name(**_action);
03544 
03545          _button[BUT_CANCEL]->enable();
03546          _button[BUT_CANCEL]->set_name("Cancel");
03547 
03548          _edittext[EDITTEXT_FILE]->enable();
03549          _edittext[EDITTEXT_FILE]->set_name("Filename ");
03550          _edittext[EDITTEXT_FILE]->set_w(GLUI_FILE_SELECT_FILTER_WIDTH - 
03551                                        (_edittext[EDITTEXT_FILE]->string_width(_listbox[LIST_FILTER]->get_name()) - 
03552                                                 _edittext[EDITTEXT_FILE]->string_width(_edittext[EDITTEXT_FILE]->get_name())));
03553 
03554       }
03555    }
03556 }
03557 
03558 //////////////////////////////////////////////////////
03559 // checkbox_cb()
03560 //////////////////////////////////////////////////////
03561 void
03562 GLUIFileSelect::checkbox_cb(int id)
03563 {
03564    switch(id)
03565    {
03566       case CHECKBOX_DOT:
03567          do_refresh();
03568       break;
03569       default:
03570          assert(0);
03571    }
03572 }
03573 
03574 //////////////////////////////////////////////////////
03575 // listbox_cb()
03576 //////////////////////////////////////////////////////
03577 void
03578 GLUIFileSelect::listbox_cb(int id)
03579 {
03580    switch(id)
03581    {
03582       case LIST_FILTER:
03583          if (_filter != _listbox[LIST_FILTER]->get_int_val())
03584          {
03585             _filter = _listbox[LIST_FILTER]->get_int_val();
03586             do_refresh();
03587          }
03588       break;
03589       case LIST_PATH:
03590          do_path_listbox();
03591       break;
03592       default:
03593          assert(0);
03594    }
03595 }
03596 
03597 //////////////////////////////////////////////////////
03598 // edittext_cb()
03599 //////////////////////////////////////////////////////
03600 void
03601 GLUIFileSelect::edittext_cb(int id)
03602 {
03603    switch(id)
03604    {
03605       case EDITTEXT_FILE:
03606          do_edittext_event();
03607       break;
03608       default:
03609          assert(0);
03610    }
03611 }
03612 
03613 //////////////////////////////////////////////////////
03614 // button_cb()
03615 //////////////////////////////////////////////////////
03616 void
03617 GLUIFileSelect::button_cb(int id)
03618 {
03619    if (_current_mode != MODE_NORMAL)
03620    {
03621       switch(id)
03622       {
03623          case BUT_ACTION:
03624             if (_current_mode == MODE_RENAME)
03625             {
03626                do_rename_action();
03627             }
03628             else if (_current_mode == MODE_DELETE)
03629             {
03630                do_delete_action();
03631             }
03632             else if (_current_mode == MODE_ADD) 
03633             {
03634                do_add_action();
03635             }  
03636             else
03637             {
03638                assert(0);
03639             }
03640          break;
03641          case BUT_CANCEL:
03642             do_cancel_action();
03643          break;
03644          default:
03645             assert(0);
03646          break;
03647       }
03648    }
03649    else
03650    {
03651       assert(_current_path != NULL);
03652 
03653       str_ptr text;
03654       str_list filter_chars, bad_chars;
03655       
03656       filter_chars += "*";
03657       filter_chars += "?";
03658 
03659       bad_chars += "/";
03660       bad_chars += "\\";
03661       
03662 #ifdef WIN32
03663       bad_chars += ";";
03664       bad_chars += "\"";
03665       bad_chars += "<";
03666       bad_chars += ">";
03667       bad_chars += "|";
03668 #endif
03669 
03670       switch(id)
03671       {
03672          case BUT_ACTION:
03673             //If the filename contains a filter character, we must be tryin
03674             //to change filters... go fot it.
03675             text = _edittext[EDITTEXT_FILE]->get_text();
03676             if (text.contains(filter_chars))
03677             {
03678                _filters.add_uniquely(text);
03679                _filter = _filters.get_index(text);
03680                _edittext[EDITTEXT_FILE]->set_text("");
03681                do_refresh();
03682             }
03683             else if (text.contains(bad_chars))
03684             {
03685                _edittext[EDITTEXT_FILE]->set_text("BadFilename");
03686                _glui->activate_control(_edittext[EDITTEXT_FILE],GLUI_ACTIVATE_DEFAULT);
03687                do_refresh();
03688             }
03689             else
03690             {
03691                //Only exit successfully with a valid directory... 
03692                //The file root doesn't count!
03693                if (_current_path->_type != DIR_ENTRY::DIR_ENTRY_ROOT)
03694                {
03695                   undisplay(OK_ACTION, 
03696                         _current_path->_full_path +
03697                            ((_current_path->_type == DIR_ENTRY::DIR_ENTRY_DRIVE)?(NULL_STR):("/")),
03698                               _edittext[EDITTEXT_FILE]->get_text());
03699                }
03700                else
03701                {
03702                   //Shouldn't be able to get here...
03703                   assert(0);
03704                }
03705             }
03706          break;
03707          case BUT_CANCEL:
03708             undisplay(CANCEL_ACTION, _path, _file);
03709          break;
03710          case BUT_HEADING_NAME:
03711          case BUT_HEADING_SIZE:
03712          case BUT_HEADING_DATE:
03713             do_sort_toggle(id);
03714          break;
03715          default:
03716             assert(0);
03717       }
03718    }
03719 }
03720 
03721 //////////////////////////////////////////////////////
03722 // bitmapbox_cb()
03723 //////////////////////////////////////////////////////
03724 void
03725 GLUIFileSelect::bitmapbox_cb(int id)
03726 {
03727    if (id == BITMAPBOX_SCROLL_FILE)
03728    {
03729       int e = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event();
03730       int x = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event_x();
03731       int y = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event_y();
03732       int i = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event_in();
03733       int k = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event_key();
03734       int m = _bitmapbox[BITMAPBOX_SCROLL_FILE]->get_event_mod();
03735       do_scrollbar(e,x,y,i,k,m);
03736    }
03737    else
03738    {
03739       switch (_bitmapbox[id]->get_event())
03740       {
03741          case GLUI_BITMAPBOX_EVENT_NONE:
03742          case GLUI_BITMAPBOX_EVENT_MOUSE_DOWN:
03743          case GLUI_BITMAPBOX_EVENT_MOUSE_MOVE:
03744          case GLUI_BITMAPBOX_EVENT_KEY:
03745          case GLUI_BITMAPBOX_EVENT_MIDDLE_DOWN:
03746          case GLUI_BITMAPBOX_EVENT_MIDDLE_MOVE:
03747          case GLUI_BITMAPBOX_EVENT_MIDDLE_UP:
03748          case GLUI_BITMAPBOX_EVENT_RIGHT_DOWN:
03749          case GLUI_BITMAPBOX_EVENT_RIGHT_MOVE:
03750          case GLUI_BITMAPBOX_EVENT_RIGHT_UP:
03751             //Do nothing for these events...
03752          break;
03753          case GLUI_BITMAPBOX_EVENT_MOUSE_UP:
03754             //Do respeective event on mouse up
03755             //if the pointer's still inside the
03756             //bitmap...
03757             if (_bitmapbox[id]->get_event_in())
03758             {
03759                switch(id)
03760                {
03761                   case BITMAPBOX_UP_FILE:
03762                      do_scroll_delta(-1);
03763                   break;
03764                   case BITMAPBOX_DOWN_FILE:
03765                      do_scroll_delta(+1);
03766                   break;
03767                   case BITMAPBOX_UP:
03768                      do_up_directory();
03769                   break;
03770                   case BITMAPBOX_DOT:
03771                      do_refresh();
03772                   break;
03773                   case BITMAPBOX_R:
03774                      do_rename_mode();
03775                   break;
03776                   case BITMAPBOX_X:
03777                      do_delete_mode();
03778                   break;
03779                   case BITMAPBOX_PLUS:
03780                      do_add_mode();
03781                   break;
03782                   default:
03783                      assert(0);
03784                   break;
03785                }
03786             }
03787          break;
03788          default:
03789             assert(0);
03790          break;
03791       }
03792    }
03793 }
03794 
03795 //////////////////////////////////////////////////////
03796 // activetext_cb()
03797 //////////////////////////////////////////////////////
03798 void
03799 GLUIFileSelect::activetext_cb(int id)
03800 {
03801 
03802    if (id < ACTIVETEXT_NUM)
03803    {
03804       //Switch on possible 'named' active text controls...
03805 /*      
03806       switch(id)
03807       {
03808          case ACTIVETEXT_XXX:
03809 
03810          break;
03811          default:
03812             assert(0);
03813          break;
03814       }
03815 */
03816    }
03817    else
03818    {
03819       do_entry_select(id-ACTIVETEXT_NUM);
03820    }
03821 
03822 }

Generated on Mon Sep 18 11:39:31 2006 for jot by  doxygen 1.4.4