1 /*
2 * This file is part of the XForms library package.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 /**
20 * \file formbrowser.c
21 *
22 * This file is part of the XForms library package.
23 *
24 * Copyright (c) 1997 By T.C. Zhao and Mark Overmars
25 * Copyright (c) 1998 By Steve Lamont of the National Center for
26 * Microscopy and Imaging Research
27 * Copyright (c) 1999-2002 by T.C. Zhao and Steve Lamont
28 * All rights reserved.
29 *
30 * form browser.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "include/forms.h"
38 #include "flinternal.h"
39 #include "private/pformbrowser.h"
40
41
42 static void check_scrollbar( FL_OBJECT * ob );
43 static int canvas_cleanup( FL_OBJECT * ob );
44 static int canvas_handler( FL_OBJECT * ob,
45 Window win,
46 int w,
47 int h,
48 XEvent * ev,
49 void * data );
50 static void delete_form( FLI_FORMBROWSER_SPEC * sp,
51 int f );
52 static void display_forms( FLI_FORMBROWSER_SPEC * sp );
53 static void form_cb( FL_OBJECT * ob,
54 void * data );
55 static int handle_formbrowser( FL_OBJECT * ob,
56 int event,
57 FL_Coord mx,
58 FL_Coord my,
59 int key,
60 void * ev );
61 static void hcb( FL_OBJECT * ob,
62 long data );
63 static void parentize_form( FL_FORM * form,
64 FL_OBJECT * ob );
65 static void set_form_position( FL_FORM * form,
66 int x,
67 int y );
68 static void vcb( FL_OBJECT * ob,
69 long data );
70 static void set_formbrowser_return( FL_OBJECT * obj,
71 unsigned int when );
72
73
74 /***************************************
75 ***************************************/
76
77 FL_OBJECT *
fl_create_formbrowser(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)78 fl_create_formbrowser( int type,
79 FL_Coord x,
80 FL_Coord y,
81 FL_Coord w,
82 FL_Coord h,
83 const char * label )
84 {
85 FL_OBJECT *ob;
86 FLI_FORMBROWSER_SPEC *sp;
87 int absbw, oldu = fl_get_coordunit( );
88 int D;
89
90 ob = fl_make_object( FL_FORMBROWSER, type, x, y, w, h, label,
91 handle_formbrowser );
92 fl_set_coordunit( FL_COORD_PIXEL );
93 ob->boxtype = FL_FORMBROWSER_BOXTYPE;
94 ob->align = FL_FORMBROWSER_ALIGN;
95 ob->col1 = FL_FORMBROWSER_COL1;
96 ob->col2 = FL_BLACK;
97 ob->set_return = set_formbrowser_return;
98 ob->spec = sp = fl_calloc( 1, sizeof *sp );
99
100 absbw = FL_abs( ob->bw );
101
102 sp->form = NULL;
103 sp->parent = ob;
104 sp->scroll = FL_SMOOTH_SCROLL;
105 sp->vw_def = sp->hh_def = D = fli_get_default_scrollbarsize( ob );
106 sp->canvas = fl_create_canvas( FL_CANVAS,
107 ob->x + absbw, ob->y + absbw,
108 ob->w - 2 * absbw - sp->vw_def,
109 ob->h - 2 * absbw - sp->hh_def,
110 label );
111
112 sp->canvas->u_vdata = sp;
113
114 fl_modify_canvas_prop( sp->canvas, NULL, NULL, canvas_cleanup );
115
116 fl_set_object_color( sp->canvas, ob->col1, ob->col2 );
117 fl_set_object_bw( sp->canvas, ob->bw );
118
119 fl_set_object_boxtype( sp->canvas,
120 fli_boxtype2frametype( ob->boxtype ) );
121 fl_add_canvas_handler( sp->canvas, Expose, canvas_handler, NULL );
122
123 sp->v_pref = sp->h_pref = FL_AUTO;
124
125 sp->hsl = fl_create_scrollbar( FL_HOR_THIN_SCROLLBAR, ob->x,
126 y + h - D, w - D, D, "" );
127 fl_set_scrollbar_value( sp->hsl, sp->old_hval = 0.0 );
128 fl_set_object_boxtype( sp->hsl, ob->boxtype );
129 sp->hsl->visible = sp->h_pref == FL_ON;
130 sp->hsl->resize = FL_RESIZE_X;
131 fl_set_object_callback( sp->hsl, hcb, 0 );
132
133 sp->vsl = fl_create_scrollbar( FL_VERT_THIN_SCROLLBAR,
134 x + w - D, y, D, h - D, "" );
135 fl_set_object_boxtype( sp->vsl, ob->boxtype );
136 sp->vsl->visible = sp->v_pref == FL_ON;
137 fl_set_scrollbar_value( sp->vsl, sp->old_hval = 0.0 );
138 sp->vsl->resize = FL_RESIZE_Y;
139 fl_set_object_callback( sp->vsl, vcb, 0 );
140
141 fl_add_child( ob, sp->canvas );
142 fl_add_child( ob, sp->hsl );
143 fl_add_child( ob, sp->vsl );
144
145 fl_set_coordunit( oldu );
146
147 /* Set default return policy for the object */
148
149 fl_set_object_return( ob, FL_RETURN_NONE );
150
151 return ob;
152 }
153
154
155 /***************************************
156 ***************************************/
157
158 FL_OBJECT *
fl_add_formbrowser(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)159 fl_add_formbrowser( int type,
160 FL_Coord x,
161 FL_Coord y,
162 FL_Coord w,
163 FL_Coord h,
164 const char * label )
165 {
166
167 FL_OBJECT *obj = fl_create_formbrowser( type, x, y, w, h, label );
168
169 fl_add_object( fl_current_form, obj );
170
171 return obj;
172 }
173
174
175 /***************************************
176 ***************************************/
177
178 FL_FORM *
fl_get_formbrowser_topform(FL_OBJECT * ob)179 fl_get_formbrowser_topform( FL_OBJECT * ob )
180 {
181 int topline;
182 FLI_FORMBROWSER_SPEC *sp;
183
184 if ( ! IsFormBrowserClass( ob ) )
185 {
186 M_err( "fl_get_formbrowser_topform", "%s not a formbrowser",
187 ob ? ob->label : "null" );
188 return NULL;
189 }
190
191 sp = ob->spec;
192 topline = sp->top_form + 1;
193
194 return topline ? sp->form[ topline - 1 ] : NULL;
195 }
196
197
198 /***************************************
199 ***************************************/
200
201 int
fl_set_formbrowser_topform(FL_OBJECT * ob,FL_FORM * form)202 fl_set_formbrowser_topform( FL_OBJECT * ob,
203 FL_FORM * form )
204 {
205 int n = fl_find_formbrowser_form_number( ob, form );
206
207 if ( n > 0 )
208 fl_set_formbrowser_topform_bynumber( ob, n );
209
210 return n;
211 }
212
213
214 /***************************************
215 ***************************************/
216
217 FL_FORM *
fl_set_formbrowser_topform_bynumber(FL_OBJECT * ob,int n)218 fl_set_formbrowser_topform_bynumber( FL_OBJECT * ob,
219 int n )
220 {
221 FLI_FORMBROWSER_SPEC *sp = ob->spec;
222 FL_FORM *form = NULL;
223
224 if ( n > 0 && n <= sp->nforms )
225 {
226 int h,
227 f;
228
229 sp->top_form = n - 1;
230 sp->top_edge = 0;
231 form = sp->form[ sp->top_form ];
232 display_forms( sp );
233
234 for ( h = f = 0; f < sp->top_form; f++ )
235 h += sp->form[ f ]->h;
236
237 sp->old_vval = ( double ) h / ( sp->max_height - sp->canvas->h );
238 fl_set_scrollbar_value( sp->vsl, sp->old_vval );
239 }
240
241 return form;
242 }
243
244
245 /***************************************
246 ***************************************/
247
248 int
fl_addto_formbrowser(FL_OBJECT * ob,FL_FORM * form)249 fl_addto_formbrowser( FL_OBJECT * ob,
250 FL_FORM * form )
251 {
252 FLI_FORMBROWSER_SPEC *sp;
253
254 if ( ! IsFormBrowserClass( ob ) )
255 {
256 M_err( "fl_addto_formbrowser", "%s not a formbrowser",
257 ob ? ob->label : "null" );
258 return 0;
259 }
260
261 if ( ! form )
262 {
263 M_err( "fl_addto_formbrowser", "Invalid argument" );
264 return 0;
265 }
266
267 if ( form->attached )
268 {
269 M_err( "fl_addto_formbrowser", "Already attached ?" );
270 return 0;
271 }
272
273 sp = ob->spec;
274
275 if ( form->visible == FL_VISIBLE )
276 fl_hide_form( form );
277
278 if ( ! form->form_callback )
279 fl_set_form_callback( form, form_cb, NULL );
280
281 parentize_form( form, ob );
282 sp->form = fl_realloc( sp->form, ( sp->nforms + 1 ) * sizeof *sp->form );
283 sp->form[ sp->nforms++ ] = form;
284 form->attached = 1;
285
286 if ( form->pre_attach )
287 form->pre_attach( form );
288
289 if ( sp->max_width < form->w )
290 sp->max_width = form->w;
291
292 sp->max_height += form->h;
293 display_forms( sp );
294
295 return sp->nforms;
296 }
297
298
299 /***************************************
300 ***************************************/
301
302 int
fl_find_formbrowser_form_number(FL_OBJECT * ob,FL_FORM * form)303 fl_find_formbrowser_form_number( FL_OBJECT * ob,
304 FL_FORM * form )
305 {
306 FLI_FORMBROWSER_SPEC *sp;
307 int num;
308
309 if ( ! IsFormBrowserClass( ob ) )
310 {
311 M_err( "fl_find_formbrowser_form_number", "%s not a formbrowser",
312 ob ? ob->label : "null" );
313 return 0;
314 }
315
316 if ( ! form )
317 {
318 M_err( "fl_find_formbrowser_form_number", "Invalid argument" );
319 return 0;
320 }
321
322 sp = ob->spec;
323
324 for ( num = 0; num < sp->nforms; num++ )
325 if ( sp->form[ num ] == form )
326 break;
327
328 return num == sp->nforms ? 0 : num + 1;
329 }
330
331
332 /***************************************
333 ***************************************/
334
335 int
fl_delete_formbrowser(FL_OBJECT * ob,FL_FORM * form)336 fl_delete_formbrowser( FL_OBJECT * ob,
337 FL_FORM * form )
338 {
339 FLI_FORMBROWSER_SPEC *sp;
340 int f;
341
342 if ( ! IsFormBrowserClass( ob ) )
343 {
344 M_err( "fl_delete_formbrowser", "%s not a formbrowser",
345 ob ? ob->label : "null" );
346 return -1;
347 }
348
349 if ( ! form )
350 {
351 M_err( "fl_delete_formbrowser", "Invalid argument" );
352 return -1;
353 }
354
355 sp = ob->spec;
356 f = fl_find_formbrowser_form_number( ob, form );
357
358 if ( f )
359 delete_form( sp, f - 1 );
360
361 return f ? sp->nforms : -1;
362 }
363
364
365 /***************************************
366 ***************************************/
367
368 #if 0
369
370 FL_FORM *
371 fl_get_formbrowser_parent_form( FL_OBJECT * ob )
372 {
373 return ob->form->parent;
374 }
375
376 #endif
377
378
379 /***************************************
380 ***************************************/
381
382 FL_FORM *
fl_delete_formbrowser_bynumber(FL_OBJECT * ob,int num)383 fl_delete_formbrowser_bynumber( FL_OBJECT * ob,
384 int num )
385 {
386 FL_FORM *form;
387 FLI_FORMBROWSER_SPEC *sp;
388
389 if ( ! IsFormBrowserClass( ob ) )
390 {
391 M_err( "fl_delete_formbrowser_bynumber", "%s not a formbrowser",
392 ob ? ob->label : "null" );
393 return NULL;
394 }
395
396 sp = ob->spec;
397
398 if ( num <= 0 || num > sp->nforms )
399 {
400 M_err( "fl_delete_formbrowser_bynumber",
401 "Invalid argument -- %d not between 1 and %d",
402 num, sp->nforms );
403 return NULL;
404 }
405
406 form = sp->form[ --num ];
407 delete_form( sp, num );
408
409 return form;
410 }
411
412
413 /***************************************
414 ***************************************/
415
416 FL_FORM *
fl_replace_formbrowser(FL_OBJECT * ob,int num,FL_FORM * form)417 fl_replace_formbrowser( FL_OBJECT * ob,
418 int num,
419 FL_FORM * form )
420 {
421 FL_FORM *old_form;
422 FLI_FORMBROWSER_SPEC *sp;
423
424 if ( ! IsFormBrowserClass( ob ) )
425 {
426 M_err( "fl_replace_formbrowser", "%s not a formbrowser",
427 ob ? ob->label : "null" );
428 return NULL;
429 }
430
431 sp = ob->spec;
432
433 if ( num <= 0 || num > sp->nforms )
434 {
435 M_err( "fl_replace_formbrowser",
436 "Invalid argument -- %d not between 1 and %d",
437 num, sp->nforms );
438 return NULL;
439 }
440
441
442 old_form = sp->form[ --num ];
443 fl_hide_form( old_form );
444 sp->form[ num ] = form;
445 display_forms( sp );
446
447 return old_form;
448 }
449
450
451 /***************************************
452 ***************************************/
453
454 int
fl_get_formbrowser_area(FL_OBJECT * ob,int * x,int * y,int * w,int * h)455 fl_get_formbrowser_area( FL_OBJECT * ob,
456 int * x,
457 int * y,
458 int * w,
459 int * h )
460 {
461 FLI_FORMBROWSER_SPEC *sp;
462
463 if ( ! IsFormBrowserClass( ob ) )
464 {
465 M_err( "fl_get_formbrowser_area", "%s not a formbrowser",
466 ob ? ob->label : "null" );
467 return 0;
468 }
469
470 sp = ob->spec;
471
472 *x = sp->canvas->x;
473 *y = sp->canvas->y;
474 *w = sp->canvas->w;
475 *h = sp->canvas->h;
476
477 return 1;
478 }
479
480
481 /***************************************
482 ***************************************/
483
484 int
fl_insert_formbrowser(FL_OBJECT * ob,int line,FL_FORM * new_form)485 fl_insert_formbrowser( FL_OBJECT * ob,
486 int line,
487 FL_FORM * new_form )
488 {
489 FLI_FORMBROWSER_SPEC *sp;
490 int nforms;
491 FL_FORM **form;
492 int n = line - 1;
493
494 if ( ! IsFormBrowserClass( ob ) )
495 {
496 M_err( "fl_insert_formbrowser", "%s not a formbrowser",
497 ob ? ob->label : "null" );
498 return -1;
499 }
500
501 sp = ob->spec;
502 nforms = sp->nforms;
503
504 if ( line <= 0 || line > nforms )
505 {
506 M_err( "fl_insert_formbrowser", "Invalid argument" );
507 return -1;
508 }
509
510 form = fl_realloc( sp->form, ( nforms + 1 ) * sizeof *form );
511
512 if ( ! form )
513 {
514 M_err( "fl_insert_formbrowser", "Running out of memory" );
515 return -1;
516 }
517
518 parentize_form( new_form, ob );
519
520 if ( n != nforms )
521 memmove( form + n + 1, form + n, sizeof *form * ( nforms - n ) );
522 form[ n ] = new_form;
523 sp->form = form;
524 sp->nforms++;
525 display_forms( sp );
526
527 return sp->nforms;
528 }
529
530
531 /***************************************
532 ***************************************/
533
534 void
fl_set_formbrowser_hscrollbar(FL_OBJECT * ob,int how)535 fl_set_formbrowser_hscrollbar( FL_OBJECT * ob,
536 int how )
537 {
538 FLI_FORMBROWSER_SPEC *sp = ob->spec;
539
540 if ( sp->h_pref != how )
541 {
542 sp->h_pref = how;
543 fl_redraw_object( ob );
544 }
545 }
546
547
548 /***************************************
549 ***************************************/
550
551 void
fl_set_formbrowser_vscrollbar(FL_OBJECT * ob,int how)552 fl_set_formbrowser_vscrollbar( FL_OBJECT * ob,
553 int how )
554 {
555 FLI_FORMBROWSER_SPEC *sp = ob->spec;
556
557 if ( sp->v_pref != how )
558 {
559 sp->v_pref = how;
560 fl_redraw_object( ob );
561 }
562 }
563
564
565 /***************************************
566 ***************************************/
567
568 void
fl_set_formbrowser_scroll(FL_OBJECT * ob,int how)569 fl_set_formbrowser_scroll( FL_OBJECT * ob,
570 int how )
571 {
572 FLI_FORMBROWSER_SPEC *sp = ob->spec;
573
574 if ( sp->scroll != how )
575 {
576 if ( ( sp->scroll = how ) == FL_JUMP_SCROLL )
577 sp->top_edge = 0;
578 fl_redraw_object( ob );
579 }
580 }
581
582
583 /***************************************
584 ***************************************/
585
586 int
fl_set_formbrowser_xoffset(FL_OBJECT * ob,int offset)587 fl_set_formbrowser_xoffset( FL_OBJECT * ob,
588 int offset )
589 {
590 FLI_FORMBROWSER_SPEC *sp;
591 int current;
592
593 if ( ! IsFormBrowserClass( ob ) )
594 {
595 M_err( "fl_set_formbrowser_xoffset", "%s not a formbrowser",
596 ob ? ob->label : "null" );
597 return 0;
598 }
599
600 sp = ob->spec;
601 current = sp->left_edge;
602
603 if ( sp->max_width < sp->canvas->w )
604 offset = 0;
605 if ( offset < 0 )
606 offset = 0;
607 if ( offset > sp->max_width - sp->canvas->w )
608 offset = sp->max_width - sp->canvas->w;
609
610 sp->left_edge = offset;
611 sp->old_hval = ( double ) sp->left_edge / ( sp->max_width - sp->canvas->w );
612 fl_set_scrollbar_value( sp->hsl, sp->old_hval );
613
614 return current;
615 }
616
617
618 /***************************************
619 ***************************************/
620
621 int
fl_get_formbrowser_xoffset(FL_OBJECT * ob)622 fl_get_formbrowser_xoffset( FL_OBJECT * ob )
623 {
624 if ( ! IsFormBrowserClass( ob ) )
625 {
626 M_err( "fl_get_formbrowser_xoffset", "%s not a formbrowser",
627 ob ? ob->label : "null" );
628 return 0;
629 }
630
631 return ( ( FLI_FORMBROWSER_SPEC * ) ob->spec )->left_edge;
632 }
633
634
635 /***************************************
636 ***************************************/
637
638 int
fl_set_formbrowser_yoffset(FL_OBJECT * ob,int offset)639 fl_set_formbrowser_yoffset( FL_OBJECT * ob,
640 int offset )
641 {
642 FLI_FORMBROWSER_SPEC *sp;
643 int current;
644 int h,
645 f;
646
647 if ( ! IsFormBrowserClass( ob ) )
648 {
649 M_err( "fl_set_formbrowser_yoffset", "%s not a formbrowser",
650 ob ? ob->label : "null" );
651 return 0;
652 }
653
654 sp = ob->spec;
655 current = fl_get_formbrowser_yoffset( ob );
656
657 if ( sp->max_height < sp->canvas->h )
658 offset = 0;
659 if ( offset < 0 )
660 offset = 0;
661 if ( offset > sp->max_height - sp->canvas->h )
662 offset = sp->max_height - sp->canvas->h;
663
664 h = sp->max_height;
665 for ( f = sp->nforms - 1; f >= 0 && offset < h; f-- )
666 h -= sp->form[ f ]->h;
667
668 sp->top_form = ++f;
669 sp->top_edge = offset - h;
670
671 sp->old_vval = ( double ) offset / ( sp->max_height - sp->canvas->h );
672 fl_set_scrollbar_value( sp->vsl, sp->old_vval );
673
674 return current;
675 }
676
677
678 /***************************************
679 ***************************************/
680
681 int
fl_get_formbrowser_yoffset(FL_OBJECT * ob)682 fl_get_formbrowser_yoffset( FL_OBJECT * ob )
683 {
684 FLI_FORMBROWSER_SPEC *sp;
685 int h,
686 f;
687
688 if ( ! IsFormBrowserClass( ob ) )
689 {
690 M_err( "fl_get_formbrowser_yoffset", "%s not a formbrowser",
691 ob ? ob->label : "null" );
692 return 0;
693 }
694
695 sp = ob->spec;
696 for ( h = f = 0; f < sp->top_form; f++ )
697 h += sp->form[ f ]->h;
698
699 return h + sp->top_edge;
700 }
701
702
703 /***************************************
704 ***************************************/
705
706 int
fl_get_formbrowser_numforms(FL_OBJECT * ob)707 fl_get_formbrowser_numforms( FL_OBJECT * ob )
708 {
709 if ( ! IsFormBrowserClass( ob ) )
710 {
711 M_err( "fl_get_formbrowser_numforms", "%s not a formbrowser",
712 ob ? ob->label : "null" );
713 return -1;
714 }
715
716 return ( ( FLI_FORMBROWSER_SPEC * ) ob->spec )->nforms;
717 }
718
719
720 /***************************************
721 ***************************************/
722
723 FL_FORM *
fl_get_formbrowser_form(FL_OBJECT * ob,int n)724 fl_get_formbrowser_form( FL_OBJECT * ob,
725 int n )
726 {
727 FL_FORM *form = NULL;
728 FLI_FORMBROWSER_SPEC *sp;
729
730 if ( ! IsFormBrowserClass( ob ) )
731 {
732 M_err( "fl_get_formbrowser_form", "%s not a formbrowser",
733 ob ? ob->label : "null" );
734 return NULL;
735 }
736
737 sp = ob->spec;
738
739 if ( n >= 1 && n <= sp->nforms )
740 form = sp->form[ n - 1 ];
741 else
742 M_err( "fl_get_formbrowser_form",
743 "%d is not an allowable form number", n );
744
745 return form;
746 }
747
748
749 /* Internals */
750
751 /***************************************
752 ***************************************/
753
754 static void
display_forms(FLI_FORMBROWSER_SPEC * sp)755 display_forms( FLI_FORMBROWSER_SPEC * sp )
756 {
757 int f;
758 int y_pos;
759 FL_OBJECT *canvas = sp->canvas;
760 FL_FORM **form = sp->form;
761 int nforms = sp->nforms;
762 int top_form = sp->top_form;
763 int left_edge = - sp->left_edge;
764 int height = canvas->h; /* - (2 * absbw); */
765
766 if ( ! FL_ObjWin( sp->canvas ) )
767 return;
768
769 fli_inherit_attributes( sp->parent, sp->canvas );
770
771 for ( f = 0; f < top_form; f++ )
772 if ( form[ f ]->visible )
773 fl_hide_form( form[ f ] );
774
775 fli_inherit_attributes( sp->parent, sp->vsl );
776 fli_inherit_attributes( sp->parent, sp->hsl );
777
778 /* I prefer to keep scrollbar unresizable */
779
780 sp->vsl->resize = sp->hsl->resize = FL_RESIZE_NONE;
781
782 y_pos = sp->scroll == FL_JUMP_SCROLL ? 0 : -sp->top_edge;
783
784 for ( f = top_form; y_pos < height && f < nforms; f++ )
785 {
786 if ( form[ f ]->visible )
787 set_form_position( form[ f ], left_edge, y_pos );
788 else
789 {
790 fl_prepare_form_window( form[ f ], 0, FL_NOBORDER, "Formbrowser" );
791 form[ f ]->parent_obj = sp->parent;
792 XReparentWindow( fl_get_display( ),
793 form[ f ]->window,
794 FL_ObjWin( sp->canvas ),
795 left_edge, y_pos );
796 fl_show_form_window( form[ f ] );
797 }
798
799 y_pos += form[ f ]->h;
800 }
801
802 for ( ; f < nforms; f++ )
803 if ( form[ f ]->visible )
804 fl_hide_form( form[ f ] );
805 }
806
807
808 /***************************************
809 ***************************************/
810
811 static int
handle_formbrowser(FL_OBJECT * ob,int event,FL_Coord mx FL_UNUSED_ARG,FL_Coord my FL_UNUSED_ARG,int key FL_UNUSED_ARG,void * ev FL_UNUSED_ARG)812 handle_formbrowser( FL_OBJECT * ob,
813 int event,
814 FL_Coord mx FL_UNUSED_ARG,
815 FL_Coord my FL_UNUSED_ARG,
816 int key FL_UNUSED_ARG,
817 void * ev FL_UNUSED_ARG )
818 {
819 FLI_FORMBROWSER_SPEC *sp = ob->spec;
820
821 switch ( event )
822 {
823 case FL_RESIZED :
824 fl_redraw_object( ob );
825 break;
826
827 case FL_DRAW :
828 fl_set_object_boxtype( sp->canvas,
829 fli_boxtype2frametype( ob->boxtype ) );
830 sp->processing_destroy = 0;
831 check_scrollbar( ob );
832 if ( ! sp->in_draw && FL_ObjWin( sp->canvas ) )
833 {
834 sp->in_draw = 1;
835 display_forms( sp );
836 sp->in_draw = 0;
837 }
838 break;
839
840 case FL_FREEMEM :
841 fl_free( sp );
842 break;
843 }
844
845 return FL_RETURN_NONE;
846 }
847
848
849 /***************************************
850 * Canvas expose handler.
851 ***************************************/
852
853 static int
canvas_handler(FL_OBJECT * ob,Window win FL_UNUSED_ARG,int w FL_UNUSED_ARG,int h FL_UNUSED_ARG,XEvent * ev FL_UNUSED_ARG,void * data FL_UNUSED_ARG)854 canvas_handler( FL_OBJECT * ob,
855 Window win FL_UNUSED_ARG,
856 int w FL_UNUSED_ARG,
857 int h FL_UNUSED_ARG,
858 XEvent * ev FL_UNUSED_ARG,
859 void * data FL_UNUSED_ARG )
860 {
861 display_forms( ( FLI_FORMBROWSER_SPEC * ) ob->u_vdata );
862 return 0;
863 }
864
865
866 /***************************************
867 * Before canvas is destroyed, this routine will be called.
868 * we need to close the form that is attached to this canvas
869 ***************************************/
870
871 static int
canvas_cleanup(FL_OBJECT * ob)872 canvas_cleanup( FL_OBJECT * ob )
873 {
874
875 FLI_FORMBROWSER_SPEC *sp = ob->u_vdata;
876 int i;
877
878 sp->processing_destroy = 1;
879
880 sp->h_on = FL_OFF;
881 sp->v_on = FL_OFF;
882
883 for ( i = 0; i < sp->nforms; i++ )
884 if ( sp->form[ i ]->visible )
885 fl_hide_form( sp->form[ i ] );
886
887 return 0;
888 }
889
890
891 /***************************************
892 * Dummy
893 ***************************************/
894
895 static void
form_cb(FL_OBJECT * ob FL_UNUSED_ARG,void * data FL_UNUSED_ARG)896 form_cb( FL_OBJECT * ob FL_UNUSED_ARG,
897 void * data FL_UNUSED_ARG )
898 {
899 }
900
901
902 /***************************************
903 ***************************************/
904
905 static void
hcb(FL_OBJECT * obj,long data FL_UNUSED_ARG)906 hcb( FL_OBJECT * obj,
907 long data FL_UNUSED_ARG )
908 {
909 FLI_FORMBROWSER_SPEC *sp = obj->parent->spec;
910 double nval = fl_get_scrollbar_value( sp->hsl );
911 int old_left_edge = sp->left_edge;
912
913 sp->left_edge = ( sp->max_width - sp->canvas->w ) * nval;
914 if ( old_left_edge != sp->left_edge )
915 {
916 fl_freeze_form( obj->form );
917 display_forms( sp );
918 fl_unfreeze_form( obj->form );
919 }
920
921 if ( obj->returned & FL_RETURN_END )
922 obj->parent->returned |= FL_RETURN_END;
923
924 if ( nval != sp->old_hval )
925 obj->parent->returned |= FL_RETURN_CHANGED;
926
927 if ( obj->parent->how_return & FL_RETURN_END_CHANGED
928 && ! ( obj->parent->returned & FL_RETURN_CHANGED
929 && obj->parent->returned & FL_RETURN_END ) )
930 obj->parent->returned = FL_RETURN_NONE;
931
932 if ( obj->parent->returned & FL_RETURN_END )
933 sp->old_hval = nval;
934 }
935
936
937 /***************************************
938 ***************************************/
939
940 static void
vcb(FL_OBJECT * obj,long data FL_UNUSED_ARG)941 vcb( FL_OBJECT * obj,
942 long data FL_UNUSED_ARG )
943 {
944 FLI_FORMBROWSER_SPEC *sp = obj->parent->spec;
945 double nval = fl_get_scrollbar_value( sp->vsl );
946
947 if ( sp->scroll == FL_JUMP_SCROLL )
948 sp->top_form = ( sp->nforms - 1 ) * nval;
949 else
950 {
951 /* do pixel based scrolling */
952
953 int pos = ( sp->max_height - sp->canvas->h ) * nval;
954 int h = 0,
955 f;
956
957 for ( f = 0; h <= pos && f < sp->nforms; f++ )
958 h += sp->form[ f ]->h;
959
960 sp->top_form = f ? ( f - 1 ) : f;
961 sp->top_edge = sp->form[ sp->top_form ]->h - h + pos;
962 }
963
964 fl_freeze_form( obj->form );
965 display_forms( sp );
966 fl_unfreeze_form( obj->form );
967
968 if ( obj->returned & FL_RETURN_END )
969 obj->parent->returned |= FL_RETURN_END;
970
971 if ( nval != sp->old_vval )
972 obj->parent->returned |= FL_RETURN_CHANGED;
973
974 if ( obj->parent->how_return & FL_RETURN_END_CHANGED
975 && ! ( obj->parent->returned & FL_RETURN_CHANGED
976 && obj->parent->returned & FL_RETURN_END ) )
977 obj->parent->returned = FL_RETURN_NONE;
978
979 if ( obj->parent->returned & FL_RETURN_END )
980 sp->old_vval = nval;
981 }
982
983
984 /***************************************
985 ***************************************/
986
987 static void
set_form_position(FL_FORM * form,int x,int y)988 set_form_position( FL_FORM * form,
989 int x,
990 int y )
991 {
992 XMoveWindow( fl_get_display( ), form->window, x, y );
993 }
994
995
996 /***************************************
997 ***************************************/
998
999 static void
delete_form(FLI_FORMBROWSER_SPEC * sp,int f)1000 delete_form( FLI_FORMBROWSER_SPEC * sp,
1001 int f )
1002 {
1003 fl_hide_form( sp->form[ f ] );
1004 sp->form[ f ]->attached = 0;
1005 sp->nforms--;
1006 sp->max_height -= sp->form[ f ]->h;
1007 for ( ; f < sp->nforms; f++ )
1008 sp->form[ f ] = sp->form[ f + 1 ];
1009 sp->form = fl_realloc( sp->form, sizeof *sp->form * sp->nforms );
1010 display_forms( sp );
1011 }
1012
1013
1014 /***************************************
1015 ***************************************/
1016
1017 static void
parentize_form(FL_FORM * form,FL_OBJECT * ob)1018 parentize_form( FL_FORM * form,
1019 FL_OBJECT * ob )
1020 {
1021 form->parent = ob->form; /* This is probably the wrong way to do it. */
1022 }
1023
1024
1025 /***************************************
1026 ***************************************/
1027
1028 static void
check_scrollbar(FL_OBJECT * ob)1029 check_scrollbar( FL_OBJECT * ob )
1030 {
1031 FLI_FORMBROWSER_SPEC *sp = ob->spec;
1032 int absbw = FL_abs( ob->bw );
1033 int h_on = sp->h_on,
1034 v_on = sp->v_on;
1035
1036 /* Inherit the boxtype of the parent */
1037
1038 sp->hsl->boxtype = ob->boxtype;
1039 sp->vsl->boxtype = ob->boxtype;
1040
1041 /* Gravity/resize may screw up the ratios. Recompute */
1042
1043 sp->canvas->x = ob->x + absbw;
1044 sp->canvas->y = ob->y + absbw;
1045 sp->canvas->w = ob->w - 2 * absbw;
1046 sp->canvas->h = ob->h - 2 * absbw;
1047
1048 sp->h_on = sp->canvas->w - 2 * absbw - sp->vw_def > 0
1049 && sp->canvas->h - 2 * absbw - sp->hh_def > 0
1050 && ( sp->h_pref == FL_ON
1051 || ( sp->h_pref != FL_OFF
1052 && sp->canvas->w < sp->max_width ) );
1053
1054 sp->v_on = sp->canvas->w - 2 * absbw - sp->vw_def > 0
1055 && sp->canvas->h - 2 * absbw - sp->hh_def > 0
1056 && ( sp->v_pref == FL_ON
1057 || ( sp->v_pref != FL_OFF
1058 && sp->canvas->h < sp->max_height ) );
1059
1060 if ( sp->h_on && ! sp->v_on )
1061 sp->v_on = sp->canvas->w - 2 * absbw - sp->vw_def > 0
1062 && sp->canvas->h - 2 * absbw - sp->hh_def > 0
1063 && sp->v_pref != FL_OFF
1064 && sp->canvas->h < sp->max_height + sp->hh_def;
1065 else if ( ! sp->h_on && sp->v_on )
1066 sp->h_on = sp->canvas->w - 2 * absbw - sp->vw_def > 0
1067 && sp->canvas->h - 2 * absbw - sp->hh_def > 0
1068 && sp->h_pref != FL_OFF
1069 && sp->canvas->w < sp->max_width + sp->vw_def;
1070
1071 if ( sp->v_on )
1072 {
1073 sp->vw = sp->vw_def;
1074 sp->vsl->x = ob->x + ob->w - sp->vw;
1075 sp->vsl->y = ob->y;
1076 sp->vsl->w = sp->vw;
1077 fli_set_object_visibility( sp->vsl, FL_VISIBLE );
1078 fli_notify_object( sp->vsl, FL_RESIZED );
1079 }
1080 else
1081 {
1082 fli_set_object_visibility( sp->vsl, FL_HIDDEN );
1083 sp->vw = 0;
1084 }
1085
1086 if ( sp->h_on )
1087 {
1088 sp->hh = sp->hh_def;
1089 sp->hsl->x = ob->x;
1090 sp->hsl->y = ob->y + ob->h - sp->hh;
1091 sp->hsl->h = sp->hh;
1092 fli_set_object_visibility( sp->hsl, FL_VISIBLE );
1093 fli_notify_object( sp->hsl, FL_RESIZED );
1094 }
1095 else
1096 {
1097 fli_set_object_visibility( sp->hsl, FL_HIDDEN );
1098 sp->hh = 0;
1099 }
1100
1101 /* Recheck vertical */
1102
1103 if ( ! sp->v_on
1104 && sp->canvas->w - 2 * absbw - sp->vw_def > 0
1105 && sp->canvas->h - 2 * absbw - sp->hh_def > 0
1106 && sp->v_pref != FL_OFF
1107 && sp->canvas->h < sp->max_height )
1108 {
1109 sp->v_on = 1;
1110 sp->vw = sp->vw_def;
1111 sp->vsl->x = ob->x + ob->w - sp->vw;
1112 sp->vsl->y = ob->y;
1113 sp->canvas->w = ob->w - 2 * absbw - sp->vw;
1114 }
1115
1116 sp->canvas->w = ob->w - 2 * absbw
1117 - ( sp->v_on ? 2 * absbw + sp->vw_def : 0 );
1118 sp->canvas->h = ob->h - 2 * absbw
1119 - ( sp->h_on ? 2 * absbw + sp->hh_def : 0 );
1120
1121 sp->hsl->w = sp->canvas->w + 2 * absbw;
1122 sp->vsl->h = sp->canvas->h + 2 * absbw;
1123
1124 /* If scrollbars get turned off adjust the offsets. */
1125
1126 if ( ! sp->v_on && v_on && sp->canvas->h >= sp->max_height )
1127 {
1128 sp->top_edge = 0;
1129 sp->top_form = 0;
1130 fl_set_scrollbar_value( sp->vsl, sp->old_vval = 0.0 );
1131 }
1132
1133 if ( ! sp->h_on && h_on && sp->canvas->w >= sp->max_width )
1134 {
1135 sp->left_edge = 0;
1136 fl_set_scrollbar_value( sp->hsl, sp->old_hval = 0.0 );
1137 }
1138
1139 if ( sp->h_on )
1140 {
1141 fl_set_scrollbar_size( sp->hsl,
1142 ( double ) sp->canvas->w / sp->max_width );
1143 fl_set_formbrowser_xoffset( ob, fl_get_formbrowser_xoffset( ob ) );
1144 }
1145
1146 if ( sp->v_on )
1147 {
1148 fl_set_scrollbar_size( sp->vsl,
1149 ( double ) sp->canvas->h / sp->max_height );
1150 fl_set_formbrowser_yoffset( ob, fl_get_formbrowser_yoffset( ob ) );
1151 }
1152
1153 if ( sp->canvas->w > 0 && sp->canvas->h > 0 )
1154 fl_winresize( FL_ObjWin( sp->canvas ), sp->canvas->w, sp->canvas->h );
1155 }
1156
1157
1158 /***************************************
1159 * Sets under which conditions the object is to be returned to the
1160 * application. This function is for interal use only, the user
1161 * must call fl_set_object_return() (which then will call this
1162 * function).
1163 ***************************************/
1164
1165 static void
set_formbrowser_return(FL_OBJECT * obj,unsigned int when)1166 set_formbrowser_return( FL_OBJECT * obj,
1167 unsigned int when )
1168 {
1169 FLI_FORMBROWSER_SPEC *sp = obj->spec;
1170
1171 if ( when & FL_RETURN_END_CHANGED )
1172 when &= ~ ( FL_RETURN_NONE | FL_RETURN_CHANGED );
1173
1174 obj->how_return = when;
1175
1176 if ( when == FL_RETURN_NONE || when == FL_RETURN_CHANGED )
1177 {
1178 fl_set_scrollbar_return( sp->vsl, FL_RETURN_CHANGED );
1179 fl_set_scrollbar_return( sp->hsl, FL_RETURN_CHANGED );
1180 }
1181 else
1182 {
1183 fl_set_scrollbar_return( sp->vsl, FL_RETURN_ALWAYS );
1184 fl_set_scrollbar_return( sp->hsl, FL_RETURN_ALWAYS );
1185 }
1186 }
1187
1188
1189 /*
1190 * Local variables:
1191 * tab-width: 4
1192 * indent-tabs-mode: nil
1193 * End:
1194 */
1195