4 * Copyright (C) 1997-2017 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcfilebox.h"
24 #include "bclistboxitem.h"
25 #include "bcnewfolder.h"
28 #include "bcresources.h"
29 #include "bcsignals.h"
32 #include "condition.h"
33 #include "filesystem.h"
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,
48 this->filebox = filebox;
49 set_tooltip(_("Recent paths"));
52 int BC_FileBoxRecent::handle_event()
54 BC_ListBoxItem *selection = get_selection(0, 0);
55 if( selection != 0 ) {
56 char *path = selection->get_text();
57 filebox->submit_dir(path);
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,
71 this->filebox = filebox;
72 set_sort_column(filebox->sort_column);
73 set_sort_order(filebox->sort_order);
74 set_allow_drag_column(1);
77 BC_FileBoxListBox::~BC_FileBoxListBox()
81 int BC_FileBoxListBox::handle_event()
83 filebox->submit_file(filebox->textbox->get_text());
87 int BC_FileBoxListBox::selection_changed()
89 BC_ListBoxItem *item = get_selection(
90 filebox->column_of_type(FILEBOX_NAME), 0);
93 filebox->textbox->update(item->get_text());
94 filebox->update_paths(item->get_text());
99 int BC_FileBoxListBox::column_resize_event()
101 for(int i = 0; i < filebox->columns; i++)
102 BC_WindowBase::get_resources()->filebox_columnwidth[i] =
103 filebox->column_width[i] =
108 int BC_FileBoxListBox::sort_order_event()
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);
116 int BC_FileBoxListBox::move_column_event()
118 filebox->move_column(get_from_column(), get_to_column());
122 int BC_FileBoxListBox::evaluate_query(char *string)
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);
130 // Get best score in remaining items
131 int lowest_score = 0x7fffffff;
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++)
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(),
142 //printf(" %d i=%d %d %s %s\n", __LINE__, i, current_score, string, column->get(i)->get_text());
144 if(abs(current_score) < lowest_score)
146 lowest_score = abs(current_score);
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)
160 this->filebox = filebox;
163 BC_FileBoxTextBox::~BC_FileBoxTextBox()
167 int BC_FileBoxTextBox::handle_event()
169 int key = get_keypress(), result = 1;
170 if( !key || key == RETURN ) // not a text update
171 filebox->update_paths(filebox->textbox->get_text());
173 result = calculate_suggestions(&filebox->list_column[0]);
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())
181 this->filebox = filebox;
184 int BC_FileBoxDirectoryText::handle_event()
186 const char *path = get_text();
187 if( !filebox->fs->is_dir(path) ) return 0;
188 const char *cp = path;
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;
195 strcpy(filebox->directory, file_path);
196 filebox->update_history();
197 filebox->fs->change_dir(file_path);
206 BC_FileBoxSearchText::BC_FileBoxSearchText(int x, int y, BC_FileBox *filebox)
207 : BC_TextBox(x, y, filebox->get_w() - x - xS(40), 1, "")
209 this->filebox = filebox;
212 int BC_FileBoxSearchText::handle_event()
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)
222 this->filebox = filebox;
225 int BC_FileBoxFilterText::handle_event()
227 filebox->update_filter(get_text());
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)
236 this->filebox = filebox;
237 set_tooltip(_("Change the filter"));
240 int BC_FileBoxFilterMenu::handle_event()
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());
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])
254 this->file_box = file_box;
255 set_tooltip(_("Size numeric format"));
257 BC_FileBoxSizeFormat::~BC_FileBoxSizeFormat()
261 int BC_FileBoxSizeFormat::handle_event()
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]);
269 file_box->refresh(0);
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)
280 this->filebox = filebox;
281 set_tooltip(_("Submit the directory"));
284 BC_FileBoxUseThis::~BC_FileBoxUseThis()
288 int BC_FileBoxUseThis::handle_event()
290 // printf("BC_FileBoxUseThis::handle_event %d '%s'\n",
292 // filebox->textbox->get_text());
293 filebox->submit_file(filebox->textbox->get_text(), 1);
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)
304 this->filebox = filebox;
305 if(filebox->want_directory)
306 set_tooltip(_("Descend directory"));
308 set_tooltip(_("Submit the file"));
311 BC_FileBoxOK::~BC_FileBoxOK()
315 int BC_FileBoxOK::handle_event()
317 //printf("BC_FileBoxOK::handle_event %d\n", __LINE__);
318 const char *path = filebox->textbox->get_text();
319 if( *path ) filebox->submit_file(path);
323 BC_FileBoxCancel::BC_FileBoxCancel(BC_FileBox *filebox)
324 : BC_CancelButton(filebox)
326 this->filebox = filebox;
327 set_tooltip(_("Cancel the operation"));
330 BC_FileBoxCancel::~BC_FileBoxCancel()
334 int BC_FileBoxCancel::handle_event()
336 // filebox->submit_file(filebox->textbox->get_text());
337 filebox->newfolder_thread->interrupt();
338 filebox->set_done(1);
344 BC_FileBoxText::BC_FileBoxText(int x, int y, BC_FileBox *filebox)
345 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_text_images)
347 this->filebox = filebox;
348 set_tooltip(_("Display text"));
350 int BC_FileBoxText::handle_event()
352 filebox->create_listbox(filebox->listbox->get_x(), filebox->listbox->get_y(), LISTBOX_TEXT);
353 filebox->listbox->show_window(1);
358 BC_FileBoxIcons::BC_FileBoxIcons(int x, int y, BC_FileBox *filebox)
359 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_icons_images)
361 this->filebox = filebox;
362 set_tooltip(_("Display icons"));
364 int BC_FileBoxIcons::handle_event()
366 filebox->create_listbox(filebox->listbox->get_x(), filebox->listbox->get_y(), LISTBOX_ICONS);
367 filebox->listbox->show_window(1);
372 BC_FileBoxNewfolder::BC_FileBoxNewfolder(int x, int y, BC_FileBox *filebox)
373 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_newfolder_images)
375 this->filebox = filebox;
376 set_tooltip(_("Create new folder"));
378 int BC_FileBoxNewfolder::handle_event()
380 filebox->newfolder_thread->start_new_folder();
385 BC_FileBoxRename::BC_FileBoxRename(int x, int y, BC_FileBox *filebox)
386 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_rename_images)
388 this->filebox = filebox;
389 set_tooltip(_("Rename file"));
391 int BC_FileBoxRename::handle_event()
393 filebox->rename_thread->start_rename();
397 BC_FileBoxUpdir::BC_FileBoxUpdir(int x, int y, BC_FileBox *filebox)
398 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_updir_images)
400 this->filebox = filebox;
401 set_tooltip(_("Up a directory"));
403 int BC_FileBoxUpdir::handle_event()
405 // Need a temp so submit_file can expand it
406 sprintf(string, "..");
407 filebox->submit_file(string);
411 BC_FileBoxDelete::BC_FileBoxDelete(int x, int y, BC_FileBox *filebox)
412 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_delete_images)
414 this->filebox = filebox;
415 set_tooltip(_("Delete files"));
417 int BC_FileBoxDelete::handle_event()
419 filebox->unlock_window();
420 filebox->delete_thread->start();
421 filebox->lock_window("BC_FileBoxDelete::handle_event");
425 BC_FileBoxReload::BC_FileBoxReload(int x, int y, BC_FileBox *filebox)
426 : BC_Button(x, y, BC_WindowBase::get_resources()->filebox_reload_images)
428 this->filebox = filebox;
429 set_tooltip(_("Refresh"));
431 int BC_FileBoxReload::handle_event()
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(450), yS(350), 1, 0, 1)
448 // if(want_directory)
450 // fs->set_want_directory();
451 // columns = DIRBOX_COLUMNS;
452 // columns = FILEBOX_COLUMNS;
456 columns = FILEBOX_COLUMNS;
459 list_column = new ArrayList<BC_ListBoxItem*>[columns];
460 column_type = new int[columns];
461 column_width = new int[columns];
467 size_format = BC_WindowBase::get_resources()->filebox_size_format;
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);
480 // printf("BC_FileBox::BC_FileBox %d '%s' '%s' '%s'\n",
482 // this->submitted_path,
486 // if(want_directory)
488 // for(int i = 0; i < columns; i++)
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]);
494 // sort_column = get_resources()->dirbox_sortcolumn;
495 // sort_order = get_resources()->dirbox_sortorder;
499 for(int i = 0; i < columns; i++)
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]);
505 sort_column = get_resources()->filebox_sortcolumn;
506 sort_order = get_resources()->filebox_sortorder;
511 // Test if current directory exists
512 if(!fs->is_dir(directory))
514 sprintf(directory, "~");
515 fs->complete_path(directory);
516 strcpy(current_path,directory);
519 fs->set_current_dir(directory);
523 h_padding = BC_WindowBase::get_resources()->ok_images[0]->get_h() - yS(20);
525 this->h_padding = h_padding;
526 delete_thread = new BC_DeleteThread(this);
531 BC_FileBox::~BC_FileBox()
533 // this has to be destroyed before tables, because it can call for an update!
534 delete newfolder_thread;
537 for(int i = 0; i < TOTAL_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();
548 void BC_FileBox::create_objects()
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());
558 // Directories aren't filtered in FileSystem so skip this
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);
574 add_subwindow(ok_button = new BC_FileBoxOK(this));
576 add_subwindow(usethis_button = new BC_FileBoxUseThis(this));
577 add_subwindow(cancel_button = new BC_FileBoxCancel(this));
579 add_subwindow(new BC_Title(x, y, caption));
581 x = get_w() - resources->filebox_icons_images[0]->get_w() - xs10;
583 add_subwindow(icon_button = new BC_FileBoxIcons(x, y, this));
584 x -= resources->filebox_text_images[0]->get_w() + xs5;
586 add_subwindow(text_button = new BC_FileBoxText(x, y, this));
587 x -= resources->filebox_newfolder_images[0]->get_w() + xs5;
589 add_subwindow(folder_button = new BC_FileBoxNewfolder(x, y, this));
590 x -= resources->filebox_delete_images[0]->get_w() + xs5;
592 add_subwindow(rename_button = new BC_FileBoxRename(x, y, this));
593 x -= resources->filebox_delete_images[0]->get_w() + xs5;
595 add_subwindow(delete_button = new BC_FileBoxDelete(x, y, this));
596 x -= resources->filebox_reload_images[0]->get_w() + xs5;
598 add_subwindow(reload_button = new BC_FileBoxReload(x, y, this));
599 x -= resources->filebox_updir_images[0]->get_w() + xs5;
601 add_subwindow(updir_button = new BC_FileBoxUpdir(x, y, this));
602 x -= resources->filebox_szfmt_images[0]->get_w() + xs5;
604 add_subwindow(szfmt_button = new BC_FileBoxSizeFormat(x, y, this));
607 y += directory_title_margin + yS(3);
609 add_subwindow(recent_popup = new BC_FileBoxRecent(this, x, y));
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));
618 y += directory_title->get_h() + ys5;
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));
626 y += search_text->get_h() + ys5;
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;
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());
642 fs->set_sort_order(sort_order);
643 fs->set_sort_field(column_type[sort_column]);
644 fs->update(directory);
646 // Create recent dir list
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;
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;
668 // listbox has to be active because refresh might be called from newfolder_thread
670 newfolder_thread = new BC_NewFolderThread(this);
672 rename_thread = new BC_RenameThread(this);
680 int BC_FileBox::get_listbox_w()
682 return get_w() - xS(20);
685 int BC_FileBox::get_listbox_h(int y)
687 int result = get_h() - y - h_padding - yS(10);
689 result -= BC_WindowBase::get_resources()->dirbox_margin;
691 result -= BC_WindowBase::get_resources()->filebox_margin;
696 int BC_FileBox::create_icons()
698 for(int i = 0; i < TOTAL_ICONS; i++)
700 icons[i] = new BC_Pixmap(this,
701 BC_WindowBase::get_resources()->type_to_icon[i],
707 int BC_FileBox::resize_event(int w, int h)
709 draw_background(0, 0, w, h);
711 int dw = w - get_w();
712 int dh = h - get_h();
714 // OK button handles resize event itself
715 // ok_button->reposition_window(ok_button->get_x(),
716 // ok_button->get_y() + dh);
717 // cancel_button->reposition_window(cancel_button->get_x() + dw,
718 // cancel_button->get_y() + dh);
720 usethis_button->reposition_window(w / 2 - xS(50),
721 usethis_button->get_y() + dh);
725 filter_popup->reposition_window(filter_popup->get_x() + dw,
726 filter_popup->get_y() + dh, w - xS(30), 0);
729 filter_title->reposition_window(filter_title->get_x(),
730 filter_title->get_y() + dh);
731 if(filter_text) filter_text->reposition_window(filter_text->get_x(),
732 filter_text->get_y() + dh, filter_text->get_w() + dw, 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(), search_text->get_y(),
742 get_w() - search_text->get_x() - xS(40), 1);
743 file_title->reposition_window(file_title->get_x(),
744 file_title->get_y() + dh);
745 textbox->reposition_window(textbox->get_x(),
746 textbox->get_y() + dh, textbox->get_w() + dw, 1);
747 listbox->reposition_window(listbox->get_x(), listbox->get_y(),
748 listbox->get_w() + dw, listbox->get_h() + dh, 0);
749 icon_button->reposition_window(icon_button->get_x()+dw, icon_button->get_y());
750 text_button->reposition_window(text_button->get_x()+dw, text_button->get_y());
751 folder_button->reposition_window(folder_button->get_x()+dw, folder_button->get_y());
752 rename_button->reposition_window(rename_button->get_x()+dw, rename_button->get_y());
753 reload_button->reposition_window(reload_button->get_x()+dw, reload_button->get_y());
754 delete_button->reposition_window(delete_button->get_x()+dw, delete_button->get_y());
755 updir_button->reposition_window(updir_button->get_x()+dw, updir_button->get_y());
756 szfmt_button->reposition_window(szfmt_button->get_x()+dw, szfmt_button->get_y());
758 get_resources()->filebox_w = get_w();
759 get_resources()->filebox_h = get_h();
760 y_margin = filter_text ?
761 filter_text->get_y() + filter_text->get_h() + yS(10) :
762 textbox->get_y() + textbox->get_h() + yS(10) ;
767 int BC_FileBox::keypress_event()
769 switch(get_keypress()) {
771 if( !ctrl_down() ) break;
775 if( !ctrl_down() ) break;
779 if( !ctrl_down() ) break;
786 int BC_FileBox::close_event()
792 int BC_FileBox::handle_event()
797 int BC_FileBox::extract_extension(char *out, const char *in)
801 while( --i>=0 && in[i]!='.' );
802 if( i >= 0 ) strcpy(out, &in[++i]);
806 static inline int64_t ipow(int m, int n)
809 for( int64_t vv=m; n>0; vv*=vv,n>>=1 ) if( n & 1 ) v *= vv;
812 static inline int ilen(int64_t v)
815 while( len<16 && (v/=10)>0 ) ++len;
819 int BC_FileBox::create_tables(int select_all)
821 int preload_textbox = select_all;
823 char string[BCTEXTLEN];
824 BC_ListBoxItem *new_item;
826 fs->set_sort_order(sort_order);
827 fs->set_sort_field(column_type[sort_column]);
829 for(int i = 0; i < fs->total_files(); i++)
831 FileItem *file_item = fs->get_entry(i);
832 const char *text = search_text->get_text();
833 if( text && text[0] && !bstrcasestr(file_item->name, text) )
835 int is_dir = file_item->is_dir;
836 BC_Pixmap* icon = get_icon(file_item->name, is_dir);
839 new_item = new BC_ListBoxItem(file_item->name,
841 is_dir ? get_resources()->directory_color : get_resources()->file_color);
842 if(is_dir) new_item->set_searchable(0);
843 list_column[column_of_type(FILEBOX_NAME)].append(new_item);
846 // if(!want_directory)
850 if( preload_textbox ) {
852 textbox->update(new_item->get_text());
854 int64_t size = file_item->size;
855 if( (size_format == FILEBOX_SIZE_1000 && size >= 1000) ||
856 (size_format == FILEBOX_SIZE_1024 && size >= 1024) ) {
857 static const char *suffix[] = { "", "K", "M", "G", "T", "P" };
858 if( size_format == FILEBOX_SIZE_1024 ) {
859 static const long double kk = logl(1000.)/logl(1024.);
860 size = expl(kk*logl((long double)size)) + 0.5;
862 int len = ilen(size), drop = len-3, round = 1;
863 if( round && drop > 0 ) { //round
864 size += ipow(10,drop)/2;
865 len = ilen(size); drop = len-3;
867 size /= ipow(10,drop);
869 int digits = (sfx+1)*3 - len;
870 int64_t frac = ipow(10,digits);
871 int mant = size / frac;
872 int fraction = size - mant*frac;
874 if( sfx && size_format == FILEBOX_SIZE_1000 ) sfx += 'a'-'A';
876 sprintf(string, "%d.%0*d%c", mant, digits, fraction, sfx);
878 sprintf(string, "%d%c", mant, sfx);
881 sprintf(string, "%jd", size);
882 if( size_format == FILEBOX_SIZE_THOU )
883 Units::punctuate(string);
885 new_item = new BC_ListBoxItem(string, get_resources()->file_color);
889 new_item = new BC_ListBoxItem("", get_resources()->directory_color);
892 list_column[column_of_type(FILEBOX_SIZE)].append(new_item);
899 localtime_r(&file_item->mtime, &mod_time);
900 sprintf(string, "%04d.%02d.%02d %02d:%02d:%02d",
901 mod_time.tm_year+1900, mod_time.tm_mon+1, mod_time.tm_mday,
902 mod_time.tm_hour, mod_time.tm_min, mod_time.tm_sec);
903 new_item = new BC_ListBoxItem(string, get_resources()->file_color);
907 new_item = new BC_ListBoxItem("", get_resources()->directory_color);
910 list_column[column_of_type(FILEBOX_DATE)].append(new_item);
913 // if(!want_directory)
916 extract_extension(string, file_item->name);
917 new_item = new BC_ListBoxItem(string, get_resources()->file_color);
920 new_item = new BC_ListBoxItem("", get_resources()->directory_color);
922 list_column[column_of_type(FILEBOX_EXTENSION)].append(new_item);
925 if( !is_dir && select_all ) {
926 int k = list_column[0].size()-1;
927 for( int j=0; j<columns; ++j )
928 list_column[j][k]->set_selected(1);
935 int BC_FileBox::delete_tables()
937 for(int j = 0; j < columns; j++)
939 list_column[j].remove_all_objects();
944 BC_Pixmap* BC_FileBox::get_icon(char *path, int is_dir)
946 if( is_dir ) return icons[ICON_FOLDER];
947 int icon_type = ICON_UNKNOWN;
948 char *suffix = strrchr(path, '.');
949 if( suffix && *++suffix ) {
950 suffix_to_type_t *stp = &BC_WindowBase::get_resources()->suffix_to_type[0];
951 while( stp->suffix && strcasecmp(stp->suffix, suffix) ) ++stp;
952 if( stp->icon_type ) icon_type = stp->icon_type;
955 return icons[icon_type];
958 const char* BC_FileBox::columntype_to_text(int type)
961 case FILEBOX_NAME: return FILEBOX_NAME_TEXT;
962 case FILEBOX_SIZE: return FILEBOX_SIZE_TEXT;
963 case FILEBOX_DATE: return FILEBOX_DATE_TEXT;
964 case FILEBOX_EXTENSION: return FILEBOX_EXTENSION_TEXT;
969 int BC_FileBox::column_of_type(int type)
971 for(int i = 0; i < columns; i++)
972 if(column_type[i] == type) return i;
978 int BC_FileBox::refresh(int reset, int select_all)
980 fs->set_sort_order(sort_order);
981 fs->set_sort_field(column_type[sort_column]);
986 create_tables(select_all);
987 listbox->set_master_column(column_of_type(FILEBOX_NAME), 0);
988 listbox->update(list_column, column_titles, column_width, columns,
989 reset>0 ? 0 : listbox->get_xposition(),
990 reset>0 ? 0 : listbox->get_yposition(),
995 int BC_FileBox::update_filter(const char *filter)
997 fs->set_filter(filter);
1000 strcpy(get_resources()->filebox_filter, filter);
1006 void BC_FileBox::update_paths(const char *text)
1008 char path[BCTEXTLEN];
1009 strncpy(path, text, sizeof(path)-1);
1010 fs->extract_dir(directory, path);
1011 fs->extract_name(filename, path);
1012 fs->complete_path(path);
1013 strcpy(current_path, path);
1014 strcpy(submitted_path, path);
1017 void BC_FileBox::move_column(int src, int dst)
1021 ArrayList<BC_ListBoxItem*> *new_columns =
1022 new ArrayList<BC_ListBoxItem*>[columns];
1023 int *new_types = new int[columns];
1024 int *new_widths = new int[columns];
1026 // Fill in remaining columns with consecutive data
1027 for(int out_column = 0, in_column = 0;
1028 out_column < columns;
1032 // Copy destination column from src column
1033 if(out_column == dst)
1035 for(int i = 0; i < list_column[src].total; i++)
1037 new_columns[out_column].append(list_column[src].values[i]);
1039 new_types[out_column] = column_type[src];
1040 new_widths[out_column] = column_width[src];
1045 // Skip source column
1046 if(in_column == src) in_column++;
1047 for(int i = 0; i < list_column[src].total; i++)
1049 new_columns[out_column].append(list_column[in_column].values[i]);
1051 new_types[out_column] = column_type[in_column];
1052 new_widths[out_column] = column_width[in_column];
1057 delete [] list_column;
1058 delete [] column_type;
1059 delete [] column_width;
1060 list_column = new_columns;
1061 column_type = new_types;
1062 column_width = new_widths;
1064 for(int i = 0; i < columns; i++)
1066 get_resources()->filebox_columntype[i] = column_type[i];
1067 get_resources()->filebox_columnwidth[i] = column_width[i];
1068 column_titles[i] = (char*)BC_FileBox::columntype_to_text(column_type[i]);
1076 int BC_FileBox::submit_dir(char *dir)
1078 strcpy(directory, dir);
1079 fs->join_names(current_path, directory, filename);
1081 // printf("BC_FileBox::submit_dir %d '%s' '%s' '%s'\n",
1086 strcpy(submitted_path, current_path);
1087 fs->change_dir(dir, 0);
1089 directory_title->update(fs->get_current_dir());
1091 textbox->update(fs->get_current_dir());
1093 textbox->update(filename);
1094 listbox->reset_query();
1098 int BC_FileBox::submit_file(const char *path, int use_this)
1100 char path1[BCTEXTLEN];
1101 strcpy(path1, path);
1102 char *cp = strchr(path1,'\n');
1105 // Deactivate textbox to hide suggestions
1106 textbox->deactivate();
1108 // If file wanted, take the current directory as the desired file.
1109 // If directory wanted, ignore it.
1110 if(!path1[0] && !want_directory)
1112 // save complete path
1113 strcpy(this->current_path, directory);
1114 // save complete path
1115 strcpy(this->submitted_path, directory);
1117 // Zero out filename
1123 // is a directory, change directories
1124 if(fs->is_dir(path1) && !use_this)
1126 fs->change_dir(path1, 0);
1128 directory_title->update(fs->get_current_dir());
1129 strcpy(this->current_path, fs->get_current_dir());
1130 strcpy(this->submitted_path, fs->get_current_dir());
1131 strcpy(this->directory, fs->get_current_dir());
1135 textbox->update(fs->get_current_dir());
1137 textbox->update("");
1138 listbox->reset_query();
1142 // Is a file or desired directory. Quit the operation.
1144 char path2[BCTEXTLEN];
1145 strcpy(path2, path1);
1147 // save directory for defaults
1148 fs->extract_dir(directory, path2);
1150 // Just take the directory
1154 strcpy(path2, directory);
1157 // Take the complete path
1159 fs->extract_name(filename, path2); // save filename
1162 fs->complete_path(path2);
1163 strcpy(this->current_path, path2); // save complete path
1164 strcpy(this->submitted_path, path2); // save complete path
1166 newfolder_thread->interrupt();
1173 void BC_FileBox::update_history()
1175 // Look for path already in history
1176 BC_Resources *resources = get_resources();
1177 char path[BCTEXTLEN];
1178 strcpy(path, directory);
1179 // enfore one trailing slash
1181 while( *cp && *cp != '\n' ) ++cp;
1182 while( cp > path && *(cp-1) == '/' ) --cp;
1183 *cp++ = '/'; *cp = 0;
1185 // int new_slot = FILEBOX_HISTORY_SIZE - 1;
1187 for(int i = FILEBOX_HISTORY_SIZE - 1; i >= 0; i--)
1189 if(resources->filebox_history[i].path[0] &&
1190 !strcmp(resources->filebox_history[i].path, path))
1192 // Got matching path.
1194 resources->filebox_history[i].id = resources->get_filebox_id();
1197 // // Shift down from this point.
1200 // strcpy(resources->filebox_history[i],
1201 // resources->filebox_history[i - 1]);
1202 // if(resources->filebox_history[i][0]) new_slot--;
1208 // if(resources->filebox_history[i][0])
1214 // Remove oldest entry if full
1215 if(resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].path[0])
1217 int oldest_id = 0x7fffffff;
1219 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++)
1221 if(resources->filebox_history[i].path[0] &&
1222 resources->filebox_history[i].id < oldest_id)
1224 oldest_id = resources->filebox_history[i].id;
1229 for(int i = oldest; i < FILEBOX_HISTORY_SIZE - 1; i++)
1231 strcpy(resources->filebox_history[i].path,
1232 resources->filebox_history[i + 1].path);
1233 resources->filebox_history[i].id =
1234 resources->filebox_history[i + 1].id;
1239 strcpy(resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].path, path);
1240 resources->filebox_history[FILEBOX_HISTORY_SIZE - 1].id = resources->get_filebox_id();
1247 for(int i = 1; i < FILEBOX_HISTORY_SIZE; i++)
1249 if( (resources->filebox_history[i - 1].path[0] &&
1250 resources->filebox_history[i].path[0] &&
1251 strcasecmp(resources->filebox_history[i - 1].path,
1252 resources->filebox_history[i].path) > 0) ||
1253 (resources->filebox_history[i - 1].path[0] == 0 &&
1254 resources->filebox_history[i].path[0]) )
1257 char temp[BCTEXTLEN];
1259 strcpy(temp, resources->filebox_history[i - 1].path);
1260 id_temp = resources->filebox_history[i - 1].id;
1261 strcpy(resources->filebox_history[i - 1].path,
1262 resources->filebox_history[i].path);
1263 resources->filebox_history[i - 1].id =
1264 resources->filebox_history[i].id;
1265 strcpy(resources->filebox_history[i].path, temp);
1266 resources->filebox_history[i].id = id_temp;
1273 // for(int i = FILEBOX_HISTORY_SIZE - 1; i > 0; i--)
1275 // strcpy(resources->filebox_history[i],
1276 // resources->filebox_history[i - 1]);
1281 // strcpy(resources->filebox_history[new_slot], path);
1284 recent_popup->update(&recent_dirs, 0, 0, 1);
1287 void BC_FileBox::create_history()
1289 BC_Resources *resources = get_resources();
1290 recent_dirs.remove_all_objects();
1291 for(int i = 0; i < FILEBOX_HISTORY_SIZE; i++) {
1292 if(resources->filebox_history[i].path[0]) {
1293 recent_dirs.append(new BC_ListBoxItem(resources->filebox_history[i].path));
1299 int BC_FileBox::get_display_mode()
1301 return top_level->get_resources()->filebox_mode;
1304 void BC_FileBox::create_listbox(int x, int y, int mode)
1306 if(listbox && listbox->get_display_mode() != mode)
1310 top_level->get_resources()->filebox_mode = mode;
1314 add_subwindow(listbox = new BC_FileBoxListBox(x, y, this));
1317 int BC_FileBox::get_y_margin()
1322 char* BC_FileBox::get_path(int selection)
1325 return get_submitted_path();
1326 BC_ListBoxItem *item = listbox->get_selection(
1327 column_of_type(FILEBOX_NAME), selection - 1);
1329 fs->join_names(string, directory, item->get_text());
1335 char* BC_FileBox::get_submitted_path()
1337 update_paths(textbox->get_text());
1338 return submitted_path;
1341 char* BC_FileBox::get_current_path()
1343 //printf("BC_FileBox::get_current_path 1 %s\n", current_path);
1344 return current_path;
1347 char* BC_FileBox::get_newfolder_title()
1349 char *letter2 = strchr(title, ':');
1350 new_folder_title[0] = 0;
1353 memcpy(new_folder_title, title, letter2 - title);
1354 new_folder_title[letter2 - title] = 0;
1357 strcat(new_folder_title, _(": New folder"));
1359 return new_folder_title;
1362 char* BC_FileBox::get_rename_title()
1364 char *letter2 = strchr(title, ':');
1365 new_folder_title[0] = 0;
1368 memcpy(new_folder_title, title, letter2 - title);
1369 new_folder_title[letter2 - title] = 0;
1372 strcat(new_folder_title, _(": Rename"));
1374 return new_folder_title;
1377 char* BC_FileBox::get_delete_title()
1379 char *letter2 = strchr(title, ':');
1380 new_folder_title[0] = 0;
1383 memcpy(new_folder_title, title, letter2 - title);
1384 new_folder_title[letter2 - title] = 0;
1387 strcat(new_folder_title, _(": Delete"));
1389 return new_folder_title;
1392 void BC_FileBox::delete_files()
1394 // Starting at 1 causes it to ignore what's in the textbox.
1398 while((path = get_path(i)))
1400 // Not directory. Remove it.
1401 if(!fs.is_dir(path))
1403 //printf("BC_FileBox::delete_files: removing \"%s\"\n", path);
1411 BC_Button* BC_FileBox::get_ok_button()
1416 BC_Button* BC_FileBox::get_cancel_button()
1418 return cancel_button;