fa2f8b24401483dc332e28db2a8cd5ace6419d20
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcfilebox.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcdelete.h"
23 #include "bcfilebox.h"
24 #include "bclistboxitem.h"
25 #include "bcnewfolder.h"
26 #include "bcpixmap.h"
27 #include "bcrename.h"
28 #include "bcresources.h"
29 #include "bcsignals.h"
30 #include "bctitle.h"
31 #include "clip.h"
32 #include "condition.h"
33 #include "filesystem.h"
34 #include "keys.h"
35 #include "language.h"
36 #include "mutex.h"
37 #include <string.h>
38 #include <sys/stat.h>
39
40
41
42
43
44
45
46 BC_FileBoxRecent::BC_FileBoxRecent(BC_FileBox *filebox, int x, int y)
47  : BC_ListBox(x, y, 250,
48                 filebox->get_text_height(MEDIUMFONT) * FILEBOX_HISTORY_SIZE +
49                 BC_ScrollBar::get_span(SCROLL_HORIZ) +
50                 LISTBOX_MARGIN * 2, LISTBOX_TEXT, &filebox->recent_dirs,
51                 0, 0, 1, 0, 1)
52 {
53         this->filebox = filebox;
54 }
55
56 int BC_FileBoxRecent::handle_event()
57 {
58         BC_ListBoxItem *selection = get_selection(0, 0);
59         if( selection != 0 ) {
60                 char *path = selection->get_text();
61                 filebox->submit_dir(path);
62         }
63         return 1;
64 }
65
66
67
68
69
70
71
72
73
74
75
76 BC_FileBoxListBox::BC_FileBoxListBox(int x, int y, BC_FileBox *filebox)
77  : BC_ListBox(x, y, filebox->get_listbox_w(), filebox->get_listbox_h(y),
78                 filebox->get_display_mode(), filebox->list_column,
79                 filebox->column_titles, filebox->column_width,
80                 filebox->columns, 0, 0,
81                 filebox->select_multiple ? LISTBOX_MULTIPLE : LISTBOX_SINGLE,
82                 ICON_LEFT, 0)
83 {
84         this->filebox = filebox;
85         set_sort_column(filebox->sort_column);
86         set_sort_order(filebox->sort_order);
87         set_allow_drag_column(1);
88 }
89
90 BC_FileBoxListBox::~BC_FileBoxListBox()
91 {
92 }
93
94 int BC_FileBoxListBox::handle_event()
95 {
96         filebox->submit_file(filebox->textbox->get_text());
97         return 1;
98 }
99
100 int BC_FileBoxListBox::selection_changed()
101 {
102         BC_ListBoxItem *item = get_selection(
103                 filebox->column_of_type(FILEBOX_NAME), 0);
104
105         if(item) {
106                 char path[BCTEXTLEN];
107                 strcpy(path, item->get_text());
108                 filebox->textbox->update(path);
109                 filebox->fs->extract_dir(filebox->directory, path);
110                 filebox->fs->extract_name(filebox->filename, path);
111                 filebox->fs->complete_path(path);
112                 strcpy(filebox->current_path, path);
113                 strcpy(filebox->submitted_path, path);
114         }
115         return 1;
116 }
117
118 int BC_FileBoxListBox::column_resize_event()
119 {
120         for(int i = 0; i < filebox->columns; i++)
121                 BC_WindowBase::get_resources()->filebox_columnwidth[i] =
122                         filebox->column_width[i] =
123                         get_column_width(i);
124         return 1;
125 }
126
127 int BC_FileBoxListBox::sort_order_event()
128 {
129         get_resources()->filebox_sortcolumn = filebox->sort_column = get_sort_column();
130         get_resources()->filebox_sortorder = filebox->sort_order = get_sort_order();
131         filebox->refresh(-1);
132         return 1;
133 }
134
135 int BC_FileBoxListBox::move_column_event()
136 {
137         filebox->move_column(get_from_column(), get_to_column());
138         return 1;
139 }
140
141 int BC_FileBoxListBox::evaluate_query(char *string)
142 {
143 // Search name column
144         ArrayList<BC_ListBoxItem*> *column =
145                 &filebox->list_column[filebox->column_of_type(FILEBOX_NAME)];
146 // Get current selection
147         int current_selection = get_selection_number(0, 0);
148
149 // Get best score in remaining items
150         int lowest_score = 0x7fffffff;
151         int best_item = -1;
152         if(current_selection < 0) current_selection = 0;
153 //      for(int i = current_selection + 1; i < column->size(); i++)
154         for(int i = current_selection; i < column->size(); i++)
155         {
156                 int len1 = strlen(string);
157                 int len2 = strlen(column->get(i)->get_text());
158                 int current_score = strncasecmp(string,
159                         column->get(i)->get_text(),
160                         MIN(len1, len2));
161 //printf(" %d i=%d %d %s %s\n", __LINE__, i, current_score, string, column->get(i)->get_text());
162
163                 if(abs(current_score) < lowest_score)
164                 {
165                         lowest_score = abs(current_score);
166                         best_item = i;
167                 }
168         }
169
170
171         return best_item;
172 }
173
174
175 BC_FileBoxTextBox::BC_FileBoxTextBox(int x, int y, BC_FileBox *filebox)
176  : BC_TextBox(x, y, filebox->get_w() - 20, 1,
177         filebox->want_directory ?  filebox->directory : filebox->filename)
178 {
179         this->filebox = filebox;
180 }
181
182 BC_FileBoxTextBox::~BC_FileBoxTextBox()
183 {
184 }
185
186 int BC_FileBoxTextBox::handle_event()
187 {
188         int result = 0;
189         if(get_keypress() != RETURN)
190         {
191                 result = calculate_suggestions(&filebox->list_column[0]);
192         }
193         return result;
194 }
195
196
197 BC_FileBoxDirectoryText::BC_FileBoxDirectoryText(int x, int y, BC_FileBox *filebox)
198  : BC_TextBox(x, y, filebox->get_w() - 40, 1, filebox->fs->get_current_dir())
199 {
200         this->filebox = filebox;
201 }
202
203 int BC_FileBoxDirectoryText::handle_event()
204 {
205         const char *path = get_text();
206         if( !filebox->fs->is_dir(path) ) return 0;
207         const char *cp = path;
208         while( *cp ) ++cp;
209         if( cp > path && *--cp != '/' ) return 0;
210         char *file_path = FileSystem::basepath(path);
211         char *dir_path = FileSystem::basepath(filebox->directory);
212         int ret = !strcmp(file_path, dir_path) ? 0 : 1;
213         if( ret ) {
214                 strcpy(filebox->directory, file_path);
215                 filebox->update_history();
216                 filebox->fs->change_dir(file_path);
217                 filebox->refresh(1);
218         }
219         delete [] dir_path;
220         delete [] file_path;
221         return ret;
222 }
223
224
225 BC_FileBoxSearchText::BC_FileBoxSearchText(int x, int y, BC_FileBox *filebox)
226  : BC_TextBox(x, y, filebox->get_w() - x - 40, 1, "")
227 {
228         this->filebox = filebox;
229 }
230
231 int BC_FileBoxSearchText::handle_event()
232 {
233         filebox->refresh();
234         return 1;
235 }
236
237
238 BC_FileBoxFilterText::BC_FileBoxFilterText(int x, int y, BC_FileBox *filebox)
239  : BC_TextBox(x, y, filebox->get_w() - x - 50, 1, filebox->get_resources()->filebox_filter)
240 {
241         this->filebox = filebox;
242 }
243
244 int BC_FileBoxFilterText::handle_event()
245 {
246         filebox->update_filter(get_text());
247         return 1;
248 }
249
250
251 BC_FileBoxFilterMenu::BC_FileBoxFilterMenu(int x, int y, BC_FileBox *filebox)
252  : BC_ListBox(x, y, filebox->get_w() - 30, 120,
253         LISTBOX_TEXT, &filebox->filter_list, 0, 0, 1, 0, 1)
254 {
255         this->filebox = filebox;
256         set_tooltip(_("Change the filter"));
257 }
258
259 int BC_FileBoxFilterMenu::handle_event()
260 {
261         filebox->filter_text->update(
262                 get_selection(filebox->column_of_type(FILEBOX_NAME), 0)->get_text());
263         filebox->update_filter(
264                 get_selection(filebox->column_of_type(FILEBOX_NAME), 0)->get_text());
265         return 1;
266 }
267
268
269 BC_FileBoxSizeFormat::BC_FileBoxSizeFormat(int x, int y, BC_FileBox *file_box)
270  : BC_Button(x, y, &BC_WindowBase::get_resources()->
271                 filebox_szfmt_images[3*file_box->size_format])
272 {
273         this->file_box = file_box;
274         set_tooltip(_("Size numeric format"));
275 }
276 BC_FileBoxSizeFormat::~BC_FileBoxSizeFormat()
277 {
278 }
279
280 int BC_FileBoxSizeFormat::handle_event()
281 {
282         if( ++file_box->size_format > FILEBOX_SIZE_THOU )
283                 file_box->size_format = FILEBOX_SIZE_RAW;
284         BC_WindowBase::get_resources()->filebox_size_format = file_box->size_format;
285         set_images(&BC_WindowBase::get_resources()->
286                 filebox_szfmt_images[3*file_box->size_format]);
287         draw_face(0);
288         file_box->refresh(0);
289         return 1;
290 }
291
292
293 BC_FileBoxUseThis::BC_FileBoxUseThis(BC_FileBox *filebox)
294  : BC_Button(filebox->get_w() / 2 -
295                 BC_WindowBase::get_resources()->usethis_button_images[0]->get_w() / 2,
296         filebox->ok_button->get_y(),
297         BC_WindowBase::get_resources()->usethis_button_images)
298 {
299         this->filebox = filebox;
300         set_tooltip(_("Submit the directory"));
301 }
302
303 BC_FileBoxUseThis::~BC_FileBoxUseThis()
304 {
305 }
306
307 int BC_FileBoxUseThis::handle_event()
308 {
309 // printf("BC_FileBoxUseThis::handle_event %d '%s'\n",
310 // __LINE__,
311 // filebox->textbox->get_text());
312         filebox->submit_file(filebox->textbox->get_text(), 1);
313         return 1;
314 }
315
316
317 BC_FileBoxOK::BC_FileBoxOK(BC_FileBox *filebox)
318  : BC_OKButton(filebox,
319         !filebox->want_directory ?
320                 BC_WindowBase::get_resources()->ok_images :
321                 BC_WindowBase::get_resources()->filebox_descend_images)
322 {
323         this->filebox = filebox;
324         if(filebox->want_directory)
325                 set_tooltip(_("Descend directory"));
326         else
327                 set_tooltip(_("Submit the file"));
328 }
329
330 BC_FileBoxOK::~BC_FileBoxOK()
331 {
332 }
333
334 int BC_FileBoxOK::handle_event()
335 {
336 //printf("BC_FileBoxOK::handle_event %d\n", __LINE__);
337         const char *path = filebox->textbox->get_text();
338         if( *path ) filebox->submit_file(path);
339         return 1;
340 }
341
342 BC_FileBoxCancel::BC_FileBoxCancel(BC_FileBox *filebox)
343  : BC_CancelButton(filebox)
344 {
345         this->filebox = filebox;
346         set_tooltip(_("Cancel the operation"));
347 }
348
349 BC_FileBoxCancel::~BC_FileBoxCancel()
350 {
351 }
352
353 int BC_FileBoxCancel::handle_event()
354 {
355 //      filebox->submit_file(filebox->textbox->get_text());
356         filebox->newfolder_thread->interrupt();
357         filebox->set_done(1);
358         return 1;
359 }
360
361
362
363 BC_FileBoxText::BC_FileBoxText(int x, int y, BC_FileBox *filebox)
364  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_text_images)
365 {
366         this->filebox = filebox;
367         set_tooltip(_("Display text"));
368 }
369 int BC_FileBoxText::handle_event()
370 {
371         filebox->create_listbox(filebox->listbox->get_x(), filebox->listbox->get_y(), LISTBOX_TEXT);
372         filebox->listbox->show_window(1);
373         return 1;
374 }
375
376
377 BC_FileBoxIcons::BC_FileBoxIcons(int x, int y, BC_FileBox *filebox)
378  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_icons_images)
379 {
380         this->filebox = filebox;
381         set_tooltip(_("Display icons"));
382 }
383 int BC_FileBoxIcons::handle_event()
384 {
385         filebox->create_listbox(filebox->listbox->get_x(), filebox->listbox->get_y(), LISTBOX_ICONS);
386         filebox->listbox->show_window(1);
387         return 1;
388 }
389
390
391 BC_FileBoxNewfolder::BC_FileBoxNewfolder(int x, int y, BC_FileBox *filebox)
392  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_newfolder_images)
393 {
394         this->filebox = filebox;
395         set_tooltip(_("Create new folder"));
396 }
397 int BC_FileBoxNewfolder::handle_event()
398 {
399         filebox->newfolder_thread->start_new_folder();
400         return 1;
401 }
402
403
404 BC_FileBoxRename::BC_FileBoxRename(int x, int y, BC_FileBox *filebox)
405  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_rename_images)
406 {
407         this->filebox = filebox;
408         set_tooltip(_("Rename file"));
409 }
410 int BC_FileBoxRename::handle_event()
411 {
412         filebox->rename_thread->start_rename();
413         return 1;
414 }
415
416 BC_FileBoxUpdir::BC_FileBoxUpdir(int x, int y, BC_FileBox *filebox)
417  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_updir_images)
418 {
419         this->filebox = filebox;
420         set_tooltip(_("Up a directory"));
421 }
422 int BC_FileBoxUpdir::handle_event()
423 {
424 // Need a temp so submit_file can expand it
425         sprintf(string, "..");
426         filebox->submit_file(string);
427         return 1;
428 }
429
430 BC_FileBoxDelete::BC_FileBoxDelete(int x, int y, BC_FileBox *filebox)
431  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_delete_images)
432 {
433         this->filebox = filebox;
434         set_tooltip(_("Delete files"));
435 }
436 int BC_FileBoxDelete::handle_event()
437 {
438         filebox->unlock_window();
439         filebox->delete_thread->start();
440         filebox->lock_window("BC_FileBoxDelete::handle_event");
441         return 1;
442 }
443
444 BC_FileBoxReload::BC_FileBoxReload(int x, int y, BC_FileBox *filebox)
445  : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_reload_images)
446 {
447         this->filebox = filebox;
448         set_tooltip(_("Refresh"));
449 }
450 int BC_FileBoxReload::handle_event()
451 {
452         filebox->refresh();
453         return 1;
454 }
455
456
457
458 BC_FileBox::BC_FileBox(int x, int y, const char *init_path,
459                 const char *title, const char *caption, int show_all_files,
460                 int want_directory, int multiple_files, int h_padding)
461  : BC_Window(title, x, y,
462         BC_WindowBase::get_resources()->filebox_w,
463         BC_WindowBase::get_resources()->filebox_h,
464         400, 300, 1, 0, 1)
465 {
466         fs = new FileSystem;
467 //      if(want_directory)
468 //      {
469 //              fs->set_want_directory();
470 //              columns = DIRBOX_COLUMNS;
471 //              columns = FILEBOX_COLUMNS;
472 //      }
473 //      else
474         {
475                 columns = FILEBOX_COLUMNS;
476         }
477
478         list_column = new ArrayList<BC_ListBoxItem*>[columns];
479         column_type = new int[columns];
480         column_width = new int[columns];
481
482         filter_title = 0;
483         filter_text = 0;
484         filter_popup = 0;
485         usethis_button = 0;
486         size_format = BC_WindowBase::get_resources()->filebox_size_format;
487
488         strcpy(this->caption, caption);
489         strcpy(this->current_path, init_path);
490         strcpy(this->submitted_path, init_path);
491         select_multiple = multiple_files;
492         this->want_directory = want_directory;
493         if(show_all_files) fs->set_show_all();
494         fs->complete_path(this->current_path);
495         strcpy(this->submitted_path, this->current_path);
496         fs->extract_dir(directory, this->current_path);
497         fs->extract_name(filename, this->current_path);
498
499 // printf("BC_FileBox::BC_FileBox %d '%s' '%s' '%s'\n",
500 // __LINE__,
501 // this->submitted_path,
502 // directory,
503 // filename);
504
505 //      if(want_directory)
506 //      {
507 //              for(int i = 0; i < columns; i++)
508 //              {
509 //                      column_type[i] = get_resources()->dirbox_columntype[i];
510 //                      column_width[i] = get_resources()->dirbox_columnwidth[i];
511 //                      column_titles[i] = BC_FileBox::columntype_to_text(column_type[i]);
512 //              }
513 //              sort_column = get_resources()->dirbox_sortcolumn;
514 //              sort_order = get_resources()->dirbox_sortorder;
515 //      }
516 //      else
517         {
518                 for(int i = 0; i < columns; i++)
519                 {
520                         column_type[i] = get_resources()->filebox_columntype[i];
521                         column_width[i] = get_resources()->filebox_columnwidth[i];
522                         column_titles[i] = (char*)BC_FileBox::columntype_to_text(column_type[i]);
523                 }
524                 sort_column = get_resources()->filebox_sortcolumn;
525                 sort_order = get_resources()->filebox_sortorder;
526         }
527
528
529
530 // Test if current directory exists
531         if(!fs->is_dir(directory))
532         {
533                 sprintf(directory, "~");
534                 fs->complete_path(directory);
535                 strcpy(current_path,directory);
536                 filename[0] = 0;
537         }
538         fs->set_current_dir(directory);
539
540         if(h_padding == -1)
541         {
542                 h_padding = BC_WindowBase::get_resources()->ok_images[0]->get_h() -
543                         20;
544         }
545         this->h_padding = h_padding;
546         delete_thread = new BC_DeleteThread(this);
547         rename_thread = 0;
548 }
549
550 BC_FileBox::~BC_FileBox()
551 {
552 // this has to be destroyed before tables, because it can call for an update!
553         delete newfolder_thread;
554         delete fs;
555         delete_tables();
556         for(int i = 0; i < TOTAL_ICONS; i++)
557                 delete icons[i];
558         filter_list.remove_all_objects();
559         delete [] list_column;
560         delete [] column_type;
561         delete [] column_width;
562         delete delete_thread;
563         delete rename_thread;
564         recent_dirs.remove_all_objects();
565 }
566
567 void BC_FileBox::create_objects()
568 {
569         lock_window("BC_FileBox::create_objects");
570         int x = 10, y = 10;
571         BC_Resources *resources = BC_WindowBase::get_resources();
572         int directory_title_margin = MAX(20,
573                 resources->filebox_text_images[0]->get_h());
574
575 // Directories aren't filtered in FileSystem so skip this
576         if(!want_directory)
577         {
578                 filter_list.append(new BC_ListBoxItem("*"));
579                 filter_list.append(new BC_ListBoxItem("[*.mkv][*.webm]"));
580                 filter_list.append(new BC_ListBoxItem("[*.mp4][*.MP4]"));
581                 filter_list.append(new BC_ListBoxItem("[*.mp2][*.mp3][*.wav]"));
582                 filter_list.append(new BC_ListBoxItem("[*.avi][*.mpg][*.m2v][*.m1v][*.mov]"));
583                 filter_list.append(new BC_ListBoxItem("[*.jpg][*.JPG][*.png][*.gif][*.tiff]"));
584                 filter_list.append(new BC_ListBoxItem("*.xml"));
585                 fs->set_filter(get_resources()->filebox_filter);
586         }
587
588         create_icons();
589         create_tables(0);
590
591         add_subwindow(ok_button = new BC_FileBoxOK(this));
592         if(want_directory)
593                 add_subwindow(usethis_button = new BC_FileBoxUseThis(this));
594         add_subwindow(cancel_button = new BC_FileBoxCancel(this));
595
596         add_subwindow(new BC_Title(x, y, caption));
597
598         x = get_w() - resources->filebox_icons_images[0]->get_w() - 10;
599
600         add_subwindow(icon_button = new BC_FileBoxIcons(x, y, this));
601         x -= resources->filebox_text_images[0]->get_w() + 5;
602
603         add_subwindow(text_button = new BC_FileBoxText(x, y, this));
604         x -= resources->filebox_newfolder_images[0]->get_w() + 5;
605
606         add_subwindow(folder_button = new BC_FileBoxNewfolder(x, y, this));
607         x -= resources->filebox_delete_images[0]->get_w() + 5;
608
609         add_subwindow(rename_button = new BC_FileBoxRename(x, y, this));
610         x -= resources->filebox_delete_images[0]->get_w() + 5;
611
612         add_subwindow(delete_button = new BC_FileBoxDelete(x, y, this));
613         x -= resources->filebox_reload_images[0]->get_w() + 5;
614
615         add_subwindow(reload_button = new BC_FileBoxReload(x, y, this));
616         x -= resources->filebox_updir_images[0]->get_w() + 5;
617
618         add_subwindow(updir_button = new BC_FileBoxUpdir(x, y, this));
619         x -= resources->filebox_szfmt_images[0]->get_w() + 5;
620
621         add_subwindow(szfmt_button = new BC_FileBoxSizeFormat(x, y, this));
622
623         x = 10;
624         y += directory_title_margin + 3;
625
626         add_subwindow(recent_popup = new BC_FileBoxRecent(this, x, y));
627         add_subwindow(directory_title = new BC_FileBoxDirectoryText(x, y, this));
628         directory_title->reposition_window(x, y, get_w() - recent_popup->get_w() -  20, 1);
629         x += directory_title->get_w() + 8;
630         recent_popup->reposition_window(x, y, directory_title->get_w(), 200);
631
632         x = 10;
633         y += directory_title->get_h() + 5;
634
635         BC_Title *search_title;
636         add_subwindow(search_title = new BC_Title(x, y, _("Search:")));
637         x += search_title->get_w() + 10;
638         add_subwindow(search_text = new BC_FileBoxSearchText(x, y, this));
639
640         x = 10;
641         y += search_text->get_h() + 5;
642
643         int newest_id = 0, newest = -1;
644         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++) {
645                 if( !resources->filebox_history[i].path[0] ) continue;
646                 if( resources->filebox_history[i].id > newest_id ) {
647                         newest_id = resources->filebox_history[i].id;
648                         newest = i;
649                 }
650         }
651         if( newest >= 0 ) {
652                 strcpy(directory, resources->filebox_history[newest].path);
653                 fs->change_dir(directory, 0);
654                 strcpy(directory, fs->get_current_dir());
655                 directory_title->update(fs->get_current_dir());
656         }
657         fs->set_sort_order(sort_order);
658         fs->set_sort_field(column_type[sort_column]);
659         fs->update(directory);
660
661 // Create recent dir list
662         create_history();
663         update_history();
664
665         listbox = 0;
666         create_listbox(x, y, get_display_mode());
667         y += listbox->get_h() + 10;
668         add_subwindow(textbox = new BC_FileBoxTextBox(x, y, this));
669         y += textbox->get_h() + 10;
670
671         if(!want_directory) {
672                 add_subwindow(filter_title = new BC_Title(x, y, _("Specify filter:")));
673                 int x1 = x + filter_title->get_w() + 10;
674                 add_subwindow(filter_text = new BC_FileBoxFilterText(x1, y, this));
675                 add_subwindow(filter_popup =
676                         new BC_FileBoxFilterMenu(x1 + filter_text->get_w(), y, this));
677         }
678
679 // listbox has to be active because refresh might be called from newfolder_thread
680         listbox->activate();
681         newfolder_thread = new BC_NewFolderThread(this);
682
683         rename_thread = new BC_RenameThread(this);
684
685         refresh();
686         show_window();
687         unlock_window();
688 }
689
690 int BC_FileBox::get_listbox_w()
691 {
692         return get_w() - 20;
693 }
694
695 int BC_FileBox::get_listbox_h(int y)
696 {
697         int result = get_h() - y - h_padding - 10;
698         if(want_directory)
699                 result -= BC_WindowBase::get_resources()->dirbox_margin;
700         else
701                 result -= BC_WindowBase::get_resources()->filebox_margin;
702
703         return result;
704 }
705
706 int BC_FileBox::create_icons()
707 {
708         for(int i = 0; i < TOTAL_ICONS; i++)
709         {
710                 icons[i] = new BC_Pixmap(this,
711                         BC_WindowBase::get_resources()->type_to_icon[i],
712                         PIXMAP_ALPHA);
713         }
714         return 0;
715 }
716
717 int BC_FileBox::resize_event(int w, int h)
718 {
719         draw_background(0, 0, w, h);
720         flash(0);
721
722 // OK button handles resize event itself
723 //      ok_button->reposition_window(ok_button->get_x(),
724 //              h - (get_h() - ok_button->get_y()));
725 //      cancel_button->reposition_window(w - (get_w() - cancel_button->get_x()),
726 //              h - (get_h() - cancel_button->get_y()));
727         if(usethis_button)
728                 usethis_button->reposition_window(w / 2 - 50,
729                         h - (get_h() - usethis_button->get_y()));
730
731
732         if(filter_popup) filter_popup->reposition_window(w - (get_w() - filter_popup->get_x()),
733                 h - (get_h() - filter_popup->get_y()),
734                 w - 30,
735                 0);
736
737         if(filter_title) filter_title->reposition_window(filter_title->get_x(),
738                 h - (get_h() - filter_title->get_y()));
739         if(filter_text) filter_text->reposition_window(filter_text->get_x(),
740                 h - (get_h() - filter_text->get_y()),
741                 w - (get_w() - filter_text->get_w()),
742                 1);
743         directory_title->reposition_window(
744                 directory_title->get_x(),
745                 directory_title->get_y(),
746                 get_w() - recent_popup->get_w() -  20,
747                 1);
748         recent_popup->reposition_window(
749                 directory_title->get_x() + directory_title->get_w() + 8,
750                 directory_title->get_y(),
751                 directory_title->get_w() + recent_popup->get_w(),
752                 recent_popup->get_h());
753         search_text->reposition_window(
754                 search_text->get_x(),
755                 search_text->get_y(),
756                 get_w() - search_text->get_x() -  40,
757                 1);
758         textbox->reposition_window(textbox->get_x(),
759                 h - (get_h() - textbox->get_y()),
760                 w - (get_w() - textbox->get_w()),
761                 1);
762         listbox->reposition_window(listbox->get_x(),
763                 listbox->get_y(),
764                 w - (get_w() - listbox->get_w()),
765                 h - (get_h() - listbox->get_h()),
766                 0);
767         int dx = w - get_w();
768         icon_button->reposition_window(icon_button->get_x()+dx, icon_button->get_y());
769         text_button->reposition_window(text_button->get_x()+dx, text_button->get_y());
770         folder_button->reposition_window(folder_button->get_x()+dx, folder_button->get_y());
771         rename_button->reposition_window(rename_button->get_x()+dx, rename_button->get_y());
772         reload_button->reposition_window(reload_button->get_x()+dx, reload_button->get_y());
773         delete_button->reposition_window(delete_button->get_x()+dx, delete_button->get_y());
774         updir_button->reposition_window(updir_button->get_x()+dx, updir_button->get_y());
775         szfmt_button->reposition_window(szfmt_button->get_x()+dx, szfmt_button->get_y());
776         set_w(w);  set_h(h);
777         get_resources()->filebox_w = get_w();
778         get_resources()->filebox_h = get_h();
779         flush();
780         return 1;
781 }
782
783 int BC_FileBox::keypress_event()
784 {
785         switch(get_keypress()) {
786         case 'a':
787                 if( !ctrl_down() ) break;
788                 refresh(0, 1);
789                 return 1;
790         case 'z':
791                 if( !ctrl_down() ) break;
792                 refresh(0, 0);
793                 return 1;
794         case 'w':
795                 if( !ctrl_down() ) break;
796                 set_done(1);
797                 return 1;
798         }
799         return 0;
800 }
801
802 int BC_FileBox::close_event()
803 {
804         set_done(1);
805         return 1;
806 }
807
808 int BC_FileBox::handle_event()
809 {
810         return 0;
811 }
812
813 int BC_FileBox::extract_extension(char *out, const char *in)
814 {
815         *out = 0;
816         int i = strlen(in);
817         while( --i>=0 && in[i]!='.' );
818         if( i >= 0 ) strcpy(out, &in[++i]);
819         return 0;
820 }
821
822 static inline int64_t ipow(int m, int n)
823 {
824         int64_t v = 1;
825         for( int64_t vv=m; n>0; vv*=vv,n>>=1 ) if( n & 1 ) v *= vv;
826         return v;
827 }
828 static inline int ilen(int64_t v)
829 {
830         int len = 1;
831         while( len<16 && (v/=10)>0 ) ++len;
832         return len;
833 }
834
835 int BC_FileBox::create_tables(int select_all)
836 {
837         int preload_textbox = select_all;
838         delete_tables();
839         char string[BCTEXTLEN];
840         BC_ListBoxItem *new_item;
841
842         fs->set_sort_order(sort_order);
843         fs->set_sort_field(column_type[sort_column]);
844
845         for(int i = 0; i < fs->total_files(); i++)
846         {
847                 FileItem *file_item = fs->get_entry(i);
848                 const char *text = search_text->get_text();
849                 if( text && text[0] && !bstrcasestr(file_item->name, text) )
850                         continue;
851                 int is_dir = file_item->is_dir;
852                 BC_Pixmap* icon = get_icon(file_item->name, is_dir);
853
854 // Name entry
855                 new_item = new BC_ListBoxItem(file_item->name,
856                         icon,
857                         is_dir ? get_resources()->directory_color : get_resources()->file_color);
858                 if(is_dir) new_item->set_searchable(0);
859                 list_column[column_of_type(FILEBOX_NAME)].append(new_item);
860
861 // Size entry
862 //              if(!want_directory)
863 //              {
864                         if(!is_dir)
865                         {
866                                 if( preload_textbox ) {
867                                         preload_textbox = 0;
868                                         textbox->update(new_item->get_text());
869                                 }
870                                 int64_t size = file_item->size;
871                                 if( (size_format == FILEBOX_SIZE_1000 && size >= 1000) ||
872                                     (size_format == FILEBOX_SIZE_1024 && size >= 1024) ) {
873                                         static const char *suffix[] = { "", "K", "M", "G", "T", "P" };
874                                         if( size_format == FILEBOX_SIZE_1024 ) {
875                                                 static const long double kk = logl(1000.)/logl(1024.);
876                                                 size = expl(kk*logl((long double)size)) + 0.5;
877                                         }
878                                         int len = ilen(size), drop = len-3, round = 1;
879                                         if( round && drop > 0 ) { //round
880                                                 size += ipow(10,drop)/2;
881                                                 len = ilen(size);  drop = len-3;
882                                         }
883                                         size /= ipow(10,drop);
884                                         int sfx = (len-1)/3;
885                                         int digits = (sfx+1)*3 - len;
886                                         int64_t frac = ipow(10,digits);
887                                         int mant  = size / frac;
888                                         int fraction = size - mant*frac;
889                                         sfx = *suffix[sfx];
890                                         if( sfx && size_format == FILEBOX_SIZE_1000 ) sfx += 'a'-'A';
891                                         if( digits )
892                                                 sprintf(string, "%d.%0*d%c", mant, digits, fraction, sfx);
893                                         else
894                                                 sprintf(string, "%d%c", mant, sfx);
895                                 }
896                                 else {
897                                         sprintf(string, "%jd", size);
898                                         if( size_format == FILEBOX_SIZE_THOU )
899                                                 Units::punctuate(string);
900                                 }
901                                 new_item = new BC_ListBoxItem(string, get_resources()->file_color);
902                         }
903                         else
904                         {
905                                 new_item = new BC_ListBoxItem("", get_resources()->directory_color);
906                         }
907
908                         list_column[column_of_type(FILEBOX_SIZE)].append(new_item);
909 //              }
910
911 // Date entry
912                 if(!is_dir || 1)
913                 {
914                         struct tm mod_time;
915                         localtime_r(&file_item->mtime, &mod_time);
916                         sprintf(string, "%04d.%02d.%02d  %02d:%02d:%02d",
917                                 mod_time.tm_year+1900, mod_time.tm_mon+1, mod_time.tm_mday,
918                                 mod_time.tm_hour, mod_time.tm_min, mod_time.tm_sec);
919                         new_item = new BC_ListBoxItem(string, get_resources()->file_color);
920                 }
921                 else
922                 {
923                         new_item = new BC_ListBoxItem("", get_resources()->directory_color);
924                 }
925
926                 list_column[column_of_type(FILEBOX_DATE)].append(new_item);
927
928 // Extension entry
929 //              if(!want_directory)
930 //              {
931                         if(!is_dir) {
932                                 extract_extension(string, file_item->name);
933                                 new_item = new BC_ListBoxItem(string, get_resources()->file_color);
934                         }
935                         else {
936                                 new_item = new BC_ListBoxItem("", get_resources()->directory_color);
937                         }
938                         list_column[column_of_type(FILEBOX_EXTENSION)].append(new_item);
939 //              }
940
941                 if( !is_dir && select_all ) {
942                         int k = list_column[0].size()-1;
943                         for( int j=0; j<columns; ++j )
944                                 list_column[j][k]->set_selected(1);
945                 }
946         }
947
948         return 0;
949 }
950
951 int BC_FileBox::delete_tables()
952 {
953         for(int j = 0; j < columns; j++)
954         {
955                 list_column[j].remove_all_objects();
956         }
957         return 0;
958 }
959
960 BC_Pixmap* BC_FileBox::get_icon(char *path, int is_dir)
961 {
962         if( is_dir ) return icons[ICON_FOLDER];
963         int icon_type = ICON_UNKNOWN;
964         char *suffix = strrchr(path, '.');
965         if( suffix && *++suffix ) {
966                 suffix_to_type_t *stp = &BC_WindowBase::get_resources()->suffix_to_type[0];
967                 while( stp->suffix && strcasecmp(stp->suffix, suffix) ) ++stp;
968                 if( stp->icon_type ) icon_type = stp->icon_type;
969         }
970
971         return icons[icon_type];
972 }
973
974 const char* BC_FileBox::columntype_to_text(int type)
975 {
976         switch(type) {
977                 case FILEBOX_NAME: return FILEBOX_NAME_TEXT;
978                 case FILEBOX_SIZE: return FILEBOX_SIZE_TEXT;
979                 case FILEBOX_DATE: return FILEBOX_DATE_TEXT;
980                 case FILEBOX_EXTENSION: return FILEBOX_EXTENSION_TEXT;
981         }
982         return "";
983 }
984
985 int BC_FileBox::column_of_type(int type)
986 {
987         for(int i = 0; i < columns; i++)
988                 if(column_type[i] == type) return i;
989         return 0;
990 }
991
992
993
994 int BC_FileBox::refresh(int reset, int select_all)
995 {
996         fs->set_sort_order(sort_order);
997         fs->set_sort_field(column_type[sort_column]);
998         if( reset >= 0 )
999                 fs->update(0);
1000         else
1001                 fs->update_sort();
1002         create_tables(select_all);
1003         listbox->set_master_column(column_of_type(FILEBOX_NAME), 0);
1004         listbox->update(list_column, column_titles, column_width, columns,
1005                 reset>0 ? 0 : listbox->get_xposition(),
1006                 reset>0 ? 0 : listbox->get_yposition(),
1007                 -1, 1);
1008         return 0;
1009 }
1010
1011 int BC_FileBox::update_filter(const char *filter)
1012 {
1013         fs->set_filter(filter);
1014 //      fs->update(0);
1015         refresh();
1016         strcpy(get_resources()->filebox_filter, filter);
1017
1018         return 0;
1019 }
1020
1021
1022 void BC_FileBox::move_column(int src, int dst)
1023 {
1024         if(src != dst)
1025         {
1026                 ArrayList<BC_ListBoxItem*> *new_columns =
1027                         new ArrayList<BC_ListBoxItem*>[columns];
1028                 int *new_types = new int[columns];
1029                 int *new_widths = new int[columns];
1030
1031         // Fill in remaining columns with consecutive data
1032                 for(int out_column = 0, in_column = 0;
1033                         out_column < columns;
1034                         out_column++,
1035                         in_column++)
1036                 {
1037         // Copy destination column from src column
1038                         if(out_column == dst)
1039                         {
1040                                 for(int i = 0; i < list_column[src].total; i++)
1041                                 {
1042                                         new_columns[out_column].append(list_column[src].values[i]);
1043                                 }
1044                                 new_types[out_column] = column_type[src];
1045                                 new_widths[out_column] = column_width[src];
1046                                 in_column--;
1047                         }
1048                         else
1049                         {
1050         // Skip source column
1051                                 if(in_column == src) in_column++;
1052                                 for(int i = 0; i < list_column[src].total; i++)
1053                                 {
1054                                         new_columns[out_column].append(list_column[in_column].values[i]);
1055                                 }
1056                                 new_types[out_column] = column_type[in_column];
1057                                 new_widths[out_column] = column_width[in_column];
1058                         }
1059                 }
1060
1061         // Swap tables
1062                 delete [] list_column;
1063                 delete [] column_type;
1064                 delete [] column_width;
1065                 list_column = new_columns;
1066                 column_type = new_types;
1067                 column_width = new_widths;
1068
1069                 for(int i = 0; i < columns; i++)
1070                 {
1071                         get_resources()->filebox_columntype[i] = column_type[i];
1072                         get_resources()->filebox_columnwidth[i] = column_width[i];
1073                         column_titles[i] = (char*)BC_FileBox::columntype_to_text(column_type[i]);
1074                 }
1075         }
1076
1077         refresh();
1078 }
1079
1080
1081 int BC_FileBox::submit_dir(char *dir)
1082 {
1083         strcpy(directory, dir);
1084         fs->join_names(current_path, directory, filename);
1085
1086 // printf("BC_FileBox::submit_dir %d '%s' '%s' '%s'\n",
1087 // __LINE__,
1088 // current_path,
1089 // directory,
1090 // filename);
1091         strcpy(submitted_path, current_path);
1092         fs->change_dir(dir, 0);
1093         refresh(1);
1094         directory_title->update(fs->get_current_dir());
1095         if(want_directory)
1096                 textbox->update(fs->get_current_dir());
1097         else
1098                 textbox->update(filename);
1099         listbox->reset_query();
1100         return 0;
1101 }
1102
1103 int BC_FileBox::submit_file(const char *path, int use_this)
1104 {
1105         char path1[BCTEXTLEN];
1106         strcpy(path1, path);
1107         char *cp = strchr(path1,'\n');
1108         if( cp ) *cp = 0;
1109
1110 // Deactivate textbox to hide suggestions
1111         textbox->deactivate();
1112
1113 // If file wanted, take the current directory as the desired file.
1114 // If directory wanted, ignore it.
1115         if(!path1[0] && !want_directory)
1116         {
1117 // save complete path
1118                 strcpy(this->current_path, directory);
1119 // save complete path
1120                 strcpy(this->submitted_path, directory);
1121                 update_history();
1122 // Zero out filename
1123                 filename[0] = 0;
1124                 set_done(0);
1125                 return 0;
1126         }
1127
1128 // is a directory, change directories
1129         if(fs->is_dir(path1) && !use_this)
1130         {
1131                 fs->change_dir(path1, 0);
1132                 refresh(1);
1133                 directory_title->update(fs->get_current_dir());
1134                 strcpy(this->current_path, fs->get_current_dir());
1135                 strcpy(this->submitted_path, fs->get_current_dir());
1136                 strcpy(this->directory, fs->get_current_dir());
1137                 update_history();
1138                 filename[0] = 0;
1139                 if(want_directory)
1140                         textbox->update(fs->get_current_dir());
1141                 else
1142                         textbox->update("");
1143                 listbox->reset_query();
1144                 return 1;
1145         }
1146         else
1147 // Is a file or desired directory.  Quit the operation.
1148         {
1149                 char path2[BCTEXTLEN];
1150                 strcpy(path2, path1);
1151
1152 // save directory for defaults
1153                 fs->extract_dir(directory, path2);
1154
1155 // Just take the directory
1156                 if(want_directory)
1157                 {
1158                         filename[0] = 0;
1159                         strcpy(path2, directory);
1160                 }
1161                 else
1162 // Take the complete path
1163                 {
1164                         fs->extract_name(filename, path2);     // save filename
1165                 }
1166
1167                 fs->complete_path(path2);
1168                 strcpy(this->current_path, path2);          // save complete path
1169                 strcpy(this->submitted_path, path2);          // save complete path
1170                 update_history();
1171                 newfolder_thread->interrupt();
1172                 set_done(0);
1173                 return 0;
1174         }
1175         return 0;
1176 }
1177
1178 void BC_FileBox::update_history()
1179 {
1180 // Look for path already in history
1181         BC_Resources *resources = get_resources();
1182         char path[BCTEXTLEN];
1183         strcpy(path, directory);
1184 // enfore one trailing slash
1185         char *cp = path;
1186         while( *cp && *cp != '\n' ) ++cp;
1187         while( cp > path && *(cp-1) == '/' ) --cp;
1188         *cp++ = '/';  *cp = 0;
1189
1190 //      int new_slot = FILEBOX_HISTORY_SIZE - 1;
1191
1192         for(int i = FILEBOX_HISTORY_SIZE - 1; i >= 0; i--)
1193         {
1194                 if(resources->filebox_history[i].path[0] &&
1195                         !strcmp(resources->filebox_history[i].path, path))
1196                 {
1197 // Got matching path.
1198 // Update ID.
1199                         resources->filebox_history[i].id = resources->get_filebox_id();
1200                         return;
1201                 }
1202 // // Shift down from this point.
1203 //                      while(i > 0)
1204 //                      {
1205 //                              strcpy(resources->filebox_history[i],
1206 //                                      resources->filebox_history[i - 1]);
1207 //                              if(resources->filebox_history[i][0]) new_slot--;
1208 //                              i--;
1209 //                      }
1210 //                      break;
1211 //              }
1212 //              else
1213 //                      if(resources->filebox_history[i][0])
1214 //                              new_slot--;
1215 //              else
1216 //                      break;
1217         }
1218
1219 // Remove oldest entry if full
1220         if(resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].path[0])
1221         {
1222                 int oldest_id = 0x7fffffff;
1223                 int oldest = 0;
1224                 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
1225                 {
1226                         if(resources->filebox_history[i].path[0] &&
1227                                 resources->filebox_history[i].id < oldest_id)
1228                         {
1229                                 oldest_id = resources->filebox_history[i].id;
1230                                 oldest = i;
1231                         }
1232                 }
1233
1234                 for(int i = oldest; i < FILEBOX_HISTORY_SIZE - 1; i++)
1235                 {
1236                         strcpy(resources->filebox_history[i].path,
1237                                 resources->filebox_history[i + 1].path);
1238                         resources->filebox_history[i].id =
1239                                 resources->filebox_history[i + 1].id;
1240                 }
1241         }
1242
1243 // Create new entry
1244         strcpy(resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].path, path);
1245         resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].id = resources->get_filebox_id();
1246
1247 // Alphabetize
1248         int done = 0;
1249         while(!done)
1250         {
1251                 done = 1;
1252                 for(int i = 1; i < FILEBOX_HISTORY_SIZE; i++)
1253                 {
1254                         if( (resources->filebox_history[i - 1].path[0] &&
1255                                 resources->filebox_history[i].path[0] &&
1256                                 strcasecmp(resources->filebox_history[i - 1].path,
1257                                         resources->filebox_history[i].path) > 0) ||
1258                                 (resources->filebox_history[i - 1].path[0] == 0 &&
1259                                         resources->filebox_history[i].path[0]) )
1260                         {
1261                                 done = 0;
1262                                 char temp[BCTEXTLEN];
1263                                 int id_temp;
1264                                 strcpy(temp, resources->filebox_history[i - 1].path);
1265                                 id_temp = resources->filebox_history[i - 1].id;
1266                                 strcpy(resources->filebox_history[i - 1].path,
1267                                         resources->filebox_history[i].path);
1268                                 resources->filebox_history[i - 1].id =
1269                                         resources->filebox_history[i].id;
1270                                 strcpy(resources->filebox_history[i].path, temp);
1271                                 resources->filebox_history[i].id = id_temp;
1272                         }
1273                 }
1274         }
1275
1276 //      if(new_slot < 0)
1277 //      {
1278 //              for(int i = FILEBOX_HISTORY_SIZE - 1; i > 0; i--)
1279 //              {
1280 //                      strcpy(resources->filebox_history[i],
1281 //                                      resources->filebox_history[i - 1]);
1282 //              }
1283 //              new_slot = 0;
1284 //      }
1285 //
1286 //      strcpy(resources->filebox_history[new_slot], path);
1287
1288         create_history();
1289         recent_popup->update(&recent_dirs, 0, 0, 1);
1290 }
1291
1292 void BC_FileBox::create_history()
1293 {
1294         BC_Resources *resources = get_resources();
1295         recent_dirs.remove_all_objects();
1296         for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++) {
1297                 if(resources->filebox_history[i].path[0]) {
1298                         recent_dirs.append(new BC_ListBoxItem(resources->filebox_history[i].path));
1299                 }
1300         }
1301 }
1302
1303
1304 int BC_FileBox::get_display_mode()
1305 {
1306         return top_level->get_resources()->filebox_mode;
1307 }
1308
1309 void BC_FileBox::create_listbox(int x, int y, int mode)
1310 {
1311         if(listbox && listbox->get_display_mode() != mode)
1312         {
1313                 delete listbox;
1314                 listbox = 0;
1315                 top_level->get_resources()->filebox_mode = mode;
1316         }
1317
1318         if(!listbox)
1319                 add_subwindow(listbox = new BC_FileBoxListBox(x, y, this));
1320 }
1321
1322 char* BC_FileBox::get_path(int selection)
1323 {
1324         if(selection == 0)
1325         {
1326                 return get_submitted_path();
1327         }
1328         else
1329         {
1330                 BC_ListBoxItem *item = listbox->get_selection(
1331                         column_of_type(FILEBOX_NAME), selection - 1);
1332                 if(item)
1333                 {
1334                         fs->join_names(string, directory, item->get_text());
1335                         return string;
1336                 }
1337         }
1338         return 0;
1339 }
1340
1341 char* BC_FileBox::get_submitted_path()
1342 {
1343         return submitted_path;
1344 }
1345
1346 char* BC_FileBox::get_current_path()
1347 {
1348 //printf("BC_FileBox::get_current_path 1 %s\n", current_path);
1349         return current_path;
1350 }
1351
1352 char* BC_FileBox::get_newfolder_title()
1353 {
1354         char *letter2 = strchr(title, ':');
1355         new_folder_title[0] = 0;
1356         if(letter2)
1357         {
1358                 memcpy(new_folder_title, title, letter2 - title);
1359                 new_folder_title[letter2 - title] = 0;
1360         }
1361
1362         strcat(new_folder_title, _(": New folder"));
1363
1364         return new_folder_title;
1365 }
1366
1367 char* BC_FileBox::get_rename_title()
1368 {
1369         char *letter2 = strchr(title, ':');
1370         new_folder_title[0] = 0;
1371         if(letter2)
1372         {
1373                 memcpy(new_folder_title, title, letter2 - title);
1374                 new_folder_title[letter2 - title] = 0;
1375         }
1376
1377         strcat(new_folder_title, _(": Rename"));
1378
1379         return new_folder_title;
1380 }
1381
1382 char* BC_FileBox::get_delete_title()
1383 {
1384         char *letter2 = strchr(title, ':');
1385         new_folder_title[0] = 0;
1386         if(letter2)
1387         {
1388                 memcpy(new_folder_title, title, letter2 - title);
1389                 new_folder_title[letter2 - title] = 0;
1390         }
1391
1392         strcat(new_folder_title, _(": Delete"));
1393
1394         return new_folder_title;
1395 }
1396
1397 void BC_FileBox::delete_files()
1398 {
1399 // Starting at 1 causes it to ignore what's in the textbox.
1400         int i = 1;
1401         char *path;
1402         FileSystem fs;
1403         while((path = get_path(i)))
1404         {
1405 // Not directory.  Remove it.
1406                 if(!fs.is_dir(path))
1407                 {
1408 //printf("BC_FileBox::delete_files: removing \"%s\"\n", path);
1409                         remove(path);
1410                 }
1411                 i++;
1412         }
1413         refresh();
1414 }
1415
1416 BC_Button* BC_FileBox::get_ok_button()
1417 {
1418         return ok_button;
1419 }
1420
1421 BC_Button* BC_FileBox::get_cancel_button()
1422 {
1423         return cancel_button;
1424 }
1425