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