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