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