Freeciv-3.2
Loading...
Searching...
No Matches
widget_scrollbar.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2006 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* SDL3 */
19#include <SDL3/SDL.h>
20
21/* utility */
22#include "log.h"
23
24/* gui-sdl3 */
25#include "colors.h"
26#include "graphics.h"
27#include "gui_id.h"
28#include "gui_tilespec.h"
29#include "mapview.h"
30#include "themespec.h"
31
32#include "widget.h"
33#include "widget_p.h"
34
35struct up_down {
36 struct widget *begin;
37 struct widget *end;
41 float old_y;
42 int step;
43 float prev_x;
44 float prev_y;
45 int offset; /* Number of pixels the mouse is away from the slider origin */
46};
47
48#define widget_add_next(new_widget, add_dock) \
49do { \
50 new_widget->prev = add_dock; \
51 new_widget->next = add_dock->next; \
52 if (add_dock->next) { \
53 add_dock->next->prev = new_widget; \
54 } \
55 add_dock->next = new_widget; \
56} while (FALSE)
57
58static int (*baseclass_redraw)(struct widget *pwidget);
59
60/* =================================================== */
61/* ===================== VSCROLLBAR ================== */
62/* =================================================== */
63
64/**********************************************************************/
71 enum widget_state state,
73{
75 SDL_Rect src, des;
76 Uint16 i;
81
82 tile_len_end = vert_theme->h / 16;
83
84 start_y = 0 + state * (vert_theme->h / 4);
85
87
89
90 /* Correction */
93 }
94
95 if (!tile_count_midd) {
97 } else {
99 }
100
101 src.x = 0;
102 src.y = start_y;
103 src.w = vert_theme->w;
104 src.h = tile_len_end;
105 alphablit(vert_theme, &src, versurf, NULL, 255);
106
107 src.y = start_y + tile_len_end;
108 src.h = tile_len_midd;
109
110 des.x = 0;
111
112 for (i = 0; i < tile_count_midd; i++) {
114 alphablit(vert_theme, &src, versurf, &des, 255);
115 }
116
118 src.h = tile_len_end;
119 des.y = versurf->h - tile_len_end;
120 alphablit(vert_theme, &src, versurf, &des, 255);
121
122 return versurf;
123}
124
125/**********************************************************************/
128static int redraw_vert(struct widget *vert)
129{
130 int ret;
132
133 ret = (*baseclass_redraw)(vert);
134 if (ret != 0) {
135 return ret;
136 }
137
140 vert->size.h);
141 ret = blit_entire_src(vert_surf, vert->dst->surface,
142 vert->size.x, vert->size.y);
143
145
146 return ret;
147}
148
149/**********************************************************************/
161 Uint16 height, Uint32 flags)
162{
163 struct widget *vert = widget_new();
164
165 vert->theme = vert_theme;
166 vert->size.w = vert_theme->w;
167 vert->size.h = height;
171 vert->mod = SDL_KMOD_NONE;
172 vert->dst = pdest;
173
174 baseclass_redraw = vert->redraw;
175 vert->redraw = redraw_vert;
176
177 return vert;
178}
179
180/**********************************************************************/
184{
185 vert->size.x = x;
186 vert->size.y = y;
187 vert->gfx = crop_rect_from_surface(vert->dst->surface, &vert->size);
188
189 return redraw_vert(vert);
190}
191
192/* =================================================== */
193/* ===================== HSCROLLBAR ================== */
194/* =================================================== */
195
196/**********************************************************************/
203 enum widget_state state,
205{
207 SDL_Rect src, des;
208 Uint16 i;
209 Uint16 start_x;
213
214 tile_len_end = horiz_theme->w / 16;
215
216 start_x = 0 + state * (horiz_theme->w / 4);
217
219
221
222 /* Correction */
225 }
226
227 if (!tile_count_midd) {
229 } else {
231 }
232
233 src.y = 0;
234 src.x = start_x;
235 src.h = horiz_theme->h;
236 src.w = tile_len_end;
237 alphablit(horiz_theme, &src, horsurf, NULL, 255);
238
239 src.x = start_x + tile_len_end;
240 src.w = tile_len_midd;
241
242 des.y = 0;
243
244 for (i = 0; i < tile_count_midd; i++) {
246 alphablit(horiz_theme, &src, horsurf, &des, 255);
247 }
248
249 src.x = start_x + tile_len_end + tile_len_midd;
250 src.w = tile_len_end;
251 des.x = horsurf->w - tile_len_end;
252 alphablit(horiz_theme, &src, horsurf, &des, 255);
253
254 return horsurf;
255}
256
257/**********************************************************************/
260static int redraw_horiz(struct widget *horiz)
261{
262 int ret;
264
265 ret = (*baseclass_redraw)(horiz);
266 if (ret != 0) {
267 return ret;
268 }
269
271 get_wstate(horiz),
272 horiz->size.w);
274 horiz->size.x, horiz->size.y);
275
277
278 return ret;
279}
280
281/**********************************************************************/
293 struct gui_layer *pdest,
294 Uint16 width, Uint32 flags)
295{
296 struct widget *hor = widget_new();
297
298 hor->theme = horiz_theme;
299 hor->size.w = width;
300 hor->size.h = horiz_theme->h;
301 set_wflag(hor, WF_FREE_STRING | flags);
304 hor->mod = SDL_KMOD_NONE;
305 hor->dst = pdest;
306
307 baseclass_redraw = hor->redraw;
308 hor->redraw = redraw_horiz;
309
310 return hor;
311}
312
313/**********************************************************************/
316int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
317{
318 horiz->size.x = x;
319 horiz->size.y = y;
320 horiz->gfx = crop_rect_from_surface(horiz->dst->surface, &horiz->size);
321
322 return redraw_horiz(horiz);
323}
324
325/* =================================================== */
326/* ===================== ================== */
327/* =================================================== */
328
329/**********************************************************************/
332static int get_step(struct scroll_bar *scroll)
333{
334 float step = scroll->max - scroll->min;
335
336 step *= (float) (1.0 - (float) (scroll->active * scroll->step) /
337 (float)scroll->count);
338 step /= (float)(scroll->count - scroll->active * scroll->step);
339 step *= (float)scroll->step;
340 step++;
341
342 return (int)step;
343}
344
345/**********************************************************************/
348static int get_position(struct advanced_dialog *dlg)
349{
350 struct widget *buf = dlg->active_widget_list;
351 int count = dlg->scroll->active * dlg->scroll->step - 1;
352 int step = get_step(dlg->scroll);
353
354 /* find last seen widget */
355 while (count) {
356 if (buf == dlg->begin_active_widget_list) {
357 break;
358 }
359 count--;
360 buf = buf->prev;
361 }
362
363 count = 0;
364 if (buf != dlg->begin_active_widget_list) {
365 do {
366 count++;
367 buf = buf->prev;
368 } while (buf != dlg->begin_active_widget_list);
369 }
370
371 if (dlg->scroll->pscroll_bar) {
372 return dlg->scroll->max - dlg->scroll->pscroll_bar->size.h -
373 count * (float)step / dlg->scroll->step;
374 } else {
375 return dlg->scroll->max - count * (float)step / dlg->scroll->step;
376 }
377}
378
379/**************************************************************************
380 Vertical scroll_bar
381**************************************************************************/
382
383static struct widget *up_scroll_widget_list(struct scroll_bar *vscroll,
384 struct widget *begin_active_widget_list,
385 struct widget *begin_widget_list,
386 struct widget *end_widget_list);
387
388static struct widget *down_scroll_widget_list(struct scroll_bar *vscroll,
389 struct widget *begin_active_widget_list,
390 struct widget *begin_widget_list,
391 struct widget *end_widget_list);
392
393static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
394 struct widget *begin_active_widget_list,
395 struct widget *begin_widget_list,
396 struct widget *end_widget_list);
397
398/**********************************************************************/
401static int std_up_advanced_dlg_callback(struct widget *pwidget)
402{
404 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
405 struct widget *begin = up_scroll_widget_list(
406 dlg->scroll,
410
411 if (begin) {
412 dlg->active_widget_list = begin;
413 }
414
416 selected_widget = pwidget;
417 set_wstate(pwidget, FC_WS_SELECTED);
418 widget_redraw(pwidget);
419 widget_flush(pwidget);
420 }
421
422 return -1;
423}
424
425/**********************************************************************/
428static int std_down_advanced_dlg_callback(struct widget *pwidget)
429{
431 struct advanced_dialog *dlg = pwidget->private_data.adv_dlg;
432 struct widget *begin = down_scroll_widget_list(
433 dlg->scroll,
437
438 if (begin) {
439 dlg->active_widget_list = begin;
440 }
441
443 selected_widget = pwidget;
444 set_wstate(pwidget, FC_WS_SELECTED);
445 widget_redraw(pwidget);
446 widget_flush(pwidget);
447 }
448
449 return -1;
450}
451
452/**********************************************************************/
455static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
456{
458 struct advanced_dialog *dlg = pscroll_bar->private_data.adv_dlg;
459 struct widget *begin = vertic_scroll_widget_list(
460 dlg->scroll,
464
465 if (begin) {
466 dlg->active_widget_list = begin;
467 }
468
470 set_wstate(pscroll_bar, FC_WS_SELECTED);
471 selected_widget = pscroll_bar;
472 redraw_vert(pscroll_bar);
473 widget_flush(pscroll_bar);
474 }
475
476 return -1;
477}
478
479/**********************************************************************/
483 Uint8 step, Uint8 active,
485{
486 Uint16 count = 0;
487 struct widget *buf = NULL, *pwindow = NULL;
488
489 fc_assert_ret_val(dlg != NULL, 0);
490
491 pwindow = dlg->end_widget_list;
492
493 if (!dlg->scroll) {
494 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
495
497 while (buf && (buf != dlg->begin_active_widget_list->prev)) {
498 buf = buf->prev;
499 count++;
500 }
501
502 dlg->scroll->count = count;
503 }
504
505 dlg->scroll->active = active;
506 dlg->scroll->step = step;
507
508 if (create_buttons) {
509 /* create up button */
510 buf = create_themeicon_button(current_theme->up_icon, pwindow->dst,
512
513 buf->id = ID_BUTTON;
514 buf->private_data.adv_dlg = dlg;
517
518 dlg->scroll->up_left_button = buf;
520 dlg->begin_widget_list = buf;
521
522 count = buf->size.w;
523
524 /* create down button */
525 buf = create_themeicon_button(current_theme->down_icon, pwindow->dst,
527
528 buf->id = ID_BUTTON;
529 buf->private_data.adv_dlg = dlg;
532
535 dlg->begin_widget_list = buf;
536 }
537
538 if (create_scrollbar) {
539 /* create vscrollbar */
540 buf = create_vertical(current_theme->vertic, pwindow->dst,
542
543 buf->id = ID_SCROLLBAR;
544 buf->private_data.adv_dlg = dlg;
547
548 dlg->scroll->pscroll_bar = buf;
550 dlg->begin_widget_list = buf;
551
552 if (!count) {
553 count = buf->size.w;
554 }
555 }
556
557 return count;
558}
559
560/**********************************************************************/
564 Sint16 start_x, Sint16 start_y,
566{
567 bool buttons_exist;
568
569 fc_assert_ret(scroll != NULL);
570
571 buttons_exist = (scroll->down_right_button && scroll->up_left_button);
572
573 if (buttons_exist) {
574 /* up */
575 scroll->up_left_button->size.y = start_y;
576 if (swap_start_x) {
577 scroll->up_left_button->size.x = start_x -
578 scroll->up_left_button->size.w;
579 } else {
580 scroll->up_left_button->size.x = start_x;
581 }
582 scroll->min = start_y + scroll->up_left_button->size.h;
583 /* -------------------------- */
584 /* down */
585 scroll->down_right_button->size.y = start_y + height -
586 scroll->down_right_button->size.h;
587 if (swap_start_x) {
588 scroll->down_right_button->size.x = start_x -
589 scroll->down_right_button->size.w;
590 } else {
591 scroll->down_right_button->size.x = start_x;
592 }
593 scroll->max = scroll->down_right_button->size.y;
594 }
595 /* --------------- */
596 /* scrollbar */
597 if (scroll->pscroll_bar) {
598 if (swap_start_x) {
599 scroll->pscroll_bar->size.x = start_x - scroll->pscroll_bar->size.w + 2;
600 } else {
601 scroll->pscroll_bar->size.x = start_x;
602 }
603
604 if (buttons_exist) {
605 scroll->pscroll_bar->size.y = start_y +
606 scroll->up_left_button->size.h;
607 if (scroll->count > scroll->active * scroll->step) {
608 scroll->pscroll_bar->size.h = scrollbar_size(scroll);
609 } else {
610 scroll->pscroll_bar->size.h = scroll->max - scroll->min;
611 }
612 } else {
613 scroll->pscroll_bar->size.y = start_y;
614 scroll->pscroll_bar->size.h = height;
615 scroll->min = start_y;
616 scroll->max = start_y + height;
617 }
618 }
619}
620
621/* =================================================== */
622/* ============ Vertical Scroll Group List =========== */
623/* =================================================== */
624
625/**********************************************************************/
629static struct widget *vertical_scroll_widget_list(struct widget *active_widget_list,
630 struct widget *begin_widget_list,
631 struct widget *end_widget_list,
632 int active, int step, int dir)
633{
634 struct widget *begin = active_widget_list;
635 struct widget *buf = active_widget_list;
636 struct widget *tmp = NULL;
637 int count = active; /* row */
638 int count_step = step; /* col */
639
640 if (dir < 0) {
641 /* up */
642 bool real = TRUE;
643
644 if (buf != end_widget_list) {
645 /*
646 move pointers to positions and unhide scrolled widgets
647 B = buf - new top
648 T = tmp - current top == active_widget_list
649 [B] [ ] [ ]
650 -----------
651 [T] [ ] [ ]
652 [ ] [ ] [ ]
653 -----------
654 [ ] [ ] [ ]
655 */
656 tmp = buf; /* now buf == active_widget_list == current Top */
657 while (count_step > 0) {
658 buf = buf->next;
660 count_step--;
661 }
663
664 /* setup new ActiveWidget pointer */
665 begin = buf;
666
667 /*
668 scroll pointers up
669 B = buf
670 T = tmp
671 [B0] [B1] [B2]
672 -----------
673 [T0] [T1] [T2] => B position = T position
674 [T3] [T4] [T5]
675 -----------
676 [ ] [ ] [ ]
677
678 start from B0 and go down list
679 B0 = T0, B1 = T1, B2 = T2
680 T0 = T3, T1 = T4, T2 = T5
681 etc...
682 */
683
684 /* buf == begin == new top widget */
685
686 while (count > 0) {
687 if (real) {
688 buf->size.x = tmp->size.x;
689 buf->size.y = tmp->size.y;
690 buf->gfx = tmp->gfx;
691
692 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
697 }
698 }
699
700 tmp->gfx = NULL;
701
702 if (count == 1) {
704 }
705 if (tmp == begin_widget_list) {
706 real = FALSE;
707 }
708 tmp = tmp->prev;
709 } else {
710 /*
711 unsymmetric list support.
712 This is big problem because we can't take position from unexisting
713 list member. We must put here some hypothetical positions
714
715 [B0] [B1] [B2]
716 --------------
717 [T0] [T1]
718
719 */
720 if (active > 1) {
721 /* this works well if active > 1 but is buggy when active == 1 */
722 buf->size.y += buf->size.h;
723 } else {
724 /* this works well if active == 1 but may be broken if "next"
725 element has other "y" position */
726 buf->size.y = buf->next->size.y;
727 }
728 buf->gfx = NULL;
729 }
730
731 buf = buf->prev;
732 count_step--;
733 if (!count_step) {
735 count--;
736 }
737 }
738 }
739 } else {
740 /* down */
741 count = active * step; /* row * col */
742
743 /*
744 find end
745 B = buf
746 A - start (buf == active_widget_list)
747 [ ] [ ] [ ]
748 -----------
749 [A] [ ] [ ]
750 [ ] [ ] [ ]
751 -----------
752 [B] [ ] [ ]
753 */
754 while (count && buf != begin_widget_list->prev) {
755 buf = buf->prev;
756 count--;
757 }
758
759 if (!count && buf != begin_widget_list->prev) {
760 /*
761 move pointers to positions and unhide scrolled widgets
762 B = buf
763 T = tmp
764 A - start (active_widget_list)
765 [ ] [ ] [ ]
766 -----------
767 [A] [ ] [ ]
768 [ ] [ ] [T]
769 -----------
770 [ ] [ ] [B]
771 */
772 tmp = buf->next;
773 count_step = step - 1;
774 while (count_step && buf != begin_widget_list) {
776 buf = buf->prev;
777 count_step--;
778 }
780
781 /*
782 Unsymmetric list support.
783 correct tmp and undraw empty fields
784 B = buf
785 T = tmp
786 A - start (active_widget_list)
787 [ ] [ ] [ ]
788 -----------
789 [A] [ ] [ ]
790 [ ] [T] [U] <- undraw U
791 -----------
792 [ ] [B]
793 */
794 count = count_step;
795 while (count) {
796 /* hack - clear area under unexisting list members */
799 FREESURFACE(tmp->gfx);
800 if (active == 1) {
802 }
803 tmp = tmp->next;
804 count--;
805 }
806
807 /* reset counters */
808 count = active;
809 if (count_step) {
811 } else {
813 }
814
815 /*
816 scroll pointers down
817 B = buf
818 T = tmp
819 [ ] [ ] [ ]
820 -----------
821 [ ] [ ] [ ]
822 [T2] [T1] [T0] => B position = T position
823 -----------
824 [B2] [B1] [B0]
825 */
826 while (count) {
827 buf->size.x = tmp->size.x;
828 buf->size.y = tmp->size.y;
829 buf->gfx = tmp->gfx;
830
831 if ((buf->size.w != tmp->size.w) || (buf->size.h != tmp->size.h)) {
836 }
837 }
838
839 tmp->gfx = NULL;
840
841 if (count == 1) {
843 }
844
845 tmp = tmp->next;
846 buf = buf->next;
847 count_step--;
848 if (!count_step) {
850 count--;
851 }
852 }
853 /* setup new ActiveWidget pointer */
854 begin = buf->prev;
855 }
856 }
857
858 return begin;
859}
860
861/**********************************************************************/
865{
866 struct up_down *down = (struct up_down *)data;
867
868 if (down->end != down->begin_widget_list) {
869 if (down->vscroll->pscroll_bar
870 && down->vscroll->pscroll_bar->size.y <=
871 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
872
873 /* Draw bcgd */
876
877 if (down->vscroll->pscroll_bar->size.y + down->step >
878 down->vscroll->max - down->vscroll->pscroll_bar->size.h) {
879 down->vscroll->pscroll_bar->size.y =
880 down->vscroll->max - down->vscroll->pscroll_bar->size.h;
881 } else {
882 down->vscroll->pscroll_bar->size.y += down->step;
883 }
884 }
885
888 down->vscroll->active, down->vscroll->step, 1);
889
890 down->end = down->end->prev;
891
893
894 if (down->vscroll->pscroll_bar) {
895 /* Redraw scrollbar */
898 }
900
902 }
903
904 flush_dirty();
905 }
906}
907
908/**********************************************************************/
911static void inside_scroll_up_loop(void *data)
912{
913 struct up_down *up = (struct up_down *)data;
914
915 if (up && up->begin != up->end_widget_list) {
916
917 if (up->vscroll->pscroll_bar
918 && (up->vscroll->pscroll_bar->size.y >= up->vscroll->min)) {
919
920 /* Draw bcgd */
923
924 if (((up->vscroll->pscroll_bar->size.y - up->step) < up->vscroll->min)) {
925 up->vscroll->pscroll_bar->size.y = up->vscroll->min;
926 } else {
927 up->vscroll->pscroll_bar->size.y -= up->step;
928 }
929 }
930
933 up->vscroll->active, up->vscroll->step, -1);
934
936
937 if (up->vscroll->pscroll_bar) {
938 /* Redraw scrollbar */
941 }
944 }
945
946 flush_dirty();
947 }
948}
949
950/**********************************************************************/
954 void *data)
955{
956 struct up_down *motion = (struct up_down *)data;
957 int yrel;
958 int y;
959 int normalized_y;
960 int net_slider_area;
961 int net_count;
962 float scroll_step;
963
964 yrel = motion_event->y - motion->prev_y;
965 motion->prev_x = motion_event->x;
966 motion->prev_y = motion_event->y;
967
968 y = motion_event->y - motion->vscroll->pscroll_bar->dst->dest_rect.y;
969
970 normalized_y = (y - motion->offset);
971
972 net_slider_area = (motion->vscroll->max - motion->vscroll->min - motion->vscroll->pscroll_bar->size.h);
973 net_count = round((float)motion->vscroll->count / motion->vscroll->step) - motion->vscroll->active + 1;
975
976 if ((yrel != 0)
977 && ((normalized_y >= motion->vscroll->min)
979 && (motion->vscroll->pscroll_bar->size.y > motion->vscroll->min)))
980 && ((normalized_y <= motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)
981 || ((normalized_y > motion->vscroll->max)
982 && (motion->vscroll->pscroll_bar->size.y < (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)))) ) {
983 int count;
984
985 /* Draw bcgd */
986 widget_undraw(motion->vscroll->pscroll_bar);
987 widget_mark_dirty(motion->vscroll->pscroll_bar);
988
989 if ((motion->vscroll->pscroll_bar->size.y + yrel) >
990 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h)) {
991
992 motion->vscroll->pscroll_bar->size.y =
993 (motion->vscroll->max - motion->vscroll->pscroll_bar->size.h);
994
995 } else if ((motion->vscroll->pscroll_bar->size.y + yrel) < motion->vscroll->min) {
996 motion->vscroll->pscroll_bar->size.y = motion->vscroll->min;
997 } else {
998 motion->vscroll->pscroll_bar->size.y += yrel;
999 }
1000
1001 count = round((motion->vscroll->pscroll_bar->size.y - motion->old_y) / scroll_step);
1002
1003 if (count != 0) {
1004 int i = count;
1005
1006 while (i != 0) {
1008 motion->begin_widget_list,
1009 motion->end_widget_list,
1010 motion->vscroll->active,
1011 motion->vscroll->step, i);
1012 if (i > 0) {
1013 i--;
1014 } else {
1015 i++;
1016 }
1017 } /* while (i != 0) */
1018
1019 motion->old_y = motion->vscroll->min +
1020 ((round((motion->old_y - motion->vscroll->min) / scroll_step) + count) * scroll_step);
1021
1022 redraw_group(motion->begin_widget_list, motion->end_widget_list, TRUE);
1023 }
1024
1025 /* Redraw slider */
1026 if (get_wflags(motion->vscroll->pscroll_bar) & WF_RESTORE_BACKGROUND) {
1027 refresh_widget_background(motion->vscroll->pscroll_bar);
1028 }
1029 redraw_vert(motion->vscroll->pscroll_bar);
1030 widget_mark_dirty(motion->vscroll->pscroll_bar);
1031
1032 flush_dirty();
1033 }
1034
1035 return ID_ERROR;
1036}
1037
1038/**********************************************************************/
1042 void *data)
1043{
1044 return (Uint16)ID_SCROLLBAR;
1045}
1046
1047/**********************************************************************/
1050static struct widget *down_scroll_widget_list(struct scroll_bar *vscroll,
1051 struct widget *begin_active_widget_list,
1052 struct widget *begin_widget_list,
1053 struct widget *end_widget_list)
1054{
1055 struct up_down down;
1056 struct widget *begin = begin_active_widget_list;
1057 int step = vscroll->active * vscroll->step - 1;
1058
1059 while (step--) {
1060 begin = begin->prev;
1061 }
1062
1063 down.step = get_step(vscroll);
1064 down.begin = begin_active_widget_list;
1065 down.end = begin;
1066 down.begin_widget_list = begin_widget_list;
1067 down.end_widget_list = end_widget_list;
1068 down.vscroll = vscroll;
1069
1072
1073 return down.begin;
1074}
1075
1076/**********************************************************************/
1079static struct widget *up_scroll_widget_list(struct scroll_bar *vscroll,
1080 struct widget *begin_active_widget_list,
1081 struct widget *begin_widget_list,
1082 struct widget *end_widget_list)
1083{
1084 struct up_down up;
1085
1086 up.step = get_step(vscroll);
1087 up.begin = begin_active_widget_list;
1090 up.vscroll = vscroll;
1091
1094
1095 return up.begin;
1096}
1097
1098/**********************************************************************/
1101static struct widget *vertic_scroll_widget_list(struct scroll_bar *vscroll,
1102 struct widget *begin_active_widget_list,
1103 struct widget *begin_widget_list,
1104 struct widget *end_widget_list)
1105{
1106 struct up_down motion;
1107
1109 motion.begin = begin_active_widget_list;
1110 motion.begin_widget_list = begin_widget_list;
1111 motion.end_widget_list = end_widget_list;
1112 motion.vscroll = vscroll;
1113 motion.old_y = vscroll->pscroll_bar->size.y;
1114 SDL_GetMouseState(&motion.prev_x, &motion.prev_y);
1115 motion.offset = motion.prev_y - vscroll->pscroll_bar->dst->dest_rect.y - vscroll->pscroll_bar->size.y;
1116
1117 MOVE_STEP_X = 0;
1118 MOVE_STEP_Y = 3;
1119 /* Filter mouse motion events */
1123 /* Turn off Filter mouse motion events */
1127
1128 return motion.begin;
1129}
1130
1131/* ==================================================================== */
1132
1133/**********************************************************************/
1143 struct widget *new_widget,
1144 struct widget *add_dock,
1145 bool dir,
1146 Sint16 start_x, Sint16 start_y)
1147{
1148 struct widget *buf = NULL;
1149 struct widget *end = NULL, *old_end = NULL;
1150 bool last = FALSE, seen = TRUE;
1151
1152 fc_assert_ret_val(dlg != NULL, FALSE);
1154
1155 if (!add_dock) {
1156 add_dock = dlg->begin_widget_list; /* Last item */
1157 }
1158
1159 dlg->scroll->count++;
1160
1161 if (dlg->scroll->count > (dlg->scroll->active * dlg->scroll->step)) {
1162 /* -> Scrollbar needed */
1163
1164 if (dlg->active_widget_list) {
1165 /* -> Scrollbar is already visible */
1166 int i = 0;
1167
1168 /* Find last active widget */
1169 old_end = add_dock;
1170 while (old_end != dlg->active_widget_list) {
1171 old_end = old_end->next;
1172 i++;
1173 if (old_end == dlg->end_active_widget_list) {
1174 /* Implies (old_end == dlg->active_widget_list)? */
1175 seen = FALSE;
1176 break;
1177 }
1178 }
1179
1180 if (seen) {
1181 int count = (dlg->scroll->active * dlg->scroll->step) - 1;
1182
1183 if (i > count) {
1184 seen = FALSE;
1185 } else {
1186 while (count > 0) {
1187 old_end = old_end->prev;
1188 count--;
1189 }
1190 if (old_end == add_dock) {
1191 last = TRUE;
1192 }
1193 }
1194 }
1195
1196 } else {
1197 last = TRUE;
1199 show_scrollbar(dlg->scroll);
1200 }
1201 }
1202
1203 /* Add pointer to list */
1204 if (dir) {
1205 /* Upper add */
1207
1208 if (add_dock == dlg->end_widget_list) {
1210 }
1211 if (add_dock == dlg->end_active_widget_list) {
1213 }
1214 if (add_dock == dlg->active_widget_list) {
1216 }
1217 } else {
1218 /* Down add */
1220
1221 if (add_dock == dlg->begin_widget_list) {
1223 }
1224
1225 if (add_dock == dlg->begin_active_widget_list) {
1227 }
1228 }
1229
1230 /* Setup draw positions */
1231 if (seen) {
1232 if (!dlg->begin_active_widget_list) {
1233 /* First element ( active list empty ) */
1234 fc_assert_msg(!dir, "Forbidden List Operation");
1235
1236 new_widget->size.x = start_x;
1237 new_widget->size.y = start_y;
1240 if (!dlg->begin_widget_list) {
1243 }
1244 } else {
1245 /* There are some elements on local active list */
1246 if (last) {
1247 /* We add to last seen position */
1248 if (dir) {
1249 /* Only swap add_dock with new_widget on last seen positions */
1250 new_widget->size.x = add_dock->size.x;
1251 new_widget->size.y = add_dock->size.y;
1252 new_widget->gfx = add_dock->gfx;
1253 add_dock->gfx = NULL;
1255 } else {
1256 /* Reposition all widgets */
1257 buf = new_widget;
1258 do {
1259 buf->size.x = buf->next->size.x;
1260 buf->size.y = buf->next->size.y;
1261 buf->gfx = buf->next->gfx;
1262 buf->next->gfx = NULL;
1263 buf = buf->next;
1264 } while (buf != dlg->active_widget_list);
1265 buf->gfx = NULL;
1268 }
1269 } else { /* !last */
1270 buf = new_widget;
1271 /* Find last seen widget */
1272 if (dlg->active_widget_list) {
1273 int count = dlg->scroll->active * dlg->scroll->step - 1;
1274
1275 end = dlg->active_widget_list;
1276 while (count && end != dlg->begin_active_widget_list) {
1277 end = end->prev;
1278 count--;
1279 }
1280 }
1281 while (buf) {
1282 if (buf == dlg->begin_active_widget_list) {
1283 struct widget *tmp = buf;
1284 int count = dlg->scroll->step;
1285
1286 while (count) {
1287 tmp = tmp->next;
1288 count--;
1289 }
1290 buf->size.x = tmp->size.x;
1291 buf->size.y = tmp->size.y + tmp->size.h;
1292 /* Break when last active widget or last seen widget */
1293 break;
1294 } else {
1295 buf->size.x = buf->prev->size.x;
1296 buf->size.y = buf->prev->size.y;
1297 buf->gfx = buf->prev->gfx;
1298 buf->prev->gfx = NULL;
1299 if (buf == end) {
1300 break;
1301 }
1302 }
1303 buf = buf->prev;
1304 }
1305 if (old_end && buf->prev == old_end) {
1307 }
1308 } /* !last */
1309 } /* dlg->begin_active_widget_list */
1310 } else {
1311 /* Not seen */
1313 }
1314
1315 if (dlg->active_widget_list && dlg->scroll->pscroll_bar) {
1318
1319 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1320 if (last) {
1321 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1322 }
1325 }
1326 if (!seen) {
1328 }
1329 }
1330
1331 return last;
1332}
1333
1334/**********************************************************************/
1341 struct widget *pwidget)
1342{
1343 struct widget *buf = pwidget;
1344
1345 fc_assert_ret_val(dlg != NULL, FALSE);
1346
1347 /* If begin == end -> size = 1 */
1349
1350 if (dlg->scroll) {
1351 dlg->scroll->count = 0;
1352 }
1353
1356 }
1357
1358 if (dlg->end_active_widget_list == dlg->end_widget_list) {
1360 }
1361
1363 dlg->active_widget_list = NULL;
1365
1366 widget_undraw(pwidget);
1367 widget_mark_dirty(pwidget);
1368 del_widget_from_gui_list(pwidget);
1369
1370 return FALSE;
1371 }
1372
1373 if (dlg->scroll && dlg->active_widget_list) {
1374 /* Scrollbar exist and active, start mod. from last seen label */
1375 struct widget *last;
1376 bool widget_found = FALSE;
1377 int count;
1378
1379 /* This is always true because no-scrolbar case (active * step < count)
1380 will be supported in other part of code (see "else" part) */
1381 count = dlg->scroll->active * dlg->scroll->step;
1382
1383 /* Find last */
1384 buf = dlg->active_widget_list;
1385 while (count > 0) {
1386 buf = buf->prev;
1387 count--;
1388 }
1389 if (!buf) {
1390 last = dlg->begin_active_widget_list;
1391 } else {
1392 last = buf->next;
1393 }
1394
1395 if (last == dlg->begin_active_widget_list) {
1396 if (dlg->scroll->step == 1) {
1399
1400 /* Look for the widget in the non-visible part */
1402 while (buf != dlg->active_widget_list) {
1403 if (buf == pwidget) {
1405 buf = dlg->active_widget_list;
1406 break;
1407 }
1408 buf = buf->prev;
1409 }
1410
1411 /* If we haven't found it yet, look in the visible part and update the
1412 * positions of the other widgets */
1413 if (!widget_found) {
1414 while (buf != pwidget) {
1415 buf->gfx = buf->prev->gfx;
1416 buf->prev->gfx = NULL;
1417 buf->size.x = buf->prev->size.x;
1418 buf->size.y = buf->prev->size.y;
1419 buf = buf->prev;
1420 }
1421 }
1422 } else {
1423 buf = last;
1424 /* Undraw last widget */
1427 FREESURFACE(buf->gfx);
1428 goto std;
1429 }
1430 } else {
1432
1433std: while (buf != pwidget) {
1434 buf->gfx = buf->next->gfx;
1435 buf->next->gfx = NULL;
1436 buf->size.x = buf->next->size.x;
1437 buf->size.y = buf->next->size.y;
1438 buf = buf->next;
1439 }
1440 }
1441
1442 if ((dlg->scroll->count - 1) <= (dlg->scroll->active * dlg->scroll->step)) {
1443 /* Scrollbar not needed anymore */
1444 hide_scrollbar(dlg->scroll);
1445 dlg->active_widget_list = NULL;
1446 }
1447 dlg->scroll->count--;
1448
1449 if (dlg->active_widget_list) {
1450 if (dlg->scroll->pscroll_bar) {
1452 dlg->scroll->pscroll_bar->size.h = scrollbar_size(dlg->scroll);
1454 }
1455 }
1456
1457 } else {
1458 /* No scrollbar */
1460
1461 /* Undraw last widget */
1464 FREESURFACE(buf->gfx);
1465
1466 while (buf != pwidget) {
1467 buf->gfx = buf->next->gfx;
1468 buf->next->gfx = NULL;
1469 buf->size.x = buf->next->size.x;
1470 buf->size.y = buf->next->size.y;
1471 buf = buf->next;
1472 }
1473
1474 if (dlg->scroll) {
1475 dlg->scroll->count--;
1476 }
1477 }
1478
1479 if (pwidget == dlg->begin_widget_list) {
1480 dlg->begin_widget_list = pwidget->next;
1481 }
1482
1483 if (pwidget == dlg->begin_active_widget_list) {
1484 dlg->begin_active_widget_list = pwidget->next;
1485 }
1486
1487 if (pwidget == dlg->end_active_widget_list) {
1488 if (pwidget == dlg->end_widget_list) {
1489 dlg->end_widget_list = pwidget->prev;
1490 }
1491
1492 if (pwidget == dlg->active_widget_list) {
1493 dlg->active_widget_list = pwidget->prev;
1494 }
1495
1496 dlg->end_active_widget_list = pwidget->prev;
1497
1498 }
1499
1500 if (dlg->active_widget_list && (dlg->active_widget_list == pwidget)) {
1501 dlg->active_widget_list = pwidget->prev;
1502 }
1503
1504 del_widget_from_gui_list(pwidget);
1505
1506 if (dlg->scroll && dlg->scroll->pscroll_bar && dlg->active_widget_list) {
1508 dlg->scroll->pscroll_bar->size.y = get_position(dlg);
1510 }
1511
1512 return TRUE;
1513}
1514
1515/**********************************************************************/
1519{
1520 fc_assert_ret(scroll != NULL);
1521
1522 if (scroll->up_left_button) {
1524 }
1525 if (scroll->down_right_button) {
1527 }
1528 if (scroll->pscroll_bar) {
1530 }
1531}
1532
1533/**************************************************************************
1534 Horizontal Scrollbar
1535**************************************************************************/
1536
1537
1538/**********************************************************************/
1542 Sint16 start_x, Sint16 start_y,
1543 Uint16 width, Uint16 active,
1545 bool swap_start_y)
1546{
1547 Uint16 count = 0;
1548 struct widget *buf = NULL, *pwindow = NULL;
1549
1550 fc_assert_ret_val(dlg != NULL, 0);
1551
1552 pwindow = dlg->end_widget_list;
1553
1554 if (!dlg->scroll) {
1555 dlg->scroll = fc_calloc(1, sizeof(struct scroll_bar));
1556
1557 dlg->scroll->active = active;
1558
1560 while (buf && buf != dlg->begin_active_widget_list->prev) {
1561 buf = buf->prev;
1562 count++;
1563 }
1564
1565 dlg->scroll->count = count;
1566 }
1567
1568 if (create_buttons) {
1569 /* create up button */
1570 buf = create_themeicon_button(current_theme->left_icon, pwindow->dst, NULL, 0);
1571
1572 buf->id = ID_BUTTON;
1573 buf->data.ptr = (void *)dlg;
1575
1576 buf->size.x = start_x;
1577 if (swap_start_y) {
1578 buf->size.y = start_y - buf->size.h;
1579 } else {
1580 buf->size.y = start_y;
1581 }
1582
1583 dlg->scroll->min = start_x + buf->size.w;
1584 dlg->scroll->up_left_button = buf;
1586 dlg->begin_widget_list = buf;
1587
1588 count = buf->size.h;
1589
1590 /* create down button */
1591 buf = create_themeicon_button(current_theme->right_icon, pwindow->dst, NULL, 0);
1592
1593 buf->id = ID_BUTTON;
1594 buf->data.ptr = (void *)dlg;
1596
1597 buf->size.x = start_x + width - buf->size.w;
1598 if (swap_start_y) {
1599 buf->size.y = start_y - buf->size.h;
1600 } else {
1601 buf->size.y = start_y;
1602 }
1603
1604 dlg->scroll->max = buf->size.x;
1607 dlg->begin_widget_list = buf;
1608 }
1609
1610 if (create_scrollbar) {
1611 /* create vscrollbar */
1612 buf = create_horizontal(current_theme->horiz, pwindow->dst,
1614
1615 buf->id = ID_SCROLLBAR;
1616 buf->data.ptr = (void *)dlg;
1618
1619 if (swap_start_y) {
1620 buf->size.y = start_y - buf->size.h;
1621 } else {
1622 buf->size.y = start_y;
1623 }
1624
1625 if (create_buttons) {
1626 buf->size.x = start_x + dlg->scroll->up_left_button->size.w;
1627 if (dlg->scroll->count > dlg->scroll->active) {
1628 buf->size.w = scrollbar_size(dlg->scroll);
1629 } else {
1630 buf->size.w = dlg->scroll->max - dlg->scroll->min;
1631 }
1632 } else {
1633 buf->size.x = start_x;
1634 dlg->scroll->min = start_x;
1635 dlg->scroll->max = start_x + width;
1636 }
1637
1638 dlg->scroll->pscroll_bar = buf;
1640 dlg->begin_widget_list = buf;
1641
1642 if (!count) {
1643 count = buf->size.h;
1644 }
1645 }
1646
1647 return count;
1648}
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:75
QString current_theme
Definition fc_client.cpp:65
void flush_dirty(void)
Definition mapview.c:468
SDL_Surface * crop_rect_from_surface(SDL_Surface *psource, SDL_Rect *prect)
Definition graphics.c:236
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:199
struct sdl2_data main_data
Definition graphics.c:57
int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest, Sint16 dest_x, Sint16 dest_y)
Definition graphics.c:417
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:351
#define FREESURFACE(ptr)
Definition graphics.h:322
@ ID_ERROR
Definition gui_id.h:26
@ ID_BUTTON
Definition gui_id.h:29
@ ID_SCROLLBAR
Definition gui_id.h:32
int FilterMouseMotionEvents(void *data, SDL_Event *event)
Definition gui_main.c:581
Uint16 gui_event_loop(void *data, void(*loop_action)(void *data), Uint16(*key_down_handler)(SDL_Keysym key, void *data), Uint16(*key_up_handler)(SDL_Keysym key, void *data), Uint16(*textinput_handler)(const char *text, void *data), Uint16(*finger_down_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*finger_up_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*finger_motion_handler)(SDL_TouchFingerEvent *touch_event, void *data), Uint16(*mouse_button_down_handler)(SDL_MouseButtonEvent *button_event, void *data), Uint16(*mouse_button_up_handler)(SDL_MouseButtonEvent *button_event, void *data), Uint16(*mouse_motion_handler)(SDL_MouseMotionEvent *motion_event, void *data))
Definition gui_main.c:602
int MOVE_STEP_Y
Definition gui_main.c:105
int MOVE_STEP_X
Definition gui_main.c:104
struct widget * selected_widget
Definition widget.c:48
#define adj_size(size)
Definition gui_main.h:141
#define DEFAULT_MOVE_STEP
Definition gui_main.h:113
#define PRESSED_EVENT(event)
Definition gui_main.h:71
void refresh_widget_background(struct widget *pwidget)
Definition widget.c:1151
void unselect_widget_action(void)
Definition widget.c:418
void widget_add_as_prev(struct widget *new_widget, struct widget *add_dock)
Definition widget.c:602
Uint16 redraw_group(const struct widget *begin_group_widget_list, const struct widget *end_group_widget_list, int add_to_update)
Definition widget.c:720
widget_state
Definition widget.h:95
@ FC_WS_DISABLED
Definition widget.h:99
@ FC_WS_NORMAL
Definition widget.h:96
@ FC_WS_SELECTED
Definition widget.h:97
void clear_wflag(struct widget *pwidget, enum widget_flag flag)
Definition widget_core.c:62
static void widget_mark_dirty(struct widget *pwidget)
Definition widget.h:286
static void widget_flush(struct widget *pwidget)
Definition widget.h:291
enum widget_flag get_wflags(const struct widget *pwidget)
Definition widget_core.c:86
void set_wstate(struct widget *pwidget, enum widget_state state)
Definition widget_core.c:36
enum widget_state get_wstate(const struct widget *pwidget)
Definition widget_core.c:70
static void widget_undraw(struct widget *pwidget)
Definition widget.h:296
@ WF_FREE_GFX
Definition widget.h:70
@ WF_FREE_STRING
Definition widget.h:76
@ WF_RESTORE_BACKGROUND
Definition widget.h:85
@ WF_HIDDEN
Definition widget.h:68
static int widget_redraw(struct widget *pwidget)
Definition widget.h:276
#define del_widget_from_gui_list(__gui)
Definition widget.h:372
void set_wtype(struct widget *pwidget, enum widget_type type)
Definition widget_core.c:45
void set_wflag(struct widget *pwidget, enum widget_flag flag)
Definition widget_core.c:54
@ WT_VSCROLLBAR
Definition widget.h:50
@ WT_HSCROLLBAR
Definition widget.h:51
struct widget * create_themeicon_button(SDL_Surface *icon_theme, struct gui_layer *pdest, utf8_str *pstr, Uint32 flags)
struct widget * widget_new(void)
static int std_vscroll_advanced_dlg_callback(struct widget *pscroll_bar)
static int std_down_advanced_dlg_callback(struct widget *pwidget)
static int redraw_horiz(struct widget *horiz)
static struct widget * vertical_scroll_widget_list(struct widget *active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list, int active, int step, int dir)
static Uint16 scroll_mouse_button_up(SDL_MouseButtonEvent *button_event, void *data)
int draw_vert(struct widget *vert, Sint16 x, Sint16 y)
static int redraw_vert(struct widget *vert)
bool del_widget_from_vertical_scroll_widget_list(struct advanced_dialog *dlg, struct widget *pwidget)
Uint32 create_horizontal_scrollbar(struct advanced_dialog *dlg, Sint16 start_x, Sint16 start_y, Uint16 width, Uint16 active, bool create_scrollbar, bool create_buttons, bool swap_start_y)
#define widget_add_next(new_widget, add_dock)
static struct widget * down_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
struct widget * create_horizontal(SDL_Surface *horiz_theme, struct gui_layer *pdest, Uint16 width, Uint32 flags)
static int(* baseclass_redraw)(struct widget *pwidget)
static struct widget * up_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
static Uint16 scroll_mouse_motion_handler(SDL_MouseMotionEvent *motion_event, void *data)
static struct widget * vertic_scroll_widget_list(struct scroll_bar *vscroll, struct widget *begin_active_widget_list, struct widget *begin_widget_list, struct widget *end_widget_list)
int draw_horiz(struct widget *horiz, Sint16 x, Sint16 y)
void setup_vertical_scrollbar_default_callbacks(struct scroll_bar *scroll)
struct widget * create_vertical(SDL_Surface *vert_theme, struct gui_layer *pdest, Uint16 height, Uint32 flags)
static void inside_scroll_up_loop(void *data)
static int get_position(struct advanced_dialog *dlg)
void setup_vertical_scrollbar_area(struct scroll_bar *scroll, Sint16 start_x, Sint16 start_y, Uint16 height, bool swap_start_x)
bool add_widget_to_vertical_scroll_widget_list(struct advanced_dialog *dlg, struct widget *new_widget, struct widget *add_dock, bool dir, Sint16 start_x, Sint16 start_y)
static void inside_scroll_down_loop(void *data)
static int get_step(struct scroll_bar *scroll)
Uint32 create_vertical_scrollbar(struct advanced_dialog *dlg, Uint8 step, Uint8 active, bool create_scrollbar, bool create_buttons)
static int std_up_advanced_dlg_callback(struct widget *pwidget)
static SDL_Surface * create_vertical_surface(SDL_Surface *vert_theme, enum widget_state state, Uint16 height)
static SDL_Surface * create_horizontal_surface(SDL_Surface *horiz_theme, enum widget_state state, Uint16 width)
#define hide_scrollbar(scrollbar)
#define show_scrollbar(scrollbar)
#define scrollbar_size(scroll)
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_calloc(n, esz)
Definition mem.h:38
int step
Definition specpq.h:92
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
struct widget * begin_active_widget_list
Definition widget.h:184
struct widget * end_widget_list
Definition widget.h:182
struct widget * end_active_widget_list
Definition widget.h:185
struct widget * active_widget_list
Definition widget.h:186
struct scroll_bar * scroll
Definition widget.h:187
struct widget * begin_widget_list
Definition widget.h:181
SDL_Surface * surface
Definition graphics.h:229
SDL_Rect dest_rect
Definition graphics.h:228
struct widget * up_left_button
struct widget * down_right_button
struct widget * pscroll_bar
SDL_Event event
Definition graphics.h:217
struct widget * end
struct widget * end_widget_list
struct widget * begin
struct widget * begin_widget_list
struct scroll_bar * vscroll
union widget::@194 data
SDL_Surface * theme
Definition widget.h:118
struct widget * prev
Definition widget.h:114
struct gui_layer * dst
Definition widget.h:116
struct advanced_dialog * adv_dlg
Definition widget.h:139
int(* action)(struct widget *)
Definition widget.h:157
union widget::@195 private_data
SDL_Surface * gfx
Definition widget.h:120
struct widget * next
Definition widget.h:113
SDL_Rect size
Definition widget.h:145
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47