1 /* Checkbox widget handlers. */
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include "elinks.h"
8
9 #include "bfu/button.h"
10 #include "bfu/checkbox.h"
11 #include "bfu/dialog.h"
12 #include "bfu/text.h"
13 #include "intl/gettext/libintl.h"
14 #include "terminal/draw.h"
15 #include "terminal/mouse.h"
16 #include "terminal/terminal.h"
17
18 #define CHECKBOX_HEIGHT 1
19 #define CHECKBOX_LEN 3 /* "[X]" or "(X)" */
20 #define CHECKBOX_SPACING 1 /* "[X]" + " " + "Label" */
21 #define CHECKBOX_LS (CHECKBOX_LEN + CHECKBOX_SPACING) /* "[X] " */
22
23 void
add_dlg_radio_do(struct dialog * dlg,unsigned char * text,int groupid,int groupnum,int * data)24 add_dlg_radio_do(struct dialog *dlg, unsigned char *text,
25 int groupid, int groupnum, int *data)
26 {
27 struct widget *widget = &dlg->widgets[dlg->number_of_widgets++];
28
29 widget->type = WIDGET_CHECKBOX;
30 widget->text = text;
31 widget->datalen = sizeof(*data);
32 widget->data = (void *) data;
33
34 widget->info.checkbox.gid = groupid;
35 widget->info.checkbox.gnum = groupnum;
36 }
37
38 void
dlg_format_checkbox(struct terminal * term,struct widget_data * widget_data,int x,int * y,int w,int * rw,enum format_align align)39 dlg_format_checkbox(struct terminal *term,
40 struct widget_data *widget_data,
41 int x, int *y, int w, int *rw,
42 enum format_align align)
43 {
44 unsigned char *text = widget_data->widget->text;
45
46 set_box(&widget_data->box, x, *y, CHECKBOX_LEN, CHECKBOX_HEIGHT);
47
48 if (w <= CHECKBOX_LS) return;
49
50 if (text && *text) {
51 if (rw) *rw -= CHECKBOX_LS;
52 dlg_format_text_do(term, text, x + CHECKBOX_LS, y,
53 w - CHECKBOX_LS, rw,
54 get_bfu_color(term, "dialog.checkbox-label"),
55 align);
56 if (rw) *rw += CHECKBOX_LS;
57 }
58 }
59
60 static widget_handler_status_T
display_checkbox(struct dialog_data * dlg_data,struct widget_data * widget_data)61 display_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data)
62 {
63 struct terminal *term = dlg_data->win->term;
64 struct color_pair *color;
65 unsigned char *text;
66 struct box *pos = &widget_data->box;
67 int selected = is_selected_widget(dlg_data, widget_data);
68
69 if (selected) {
70 color = get_bfu_color(term, "dialog.checkbox-selected");
71 } else {
72 color = get_bfu_color(term, "dialog.checkbox");
73 }
74 if (!color) return EVENT_PROCESSED;
75
76 if (widget_data->info.checkbox.checked)
77 text = widget_data->widget->info.checkbox.gid ? "(X)" : "[X]";
78 else
79 text = widget_data->widget->info.checkbox.gid ? "( )" : "[ ]";
80
81 draw_text(term, pos->x, pos->y, text, CHECKBOX_LEN, 0, color);
82
83 if (selected) {
84 set_cursor(term, pos->x + 1, pos->y, 1);
85 set_window_ptr(dlg_data->win, pos->x, pos->y);
86 }
87
88 return EVENT_PROCESSED;
89 }
90
91 static widget_handler_status_T
init_checkbox(struct dialog_data * dlg_data,struct widget_data * widget_data)92 init_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data)
93 {
94 int *cdata = (int *) widget_data->cdata;
95
96 assert(cdata);
97
98 if (widget_data->widget->info.checkbox.gid) {
99 if (*cdata == widget_data->widget->info.checkbox.gnum)
100 widget_data->info.checkbox.checked = 1;
101 } else {
102 if (*cdata)
103 widget_data->info.checkbox.checked = 1;
104 }
105 return EVENT_PROCESSED;
106 }
107
108 static widget_handler_status_T
mouse_checkbox(struct dialog_data * dlg_data,struct widget_data * widget_data)109 mouse_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data)
110 {
111 struct terminal *term = dlg_data->win->term;
112 struct term_event *ev = dlg_data->term_event;
113
114 if (check_mouse_wheel(ev)
115 || !check_mouse_position(ev, &widget_data->box))
116 return EVENT_NOT_PROCESSED;
117
118 select_widget(dlg_data, widget_data);
119
120 do_not_ignore_next_mouse_event(term);
121
122 if (check_mouse_action(ev, B_UP) && widget_data->widget->ops->select)
123 widget_data->widget->ops->select(dlg_data, widget_data);
124
125 return EVENT_PROCESSED;
126 }
127
128 static widget_handler_status_T
select_checkbox(struct dialog_data * dlg_data,struct widget_data * widget_data)129 select_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data)
130 {
131
132 if (!widget_data->widget->info.checkbox.gid) {
133 /* Checkbox. */
134 int *cdata = (int *) widget_data->cdata;
135
136 assert(cdata);
137
138 widget_data->info.checkbox.checked = *cdata = !*cdata;
139
140 } else {
141 /* Group of radio buttons. */
142 struct widget_data *wdata;
143
144 foreach_widget(dlg_data, wdata) {
145 int *cdata = (int *) wdata->cdata;
146
147 if (wdata->widget->type != WIDGET_CHECKBOX)
148 continue;
149
150 if (wdata->widget->info.checkbox.gid
151 != widget_data->widget->info.checkbox.gid)
152 continue;
153
154 assert(cdata);
155
156 *cdata = widget_data->widget->info.checkbox.gnum;
157 wdata->info.checkbox.checked = 0;
158 display_widget(dlg_data, wdata);
159 }
160 widget_data->info.checkbox.checked = 1;
161 }
162
163 display_widget(dlg_data, widget_data);
164 return EVENT_PROCESSED;
165 }
166
167 struct widget_ops checkbox_ops = {
168 display_checkbox,
169 init_checkbox,
170 mouse_checkbox,
171 NULL,
172 select_checkbox,
173 NULL,
174 };
175