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 browser.c
21 *
22 * This file is part of the XForms library package.
23 * Copyright (c) 1996-2002 T.C. Zhao and Mark Overmars
24 * All rights reserved.
25 *
26 * Browser composite.
27 * scrollbar redrawing can be further optimized.
28 */
29
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "include/forms.h"
36 #include "flinternal.h"
37 #include "private/pbrowser.h"
38 #include "private/flvasprintf.h"
39
40
41 /***************************************
42 * Some attribue of the object changed, we better recalculate how
43 * it should oook like
44 ***************************************/
45
46 static void
attrib_change(FL_OBJECT * ob)47 attrib_change( FL_OBJECT * ob )
48 {
49 FLI_BROWSER_SPEC *sp = ob->spec;
50
51 /* Text box stuff */
52
53 sp->tb->x = ob->x;
54 sp->tb->y = ob->y;
55
56 fli_set_object_visibility( sp->tb, FL_VISIBLE );
57 sp->tb->input = ob->input;
58
59 sp->tb->type = ob->type;
60 sp->tb->boxtype = ob->boxtype;
61 sp->tb->lcol = ob->lcol;
62 sp->tb->col1 = ob->col1;
63 sp->tb->col2 = ob->col2;
64 sp->tb->bw = ob->bw;
65 fli_notify_object( sp->tb, FL_RESIZED );
66
67 /* Scrollbars */
68
69 if ( ob->boxtype == FL_DOWN_BOX
70 && sp->hsl->type == FL_HOR_NICE_SCROLLBAR )
71 {
72 sp->hsl->boxtype = FL_FRAME_BOX;
73 sp->vsl->boxtype = FL_FRAME_BOX;
74 }
75 else if ( ob->boxtype == FL_DOWN_BOX
76 && sp->hsl->type == FL_HOR_SCROLLBAR )
77 {
78 sp->hsl->boxtype = FL_UP_BOX;
79 sp->vsl->boxtype = FL_UP_BOX;
80 }
81 else
82 {
83 sp->hsl->boxtype = ob->boxtype;
84 sp->vsl->boxtype = ob->boxtype;
85 }
86
87 sp->hsl->bw = sp->vsl->bw = ob->bw;
88
89 if ( ! sp->user_set && ob->boxtype != FL_DOWN_BOX )
90 sp->vw = sp->vw_def = sp->hh = sp->hh_def =
91 fli_get_default_scrollbarsize( ob );
92 }
93
94
95 /***************************************
96 ***************************************/
97
98 static void
get_geometry(FL_OBJECT * obj)99 get_geometry( FL_OBJECT * obj )
100 {
101 FLI_BROWSER_SPEC *comp = obj->spec;
102 FL_OBJECT *tb = comp->tb;
103 FLI_TBOX_SPEC *sp = comp->tb->spec;
104 int h_on = comp->h_on,
105 v_on = comp->v_on;
106 double old_xrel = fli_tbox_get_rel_xoffset( tb );
107 double old_yrel = fli_tbox_get_rel_yoffset( tb );
108
109 comp->hh = comp->vw = 0;
110 comp->h_on = comp->v_on = 0;
111
112 tb->w = obj->w;
113 tb->h = obj->h;
114 fli_tbox_recalc_area( tb );
115
116 /* Check if we need a vertical slider */
117
118 if ( ( sp->max_height > sp->h && comp->v_pref != FL_OFF )
119 || comp->v_pref == FL_ON )
120 {
121 comp->v_on = 1;
122 comp->vw = comp->vw_def;
123
124 tb->w -= comp->vw;
125 fli_tbox_recalc_area( tb );
126 }
127
128 /* Check if we need a horizontal slider */
129
130 if ( ( sp->max_width > sp->w && comp->h_pref != FL_OFF )
131 || comp->h_pref == FL_ON )
132 {
133 comp->h_on = 1;
134 comp->hh = comp->hh_def;
135
136 tb->h -= comp->hh;
137 fli_tbox_recalc_area( tb );
138 }
139
140 /* Due to the addition of a horizontal slider also a vertical slider
141 may now be needed, so recheck for this possibility */
142
143 if ( ! comp->v_on && sp->max_height > sp->h && comp->v_pref != FL_OFF )
144 {
145 comp->v_on = 1;
146 comp->vw = comp->vw_def;
147
148 tb->w -= comp->vw;
149 fli_tbox_recalc_area( tb );
150 }
151
152 if ( comp->v_on )
153 {
154 comp->vsl->x = obj->x + obj->w - comp->vw;
155 comp->vsl->y = obj->y;
156 comp->vsl->w = comp->vw;
157 comp->vsl->h = obj->h - comp->hh;
158 fli_notify_object( comp->vsl, FL_RESIZED );
159
160 comp->vval = old_yrel;
161 comp->vsize = comp->vinc1 = ( double ) sp->h / sp->max_height;
162 comp->vinc2 = ( double ) sp->def_height / sp->max_height;
163 }
164 else
165 {
166 comp->vsize = 1.0;
167 comp->vval = 0.0;
168 }
169
170 if ( comp->h_on )
171 {
172 comp->hsl->x = obj->x;
173 comp->hsl->y = obj->y + obj->h - comp->hh;
174 comp->hsl->w = obj->w - comp->vw;
175 comp->hsl->h = comp->hh;
176 fli_notify_object( comp->hsl, FL_RESIZED );
177
178 comp->hval = old_xrel;
179 comp->hsize = ( double ) sp->w / sp->max_width;
180 comp->hinc1 = ( 8.0 * sp->def_height ) / sp->max_width;
181 comp->hinc2 = ( sp->def_height - 2.0 ) / sp->max_width;
182 }
183 else
184 {
185 comp->hsize = 1.0;
186 comp->hval = 1.0;
187 }
188
189 comp->dead_area = comp->h_on && comp->v_on;
190 fli_set_object_visibility( comp->hsl, comp->h_on );
191 fli_set_object_visibility( comp->vsl, comp->v_on );
192
193 comp->attrib = 1;
194
195 sp->no_redraw = 1;
196
197 if ( comp->v_on )
198 {
199 comp->vval = fli_tbox_set_rel_yoffset( tb, comp->vval );
200 fl_set_scrollbar_value( comp->vsl, comp->vval );
201 fl_set_scrollbar_size( comp->vsl, comp->vsize );
202 }
203
204 if ( comp->h_on )
205 {
206 comp->hval = fli_tbox_set_rel_xoffset( tb, comp->hval );
207 fl_set_scrollbar_value( comp->hsl, comp->hval );
208 fl_set_scrollbar_size( comp->hsl, comp->hsize );
209 }
210
211 sp->no_redraw = 0;
212
213 if ( h_on != comp->h_on || v_on != comp->v_on )
214 fli_notify_object( tb, FL_RESIZED );
215 }
216
217
218 /***************************************
219 * The "dead area" is the small square in the lower right hand corner
220 * of the browser (beside the horizontal slider and below the vertical
221 * one) that shows up when both sliders are displayed.
222 ***************************************/
223
224 static void
draw_dead_area(FL_OBJECT * obj)225 draw_dead_area( FL_OBJECT * obj )
226 {
227 FLI_BROWSER_SPEC *sp = obj->spec;
228
229 if ( FL_ObjWin( sp->tb ) )
230 {
231 fl_winset( FL_ObjWin( sp->tb ) );
232 fl_draw_box( FL_FLAT_BOX, obj->x + obj->w - sp->vw,
233 obj->y + obj->h - sp->hh, sp->vw, sp->hh,
234 sp->vsl->col1, 1 );
235 }
236 }
237
238
239 /***************************************
240 * Called for events concerning the browser
241 ***************************************/
242
243 static int
handle_browser(FL_OBJECT * obj,int event,FL_Coord mx FL_UNUSED_ARG,FL_Coord my FL_UNUSED_ARG,int key FL_UNUSED_ARG,void * ev FL_UNUSED_ARG)244 handle_browser( FL_OBJECT * obj,
245 int event,
246 FL_Coord mx FL_UNUSED_ARG,
247 FL_Coord my FL_UNUSED_ARG,
248 int key FL_UNUSED_ARG,
249 void * ev FL_UNUSED_ARG )
250 {
251 FLI_BROWSER_SPEC *sp = obj->spec;
252
253 switch ( event )
254 {
255 case FL_RESIZED :
256 case FL_ATTRIB :
257 sp->attrib = 1;
258 break;
259
260 case FL_DRAW:
261 if ( sp->attrib )
262 {
263 attrib_change( obj );
264 get_geometry( obj );
265 sp->attrib = 0;
266 }
267
268 draw_dead_area( obj );
269 /* fall through */
270
271 case FL_DRAWLABEL:
272 fl_draw_object_label( obj );
273 break;
274
275 case FL_FREEMEM:
276 fl_free( sp );
277 break;
278 }
279
280 return FL_RETURN_NONE;
281 }
282
283
284 /***************************************
285 ***************************************/
286
287 static void
redraw_scrollbar(FL_OBJECT * ob)288 redraw_scrollbar( FL_OBJECT * ob )
289 {
290 FLI_BROWSER_SPEC *comp = ob->spec;
291
292 attrib_change( ob );
293 get_geometry( ob );
294
295 fl_freeze_form( ob->form );
296
297 if ( comp->v_on )
298 {
299 fl_set_scrollbar_size( comp->vsl, comp->vsize );
300 fl_set_scrollbar_value( comp->vsl, comp->vval );
301
302 if ( comp->vsize != 1.0 )
303 fl_set_scrollbar_increment( comp->vsl, comp->vinc1, comp->vinc2 );
304 }
305
306 if ( comp->h_on )
307 {
308 fl_set_scrollbar_size( comp->hsl, comp->hsize );
309 fl_set_scrollbar_value( comp->hsl, comp->hval );
310
311 if ( comp->hsize != 1.0 )
312 fl_set_scrollbar_increment( comp->hsl, comp->hinc1, comp->hinc2 );
313 }
314
315 if ( comp->attrib )
316 {
317 if ( comp->v_on )
318 fl_redraw_object( comp->vsl );
319 if ( comp->h_on )
320 fl_redraw_object( comp->hsl );
321 fl_redraw_object( comp->tb );
322
323 comp->attrib = 0;
324 }
325
326 draw_dead_area( ob );
327 fl_unfreeze_form( ob->form );
328 }
329
330
331 /***************************************
332 ***************************************/
333
334 static void
hcb(FL_OBJECT * obj,long data FL_UNUSED_ARG)335 hcb( FL_OBJECT * obj,
336 long data FL_UNUSED_ARG )
337 {
338 FLI_BROWSER_SPEC *comp = obj->parent->spec;
339 double hp = fli_tbox_set_rel_xoffset( comp->tb,
340 fl_get_scrollbar_value( comp->hsl ) );
341
342 if ( obj->returned & FL_RETURN_END )
343 obj->parent->returned |= FL_RETURN_END;
344
345 if ( hp != comp->old_hp )
346 obj->parent->returned |= FL_RETURN_CHANGED;
347
348 if ( obj->parent->how_return & FL_RETURN_END_CHANGED
349 && ! ( obj->parent->returned & FL_RETURN_CHANGED
350 && obj->parent->returned & FL_RETURN_END ) )
351 obj->parent->returned = FL_RETURN_NONE;
352
353 if ( obj->parent->returned & FL_RETURN_END )
354 comp->old_hp = hp;
355
356 if ( obj->returned & FL_RETURN_CHANGED && comp->hcb )
357 comp->hcb( obj->parent, fli_tbox_get_topline( comp->tb ) + 1,
358 comp->hcb_data );
359 }
360
361
362 /***************************************
363 ***************************************/
364
365 static void
vcb(FL_OBJECT * obj,long data FL_UNUSED_ARG)366 vcb( FL_OBJECT * obj,
367 long data FL_UNUSED_ARG )
368 {
369 FLI_BROWSER_SPEC *comp = obj->parent->spec;
370 double vp = fli_tbox_set_rel_yoffset( comp->tb,
371 fl_get_scrollbar_value( comp->vsl ) );
372
373 if ( obj->returned & FL_RETURN_END )
374 obj->parent->returned |= FL_RETURN_END;
375
376 if ( vp != comp->old_vp )
377 obj->parent->returned |= FL_RETURN_CHANGED;
378
379 if ( obj->parent->how_return & FL_RETURN_END_CHANGED
380 && ! ( obj->parent->returned & FL_RETURN_CHANGED
381 && obj->parent->returned & FL_RETURN_END ) )
382 obj->parent->returned = FL_RETURN_NONE;
383
384 if ( obj->parent->returned & FL_RETURN_END )
385 comp->old_vp = vp;
386
387 if ( obj->returned & FL_RETURN_CHANGED && comp->vcb )
388 comp->vcb( obj->parent, fli_tbox_get_topline( comp->tb ) + 1,
389 comp->vcb_data );
390 }
391
392
393 /***************************************
394 * Textbox callback routine, we simply pass the return value of the
395 * textbox on as the parents new return value after a readjustment of
396 * the scollbars.
397 ***************************************/
398
399 static void
tbcb(FL_OBJECT * obj,long data FL_UNUSED_ARG)400 tbcb( FL_OBJECT * obj,
401 long data FL_UNUSED_ARG )
402 {
403 FLI_BROWSER_SPEC *psp = obj->parent->spec;
404 double vp = fli_tbox_get_rel_yoffset( obj );
405 double hp = fli_tbox_get_rel_xoffset( obj );
406
407 if ( obj->returned & FL_RETURN_CHANGED )
408 {
409 if ( hp != psp->old_hp )
410 {
411 fl_set_scrollbar_value( psp->hsl, psp->old_hp = hp );
412 if ( psp->hcb )
413 psp->hcb( obj->parent, fli_tbox_get_topline( psp->tb ) + 1,
414 psp->hcb_data );
415 }
416
417 if ( vp != psp->old_vp )
418 {
419 fl_set_scrollbar_value( psp->vsl, psp->old_vp = vp );
420 if ( psp->vcb )
421 psp->vcb( obj->parent, fli_tbox_get_topline( psp->tb ) + 1,
422 psp->vcb_data );
423 }
424 }
425
426 obj->parent->returned = obj->returned;
427 }
428
429
430 /***************************************
431 * Textbox dblclick callback
432 ***************************************/
433
434 static void
tb_dblcallback(FL_OBJECT * ob,long data FL_UNUSED_ARG)435 tb_dblcallback( FL_OBJECT * ob,
436 long data FL_UNUSED_ARG )
437 {
438 FLI_BROWSER_SPEC *sp = ob->parent->spec;
439
440 if ( sp->callback )
441 sp->callback( ob->parent, sp->callback_data );
442 }
443
444
445 /***************************************
446 ***************************************/
447
448 static int
tbpost(FL_OBJECT * ob,int ev,FL_Coord mx,FL_Coord my,int key,void * xev)449 tbpost( FL_OBJECT * ob,
450 int ev,
451 FL_Coord mx,
452 FL_Coord my,
453 int key,
454 void * xev )
455 {
456 FL_OBJECT *br = ob->parent;
457
458 return br->posthandle ? br->posthandle( br, ev, mx, my, key, xev ) : 0;
459 }
460
461
462 /***************************************
463 ***************************************/
464
465 static int
tbpre(FL_OBJECT * ob,int ev,FL_Coord mx,FL_Coord my,int key,void * xev)466 tbpre( FL_OBJECT * ob,
467 int ev,
468 FL_Coord mx,
469 FL_Coord my,
470 int key,
471 void * xev )
472 {
473
474 FL_OBJECT *br = ob->parent;
475
476 return br->prehandle ? br->prehandle( br, ev, mx, my, key, xev ) : 0;
477 }
478
479
480 /***************************************
481 ***************************************/
482
483 int
fli_get_default_scrollbarsize(FL_OBJECT * ob)484 fli_get_default_scrollbarsize( FL_OBJECT * ob )
485 {
486 int delta = ( FL_abs( ob->bw ) + 3 * ( ob->bw > 0 ) );
487 int flat = IS_FLATBOX( ob->boxtype ) ? 2 : 0;
488
489 if ( ob->w > 250 && ob->h > 250 )
490 return 15 + delta - flat;
491 else if ( ob->w < 150 || ob->h < 150 )
492 return 13 + delta - flat;
493 else
494 return 14 + delta - flat;
495 }
496
497
498 /***************************************
499 * Creates a new browser object to be added to a form
500 ***************************************/
501
502 FL_OBJECT *
fl_create_browser(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)503 fl_create_browser( int type,
504 FL_Coord x,
505 FL_Coord y,
506 FL_Coord w,
507 FL_Coord h,
508 const char * label )
509 {
510 FL_OBJECT *ob;
511 FLI_BROWSER_SPEC *sp;
512 int D;
513
514 ob = fl_make_object( FL_BROWSER, type, x, y, w, h, label,
515 handle_browser );
516
517 sp = ob->spec = fl_calloc( 1, sizeof *sp );
518 sp->tb = fli_create_tbox( type, x, y, w, h, NULL );
519
520 sp->callback = NULL;
521 sp->hsize = sp->vsize = sp->hval = sp->vval =
522 sp->hinc1 = sp->hinc2 = sp->vinc1 = sp->vinc2 = 0.0;
523 sp->hcb = sp->vcb = NULL;
524 sp->hcb_data = sp->vcb_data = NULL;
525 sp->old_hp = sp->old_vp = 0.0;
526 sp->attrib = 1;
527
528 /* Copy browser attributes from textbox */
529
530 ob->boxtype = sp->tb->boxtype;
531 ob->lcol = sp->tb->lcol;
532 ob->col1 = sp->tb->col1;
533 ob->col2 = sp->tb->col2;
534 ob->align = sp->tb->align;
535
536 /* Textbox handlers */
537
538 fl_set_object_callback( sp->tb, tbcb, 0 );
539 fli_tbox_set_dblclick_callback( sp->tb, tb_dblcallback, 0 );
540 fl_set_object_posthandler( sp->tb, tbpost );
541 fl_set_object_prehandler( sp->tb, tbpre );
542
543 /* Scrollbars */
544
545 D = sp->vw_def = sp->hh_def = fli_get_default_scrollbarsize( ob );
546 sp->v_pref = sp->h_pref = FL_AUTO;
547
548 sp->hsl = fl_create_scrollbar( fli_context->hscb, x, y + h - D,
549 w - D, D, NULL );
550 fli_set_object_visibility( sp->hsl, sp->h_pref == FL_ON );
551 fl_set_object_callback( sp->hsl, hcb, 0 );
552 fl_set_scrollbar_value( sp->hsl, 0.0 );
553 fl_set_scrollbar_bounds( sp->hsl, 0.0, 1.0 );
554 sp->hsl->resize = FL_RESIZE_NONE;
555
556 sp->vsl = fl_create_scrollbar( fli_context->vscb, x + w - D, y,
557 D, h - D, NULL );
558 fli_set_object_visibility( sp->vsl, sp->v_pref == FL_ON );
559 fl_set_object_callback( sp->vsl, vcb, 0 );
560 fl_set_scrollbar_value( sp->vsl, 0.0 );
561 fl_set_scrollbar_bounds( sp->hsl, 0.0, 1.0 );
562 sp->vsl->resize = FL_RESIZE_NONE;
563
564 fl_add_child( ob, sp->tb );
565 fl_add_child( ob, sp->hsl );
566 fl_add_child( ob, sp->vsl );
567
568 /* In older versions scrollbars and browsers weren't returned to e.g.
569 fl_do_forms() but still a callback associated with the object
570 got called. To emulate the old behaviour we have to set the
571 return policy to default to FL_RETURN_NONE and only change that
572 to FL_RETURN_CHANGED when a callback is installed (which is done
573 in fl_set_object_callback()) */
574
575 #if ! USE_BWC_BS_HACK
576 fl_set_object_return( ob, FL_RETURN_SELECTION | FL_RETURN_DESELECTION );
577 #else
578 fl_set_object_return( ob, FL_RETURN_NONE );
579 #endif
580
581 fl_set_object_return( sp->hsl, FL_RETURN_ALWAYS );
582 fl_set_object_return( sp->vsl, FL_RETURN_ALWAYS );
583 fl_set_object_return( sp->tb, FL_RETURN_ALWAYS );
584
585 return ob;
586 }
587
588
589 /***************************************
590 * Adds a new browser object to the current form
591 ***************************************/
592
593 FL_OBJECT *
fl_add_browser(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,const char * label)594 fl_add_browser( int type,
595 FL_Coord x,
596 FL_Coord y,
597 FL_Coord w,
598 FL_Coord h,
599 const char * label )
600 {
601 FL_OBJECT *ob = fl_create_browser( type, x, y, w, h, label );
602
603 fl_add_object( fl_current_form, ob );
604
605 return ob;
606 }
607
608
609 /***************************************
610 * Switches the vertical scrollbar of the browser on or off
611 ***************************************/
612
613 void
fl_set_browser_vscrollbar(FL_OBJECT * obj,int on_off)614 fl_set_browser_vscrollbar( FL_OBJECT * obj,
615 int on_off )
616 {
617 FLI_BROWSER_SPEC *comp = obj->spec;
618
619 if ( comp->v_pref == on_off )
620 return;
621
622 comp->v_pref = on_off;
623 redraw_scrollbar( obj );
624 fli_tbox_react_to_vert( comp->tb, on_off );
625 get_geometry( obj );
626 fl_redraw_object( obj );
627 }
628
629
630 /***************************************
631 * Switches the horizontal scrollbar of the browser on or off
632 ***************************************/
633
634 void
fl_set_browser_hscrollbar(FL_OBJECT * obj,int on_off)635 fl_set_browser_hscrollbar( FL_OBJECT * obj,
636 int on_off )
637 {
638 FLI_BROWSER_SPEC *comp = obj->spec;
639
640 if ( comp->h_pref == on_off )
641 return;
642
643 comp->h_pref = on_off;
644 redraw_scrollbar( obj );
645 fli_tbox_react_to_hori( comp->tb, on_off );
646 get_geometry( obj );
647 fl_redraw_object( obj );
648 }
649
650
651 /***************************************
652 * Sets the callback for the horizontal scrollbar of the browser
653 ***************************************/
654
655 void
fl_set_browser_hscroll_callback(FL_OBJECT * ob,FL_BROWSER_SCROLL_CALLBACK cb,void * data)656 fl_set_browser_hscroll_callback( FL_OBJECT * ob,
657 FL_BROWSER_SCROLL_CALLBACK cb,
658 void * data )
659 {
660 FLI_BROWSER_SPEC *comp = ob->spec;
661
662 comp->hcb = cb;
663 comp->hcb_data = data;
664 }
665
666
667 /***************************************
668 * Returns the callback for the horizontal scrollbar of the browser
669 ***************************************/
670
671 FL_BROWSER_SCROLL_CALLBACK
fl_get_browser_hscroll_callback(FL_OBJECT * ob)672 fl_get_browser_hscroll_callback( FL_OBJECT * ob )
673 {
674 return ( ( FLI_BROWSER_SPEC * ) ob->spec )->hcb;
675 }
676
677
678 /***************************************
679 * Sets the callback for the vertical scrollbar of the browser
680 ***************************************/
681
682 void
fl_set_browser_vscroll_callback(FL_OBJECT * ob,FL_BROWSER_SCROLL_CALLBACK cb,void * data)683 fl_set_browser_vscroll_callback( FL_OBJECT * ob,
684 FL_BROWSER_SCROLL_CALLBACK cb,
685 void * data )
686 {
687 FLI_BROWSER_SPEC *comp = ob->spec;
688
689 comp->vcb = cb;
690 comp->vcb_data = data;
691 }
692
693
694 /***************************************
695 * Returns the callback for the vertical scrollbar of the browser
696 ***************************************/
697
698 FL_BROWSER_SCROLL_CALLBACK
fl_get_browser_vscroll_callback(FL_OBJECT * ob)699 fl_get_browser_vscroll_callback( FL_OBJECT * ob )
700 {
701 return ( ( FLI_BROWSER_SPEC * ) ob->spec )->vcb;
702 }
703
704
705 /***************************************
706 * Meant for the textbox to handle scroll callback properly
707 ***************************************/
708
709 void
fli_adjust_browser_scrollbar(FL_OBJECT * ob)710 fli_adjust_browser_scrollbar( FL_OBJECT * ob )
711 {
712 FLI_BROWSER_SPEC *comp = ob->spec;
713
714 fl_call_object_callback( comp->hsl );
715 fl_call_object_callback( comp->vsl );
716 }
717
718
719 /***************************************
720 * Removes all text from the browser
721 ***************************************/
722
723 void
fl_clear_browser(FL_OBJECT * ob)724 fl_clear_browser( FL_OBJECT * ob )
725 {
726 FLI_BROWSER_SPEC *comp = ob->spec;
727
728 fl_freeze_form( ob->form );
729 fli_tbox_clear( comp->tb );
730 fl_set_scrollbar_value( comp->hsl, 0.0 );
731 fl_set_scrollbar_size( comp->hsl, 1.0 );
732 fl_set_scrollbar_value( comp->vsl, 0.0 );
733 fl_set_scrollbar_size( comp->vsl, 1.0 );
734 redraw_scrollbar( ob );
735 fl_unfreeze_form( ob->form );
736 }
737
738
739 /***************************************
740 * Returns the x-offset of the text shown in the browser as
741 * the number of pixels
742 ***************************************/
743
744 FL_Coord
fl_get_browser_xoffset(FL_OBJECT * obj)745 fl_get_browser_xoffset( FL_OBJECT * obj )
746 {
747 FLI_BROWSER_SPEC *sp = obj->spec;
748
749 return fli_tbox_get_xoffset( sp->tb );
750 }
751
752
753 /***************************************
754 * Returns the x-offset of the text shown in the browser as a
755 * number between 0 (starts of lines are shown) and 1 (end of
756 * longest line is shown)
757 ***************************************/
758
759 double
fl_get_browser_rel_xoffset(FL_OBJECT * obj)760 fl_get_browser_rel_xoffset( FL_OBJECT * obj )
761 {
762 FLI_BROWSER_SPEC *sp = obj->spec;
763
764 return fli_tbox_get_rel_xoffset( sp->tb );
765 }
766
767
768 /***************************************
769 * Sets the x-offset of the text shown in the browser as given
770 * by the number of pixels
771 ***************************************/
772
773 void
fl_set_browser_xoffset(FL_OBJECT * ob,FL_Coord npixels)774 fl_set_browser_xoffset( FL_OBJECT * ob,
775 FL_Coord npixels )
776 {
777 FLI_BROWSER_SPEC *sp = ob->spec;
778
779 fli_tbox_set_xoffset( sp->tb, npixels );
780 redraw_scrollbar( ob );
781 }
782
783
784 /***************************************
785 * Sets the x-offset of the text shown in the browser as given
786 * by a value between 0 (show start of lines) and 1 (show end
787 * of longest line)
788 ***************************************/
789
790 void
fl_set_browser_rel_xoffset(FL_OBJECT * ob,double val)791 fl_set_browser_rel_xoffset( FL_OBJECT * ob,
792 double val )
793 {
794 FLI_BROWSER_SPEC *sp = ob->spec;
795
796 fli_tbox_set_rel_xoffset( sp->tb, val );
797 redraw_scrollbar( ob );
798 }
799
800
801 /***************************************
802 * Returns the y-offset of the text shown in the browser as
803 * the number of pixels
804 ***************************************/
805
806 FL_Coord
fl_get_browser_yoffset(FL_OBJECT * obj)807 fl_get_browser_yoffset( FL_OBJECT * obj )
808 {
809 FLI_BROWSER_SPEC *sp = obj->spec;
810
811 return fli_tbox_get_yoffset( sp->tb );
812 }
813
814
815 /***************************************
816 * Returns the y-offset of the text shown in the browser as a
817 * number between 0 (start of text is shown) and 1 (end of
818 * text is shown)
819 ***************************************/
820
821 double
fl_get_browser_rel_yoffset(FL_OBJECT * obj)822 fl_get_browser_rel_yoffset( FL_OBJECT * obj )
823 {
824 FLI_BROWSER_SPEC *sp = obj->spec;
825
826 return fli_tbox_get_rel_yoffset( sp->tb );
827 }
828
829
830 /***************************************
831 * Sets the y-offset of the text shown in the browser as given
832 * by the number of pixels
833 ***************************************/
834
835 void
fl_set_browser_yoffset(FL_OBJECT * ob,FL_Coord npixels)836 fl_set_browser_yoffset( FL_OBJECT * ob,
837 FL_Coord npixels )
838 {
839 FLI_BROWSER_SPEC *sp = ob->spec;
840
841 fli_tbox_set_yoffset( sp->tb, npixels );
842 redraw_scrollbar( ob );
843 }
844
845
846 /***************************************
847 * Sets the y-offset of the text shown in the browser as given
848 * by a value between 0 (show start of text) and 1 (show end of
849 * text)
850 ***************************************/
851
852 void
fl_set_browser_rel_yoffset(FL_OBJECT * ob,double val)853 fl_set_browser_rel_yoffset( FL_OBJECT * ob,
854 double val )
855 {
856 FLI_BROWSER_SPEC *sp = ob->spec;
857
858 fli_tbox_set_rel_yoffset( sp->tb, val );
859 redraw_scrollbar( ob );
860 }
861
862
863 /***************************************
864 * Returns the y-offset for a line (or -1 if the line does not exist).
865 ***************************************/
866
867 int
fl_get_browser_line_yoffset(FL_OBJECT * obj,int line)868 fl_get_browser_line_yoffset( FL_OBJECT * obj,
869 int line )
870 {
871 FLI_BROWSER_SPEC *sp = obj->spec;
872
873 return fli_tbox_get_line_yoffset( sp->tb, line + 1 );
874 }
875
876
877 /***************************************
878 * Move a line to the top of the browser
879 ***************************************/
880
881 void
fl_set_browser_topline(FL_OBJECT * ob,int line)882 fl_set_browser_topline( FL_OBJECT * ob,
883 int line )
884 {
885 FLI_BROWSER_SPEC *sp = ob->spec;
886
887 fli_tbox_set_topline( sp->tb, line - 1 );
888 redraw_scrollbar( ob );
889 }
890
891
892 /***************************************
893 * Move a line to the bottom of the browser
894 ***************************************/
895
896 void
fl_set_browser_bottomline(FL_OBJECT * ob,int line)897 fl_set_browser_bottomline( FL_OBJECT * ob,
898 int line )
899 {
900 FLI_BROWSER_SPEC *sp = ob->spec;
901
902 fli_tbox_set_bottomline( sp->tb, line - 1 );
903 redraw_scrollbar( ob );
904 }
905
906
907 /***************************************
908 * Marks a line of the browser as selected
909 ***************************************/
910
911 void
fl_select_browser_line(FL_OBJECT * ob,int line)912 fl_select_browser_line( FL_OBJECT * ob,
913 int line )
914 {
915 fli_tbox_select_line( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb, line - 1 );
916 }
917
918
919 /***************************************
920 * Adds a line (given by a forma string and the appropriate number of
921 * argumens) to the (end of the) browser and shifts the displayed
922 * area so that the line is visible
923 ***************************************/
924
925 void
fl_addto_browser(FL_OBJECT * obj,const char * text)926 fl_addto_browser( FL_OBJECT * obj,
927 const char * text )
928 {
929 fli_tbox_add_line( ( ( FLI_BROWSER_SPEC * ) obj->spec )->tb, text, 1 );
930 redraw_scrollbar( obj );
931 }
932
933
934 /***************************************
935 * Adds a line (specified using a format string and an unspecified number
936 * of further arguments) to the (end of the) browser and shifts the
937 * displayed area so that the line is visible
938 ***************************************/
939
940 void
fl_addto_browser_f(FL_OBJECT * obj,const char * fmt,...)941 fl_addto_browser_f( FL_OBJECT * obj,
942 const char * fmt,
943 ...)
944 {
945 char *buf;
946
947 EXPAND_FORMAT_STRING( buf, fmt );
948 fl_addto_browser( obj, buf );
949 fl_free( buf );
950 }
951
952
953 /***************************************
954 * Inserts a line into the browser before the line currently
955 * having the number 'linenumb'
956 ***************************************/
957
958 void
fl_insert_browser_line(FL_OBJECT * ob,int linenumb,const char * newtext)959 fl_insert_browser_line( FL_OBJECT * ob,
960 int linenumb,
961 const char * newtext )
962 {
963 FLI_BROWSER_SPEC *sp = ob->spec;
964 FLI_TBOX_SPEC *tbsp = sp->tb->spec;
965
966 /* When inserting into an empty browser or appending at the end
967 it's treated exactly the same way as for fl_add_browser_line()
968 (including interpretation of newline characters). */
969
970 if ( tbsp->num_lines == 0 || linenumb > tbsp->num_lines )
971 fli_tbox_insert_lines( sp->tb, linenumb - 1, newtext );
972 else
973 fli_tbox_insert_line( sp->tb, linenumb - 1, newtext );
974
975 redraw_scrollbar( ob );
976 }
977
978
979 /***************************************
980 * Inserts a line (given by a format string and the aprropriate number
981 * of arguments) into the browser before the line currently having the
982 * number 'linenumb'
983 ***************************************/
984
985 void
fl_insert_browser_line_f(FL_OBJECT * ob,int linenumb,const char * fmt,...)986 fl_insert_browser_line_f( FL_OBJECT * ob,
987 int linenumb,
988 const char * fmt,
989 ... )
990 {
991 char *buf;
992
993 EXPAND_FORMAT_STRING( buf, fmt );
994 fl_insert_browser_line( ob, linenumb, buf );
995 fl_free( buf );
996 }
997
998
999 /***************************************
1000 * Deletes the line at line number 'linenumb' from the browser
1001 ***************************************/
1002
1003 void
fl_delete_browser_line(FL_OBJECT * ob,int linenumb)1004 fl_delete_browser_line( FL_OBJECT * ob,
1005 int linenumb )
1006 {
1007 fli_tbox_delete_line( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb,
1008 linenumb - 1 );
1009 redraw_scrollbar( ob );
1010 }
1011
1012
1013 /***************************************
1014 * Replaces the browser line at line number 'linenumb' with a new one
1015 ***************************************/
1016
1017 void
fl_replace_browser_line(FL_OBJECT * ob,int linenumb,const char * newtext)1018 fl_replace_browser_line( FL_OBJECT * ob,
1019 int linenumb,
1020 const char * newtext )
1021 {
1022 fli_tbox_replace_line( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb,
1023 linenumb - 1, newtext );
1024 redraw_scrollbar( ob );
1025 }
1026
1027
1028 /***************************************
1029 * Replaces the browser line at line number 'linenumb' with a new one
1030 * derived from the format string and the following arguments.
1031 ***************************************/
1032
1033 void
fl_replace_browser_line_f(FL_OBJECT * ob,int linenumb,const char * fmt,...)1034 fl_replace_browser_line_f( FL_OBJECT * ob,
1035 int linenumb,
1036 const char * fmt,
1037 ... )
1038 {
1039 char *buf;
1040
1041 EXPAND_FORMAT_STRING( buf, fmt );
1042 fl_replace_browser_line( ob, linenumb, buf );
1043 fl_free( buf );
1044 }
1045
1046
1047 /***************************************
1048 * Returns the text of the browser's line at line number 'linenum'.
1049 * Returned text may not be modified (and not free'ed!)
1050 ***************************************/
1051
1052 const char *
fl_get_browser_line(FL_OBJECT * ob,int linenumb)1053 fl_get_browser_line( FL_OBJECT * ob,
1054 int linenumb )
1055 {
1056 return fli_tbox_get_line( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb,
1057 linenumb - 1 );
1058 }
1059
1060
1061 /***************************************
1062 * Returns the number of the last line of the browser
1063 ***************************************/
1064
1065 int
fl_get_browser_maxline(FL_OBJECT * obj)1066 fl_get_browser_maxline( FL_OBJECT * obj )
1067 {
1068 FLI_BROWSER_SPEC *sp = obj->spec;
1069
1070 return fli_tbox_get_num_lines( sp->tb );
1071 }
1072
1073
1074 /***************************************
1075 * Unselects a line in the browser
1076 ***************************************/
1077
1078 void
fl_deselect_browser_line(FL_OBJECT * ob,int line)1079 fl_deselect_browser_line( FL_OBJECT * ob,
1080 int line )
1081 {
1082 fli_tbox_deselect_line( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb, line - 1 );
1083 }
1084
1085
1086 /***************************************
1087 * De-selects all lines of the browser
1088 ***************************************/
1089
1090 void
fl_deselect_browser(FL_OBJECT * ob)1091 fl_deselect_browser( FL_OBJECT * ob )
1092 {
1093 fli_tbox_deselect( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb );
1094 }
1095
1096
1097 /***************************************
1098 * Tests if a certain line of the browser is selected
1099 ***************************************/
1100
1101 int
fl_isselected_browser_line(FL_OBJECT * ob,int line)1102 fl_isselected_browser_line( FL_OBJECT * ob,
1103 int line )
1104 {
1105 FLI_BROWSER_SPEC *sp = ob->spec;
1106
1107 return fli_tbox_is_line_selected( sp->tb, line - 1 );
1108 }
1109
1110
1111 /***************************************
1112 * Returns the line last selected (or deselected) by the user
1113 ***************************************/
1114
1115 int
fl_get_browser(FL_OBJECT * ob)1116 fl_get_browser( FL_OBJECT * ob )
1117 {
1118 FLI_BROWSER_SPEC *sp = ob->spec;
1119
1120 return fli_tbox_get_selection( sp->tb );
1121 }
1122
1123
1124 /***************************************
1125 * Sets the font size to be used per default
1126 ***************************************/
1127
1128 void
fl_set_browser_fontsize(FL_OBJECT * ob,int size)1129 fl_set_browser_fontsize( FL_OBJECT * ob,
1130 int size )
1131 {
1132 FLI_BROWSER_SPEC *sp = ob->spec;
1133
1134 fli_tbox_set_fontsize( sp->tb, size );
1135 redraw_scrollbar( ob );
1136 fl_redraw_object( ob );
1137 }
1138
1139
1140 /***************************************
1141 * Sets the font style to be used per default
1142 ***************************************/
1143
1144 void
fl_set_browser_fontstyle(FL_OBJECT * ob,int style)1145 fl_set_browser_fontstyle( FL_OBJECT * ob,
1146 int style )
1147 {
1148 FLI_BROWSER_SPEC *sp = ob->spec;
1149
1150 fli_tbox_set_fontstyle( sp->tb, style );
1151 redraw_scrollbar( ob );
1152 fl_redraw_object( ob );
1153 }
1154
1155
1156 /***************************************
1157 * Returns the number of the topmost line that is completely visible,
1158 * may return 0 if there are no lines in the browser
1159 ***************************************/
1160
1161 int
fl_get_browser_topline(FL_OBJECT * obj)1162 fl_get_browser_topline( FL_OBJECT * obj )
1163 {
1164 FLI_BROWSER_SPEC *sp = obj->spec;
1165
1166 return fli_tbox_get_topline( sp->tb ) + 1;
1167 }
1168
1169
1170 /***************************************
1171 * Loads a browser with text from a file
1172 ***************************************/
1173
1174 int
fl_load_browser(FL_OBJECT * obj,const char * f)1175 fl_load_browser( FL_OBJECT * obj,
1176 const char * f )
1177 {
1178 FLI_BROWSER_SPEC *sp = obj->spec;
1179 int status;
1180
1181 fl_clear_browser( obj );
1182 status = fli_tbox_load( sp->tb, f );
1183 redraw_scrollbar( obj );
1184 return status;
1185 }
1186
1187
1188 /***************************************
1189 * Adds a line to the (end of the) browser (does not make the line
1190 * visible)
1191 ***************************************/
1192
1193 void
fl_add_browser_line(FL_OBJECT * ob,const char * newtext)1194 fl_add_browser_line( FL_OBJECT * ob,
1195 const char * newtext )
1196 {
1197 FLI_BROWSER_SPEC *sp = ob->spec;
1198
1199 fli_tbox_add_line( sp->tb, newtext, 0 );
1200 redraw_scrollbar( ob );
1201 }
1202
1203
1204 /***************************************
1205 * Adds a line to the (end of the) browser (does not make the line
1206 * visible)
1207 ***************************************/
1208
1209 void
fl_add_browser_line_f(FL_OBJECT * ob,const char * fmt,...)1210 fl_add_browser_line_f( FL_OBJECT * ob,
1211 const char * fmt,
1212 ... )
1213 {
1214 char *buf;
1215
1216 EXPAND_FORMAT_STRING( buf, fmt );
1217 fl_add_browser_line( ob,buf );
1218 fl_free( buf );
1219 }
1220
1221
1222 /***************************************
1223 * Sets a callback for double clicks in the browser
1224 ***************************************/
1225
1226 void
fl_set_browser_dblclick_callback(FL_OBJECT * ob,FL_CALLBACKPTR cb,long a)1227 fl_set_browser_dblclick_callback( FL_OBJECT * ob,
1228 FL_CALLBACKPTR cb,
1229 long a )
1230 {
1231 FLI_BROWSER_SPEC *comp = ob->spec;
1232
1233 comp->callback = cb;
1234 comp->callback_data = a;
1235 }
1236
1237
1238 /***************************************
1239 * Sets the height of the vertical and the width of the horzontal
1240 * scrollbar
1241 ***************************************/
1242
1243 void
fl_set_browser_scrollbarsize(FL_OBJECT * ob,int hh,int vw)1244 fl_set_browser_scrollbarsize( FL_OBJECT * ob,
1245 int hh,
1246 int vw )
1247 {
1248 FLI_BROWSER_SPEC *comp = ob->spec;
1249 int redraw = 0;
1250
1251 if ( hh > 0 && hh != comp->hsl->h )
1252 {
1253 comp->hsl->h = comp->hh_def = hh;
1254 redraw = 1;
1255 }
1256
1257 if ( vw > 0 && vw != comp->vsl->w )
1258 {
1259 comp->vsl->w = comp->vw_def = vw;
1260 redraw = 1;
1261 }
1262
1263 if ( redraw )
1264 {
1265 comp->user_set = 1;
1266 fl_redraw_object( ob );
1267 fl_redraw_object( comp->tb );
1268 fl_redraw_object( comp->hsl );
1269 fl_redraw_object( comp->vsl );
1270 }
1271 }
1272
1273
1274 /***************************************
1275 * Returns the position and width and height of the browsers text area
1276 ***************************************/
1277
1278 void
fl_get_browser_dimension(FL_OBJECT * obj,FL_Coord * x,FL_Coord * y,FL_Coord * w,FL_Coord * h)1279 fl_get_browser_dimension( FL_OBJECT * obj,
1280 FL_Coord * x,
1281 FL_Coord * y,
1282 FL_Coord * w,
1283 FL_Coord * h )
1284 {
1285 FLI_TBOX_SPEC *sp = ( ( FLI_BROWSER_SPEC * ) obj->spec )->tb->spec;
1286
1287 *x = obj->x + sp->x;
1288 *y = obj->y + sp->y;
1289 *w = sp->w;
1290 *h = sp->h;
1291 }
1292
1293
1294 /***************************************
1295 * Makes a browser line selectable or unselectable
1296 ***************************************/
1297
1298 void
fl_set_browser_line_selectable(FL_OBJECT * ob,int line,int flag)1299 fl_set_browser_line_selectable( FL_OBJECT * ob,
1300 int line,
1301 int flag )
1302 {
1303 fli_tbox_make_line_selectable( ob, line - 1, flag );
1304 }
1305
1306
1307 /***************************************
1308 * Appends characters to the end of the last line in the browser
1309 ***************************************/
1310
1311 void
fl_addto_browser_chars(FL_OBJECT * ob,const char * str)1312 fl_addto_browser_chars( FL_OBJECT * ob,
1313 const char * str )
1314 {
1315 FLI_BROWSER_SPEC *sp = ob->spec;
1316
1317 fli_tbox_add_chars( sp->tb, str );
1318 redraw_scrollbar( ob );
1319 }
1320
1321
1322 /***************************************
1323 * Appends characters to the end of the last line in the browser
1324 ***************************************/
1325
1326 void
fl_addto_browser_chars_f(FL_OBJECT * ob,const char * fmt,...)1327 fl_addto_browser_chars_f( FL_OBJECT * ob,
1328 const char * fmt,
1329 ... )
1330 {
1331 char *buf;
1332
1333 EXPAND_FORMAT_STRING( buf, fmt );
1334 fl_addto_browser_chars_f( ob, buf );
1335 fl_free( buf );
1336 }
1337
1338
1339 /***************************************
1340 * Returns an approximation of the number of lines shown in the browser
1341 ***************************************/
1342
1343 int
fl_get_browser_screenlines(FL_OBJECT * ob)1344 fl_get_browser_screenlines( FL_OBJECT * ob )
1345 {
1346 FLI_BROWSER_SPEC *sp = ob->spec;
1347
1348 int t = fli_tbox_get_topline( sp->tb );
1349 int b = fli_tbox_get_bottomline( sp->tb );
1350
1351 if ( t < 0 || b < 0 )
1352 return 0;
1353 return b - t + 1;
1354 }
1355
1356
1357 /***************************************
1358 * Sets the escape key used in the text
1359 ***************************************/
1360
1361 void
fl_set_browser_specialkey(FL_OBJECT * ob,int specialkey)1362 fl_set_browser_specialkey( FL_OBJECT * ob,
1363 int specialkey )
1364 {
1365 FLI_TBOX_SPEC *sp = ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb->spec;
1366
1367 sp->specialkey = specialkey;
1368 }
1369
1370
1371 /***************************************
1372 * Brings a line into view
1373 ***************************************/
1374
1375 void
fl_show_browser_line(FL_OBJECT * ob,int line)1376 fl_show_browser_line( FL_OBJECT * ob,
1377 int line )
1378 {
1379 fli_tbox_set_centerline( ( ( FLI_BROWSER_SPEC * ) ob->spec )->tb, line );
1380 redraw_scrollbar( ob );
1381 }
1382
1383
1384 /***************************************
1385 * Deprecated function, only left in for backward compatibility
1386 ***************************************/
1387
1388 int
fl_set_default_browser_maxlinelength(int n FL_UNUSED_ARG)1389 fl_set_default_browser_maxlinelength( int n FL_UNUSED_ARG )
1390 {
1391 return 0;
1392 }
1393
1394
1395 /***************************************
1396 ***************************************/
1397
1398 int
fl_get_browser_scrollbar_repeat(FL_OBJECT * ob)1399 fl_get_browser_scrollbar_repeat( FL_OBJECT * ob )
1400 {
1401 return fl_get_slider_repeat( ( ( FLI_BROWSER_SPEC * ) ob->spec )->vsl );
1402 }
1403
1404
1405 /***************************************
1406 ***************************************/
1407
1408 void
fl_set_browser_scrollbar_repeat(FL_OBJECT * ob,int millisec)1409 fl_set_browser_scrollbar_repeat( FL_OBJECT * ob,
1410 int millisec )
1411 {
1412 if ( millisec > 0 )
1413 {
1414 fl_set_slider_repeat( ( ( FLI_BROWSER_SPEC * ) ob->spec )->vsl,
1415 millisec );
1416 fl_set_slider_repeat( ( ( FLI_BROWSER_SPEC * ) ob->spec )->hsl,
1417 millisec );
1418 }
1419 }
1420
1421
1422 /*
1423 * Local variables:
1424 * tab-width: 4
1425 * indent-tabs-mode: nil
1426 * End:
1427 */
1428