3 * Copyright (C) 2016-2020 William Morrow
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 #include "bcmenuitem.h"
23 #include "commercials.h"
28 #include "mwindowgui.h"
35 static inline int min(int a,int b) { return a<b ? a : b; }
36 static inline int max(int a,int b) { return a>b ? a : b; }
38 #define MAX_SEARCH 100
40 DbSearchItem::DbSearchItem(const char *text, int color)
41 : BC_ListBoxItem(text, color)
46 DbSearchItem::~DbSearchItem()
51 DbWindow(MWindow *mwindow)
54 this->mwindow = mwindow;
55 window_lock = new Mutex("DbWindow::window_lock");
56 db_lock = new Mutex("DbWindow::db_lock");
61 DbWindow::MDb::MDb(DbWindow *d)
62 : Garbage("DbWindow::MDb"), dwin(d)
64 if( !d->mwindow->has_commercials() ) return;
85 window_lock->lock("DbWindow::start1");
86 if( Thread::running() ) {
87 gui->lock_window("DbWindow::start2");
93 gui = new DbWindowGUI(this);
96 window_lock->unlock();
103 if( Thread::running() ) {
104 window_lock->lock("DbWindow::stop");
105 if( gui ) gui->set_done(1);
106 window_lock->unlock();
115 gui->lock_window("DbWindow::run");
116 gui->create_objects();
117 gui->search(MAX_SEARCH,"");
118 gui->start_drawing(0);
119 gui->unlock_window();
121 window_lock->lock("DbWindow::stop");
123 window_lock->unlock();
128 DbWindowTitleText(DbWindowGUI *gui, int x, int y)
129 : BC_CheckBox(x, y, &gui->title_text_enable, _("titles"))
134 DbWindowTitleText::~DbWindowTitleText()
138 int DbWindowTitleText::
141 gui->title_text_enable = get_value();
142 if( !gui->title_text_enable ) gui->info_text->update(1);
148 DbWindowInfoText(DbWindowGUI *gui, int x, int y)
149 : BC_CheckBox(x, y, &gui->info_text_enable, _("info"))
154 DbWindowInfoText::~DbWindowInfoText()
158 int DbWindowInfoText::
161 gui->info_text_enable = get_value();
162 if( !gui->info_text_enable ) gui->title_text->update(1);
168 DbWindowMatchCase(DbWindowGUI *gui, int x, int y)
169 : BC_CheckBox(x, y, &gui->match_case_enable, _("match case"))
174 DbWindowMatchCase::~DbWindowMatchCase()
178 int DbWindowMatchCase::
181 gui->match_case_enable = get_value();
187 DbWindowText(DbWindowGUI *gui, int x, int y, int w)
188 : BC_TextBox(x, y, w, 1, "")
193 DbWindowText::~DbWindowText()
207 switch(get_keypress())
210 gui->search(MAX_SEARCH, get_text());
214 return BC_TextBox::keypress_event();
219 DbWindowScan(MWindow *mwindow)
220 : BC_MenuItem(_("Media DB..."), _("Shift-M"), 'M')
223 this->mwindow = mwindow;
226 DbWindowScan::~DbWindowScan()
233 mwindow->commit_commercial();
234 mwindow->gui->db_window->start();
239 DbWindowStart(DbWindowGUI *gui, int x, int y)
240 : BC_GenericButton(x, y, _("Search"))
245 DbWindowStart::~DbWindowStart()
252 gui->search(MAX_SEARCH,"");
256 DbWindowDeleteItems::
257 DbWindowDeleteItems(DbWindowGUI *gui, int x, int y)
258 : BC_GenericButton(x, y, _("Delete"))
263 DbWindowDeleteItems::~DbWindowDeleteItems()
267 int DbWindowDeleteItems::
270 gui->search_list->set_view_popup(0);
277 DbWindowCancel(DbWindowGUI *gui, int x, int y)
278 : BC_CancelButton(x, y)
283 DbWindowCancel::~DbWindowCancel()
296 DbWindowList(DbWindowGUI *gui, int x, int y, int w, int h)
297 : BC_ListBox(x, y, w, h, LISTBOX_TEXT,
298 (ArrayList<BC_ListBoxItem*> *) &gui->search_items[0],
299 &gui->search_column_titles[0], &gui->search_column_widths[0],
300 sizeof_col, 0, 0, LISTBOX_MULTIPLE)
303 set_sort_column(gui->sort_column);
304 set_sort_order(gui->sort_order);
305 set_allow_drag_column(1);
308 DbWindowList::~DbWindowList()
319 set_view_popup(DbWindowVIcon *vicon)
321 gui->vicon_thread->set_view_popup(vicon);
327 switch(get_keypress()) {
332 gui->del_items->handle_event();
344 gui->sort_events(get_sort_column(), get_sort_order());
345 gui->start_drawing();
353 gui->move_column(get_from_column(), get_to_column());
354 gui->start_drawing();
358 DbWindowVIcon::DbWindowVIcon()
359 : VIcon(SWIDTH, SHEIGHT, VICON_RATE)
365 DbWindowVIcon::~DbWindowVIcon()
369 DbWindowVIconThread::
370 DbWindowVIconThread(DbWindowGUI *gui)
371 : VIconThread(gui->search_list, SWIDTH,SHEIGHT, 4*SWIDTH,4*SHEIGHT)
377 DbWindowVIconThread::
378 ~DbWindowVIconThread()
381 vicons.remove_all_objects();
384 DbWindowVIcon *DbWindowVIconThread::get_vicon(int i, DbSearchItem *item)
386 while( i >= vicons.size() ) {
387 DbWindowVIcon *vicon = new DbWindowVIcon();
388 vicons.append(vicon);
390 DbWindowVIcon *vicon = vicons[i];
391 vicon->lbox = gui->search_list;
397 void DbWindowVIconThread::drawing_started()
399 if( !list_update ) return;
402 gui->search_list->update_images();
406 VFrame *DbWindowVIcon::frame()
408 if( seq_no >= images.size() )
409 load_frames(lbox->gui->dwindow->mdb);
410 return images[seq_no]->vfrm;
413 int64_t DbWindowVIcon::set_seq_no(int64_t no)
415 if( no >= clip_size ) no = 0;
420 void DbWindowVIcon::load_frames(DbWindow::MDb *mdb)
422 if( !mdb->attach_rd() ) {
428 void DbWindowVIcon::read_frames(DbWindow::MDb *mdb)
430 while( seq_no >= images.size() ) {
431 int no = images.size();
432 if( no >= prefix_size ) no += suffix_offset;
433 if( mdb->get_sequences(clip_id, no) ) continue;
434 if( mdb->timeline_sequence_no() != no ) continue;
435 int frame_id = mdb->timeline_frame_id();
436 if( frame_id < 0 ) continue;
437 int swidth = (SWIDTH+1) & ~1, sheight = (SHEIGHT+1) & ~1;
438 VIFrame *vifrm = new VIFrame(swidth, sheight, BC_YUV420P);
439 VFrame *img = vifrm->vfrm;
440 memset(img->get_y(),0x00,swidth * sheight);
441 memset(img->get_u(),0x80,swidth/2 * sheight/2);
442 memset(img->get_v(),0x80,swidth/2 * sheight/2);
443 uint8_t *yp = img->get_y(); int sw = -1, sh = -1;
444 mdb->get_image(frame_id, yp, sw, sh);
445 images.append(vifrm);
449 int DbWindowVIcon::get_vx()
451 return lbox->get_item_x(item);
453 int DbWindowVIcon::get_vy()
455 return lbox->get_item_y(item);
459 update_image(DbWindowGUI *gui, int clip_id)
461 DbWindow::MDb *mdb = gui->dwindow->mdb;
462 if( !mdb->attach_rd() ) {
463 if( !mdb->clip_id(clip_id) ) {
464 this->clip_id = clip_id;
465 this->clip_size = mdb->clip_size();;
466 this->prefix_size = mdb->clip_prefix_size();
467 this->suffix_offset = mdb->clip_frames() - clip_size;
468 double framerate = mdb->clip_framerate();
469 this->frame_rate = framerate > 0 ? framerate : VICON_RATE;
470 gui->vicon_thread->add_vicon(this);
477 int DbWindowList::update_images()
479 DbWindowVIconThread *thread = gui->vicon_thread;
480 thread->t_heap.remove_all();
482 int i = get_first_visible();
484 while( --k >= 0 && gui->search_columns[k] != col_vicon );
485 if( k >= 0 && i >= 0 ) {
486 int sz = gui->search_results.size();
487 int last = get_last_visible();
488 if( last < sz ) sz = last+1;
489 for( int n=0; i<sz; ++i, ++n ) {
490 DbSearchItem *item = gui->search_items[k][i];
491 DbWindowVIcon *vicon = thread->get_vicon(n, item);
492 vicon->update_image(gui, gui->search_results[i]->id);
501 BC_ListBox::update((ArrayList<BC_ListBoxItem*>*)gui->search_items,
502 &gui->search_column_titles[0], &gui->search_column_widths[0],
512 int idx = get_selection_number(0, 0);
513 if( idx >= 0 && get_selection_number(0, 1) < 0 ) {
514 DbSearchItem *item = gui->search_items[0][idx];
515 set_view_popup(item->vicon);
517 gui->start_drawing(0);
525 int xs10 = xS(10), xs15 = xS(15);
526 int ys5 = yS(5), ys10 = yS(10);
527 int pady = BC_TextBox::calculate_h(this, MEDIUMFONT, 0, 1) + ys5;
528 int padx = BC_Title::calculate_w(this, (char*)"X", MEDIUMFONT);
529 int x = padx/2, y = pady/4;
530 text_x = x; text_y = y;
531 BC_Title *title = new BC_Title(text_x, text_y, _("Text:"), MEDIUMFONT, YELLOW);
532 add_subwindow(title); x += title->get_w();
533 search_text = new DbWindowText(this, x, y, get_w()-x-xs10);
534 add_subwindow(search_text);
535 x = padx; y += pady + ys5;
536 title_text = new DbWindowTitleText(this, x, y);
537 add_subwindow(title_text); x += title_text->get_w() + padx;
538 info_text = new DbWindowInfoText(this, x, y);
539 add_subwindow(info_text); x += title_text->get_w() + padx;
540 match_case = new DbWindowMatchCase(this, x, y);
541 add_subwindow(match_case); x += match_case->get_w() + padx;
542 x = padx; y += pady + ys5;
544 search_y = get_h() - DbWindowStart::calculate_h() - ys10;
545 search_start = new DbWindowStart(this, search_x, search_y);
546 add_subwindow(search_start);
547 del_items_x = search_x + DbWindowStart::calculate_w(this, search_start->get_text()) + xs15;
548 del_items_y = search_y;
549 del_items = new DbWindowDeleteItems(this, del_items_x, del_items_y);
550 add_subwindow(del_items);
551 cancel_w = DbWindowCancel::calculate_w();
552 cancel_h = DbWindowCancel::calculate_h();
553 cancel_x = get_w() - cancel_w - xs10;
554 cancel_y = get_h() - cancel_h - ys10;
555 cancel = new DbWindowCancel(this, cancel_x, cancel_y);
556 add_subwindow(cancel);
557 list_x = x; list_y = y;
558 int list_w = get_w()-xs10 - list_x;
559 int list_h = min(search_y, cancel_y)-ys10 - list_y;
560 search_list = new DbWindowList(this, list_x, list_y, list_w, list_h);
561 add_subwindow(search_list);
562 vicon_thread = new DbWindowVIconThread(this);
563 vicon_thread->start();
564 search_list->show_window();
566 canvas_y = search_list->get_title_h();
567 canvas_w = search_list->get_w();
568 canvas_h = search_list->get_h() - canvas_y;
569 canvas = new DbWindowCanvas(this, canvas_x, canvas_y, canvas_w, canvas_h);
570 canvas->use_auxwindow(search_list);
571 canvas->create_objects(0);
572 set_icon(dwindow->mwindow->theme->get_image("record_icon"));
575 #define DBW_W xS(900)
576 #define DBW_H yS(600)
579 DbWindowGUI(DbWindow *dwindow)
580 : BC_Window(_(PROGRAM_NAME ": DbWindow"),
581 dwindow->mwindow->gui->get_abs_cursor_x(1) - DBW_W / 2,
582 dwindow->mwindow->gui->get_abs_cursor_y(1) - DBW_H / 2,
583 DBW_W, DBW_H, xS(400), yS(400))
585 this->dwindow = dwindow;
591 search_x = search_y = 0;
592 cancel_x = cancel_y = cancel_w = cancel_h = 0;
593 del_items_x = del_items_y = 0;
594 list_x = list_y = list_w = list_h = 0;
595 sort_column = 1; sort_order = 0;
597 title_text_enable = 1;
598 info_text_enable = 1;
599 match_case_enable = 1;
601 search_columns[col_vicon] = col_vicon;
602 search_columns[col_id] = col_id;
603 search_columns[col_length] = col_length;
604 search_columns[col_source] = col_source;
605 search_columns[col_title] = col_title;
606 search_columns[col_start_time] = col_start_time;
607 search_columns[col_access_time] = col_access_time;
608 search_columns[col_access_count] = col_access_count;
609 search_column_titles[col_vicon] = _("vicon");
610 search_column_titles[col_id] = _("Id");
611 search_column_titles[col_length] = _("length");
612 search_column_titles[col_source] = _("Source");
613 search_column_titles[col_title] = C_("Title");
614 search_column_titles[col_start_time] = _("Start time");
615 search_column_titles[col_access_time] = _("Access time");
616 search_column_titles[col_access_count] = _("count");
617 search_column_widths[col_vicon] = xS(90);
618 search_column_widths[col_id] = xS(60);
619 search_column_widths[col_length] = xS(80);
620 search_column_widths[col_source] = xS(50);
621 search_column_widths[col_title] = xS(160);
622 search_column_widths[col_start_time] = xS(140);
623 search_column_widths[col_access_time] = xS(140);
624 search_column_widths[col_access_count] = xS(60);
626 for( int i=0; i<sizeof_col; ++i )
627 if( i != col_title ) wd += search_column_widths[i];
628 search_column_widths[col_title] = get_w() - wd - xS(40);
631 DbWindowGUI::~DbWindowGUI()
633 for( int i=0; i<sizeof_col; ++i )
634 search_items[i].remove_all_objects();
640 resize_event(int w, int h)
642 int xs10 = xS(10), xs15 = xS(15);
645 int cancel_x = w - BC_CancelButton::calculate_w() - xs10;
646 int cancel_y = h - BC_CancelButton::calculate_h() - ys10;
647 cancel->reposition_window(cancel_x, cancel_y);
649 search_y = h - BC_GenericButton::calculate_h() - ys10;
650 search_start->reposition_window(search_x, search_y);
651 del_items_x = search_x + DbWindowStart::calculate_w(this, search_start->get_text()) + xs15;
652 del_items_y = search_y;
653 del_items->reposition_window(del_items_x,del_items_y);
654 int list_w = w-xs10 - list_x;
655 int list_h = min(search_y, cancel_y)-ys10 - list_y;
656 canvas_w = SWIDTH; canvas_h = SHEIGHT;
657 canvas_x = cancel_x - canvas_w - xs15;
658 canvas_y = get_h() - canvas_h - ys10;
659 canvas->reposition_window(0, canvas_x, canvas_y, canvas_w, canvas_h);
661 // for( int i=0; i<sizeof_col; ++i )
662 // if( i != col_title ) wd += search_column_widths[i];
663 // search_column_widths[col_title] = w - wd - xS(40);
664 search_list->reposition_window(list_x, list_y, list_w, list_h);
679 vicon_thread->stop_drawing();
684 start_drawing(int update)
687 vicon_thread->list_update = 1;
688 vicon_thread->start_drawing();
692 int DbWindowGUI::search_string(const char *text, const char *sp)
695 int n = strlen(text);
696 for( const char *cp=sp; *cp!=0; ++cp ) {
697 if( match_case_enable ? !strncmp(text, cp, n) :
698 !strncasecmp(text, cp, n) ) return 1;
704 void DbWindowGUI::search_clips(MediaDb *mdb, int n, const char *text)
706 //Db::write_blocked by(mdb->db.Clip_set);
707 if( !mdb->clips_first_id() ) do {
708 if( (title_text_enable && search_string(text, mdb->clip_title())) ||
709 (info_text_enable && search_string(text, mdb->clip_path())) ) {
710 int id = mdb->clip_id();
711 double system_time = mdb->clip_system_time();
712 double start_time = 0;
713 if( system_time > 0 )
714 start_time = system_time + mdb->clip_position();
715 double access_time = 0; int access_count = 0;
716 if( !mdb->views_clip_id(id) ) {
717 access_time = mdb->views_access_time();
718 access_count = mdb->views_access_count();
720 double length = mdb->clip_frames() / mdb->clip_framerate();
721 search_results.append(new DbWindowItem(id, mdb->clip_title(),
722 mdb->clip_path(), length, start_time, access_time, access_count));
724 } while( --n >= 0 && !mdb->clips_next_id() );
727 void DbWindowGUI::search(int n, const char *text)
730 search_results.remove_all();
731 DbWindow::MDb *mdb = dwindow->mdb;
732 if( !mdb->attach_rd() ) {
733 search_clips(mdb, n, text);
739 int DbWindowGUI::delete_selection(MediaDb *mdb)
742 for( int k=0; k<search_results.size(); ++k ) {
743 if( !search_items[0][k]->get_selected() ) continue;
744 int id = search_results[k]->id;
745 if( mdb->del_clip_set(id) ) {
746 printf(_("failed delete clip id %d\n"),id);
749 search_results.remove_object_number(k);
750 for( int i=0; i<sizeof_col; ++i )
751 search_items[i].remove_object_number(k);
754 if( n > 0 ) mdb->commitDb();
758 void DbWindowGUI::delete_items()
761 DbWindow::MDb *mdb = dwindow->mdb;
762 if( !mdb->attach_wr() ) {
763 delete_selection(mdb);
773 for( int i=0; i<sizeof_col; ++i )
774 search_items[i].remove_all_objects();
776 char text[BCTEXTLEN];
777 int n = search_results.size();
778 for( int i=0; i<n; ++i ) {
779 DbWindowItem *item = search_results[i];
780 for( int k=0; k<sizeof_col; ++k ) {
781 const char *cp = 0; text[0] = 0;
782 switch( search_columns[k] ) {
787 sprintf(text,"%4d", item->id);
791 sprintf(text, "%8.3f", item->length);
800 case col_start_time: {
801 time_t st = item->start_time;
803 struct tm stm; localtime_r(&st,&stm);
804 sprintf(text,"%02d:%02d:%02d %02d/%02d/%02d",
805 stm.tm_hour, stm.tm_min, stm.tm_sec,
806 stm.tm_year%100, stm.tm_mon, stm.tm_mday);
810 case col_access_time: {
811 time_t at = item->access_time;
813 struct tm atm; localtime_r(&at,&atm);
814 sprintf(text,"%02d/%02d/%02d %02d:%02d:%02d",
815 atm.tm_year%100, atm.tm_mon, atm.tm_mday,
816 atm.tm_hour, atm.tm_min, atm.tm_sec);
820 case col_access_count: {
821 sprintf(text,"%4d", item->access_count);
826 DbSearchItem *item = new DbSearchItem(cp, LTYELLOW);
827 if( search_columns[k] == col_vicon ) {
828 item->set_text_w(SWIDTH+xS(10));
829 item->set_text_h(SHEIGHT+yS(5));
830 item->set_searchable(0);
832 search_items[k].append(item);
836 search_list->update();
841 DbWindowItem(int id, const char *source, const char *title,
842 double length, double start_time,
843 double access_time, int access_count)
846 if( !source ) source = "";
847 this->source = new char[strlen(source)+1];
848 strcpy(this->source,source);
849 if( !title ) title = "";
850 this->title = new char[strlen(title)+1];
851 strcpy(this->title,title);
852 this->length = length;
853 this->start_time = start_time;
854 this->access_time = access_time;
855 this->access_count = access_count;
865 #define CmprFn(nm,key) int DbWindowGUI:: \
866 cmpr_##nm(const void *a, const void *b) { \
867 DbWindowItem *&ap = *(DbWindowItem **)a; \
868 DbWindowItem *&bp = *(DbWindowItem **)b; \
869 int n = key; if( !n ) n = ap->no-bp->no; \
873 extern long cin_timezone;
875 CmprFn(id_dn, ap->id - bp->id)
876 CmprFn(id_up, bp->id - ap->id)
877 CmprFn(length_dn, ap->length - bp->length)
878 CmprFn(length_up, bp->length - ap->length)
879 CmprFn(Source_dn, strcasecmp(ap->source, bp->source))
880 CmprFn(source_dn, strcmp(ap->source, bp->source))
881 CmprFn(Source_up, strcasecmp(bp->source, ap->source))
882 CmprFn(source_up, strcmp(bp->source, ap->source))
883 CmprFn(Title_dn, strcasecmp(ap->title, bp->title))
884 CmprFn(title_dn, strcmp(ap->title, bp->title))
885 CmprFn(Title_up, strcasecmp(bp->title, ap->title))
886 CmprFn(title_up, strcmp(bp->title, ap->title))
887 CmprFn(start_time_dn, fmod(ap->start_time-cin_timezone,24*3600) - fmod(bp->start_time-cin_timezone,24*3600))
888 CmprFn(start_time_up, fmod(bp->start_time-cin_timezone,24*3600) - fmod(ap->start_time-cin_timezone,24*3600))
889 CmprFn(access_time_dn, ap->access_time - bp->access_time)
890 CmprFn(access_time_up, bp->access_time - ap->access_time)
891 CmprFn(access_count_dn, ap->access_count - bp->access_count)
892 CmprFn(access_count_up, bp->access_count - ap->access_count)
896 sort_events(int column, int order)
898 sort_column = column; sort_order = order;
899 if( search_columns[sort_column] == col_vicon ) return;
900 int n = search_results.size();
902 DbWindowItem **items = &search_results[0];
903 for( int i=0; i<n; ++i ) items[i]->no = i;
905 int(*cmpr)(const void *, const void *) = 0;
906 switch( search_columns[sort_column] ) {
908 cmpr = sort_order ? cmpr_id_up : cmpr_id_dn;
911 cmpr = sort_order ? cmpr_length_up : cmpr_length_dn;
914 cmpr = match_case_enable ?
915 (sort_order ? cmpr_Source_up : cmpr_Source_dn) :
916 (sort_order ? cmpr_source_up : cmpr_source_dn) ;
919 cmpr = match_case_enable ?
920 (sort_order ? cmpr_Title_up : cmpr_Title_dn) :
921 (sort_order ? cmpr_title_up : cmpr_title_dn) ;
924 cmpr = sort_order ? cmpr_start_time_up : cmpr_start_time_dn;
926 case col_access_time:
927 cmpr = sort_order ? cmpr_access_time_up : cmpr_access_time_dn;
929 case col_access_count:
930 cmpr = sort_order ? cmpr_access_count_up : cmpr_access_count_dn;
934 if( cmpr ) qsort(items, n, sizeof(*items), cmpr);
938 move_column(int src, int dst)
940 if( src == dst ) return;
941 int src_column = search_columns[src];
942 const char *src_column_title = search_column_titles[src];
943 int src_column_width = search_column_widths[src];
945 for( int i=src; i<dst; ++i ) {
946 search_columns[i] = search_columns[i+1];
947 search_column_titles[i] = search_column_titles[i+1];
948 search_column_widths[i] = search_column_widths[i+1];
952 for( int i=src; i>dst; --i ) {
953 search_columns[i] = search_columns[i-1];
954 search_column_titles[i] = search_column_titles[i-1];
955 search_column_widths[i] = search_column_widths[i-1];
958 search_columns[dst] = src_column;
959 search_column_titles[dst] = src_column_title;
960 search_column_widths[dst] = src_column_width;
962 while( --k >= 0 && search_columns[k] != col_vicon );
963 if( k >= 0 ) search_list->set_master_column(k,0);
968 DbWindowCanvas(DbWindowGUI *gui, int x, int y, int w, int h)
969 : Canvas(gui->dwindow->mwindow, gui, x, y, w, h, w, h, 0)
979 void DbWindowCanvas::
982 BC_WindowBase* wdw = get_canvas();
983 wdw->lock_window("DbWindowCanvas::flash_canvas");
985 wdw->unlock_window();
988 void DbWindowCanvas::
989 draw_frame(VFrame *frame, int x, int y, int w, int h)
991 BC_WindowBase* wdw = get_canvas();
992 int min_y = gui->search_list->get_title_h();
993 int max_y = gui->search_list->get_view_h()+min_y;
994 min_y += 2; max_y -= 2;
995 int sx = 0, sy = 0, sw = frame->get_w(), sh = frame->get_h();
997 if( dy > 0 ) { sy += dy; y = min_y; sh -= dy; h -= dy; }
999 if( dy > 0 ) { sh -= dy; h -= dy; }
1002 //wdw->lock_window("DbWindowCanvas::draw_frame");
1003 wdw->draw_vframe(frame, x,y,w,(h&~1), sx,sy,sw,sh, 0);
1004 //wdw->unlock_window();