1 #if ! defined(PROG_DISABLE_GUI) && ! defined(PROG_DISABLE_WIDGET)
2 
3 #include "declarations.h"
4 #include "styles_str.h"
5 #include "widget_helper.h"
6 #include "widget.h"
7 #include "widget_shr.h"
8 #include "widget_defs.h"
9 
10 
11 
widget_init_global(void)12 void widget_init_global(void) {
13 	unsigned int i, j, k;
14 
15 	/* Get the style settings... */
16 #if ! defined(__GNUC__) || (__GNUC__ < 5)
17 	c_shadow_color.pixel.r = WIDGET_SHADOW_RED;
18 	c_shadow_color.pixel.g = WIDGET_SHADOW_GREEN;
19 	c_shadow_color.pixel.b = WIDGET_SHADOW_BLUE;
20 	c_shadow_color.pixel.a = 0;
21 
22 	c_slider_slit_color.pixel.r = WIDGET_SLIDER_SLIT_RED;
23 	c_slider_slit_color.pixel.g = WIDGET_SLIDER_SLIT_GREEN;
24 	c_slider_slit_color.pixel.b = WIDGET_SLIDER_SLIT_BLUE;
25 	c_slider_slit_color.pixel.a = 0;
26 #endif
27 	(void) styles_fetch_all(s_cnf_t);
28 
29 	/* ...and prepare image cache */
30 	for(i = 0; i < WIDGET_GFX_LASTINLINE; i++) {
31 		for(j = 0; j < WIDGET_GFX_TYPES; j++) {
32 			for(k = 0; k < WIDGET_GFX_CACHE; k++) {
33 				widget_predraw[i].c_t[j].c_o[k].c_h = -1.0;
34 			}
35 		}
36 	}
37 }
38 
widget_init_stack(struct w_stack * w)39 int widget_init_stack(struct w_stack *w) {
40 	unsigned int i;
41 
42 	struct w_info *p;
43 
44 	struct widget_stack *s;
45 
46 	/* Check if this id has defined widgets */
47 	if(w->id == 0) return(0);
48 
49 	for(i = 0; ; i++) {
50 		if(widget_def_t[i].stack == NULL) return(0);
51 
52 		if(widget_def_t[i].id == w->id) {
53 			s = widget_def_t[i].stack;
54 
55 			break;
56 		}
57 	}
58 
59 	/* Allocate backbuffer and mouse mask buffer for container window */
60 	if(widget_init_stack_op(w) != 0) return(-1);
61 
62 	/* Create widgets and all their tillbehor */
63 	for(i = 0; ; i++) {
64 		if(s[i].c == WIDGET_TYPE_NONE) break;
65 
66 		if((p = widget_init_stack_alloc(w, s[i].c, s[i].p)) == NULL) return(-1);
67 
68 		if(widget_init_stack_cb_add(p, s[i].cb) != 0) return(-1);
69 		if(widget_init_stack_bob(w, p, w->set, NULL) != 0) return(-1);
70 	}
71 
72 	/* Request container window refresh */
73 	(void) widget_refresh(w);
74 
75 	return(0);
76 }
77 
widget_init_stack_op(struct w_stack * w)78 static int widget_init_stack_op(struct w_stack *w) {
79 	size_t t;
80 
81 	/* Allocate backbuffer */
82 	t = (w->w * w->h) * sizeof(struct pixel_rgba_8);
83 
84 	APP_MALLOC_RET_VALUE(w->bb, t, -1);
85 
86 	(void) memset((void *) w->bb, 0, t);
87 
88 	/* Allocate mouse mask buffer */
89 	t = (w->w * w->h) * sizeof(struct pixel_c_2);
90 
91 	APP_MALLOC_RET_VALUE(w->mb, t, -1);
92 
93 	(void) memset((void *) w->mb, 0, t);
94 
95 	return(0);
96 }
97 
widget_init_stack_alloc(struct w_stack * w,unsigned int c,void * p)98 static struct w_info *widget_init_stack_alloc(struct w_stack *w, unsigned int c, void *p) {
99 	struct w_info **t;
100 
101 	APP_REALLOC_RET_VALUE(t, w->a, sizeof(struct w_info *) * (w->c + 1), NULL);
102 	APP_MALLOC_RET_VALUE(w->a[w->c], sizeof(struct w_info), NULL);
103 
104 	(void) memset((void *) w->a[w->c], 0, sizeof(struct w_info));
105 
106 	w->a[w->c]->c = c;
107 	w->a[w->c]->p = p;
108 
109 	w->a[w->c]->b = NULL;
110 	w->a[w->c]->e = NULL;
111 	w->a[w->c]->f = NULL;
112 
113 	w->a[w->c]->m_f = NULL;
114 
115 	w->a[w->c]->o.c = 0;
116 	w->a[w->c]->o.d = NULL;
117 
118 	w->a[w->c]->cb_pushbutton_push = NULL;
119 	w->a[w->c]->cb_slideswitch_slide = NULL;
120 	w->a[w->c]->cb_toggleswitch_toggle = NULL;
121 	w->a[w->c]->cb_turnswitch_turn = NULL;
122 
123 	w->a[w->c]->par_pushbutton_push.s = NULL;
124 	w->a[w->c]->par_pushbutton_push.n = 0;
125 
126 	w->a[w->c]->par_slideswitch_slide.s = NULL;
127 	w->a[w->c]->par_slideswitch_slide.n = 0;
128 
129 	w->a[w->c]->par_toggleswitch_toggle.s = NULL;
130 	w->a[w->c]->par_toggleswitch_toggle.n = 0;
131 
132 	w->a[w->c]->par_turnswitch_turn.s = NULL;
133 	w->a[w->c]->par_turnswitch_turn.n = 0;
134 
135 	w->a[w->c]->cb_generic_key_press = NULL;
136 	w->a[w->c]->cb_generic_key_release = NULL;
137 	w->a[w->c]->cb_generic_button_press = NULL;
138 	w->a[w->c]->cb_generic_button_release = NULL;
139 
140 	w->a[w->c]->par_generic_key_press.s = NULL;
141 	w->a[w->c]->par_generic_key_press.n = 0;
142 	w->a[w->c]->par_generic_key_release.s = NULL;
143 	w->a[w->c]->par_generic_key_release.n = 0;
144 	w->a[w->c]->par_generic_button_press.s = NULL;
145 	w->a[w->c]->par_generic_button_press.n = 0;
146 	w->a[w->c]->par_generic_button_release.s = NULL;
147 	w->a[w->c]->par_generic_button_release.n = 0;
148 
149 	return(w->a[w->c++]);
150 }
151 
widget_init_stack_bob(struct w_stack * w,struct w_info * d,unsigned int set,char * b)152 static int widget_init_stack_bob(struct w_stack *w, struct w_info *d, unsigned int set, char *b) {
153 	unsigned int e, f;
154 	unsigned int a_w, a_h;
155 
156 	size_t t;
157 
158 	struct pixel_rgba_8 c;
159 
160 	struct t_img *r;
161 
162 	struct widget_type_background *w_ba;
163 	struct widget_type_block *w_bl;
164 	struct widget_type_label *w_la;
165 	struct widget_type_lamp *w_lm;
166 	struct widget_type_slideswitch *w_ss;
167 	struct widget_type_toggleswitch *w_ts;
168 	struct widget_type_turnswitch *w_tw;
169 
170 	switch(d->c) {
171 		case WIDGET_TYPE_BACKGROUND:
172 			w_ba = (struct widget_type_background *) d->p;
173 
174 			if(w_ba->set != 0 && w_ba->set != set) break;
175 
176 			/* Background always covers full window */
177 			w_ba->p.x = 0;
178 			w_ba->p.y = 0;
179 			w_ba->p.w = 0;
180 			w_ba->p.h = 0;
181 
182 			if(w_ba->s != NULL) {
183 				/* Make a copy of image file name so it can be free'd later */
184 				if((w_ba->s = widget_strcpy(b, w_ba->s)) == NULL) {
185 					return(-1);
186 				}
187 
188 				/* Fill background with image */
189 				if((r = image_read(w_ba->s, 0)) == NULL) {
190 					return(-1);
191 				}
192 
193 				if(widget_init_stack_bob_av_noalpha(w, d, &w_ba->p, r, w_ba->ch, w_ba->cv) != 0) {
194 					(void) image_free(r);
195 
196 					return(-1);
197 				}
198 
199 				(void) image_free(r);
200 			}
201 			else {
202 				if(w_ba->c.pixel.a == 0xff) {
203 					/* Fill background using solid color... */
204 					if(widget_init_stack_bob_au_noalpha(w, d, &w_ba->p, &w_ba->c) != 0) {
205 						return(-1);
206 					}
207 				}
208 				else {
209 					/* ...or get the background from root window */
210 					if((r = window_get_obscure(w->hnd, w->w, w->h, &w_ba->c)) == NULL) {
211 						return(-1);
212 					}
213 
214 					if(widget_init_stack_bob_av_noalpha(w, d, &w_ba->p, r, w_ba->ch, w_ba->cv) != 0) {
215 						(void) image_free(r);
216 
217 						return(-1);
218 					}
219 
220 					(void) image_free(r);
221 				}
222 			}
223 
224 			(void) widget_init_stack_bob_sets(w, d);
225 
226 			/* Copy background content to backbuffer */
227 			t = (w->w * w->h) * sizeof(struct pixel_rgba_8);
228 
229 			(void) memcpy((void *) w->bb, (const void *) d->m_f, t);
230 
231 			/* Store background widget mouse mask id for later use */
232 			w->q.c = d->m_id.c;
233 
234 			break;
235 		case WIDGET_TYPE_BLOCK:
236 			w_bl = (struct widget_type_block *) d->p;
237 
238 			if(w_bl->set != 0 && w_bl->set != set) break;
239 
240 			if(w_bl->s != NULL) {
241 				/* Make a copy of image file name so it can be free'd later */
242 				if((w_bl->s = widget_strcpy(b, w_bl->s)) == NULL) {
243 					return(-1);
244 				}
245 
246 				/* Fill block with image */
247 				if((r = image_read(w_bl->s, 0)) == NULL) {
248 					return(-1);
249 				}
250 
251 				if(widget_init_stack_bob_av(w, d, &w_bl->p, r) != 0) {
252 					(void) image_free(r);
253 
254 					return(-1);
255 				}
256 
257 				(void) image_free(r);
258 
259 				/* Copy image to storebuffer so it can be restored if needed */
260 				if((w_bl->u = widget_init_stack_bob_store(d->m_f, d->t)) == NULL) {
261 					return(-1);
262 				}
263 
264 				(void) widget_init_stack_bob_av_border(d, &w_bl->p, &w_bl->b, w_bl->d);
265 				(void) widget_init_stack_bob_copy(w, d);
266 			}
267 			else {
268 				/* Fill block using solid color */
269 				if(widget_init_stack_bob_au(w, d, &w_bl->p, &w_bl->c, &w_bl->b, w_bl->d) != 0) {
270 					return(-1);
271 				}
272 			}
273 
274 			(void) widget_init_stack_bob_sets(w, d);
275 			(void) widget_init_stack_collision(w, d, &w_bl->e, &w_bl->p);
276 
277 			break;
278 		case WIDGET_TYPE_LABEL:
279 			w_la = (struct widget_type_label *) d->p;
280 
281 			if(w_la->set != 0 && w_la->set != set) break;
282 
283 			if(widget_init_stack_bob_af(w, d, &w_la->t, &w_la->p) != 0) {
284 				return(-1);
285 			}
286 
287 			(void) widget_init_stack_bob_sets(w, d);
288 			(void) widget_init_stack_collision(w, d, &w_la->e, &w_la->p);
289 
290 			break;
291 		case WIDGET_TYPE_LAMP:
292 			w_lm = (struct widget_type_lamp *) d->p;
293 
294 			if(w_lm->set != 0 && w_lm->set != set) break;
295 
296 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_LAMP, w_lm->o);
297 
298 			if(widget_init_stack_bob_at(w, d, &w_lm->t, &w_lm->p, NULL, WIDGET_GFX_LAMP,
299 				w_lm->o, w_lm->ch, w_lm->k, w_lm->a, w_lm->b, w_lm->c, w_lm->d,
300 				w_lm->ox, w_lm->oy, (double) (e / WIDGET_FRAME_LAMP_ANGLES)) != 0) return(-1);
301 
302 			(void) widget_init_stack_bob_copy(w, d);
303 			(void) widget_init_stack_bob_mask(w, d, WIDGET_GFX_LAMP, w_lm->o);
304 			(void) widget_init_stack_collision(w, d, &w_lm->e, &w_lm->p);
305 
306 			break;
307 		case WIDGET_TYPE_LED_1:
308 			if(widget_init_stack_bob_le(w, d, set, WIDGET_GFX_LED_1) != 0) {
309 				return(-1);
310 			}
311 
312 			break;
313 		case WIDGET_TYPE_LED_2:
314 			if(widget_init_stack_bob_le(w, d, set, WIDGET_GFX_LED_2) != 0) {
315 				return(-1);
316 			}
317 
318 			break;
319 		case WIDGET_TYPE_LED_3:
320 			if(widget_init_stack_bob_le(w, d, set, WIDGET_GFX_LED_3) != 0) {
321 				return(-1);
322 			}
323 
324 			break;
325 		case WIDGET_TYPE_PUSHBUTTON_1:
326 			if(widget_init_stack_bob_pb(w, d, set, WIDGET_GFX_PUSHBUTTON_1) != 0) {
327 				return(-1);
328 			}
329 
330 			break;
331 		case WIDGET_TYPE_PUSHBUTTON_2:
332 			if(widget_init_stack_bob_pb(w, d, set, WIDGET_GFX_PUSHBUTTON_2) != 0) {
333 				return(-1);
334 			}
335 
336 			break;
337 		case WIDGET_TYPE_PUSHBUTTON_3:
338 			if(widget_init_stack_bob_pb(w, d, set, WIDGET_GFX_PUSHBUTTON_3) != 0) {
339 				return(-1);
340 			}
341 
342 			break;
343 		case WIDGET_TYPE_SLIDESWITCH:
344 			w_ss = (struct widget_type_slideswitch *) d->p;
345 
346 			if(w_ss->set != 0 && w_ss->set != set) break;
347 
348 			/* Store slider current position to prevent overwriting */
349 			f = w_ss->d;
350 
351 			(void) widget_init_stack_bob_predraw_size(WIDGET_GFX_SLIDESWITCH,
352 				w_ss->o, &a_w, &a_h, NULL, NULL);
353 
354 			/* Allocate either vertical or horizontal container */
355 			if(w_ss->o % 2 == 0) {
356 				w_ss->p.w = a_w + w_ss->b;
357 				w_ss->p.h = a_h;
358 			}
359 			else {
360 				w_ss->p.w = a_w;
361 				w_ss->p.h = a_h + w_ss->b;
362 			}
363 
364 			/* Store container geometry for positioning the title relative to it */
365 			w_ss->q.x = w_ss->p.x;
366 			w_ss->q.y = w_ss->p.y;
367 			w_ss->q.w = w_ss->p.w;
368 			w_ss->q.h = w_ss->p.h;
369 
370 			c.pixel.p = 0;
371 
372 			(void) widget_init_stack_bob_au(w, d, &w_ss->p, &c, &c, 0);
373 			(void) widget_init_stack_bob_sets(w, d);
374 			(void) widget_init_stack_collision(w, d, &w_ss->e, &w_ss->p);
375 
376 			if(widget_init_stack_bob_at(w, d, &w_ss->t, &w_ss->p, &w_ss->q, WIDGET_GFX_SLIDESWITCH,
377 				w_ss->o, w_ss->ch, w_ss->k, w_ss->a, w_ss->b, w_ss->c, w_ss->d,
378 				w_ss->ox, w_ss->oy, 0.0) != 0) return(-1);
379 
380 			/* Restore slider current position and adjust its initial placement */
381 			w_ss->d = f;
382 
383 			if(w_ss->o % 2 == 0) {
384 				(void) widget_init_stack_bob_sl_h(w, d, w_ss);
385 
386 				d->x = w_ss->p.x + (unsigned int) round(maths_map((double) w_ss->d,
387 					0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
388 			}
389 			else {
390 				(void) widget_init_stack_bob_sl_v(w, d, w_ss);
391 
392 				d->y = w_ss->p.y + w_ss->b - (unsigned int) round(maths_map((double) w_ss->d,
393 					0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
394 			}
395 
396 			(void) widget_init_stack_bob_copy(w, d);
397 
398 			break;
399 		case WIDGET_TYPE_TOGGLESWITCH:
400 			w_ts = (struct widget_type_toggleswitch *) d->p;
401 
402 			if(w_ts->set != 0 && w_ts->set != set) break;
403 
404 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TOGGLESWITCH, w_ts->o);
405 
406 			if(widget_init_stack_bob_at(w, d, &w_ts->t, &w_ts->p, NULL, WIDGET_GFX_TOGGLESWITCH,
407 				w_ts->o, w_ts->ch, w_ts->k, w_ts->a, w_ts->b, w_ts->c, w_ts->d,
408 				w_ts->ox, w_ts->oy, (double) (e / WIDGET_FRAME_TOGGLESWITCH_ANGLES)) != 0) return(-1);
409 
410 			(void) widget_init_stack_bob_copy(w, d);
411 			(void) widget_init_stack_bob_mask(w, d, WIDGET_GFX_TOGGLESWITCH, w_ts->o);
412 			(void) widget_init_stack_collision(w, d, &w_ts->e, &w_ts->p);
413 
414 			break;
415 		case WIDGET_TYPE_TURNSWITCH:
416 			w_tw = (struct widget_type_turnswitch *) d->p;
417 
418 			if(w_tw->set != 0 && w_tw->set != set) break;
419 
420 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TURNSWITCH, w_tw->o);
421 
422 			if(widget_init_stack_bob_at(w, d, &w_tw->t, &w_tw->p, NULL, WIDGET_GFX_TURNSWITCH,
423 				w_tw->o, w_tw->ch, w_tw->k, w_tw->a, w_tw->b, w_tw->c, w_tw->d,
424 				w_tw->ox, w_tw->oy, (double) (e / WIDGET_FRAME_TURNSWITCH_ANGLES)) != 0) return(-1);
425 
426 			(void) widget_init_stack_bob_copy(w, d);
427 			(void) widget_init_stack_bob_mask(w, d, WIDGET_GFX_TURNSWITCH, w_tw->o);
428 			(void) widget_init_stack_collision(w, d, &w_tw->e, &w_tw->p);
429 
430 			break;
431 		default:
432 			(void) flush_error();
433 
434 			LOGWARN(
435 				ERROR_SLIGHT, SUBSYSTEM,
436 				_("Widget type %u is unknown, please check widget definitions"),
437 				d->c
438 			);
439 
440 			return(-1);
441 	}
442 
443 	return(0);
444 }
445 
widget_init_stack_bob_le(struct w_stack * w,struct w_info * d,unsigned int set,unsigned int g)446 static int widget_init_stack_bob_le(struct w_stack *w, struct w_info *d, unsigned int set, unsigned int g) {
447 	unsigned int e;
448 
449 	struct widget_type_led *w_le;
450 
451 	w_le = (struct widget_type_led *) d->p;
452 
453 	if(w_le->set != 0 && w_le->set != set) return(0);
454 
455 	e = widget_init_stack_bob_predraw_frame(g, w_le->o);
456 
457 	if(widget_init_stack_bob_at(w, d, &w_le->t, &w_le->p, NULL, g,
458 		w_le->o, w_le->ch, w_le->k, w_le->a, w_le->b, w_le->c, w_le->d,
459 		w_le->ox, w_le->oy, (double) (e / WIDGET_FRAME_LED_ANGLES)) != 0) return(-1);
460 
461 	(void) widget_init_stack_bob_copy(w, d);
462 	(void) widget_init_stack_bob_mask(w, d, g, w_le->o);
463 	(void) widget_init_stack_collision(w, d, &w_le->e, &w_le->p);
464 
465 	return(0);
466 }
467 
widget_init_stack_bob_pb(struct w_stack * w,struct w_info * d,unsigned int set,unsigned int g)468 static int widget_init_stack_bob_pb(struct w_stack *w, struct w_info *d, unsigned int set, unsigned int g) {
469 	unsigned int e;
470 
471 	struct widget_type_pushbutton *w_pb;
472 
473 	w_pb = (struct widget_type_pushbutton *) d->p;
474 
475 	if(w_pb->set != 0 && w_pb->set != set) return(0);
476 
477 	e = widget_init_stack_bob_predraw_frame(g, w_pb->o);
478 
479 	if(widget_init_stack_bob_at(w, d, &w_pb->t, &w_pb->p, NULL, g,
480 		w_pb->o, w_pb->ch, w_pb->k, w_pb->a, w_pb->b, w_pb->c, w_pb->d,
481 		w_pb->ox, w_pb->oy, (double) (e / WIDGET_FRAME_PUSHBUTTON_ANGLES)) != 0) return(-1);
482 
483 	(void) widget_init_stack_bob_copy(w, d);
484 	(void) widget_init_stack_bob_mask(w, d, g, w_pb->o);
485 	(void) widget_init_stack_collision(w, d, &w_pb->e, &w_pb->p);
486 
487 	return(0);
488 }
489 
widget_init_stack_bob_sl_h(struct w_stack * w,struct w_info * d,struct widget_type_slideswitch * w_ss)490 static void widget_init_stack_bob_sl_h(struct w_stack *w, struct w_info *d, struct widget_type_slideswitch *w_ss) {
491 	unsigned int i, j, k, c, o, x;
492 
493 	uint8_t a[WIDGET_SLIDER_SLIT_WIDTH] = {
494 		96, 200, 160, 160, 180, 48
495 	};
496 
497 	struct pixel_rgba_8 p_a;
498 	struct pixel_rgba_8 *m, *n;
499 
500 	struct w_info *b;
501 
502 	/* Background must exists */
503 	if((d->b = widget_get_info_by_id(w, (unsigned int) w->q.c)) == NULL) {
504 		return;
505 	}
506 
507 	b = d->b;
508 
509 	/* Widget container must be inside the background area */
510 	if(w_ss->q.x < 0 || w_ss->q.x + w_ss->q.w >= b->w || w_ss->q.y < 0 || w_ss->q.y + w_ss->q.h >= b->h) {
511 		return;
512 	}
513 
514 	p_a.pixel.p = c_slider_slit_color.pixel.p;
515 
516 	c = (w_ss->q.h - WIDGET_SLIDER_SLIT_WIDTH) / 2;
517 	o = w_ss->p.w / 2;
518 
519 	/* Draw horizontal slit... */
520 	m = b->m_f + (w_ss->q.y * b->w) + w_ss->q.x;
521 	n = w->bb + (w_ss->q.y * b->w) + w_ss->q.x;
522 
523 	for(i = 0; i < WIDGET_SLIDER_SLIT_WIDTH; i++) {
524 		k = (i + c) * b->w;
525 
526 		for(j = o; j < w_ss->q.w - o; j++) {
527 			x = k + j;
528 
529 			m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[i]);
530 			n[x].pixel.p = m[x].pixel.p;
531 		}
532 	}
533 
534 	/* ...and trim the ends, first left... */
535 	m = b->m_f + (w_ss->q.y * b->w) + (w_ss->q.x + o - 1);
536 	n = w->bb + (w_ss->q.y * b->w) + (w_ss->q.x + o - 1);
537 
538 	for(i = 0; i < WIDGET_SLIDER_SLIT_WIDTH; i++) {
539 		x = (i + c) * b->w;
540 
541 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
542 		n[x].pixel.p = m[x].pixel.p;
543 	}
544 
545 	m = b->m_f + (w_ss->q.y * b->w) + (w_ss->q.x + o);
546 	n = w->bb + (w_ss->q.y * b->w) + (w_ss->q.x + o);
547 
548 	for(i = 1; i < WIDGET_SLIDER_SLIT_WIDTH - 1; i++) {
549 		x = (i + c) * b->w;
550 
551 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
552 		n[x].pixel.p = m[x].pixel.p;
553 	}
554 
555 	/* ...and the right */
556 	m = b->m_f + (w_ss->q.y * b->w) + (w_ss->q.x + w_ss->q.w - o);
557 	n = w->bb + (w_ss->q.y * b->w) + (w_ss->q.x + w_ss->q.w - o);
558 
559 	for(i = 0; i < WIDGET_SLIDER_SLIT_WIDTH; i++) {
560 		x = (i + c) * b->w;
561 
562 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
563 		n[x].pixel.p = m[x].pixel.p;
564 	}
565 
566 	m = b->m_f + (w_ss->q.y * b->w) + (w_ss->q.x + w_ss->q.w - o - 1);
567 	n = w->bb + (w_ss->q.y * b->w) + (w_ss->q.x + w_ss->q.w - o - 1);
568 
569 	for(i = 1; i < WIDGET_SLIDER_SLIT_WIDTH - 1; i++) {
570 		x = (i + c) * b->w;
571 
572 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
573 		n[x].pixel.p = m[x].pixel.p;
574 	}
575 }
576 
widget_init_stack_bob_sl_v(struct w_stack * w,struct w_info * d,struct widget_type_slideswitch * w_ss)577 static void widget_init_stack_bob_sl_v(struct w_stack *w, struct w_info *d, struct widget_type_slideswitch *w_ss) {
578 	unsigned int i, j, k, c, o, x;
579 
580 	uint8_t a[WIDGET_SLIDER_SLIT_WIDTH] = {
581 		96, 200, 160, 160, 180, 48
582 	};
583 
584 	struct pixel_rgba_8 p_a;
585 	struct pixel_rgba_8 *m, *n;
586 
587 	struct w_info *b;
588 
589 	/* Background must exists */
590 	if((d->b = widget_get_info_by_id(w, (unsigned int) w->q.c)) == NULL) {
591 		return;
592 	}
593 
594 	b = d->b;
595 
596 	/* Widget container must be inside the background area */
597 	if(w_ss->q.x < 0 || w_ss->q.x + w_ss->q.w >= b->w || w_ss->q.y < 0 || w_ss->q.y + w_ss->q.h >= b->h) {
598 		return;
599 	}
600 
601 	p_a.pixel.p = c_slider_slit_color.pixel.p;
602 
603 	c = (w_ss->q.w - WIDGET_SLIDER_SLIT_WIDTH) / 2;
604 	o = w_ss->p.h / 2;
605 
606 	/* Draw vertical slit... */
607 	m = b->m_f + (w_ss->q.y * b->w) + w_ss->q.x;
608 	n = w->bb + (w_ss->q.y * b->w) + w_ss->q.x;
609 
610 	for(i = o; i < w_ss->q.h - o; i++) {
611 		k = i * b->w;
612 
613 		for(j = 0; j < WIDGET_SLIDER_SLIT_WIDTH; j++) {
614 			x = k + c + j;
615 
616 			m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[j]);
617 			n[x].pixel.p = m[x].pixel.p;
618 		}
619 	}
620 
621 	/* ...and trim the ends, first upper... */
622 	m = b->m_f + ((w_ss->q.y + o - 1) * b->w) + w_ss->q.x;
623 	n = w->bb + ((w_ss->q.y + o - 1) * b->w) + w_ss->q.x;
624 
625 	for(i = 0; i < WIDGET_SLIDER_SLIT_WIDTH; i++) {
626 		x = c + i;
627 
628 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
629 		n[x].pixel.p = m[x].pixel.p;
630 	}
631 
632 	m = b->m_f + ((w_ss->q.y + o) * b->w) + w_ss->q.x;
633 	n = w->bb + ((w_ss->q.y + o) * b->w) + w_ss->q.x;
634 
635 	for(i = 1; i < WIDGET_SLIDER_SLIT_WIDTH - 1; i++) {
636 		x = c + i;
637 
638 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[1]);
639 		n[x].pixel.p = m[x].pixel.p;
640 	}
641 
642 	/* ...and the lower */
643 	m = b->m_f + ((w_ss->q.y + w_ss->q.h - o) * b->w) + w_ss->q.x;
644 	n = w->bb + ((w_ss->q.y + w_ss->q.h - o) * b->w) + w_ss->q.x;
645 
646 	for(i = 0; i < WIDGET_SLIDER_SLIT_WIDTH; i++) {
647 		x = c + i;
648 
649 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[0]);
650 		n[x].pixel.p = m[x].pixel.p;
651 	}
652 
653 	m = b->m_f + ((w_ss->q.y + w_ss->q.h - o - 1) * b->w) + w_ss->q.x;
654 	n = w->bb + ((w_ss->q.y + w_ss->q.h - o - 1) * b->w) + w_ss->q.x;
655 
656 	for(i = 1; i < WIDGET_SLIDER_SLIT_WIDTH - 1; i++) {
657 		x = c + i;
658 
659 		m[x].pixel.p = draw_pixel_alpha_rgba_8(m[x].pixel.p, p_a.pixel.p, (uint32_t) a[5]);
660 		n[x].pixel.p = m[x].pixel.p;
661 	}
662 }
663 
widget_init_stack_bob_af(struct w_stack * w,struct w_info * d,struct widget_title * t,struct widget_geometry * p)664 static int widget_init_stack_bob_af(struct w_stack *w, struct w_info *d, struct widget_title *t, struct widget_geometry *p) {
665 	if(t->s == NULL) return(0);
666 
667 	if(widget_init_stack_bob_text_render(d, t) != 0) return(-1);
668 
669 	p->w = fonts_get_width(t->f);
670 	p->h = fonts_get_height(t->f);
671 
672 	(void) widget_init_stack_bob_ag_x(t, p, p->x, p->w * 2);
673 
674 	t->i.y = p->y;
675 	t->i.f = t->f;
676 
677 	(void) widget_init_stack_bob_text(w, t);
678 
679 	return(0);
680 }
681 
widget_init_stack_bob_ag(struct w_stack * w,struct w_info * d,struct widget_title * t,struct widget_geometry * p,unsigned int k,int o_x,int o_y)682 static int widget_init_stack_bob_ag(struct w_stack *w, struct w_info *d, struct widget_title *t, struct widget_geometry *p, unsigned int k, int o_x, int o_y) {
683 	int x, y;
684 	unsigned int u, v;
685 
686 	/* Leave if string is empty or text is already rendered */
687 	if(t->s == NULL || t->q == IS_YES) return(0);
688 
689 	if(widget_init_stack_bob_text_render(d, t) != 0) return(-1);
690 
691 	x = p->x;
692 	y = p->y;
693 
694 	u = fonts_get_width(t->f);
695 	v = fonts_get_height(t->f);
696 
697 	(void) widget_init_stack_bob_ag_x(t, p, x, u);
698 	(void) widget_init_stack_bob_ag_y(t, p, x, y, u, v, k);
699 
700 	/* Adjust finetune offsets for title */
701 	t->i.x += o_x;
702 	t->i.y += o_y;
703 
704 	t->i.f = t->f;
705 
706 	(void) widget_init_stack_bob_text(w, t);
707 
708 	/* Tag this label as rendered */
709 	t->q = IS_YES;
710 
711 	return(0);
712 }
713 
widget_init_stack_bob_ag_x(struct widget_title * t,struct widget_geometry * p,int x,unsigned int u)714 static void widget_init_stack_bob_ag_x(struct widget_title *t, struct widget_geometry *p, int x, unsigned int u) {
715 	switch(t->j) {
716 		case WIDGET_TITLE_JUSTIFICATION_LEFT:
717 			t->i.x = x;
718 
719 			break;
720 		case WIDGET_TITLE_JUSTIFICATION_RIGHT:
721 			t->i.x = x - u + p->w;
722 
723 			break;
724 		case WIDGET_TITLE_JUSTIFICATION_CENTER:
725 			t->i.x = x - (u / 2) + (p->w / 2);
726 
727 			break;
728 		default:
729 			break;
730 	}
731 }
732 
widget_init_stack_bob_ag_y(struct widget_title * t,struct widget_geometry * p,int x,int y,unsigned int u,unsigned int v,unsigned int k)733 static void widget_init_stack_bob_ag_y(struct widget_title *t, struct widget_geometry *p, int x, int y, unsigned int u, unsigned int v, unsigned int k) {
734 	switch(k) {
735 		case WIDGET_TITLE_POSITION_ABOVE:
736 			t->i.y = y - v;
737 
738 			break;
739 		case WIDGET_TITLE_POSITION_BELOW:
740 			t->i.y = y + p->h;
741 
742 			break;
743 		case WIDGET_TITLE_POSITION_LEFTSIDE:
744 			t->i.x = x - u;
745 			t->i.y = y + ((p->h - v) / 2);
746 
747 			break;
748 		case WIDGET_TITLE_POSITION_RIGHTSIDE:
749 			t->i.x = x + p->w;
750 			t->i.y = y + ((p->h - v) / 2);
751 
752 			break;
753 		default:
754 			break;
755 	}
756 }
757 
widget_init_stack_bob_at(struct w_stack * w,struct w_info * d,struct widget_title * t,struct widget_geometry * p,struct widget_geometry * q,unsigned int a,unsigned int k,float f,unsigned int w_k,unsigned int w_a,unsigned int w_b,unsigned int w_c,unsigned int w_d,int o_x,int o_y,double w_t)758 static int widget_init_stack_bob_at(struct w_stack *w, struct w_info *d, struct widget_title *t, struct widget_geometry *p, struct widget_geometry *q, unsigned int a, unsigned int k, float f, unsigned int w_k, unsigned int w_a, unsigned int w_b, unsigned int w_c, unsigned int w_d, int o_x, int o_y, double w_t) {
759 	unsigned int a_w, a_h, b_w, b_h;
760 
761 	int k_x, k_y;
762 
763 	struct widget_geometry b;
764 
765 	struct t_img *m_i, *m_s;
766 
767 	(void) widget_init_stack_bob_predraw_size(a, k, &a_w, &a_h, &b_w, &b_h);
768 	(void) widget_init_stack_bob_predraw_offset(a, k, &k_x, &k_y);
769 
770 	/* Append shadow offset to its size */
771 	b_w += abs(k_x);
772 	b_h += abs(k_y);
773 
774 	p->w = a_w;
775 	p->h = a_h;
776 
777 	/* Use larger, widget or shadow, geometry area as allocation geometry */
778 	if(a_w * a_h > b_w * b_h) {
779 		b.w = a_w;
780 		b.h = a_h;
781 	}
782 	else {
783 		b.w = b_w;
784 		b.h = b_h;
785 	}
786 
787 	b.x = p->x;
788 	b.y = p->y;
789 
790 	/* Use another geometry for title if supplied */
791 	if(q == NULL) q = p;
792 
793 	if(widget_init_stack_bob_ag(w, d, t, q, w_k, o_x, o_y) != 0) return(-1);
794 	if(widget_init_stack_bob_op(d, &b) != 0) return(-1);
795 
796 	if(widget_init_stack_bob_predraw(a, k, f, &m_i, &m_s) != 0) return(-1);
797 
798 	(void) widget_init_stack_bob_content(a, k, d, m_i->p, m_s->p, d->m_f,
799 		widget_init_stack_bob_frame(w_a, w_b, w_c, w_d, w_t));
800 
801 	return(0);
802 }
803 
widget_init_stack_bob_au(struct w_stack * w,struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * c,struct pixel_rgba_8 * b,unsigned int h)804 static int widget_init_stack_bob_au(struct w_stack *w, struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *c, struct pixel_rgba_8 *b, unsigned int h) {
805 	int x, y, e, f;
806 
807 	if(p->w == 0) p->w = w->w;
808 	if(p->h == 0) p->h = w->h;
809 
810 	d->m_f = NULL;
811 
812 	d->t = 0;
813 
814 	d->x = p->x;
815 	d->y = p->y;
816 	d->w = p->w;
817 	d->h = p->h;
818 
819 	(void) widget_init_stack_bob_fill_border(w, d, b, h);
820 
821 	/* Fill area must be smaller because of border to avoid overlapping */
822 	x = d->x + h;
823 	y = d->y + h;
824 	e = d->w - (h * 2);
825 	f = d->h - (h * 2);
826 
827 	(void) widget_init_stack_bob_fill(w, d, c, x, y, e, f);
828 
829 	return(0);
830 }
831 
widget_init_stack_bob_au_noalpha(struct w_stack * w,struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * c)832 static int widget_init_stack_bob_au_noalpha(struct w_stack *w, struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *c) {
833 	unsigned int i, j, k;
834 
835 	if(p->w == 0) p->w = w->w;
836 	if(p->h == 0) p->h = w->h;
837 
838 	if(widget_init_stack_bob_op(d, p) != 0) return(-1);
839 
840 	/* Fill backbuffer using background color */
841 	for(i = 0; i < p->h; i++) {
842 		k = p->w * i;
843 
844 		for(j = 0; j < p->w; j++) {
845 			d->m_f[k + j].pixel.p = c->pixel.p;
846 		}
847 	}
848 
849 	(void) widget_init_stack_bob_fill_noalpha(w, d, c);
850 
851 	return(0);
852 }
853 
widget_init_stack_bob_aw(struct w_stack * w,struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * r,unsigned int e,unsigned int f)854 static int widget_init_stack_bob_aw(struct w_stack *w, struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *r, unsigned int e, unsigned int f) {
855 	if(p->w == 0) p->w = w->w;
856 	if(p->h == 0) p->h = w->h;
857 
858 	(void) widget_init_stack_bob_av_op(d, p,
859 		r, p->h / f, p->w / e, p->h % f, p->w % e,
860 		e, f);
861 
862 	return(0);
863 }
864 
widget_init_stack_bob_av(struct w_stack * w,struct w_info * d,struct widget_geometry * p,struct t_img * r)865 static int widget_init_stack_bob_av(struct w_stack *w, struct w_info *d, struct widget_geometry *p, struct t_img *r) {
866 	if(p->w == 0) p->w = w->w;
867 	if(p->h == 0) p->h = w->h;
868 
869 	if(widget_init_stack_bob_op(d, p) != 0) return(-1);
870 
871 	(void) widget_init_stack_bob_av_op(d, p,
872 		r->p, p->h / r->h, p->w / r->w, p->h % r->h, p->w % r->w,
873 		(unsigned int) r->w, (unsigned int) r->h);
874 
875 	return(0);
876 }
877 
widget_init_stack_bob_av_noalpha(struct w_stack * w,struct w_info * d,struct widget_geometry * p,struct t_img * r,float f,float v)878 static int widget_init_stack_bob_av_noalpha(struct w_stack *w, struct w_info *d, struct widget_geometry *p, struct t_img *r, float f, float v) {
879 	if(p->w == 0) p->w = w->w;
880 	if(p->h == 0) p->h = w->h;
881 
882 	if(widget_init_stack_bob_op(d, p) != 0) return(-1);
883 
884 	(void) widget_init_stack_bob_av_op(d, p,
885 		r->p, p->h / r->h, p->w / r->w, p->h % r->h, p->w % r->w,
886 		(unsigned int) r->w, (unsigned int) r->h);
887 
888 	/* Apply hue and value to image if needed... */
889 	(void) widget_init_stack_bob_av_hue(d, r, f, v);
890 
891 	/* ...and copy it to window */
892 	(void) widget_init_stack_bob_copy_noalpha(w, d);
893 
894 	return(0);
895 }
896 
widget_init_stack_bob_av_hue(struct w_info * d,struct t_img * r,float f,float v)897 static void widget_init_stack_bob_av_hue(struct w_info *d, struct t_img *r, float f, float v) {
898 	unsigned int i, j, k;
899 
900 	struct pixel_rgba_8 *a;
901 	struct color_hsva c;
902 
903 	if((fabs(f - 0.0) > CONST_FLOAT_EQUALS) || (fabs(v - 0.0) > CONST_FLOAT_EQUALS)) {
904 		a = (struct pixel_rgba_8 *) d->m_f;
905 
906 		for(i = 0; i < (unsigned int) r->h; i++) {
907 			k = i * r->w;
908 
909 			for(j = 0; j < (unsigned int) r->w; j++) {
910 				(void) color_rgba_to_hsva(&a[k + j], &c);
911 
912 				c.h += f;
913 				c.v += v;
914 
915 				if(c.h < 0.0) {
916 					c.h = 359.0 + c.h;
917 				}
918 				else if(c.h > 359.0) c.h = c.h - 359.0;
919 
920 				if(c.v < 0.0) {
921 					c.v = 359.0 + c.v;
922 				}
923 				else if(c.v > 359.0) c.v = c.v - 359.0;
924 
925 				(void) color_hsva_to_rgba(&c, &a[k + j]);
926 			}
927 		}
928 	}
929 }
930 
widget_init_stack_bob_av_op(struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * r,unsigned int a,unsigned int b,unsigned int e,unsigned int f,unsigned int w,unsigned int h)931 static void widget_init_stack_bob_av_op(struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *r, unsigned int a, unsigned int b, unsigned int e, unsigned int f, unsigned int w, unsigned int h) {
932 	unsigned int i, j;
933 
934 	for(i = 0; i < a; i++) {
935 		/* Copy row of images to widget if needed */
936 		for(j = 0; j < b; j++) {
937 			(void) widget_init_stack_bob_av_full(d, p, r, j, i, w, h);
938 		}
939 
940 		/* Copy also partial image at the end of the row if needed */
941 		if(f != 0) (void) widget_init_stack_bob_av_part(d, p, r, j, i, f, h, w, h);
942 	}
943 
944 	if(e != 0) {
945 		/* Copy last partial line of images if needed */
946 		for(j = 0; j < b; j++) {
947 			(void) widget_init_stack_bob_av_part(d, p, r, j, a, w, e, w, h);
948 		}
949 
950 		/* Copy also partial image at the end of the last row if needed */
951 		if(f != 0) (void) widget_init_stack_bob_av_part(d, p, r, j, a, f, e, w, h);
952 	}
953 }
954 
widget_init_stack_bob_av_full(struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * r,unsigned int x,unsigned int y,unsigned int e,unsigned int f)955 static void widget_init_stack_bob_av_full(struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *r, unsigned int x, unsigned int y, unsigned int e, unsigned int f) {
956 	unsigned int i, j, k;
957 
958 	struct pixel_rgba_8 *a, *b;
959 
960 	a = (struct pixel_rgba_8 *) d->m_f;
961 
962 	/* Adjust destination coordinate for tiling */
963 	a += (y * f) * p->w;
964 	a += (x * e);
965 
966 	for(i = 0; i < f; i++) {
967 		b = a + (i * p->w);
968 		k = i * e;
969 
970 		for(j = 0; j < e; j++) b[j].pixel.p = r[k + j].pixel.p;
971 	}
972 }
973 
widget_init_stack_bob_av_part(struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * r,unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int e,unsigned int f)974 static void widget_init_stack_bob_av_part(struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *r, unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int e, unsigned int f) {
975 	unsigned int i, j, k;
976 
977 	struct pixel_rgba_8 *a, *b;
978 
979 	a = (struct pixel_rgba_8 *) d->m_f;
980 
981 	/* Adjust destination coordinate */
982 	a += (y * f) * p->w;
983 	a += (x * e);
984 
985 	for(i = 0; i < h; i++) {
986 		b = a + (i * p->w);
987 		k = i * e;
988 
989 		for(j = 0; j < w; j++) b[j].pixel.p = r[k + j].pixel.p;
990 	}
991 }
992 
widget_init_stack_bob_av_border(struct w_info * d,struct widget_geometry * p,struct pixel_rgba_8 * o,unsigned int h)993 static void widget_init_stack_bob_av_border(struct w_info *d, struct widget_geometry *p, struct pixel_rgba_8 *o, unsigned int h) {
994 	unsigned int i, j, n;
995 
996 	uint32_t r;
997 
998 	struct pixel_rgba_8 *a, *b, *c;
999 
1000 	if(h == 0 || o->pixel.a == 0) return;
1001 
1002 	n = VALUE_MIN2(p->w, p->h) / 2;
1003 
1004 	if(h > n) h = n;
1005 
1006 	a = (struct pixel_rgba_8 *) d->m_f;
1007 
1008 	/* Horizontal borders */
1009 	for(i = 0; i < h; i++) {
1010 		b = a + (i * p->w);
1011 		c = a + ((p->h - i - 1) * p->w);
1012 
1013 		for(j = 0; j < p->w; j++) {
1014 			r = draw_pixel_alpha_rgba_8(b[j].pixel.p, o->pixel.p, (uint32_t) o->pixel.a);
1015 
1016 			b[j].pixel.p = r;
1017 
1018 			r = draw_pixel_alpha_rgba_8(c[j].pixel.p, o->pixel.p, (uint32_t) o->pixel.a);
1019 
1020 			c[j].pixel.p = r;
1021 		}
1022 	}
1023 
1024 	/* Vertical borders, dont overwrite corners */
1025 	for(i = h; i < p->h - h; i++) {
1026 		b = a + (i * p->w);
1027 
1028 		for(j = 0; j < h; j++) {
1029 			r = draw_pixel_alpha_rgba_8(b[j].pixel.p, o->pixel.p, (uint32_t) o->pixel.a);
1030 
1031 			b[j].pixel.p = r;
1032 
1033 			r = draw_pixel_alpha_rgba_8(b[p->w - j - 1].pixel.p, o->pixel.p, (uint32_t) o->pixel.a);
1034 
1035 			b[p->w - j - 1].pixel.p = r;
1036 		}
1037 	}
1038 }
1039 
widget_init_stack_bob_store(struct pixel_rgba_8 * s,size_t t)1040 static struct pixel_rgba_8 *widget_init_stack_bob_store(struct pixel_rgba_8 *s, size_t t) {
1041 	struct pixel_rgba_8 *d;
1042 
1043 	APP_MALLOC_RET_VALUE(d, t, NULL);
1044 
1045 	(void) memcpy((void *) d, (const void *) s, t);
1046 
1047 	return(d);
1048 }
1049 
widget_init_stack_bob_content(unsigned int a,unsigned int k,struct w_info * d,struct pixel_rgba_8 * m_i,struct pixel_rgba_8 * m_s,struct pixel_rgba_8 * c,unsigned int f)1050 static void widget_init_stack_bob_content(unsigned int a, unsigned int k, struct w_info *d, struct pixel_rgba_8 *m_i, struct pixel_rgba_8 *m_s, struct pixel_rgba_8 *c, unsigned int f) {
1051 	unsigned int i, j, n, m, t, u;
1052 	unsigned int a_w, a_h, b_w, b_h;
1053 
1054 	int o_x, o_y;
1055 
1056 	uint32_t r;
1057 
1058 	struct pixel_rgba_8 b, p;
1059 
1060 	(void) widget_init_stack_bob_predraw_size(a, k, &a_w, &a_h, &b_w, &b_h);
1061 	(void) widget_init_stack_bob_predraw_offset(a, k, &o_x, &o_y);
1062 
1063 	/* Important to reset all alpha values */
1064 	(void) memset((void *) c, 0, (d->w * d->h) * sizeof(struct pixel_rgba_8));
1065 
1066 	t = (a_w * a_h) * f;
1067 	u = (b_w * b_h) * f;
1068 
1069 	/* First make shadow adjusting its position by offset... */
1070 	p.pixel.p = c_shadow_color.pixel.p;
1071 
1072 	for(i = 0; i < b_h; i++) {
1073 		n = (i * b_w) + u;
1074 		m = ((i + o_y) * d->w) + o_x;
1075 
1076 		for(j = 0; j < b_w; j++) {
1077 			if(m_s[n + j].pixel.a == 0) continue;
1078 
1079 			p.pixel.a = (uint8_t) round(maths_map((double) m_s[n + j].pixel.a,
1080 				0.0, 255.0, 0.0, (double) c_shadow_opaque));
1081 
1082 			c[m + j].pixel.p = p.pixel.p;
1083 		}
1084 	}
1085 
1086 	/* ...and then copy the widget on top of shadow */
1087 	for(i = 0; i < a_h; i++) {
1088 		n = (i * a_w) + t;
1089 		m = i * d->w;
1090 
1091 		for(j = 0; j < a_w; j++) {
1092 			/* Dont overwrite shadow alpha channel with too low value */
1093 			if(c[m + j].pixel.a >= m_i[n + j].pixel.a) continue;
1094 
1095 			r = draw_pixel_alpha_rgba_8(c[m + j].pixel.p, m_i[n + j].pixel.p,
1096 				(uint32_t) m_i[n + j].pixel.a);
1097 
1098 			c[m + j].pixel.p = r;
1099 		}
1100 	}
1101 
1102 	/* Draw also widget bounding boxes if needed */
1103 	if(widget_use_bbox != IS_YES) return;
1104 
1105 	b.pixel.r = WIDGET_BBOX_RED;
1106 	b.pixel.g = WIDGET_BBOX_GREEN;
1107 	b.pixel.b = WIDGET_BBOX_BLUE;
1108 	b.pixel.a = WIDGET_BBOX_ALPHA;
1109 
1110 	/* Horizontal borders */
1111 	for(i = 0; i < d->w; i++) {
1112 		c[i].pixel.p = b.pixel.p;
1113 		c[((d->h - 1) * d->w) + i].pixel.p = b.pixel.p;
1114 	}
1115 
1116 	/* Vertical borders, dont overwrite already drawn corners */
1117 	for(i = 1; i < d->h - 1; i++) {
1118 		c[i * d->w].pixel.p = b.pixel.p;
1119 		c[(i * d->w) + (d->w - 1)].pixel.p = b.pixel.p;
1120 	}
1121 }
1122 
widget_init_stack_bob_frame(unsigned int a,unsigned int b,unsigned int c,unsigned int s,double t)1123 static unsigned int widget_init_stack_bob_frame(unsigned int a, unsigned int b, unsigned int c, unsigned int s, double t) {
1124 	double f, k;
1125 
1126 	if(c == 0 || s > c) return(s + a);
1127 
1128 	k = (double) (b - a) / (double) c;
1129 	f = (k * (double) s) + (double) a;
1130 
1131 	return((unsigned int) floor(f * t));
1132 }
1133 
widget_init_stack_bob_op(struct w_info * d,struct widget_geometry * g)1134 static int widget_init_stack_bob_op(struct w_info *d, struct widget_geometry *g) {
1135 	size_t t;
1136 
1137 	t = (g->w * g->h) * sizeof(struct pixel_rgba_8);
1138 
1139 	APP_MALLOC_RET_VALUE(d->m_f, t, -1);
1140 
1141 	(void) memset((void *) d->m_f, 0, t);
1142 
1143 	d->t = t;
1144 
1145 	d->x = g->x;
1146 	d->y = g->y;
1147 	d->w = g->w;
1148 	d->h = g->h;
1149 
1150 	return(0);
1151 }
1152 
widget_init_stack_bob_text_render(struct w_info * d,struct widget_title * t)1153 static int widget_init_stack_bob_text_render(struct w_info *d, struct widget_title *t) {
1154 	char *a, *e, *f;
1155 
1156 	struct pixel_rgb_8 r;
1157 
1158 	/* If charset was not supplied, get the defaults */
1159 	if(t->c == NULL) {
1160 		if((a = (char *) conf_fetch("default_charset")) != NULL) {
1161 			t->c = a;
1162 		}
1163 		else t->c = CHARSET_DEFAULT;
1164 	}
1165 
1166 	/* If resolution was not supplied, use screen default */
1167 	if(t->d == 0) t->d = (unsigned int) c_font_dpi;
1168 	if(t->d == 0) t->d = (unsigned int) round(window_get_dpi_height());
1169 
1170 	/* If font name was not supplied, get the default */
1171 	e = t->e;
1172 
1173 	if(e == NULL || e[0] == 0) e = c_font_face;
1174 
1175 	if((f = window_get_default_font(e)) == NULL) return(-1);
1176 
1177 	if((t->f = fonts_open(f, t->y, t->d)) == 0) {
1178 		(void) window_get_default_font_free(f);
1179 
1180 		return(-1);
1181 	}
1182 
1183 	(void) window_get_default_font_free(f);
1184 
1185 	/* Store widget_title structure to w_info as well */
1186 	d->f = (void *) t;
1187 
1188 	r.r = t->r.pixel.r;
1189 	r.g = t->r.pixel.g;
1190 	r.b = t->r.pixel.b;
1191 
1192 	(void) fonts_render(t->f, t->c, t->s, t->t, &r, 2);
1193 
1194 	return(0);
1195 }
1196 
widget_init_stack_bob_text_close(struct widget_title * t)1197 static void widget_init_stack_bob_text_close(struct widget_title *t) {
1198 	if(t->f != 0) {
1199 		(void) fonts_close(t->f);
1200 
1201 		t->f = 0;
1202 	}
1203 
1204 	t->q = IS_NO;
1205 }
1206 
widget_init_stack_bob_text(struct w_stack * w,struct widget_title * t)1207 static void widget_init_stack_bob_text(struct w_stack *w, struct widget_title *t) {
1208 	(void) gui_draw_text(w->hnd, &t->i);
1209 }
1210 
widget_init_stack_bob_copy(struct w_stack * w,struct w_info * d)1211 static void widget_init_stack_bob_copy(struct w_stack *w, struct w_info *d) {
1212 	d->r_8.sx = 0;
1213 	d->r_8.sy = 0;
1214 
1215 	d->r_8.dx = d->x;
1216 	d->r_8.dy = d->y;
1217 
1218 	d->r_8.c.width = d->w;
1219 	d->r_8.c.height = d->h;
1220 	d->r_8.s.width = d->w;
1221 	d->r_8.s.height = d->h;
1222 
1223 	d->r_8.p = d->m_f;
1224 
1225 	(void) gui_draw_copy_alpha(w->hnd, &d->r_8);
1226 }
1227 
widget_init_stack_bob_copy_noalpha(struct w_stack * w,struct w_info * d)1228 static void widget_init_stack_bob_copy_noalpha(struct w_stack *w, struct w_info *d) {
1229 	d->r_8.sx = 0;
1230 	d->r_8.sy = 0;
1231 
1232 	d->r_8.dx = d->x;
1233 	d->r_8.dy = d->y;
1234 
1235 	d->r_8.c.width = d->w;
1236 	d->r_8.c.height = d->h;
1237 	d->r_8.s.width = d->w;
1238 	d->r_8.s.height = d->h;
1239 
1240 	d->r_8.p = d->m_f;
1241 
1242 	(void) gui_draw_copy(w->hnd, &d->r_8);
1243 }
1244 
widget_init_stack_bob_fill(struct w_stack * w,struct w_info * d,struct pixel_rgba_8 * c,int x,int y,int e,int f)1245 static void widget_init_stack_bob_fill(struct w_stack *w, struct w_info *d, struct pixel_rgba_8 *c, int x, int y, int e, int f) {
1246 	d->p_4.x1 = x;
1247 	d->p_4.y1 = y;
1248 	d->p_4.x2 = x + e;
1249 	d->p_4.y2 = y + f;
1250 
1251 	d->p_4.p.pixel.p = c->pixel.p;
1252 
1253 	(void) gui_draw_set_alpha(w->hnd, &d->p_4);
1254 }
1255 
widget_init_stack_bob_fill_noalpha(struct w_stack * w,struct w_info * d,struct pixel_rgba_8 * c)1256 static void widget_init_stack_bob_fill_noalpha(struct w_stack *w, struct w_info *d, struct pixel_rgba_8 *c) {
1257 	d->p_4.x1 = d->x;
1258 	d->p_4.y1 = d->y;
1259 	d->p_4.x2 = d->x + d->w;
1260 	d->p_4.y2 = d->y + d->h;
1261 
1262 	d->p_4.p.pixel.p = c->pixel.p;
1263 
1264 	(void) gui_draw_set(w->hnd, &d->p_4);
1265 }
1266 
widget_init_stack_bob_fill_border(struct w_stack * w,struct w_info * d,struct pixel_rgba_8 * c,unsigned int h)1267 static void widget_init_stack_bob_fill_border(struct w_stack *w, struct w_info *d, struct pixel_rgba_8 *c, unsigned int h) {
1268 	if(h == 0 || c->pixel.a == 0) return;
1269 
1270 	d->o_4.x = d->x;
1271 	d->o_4.y = d->y;
1272 	d->o_4.w = d->w;
1273 	d->o_4.h = d->h;
1274 
1275 	d->o_4.t = h;
1276 
1277 	d->o_4.p.pixel.p = c->pixel.p;
1278 
1279 	(void) gui_draw_border_alpha(w->hnd, &d->o_4);
1280 }
1281 
widget_init_stack_bob_mask(struct w_stack * w,struct w_info * d,unsigned int a,unsigned int b)1282 static void widget_init_stack_bob_mask(struct w_stack *w, struct w_info *d, unsigned int a, unsigned int b) {
1283 	int i, j, e, f;
1284 	unsigned int k, n, u, v;
1285 	unsigned int a_w, a_h, b_w, b_h;
1286 
1287 	uint8_t *m;
1288 
1289 	/* Always create mouse mask id for this widget */
1290 	d->m_id.c = ++w->n.c;
1291 
1292 	/* If this widget has no callback functions, mask is useless */
1293 	if(d->d == 0) return;
1294 
1295 	/* Get widget size and mouse mask bytes */
1296 	(void) widget_init_stack_bob_predraw_size(a, b, &a_w, &a_h, &b_w, &b_h);
1297 
1298 	m = widget_init_stack_bob_predraw_mask(a, b);
1299 
1300 	/* Append widget mask to mouse buffer */
1301 	e = (int) (d->x + a_w);
1302 	f = (int) (d->y + a_h);
1303 
1304 	if(e > (int) w->w) e = (int) w->w;
1305 	if(f > (int) w->h) f = (int) w->h;
1306 
1307 	for(i = d->y, u = 0; i < f; i++, u++) {
1308 		if(i < 0) continue;
1309 
1310 		k = w->w * i;
1311 		n = a_w * u;
1312 
1313 		for(j = d->x, v = 0; j < e; j++, v++) {
1314 			if(j < 0) continue;
1315 
1316 			/* Append pixel to mouse mask buffer only if it is set in widget mouse mask */
1317 			if(m[n + v] != 0) w->mb[k + j].c = d->m_id.c;
1318 		}
1319 	}
1320 }
1321 
widget_init_stack_bob_apps(struct w_stack * w,struct w_info * d,struct pixel_c_2 * c)1322 static void widget_init_stack_bob_apps(struct w_stack *w, struct w_info *d, struct pixel_c_2 *c) {
1323 	int i, j, e, f;
1324 	unsigned int k;
1325 
1326 	/* Append widget mask to mouse buffer */
1327 	e = (int) (d->x + d->w);
1328 	f = (int) (d->y + d->h);
1329 
1330 	if(e > (int) w->w) e = (int) w->w;
1331 	if(f > (int) w->h) f = (int) w->h;
1332 
1333 	for(i = d->y; i < f; i++) {
1334 		if(i < 0) continue;
1335 
1336 		k = w->w * i;
1337 
1338 		for(j = d->x; j < e; j++) {
1339 			if(j < 0) continue;
1340 
1341 			w->mb[k + j].c = c->c;
1342 		}
1343 	}
1344 }
1345 
widget_init_stack_bob_sets(struct w_stack * w,struct w_info * d)1346 static void widget_init_stack_bob_sets(struct w_stack *w, struct w_info *d) {
1347 	d->m_id.c = ++w->n.c;
1348 
1349 	/* If this widget has no callback functions, mask is useless */
1350 	if(d->d == 0) return;
1351 
1352 	/* Append widget mask to mouse buffer */
1353 	(void) widget_init_stack_bob_apps(w, d, &d->m_id);
1354 }
1355 
widget_init_stack_bob_rems(struct w_stack * w,struct w_info * d)1356 static void widget_init_stack_bob_rems(struct w_stack *w, struct w_info *d) {
1357 	int i, j, e, f;
1358 	unsigned int k;
1359 
1360 	/* If this widget has no callback functions, there is no mask */
1361 	if(d->d == 0) return;
1362 
1363 	/* Remove widget mask from mouse buffer */
1364 	e = (int) (d->x + d->w);
1365 	f = (int) (d->y + d->h);
1366 
1367 	if(e > (int) w->w) e = (int) w->w;
1368 	if(f > (int) w->h) f = (int) w->h;
1369 
1370 	for(i = d->y; i < f; i++) {
1371 		if(i < 0) continue;
1372 
1373 		k = w->w * i;
1374 
1375 		for(j = d->x; j < e; j++) {
1376 			if(j < 0) continue;
1377 
1378 			if(w->mb[k + j].c == d->m_id.c) w->mb[k + j].c = 0;
1379 		}
1380 	}
1381 }
1382 
widget_init_stack_cb_add(struct w_info * w,struct widget_cb * c)1383 static int widget_init_stack_cb_add(struct w_info *w, struct widget_cb *c) {
1384 	unsigned int i;
1385 
1386 	w->d = 0;
1387 
1388 	if(c == NULL) return(0);
1389 
1390 	for(i = 0; ; i++) {
1391 		switch(c[i].c) {
1392 			case WIDGET_CB_TYPE_NONE:
1393 				/* Save callback function count for later use */
1394 				w->d = i;
1395 
1396 				return(0);
1397 			/* Pushbutton widget callbacks */
1398 			case WIDGET_CB_TYPE_PUSHBUTTON_PUSH:
1399 				w->cb_pushbutton_push = widget_cb_pushbutton_push;
1400 
1401 				if(w->par_pushbutton_push.s != NULL) {
1402 					(void) free(w->par_pushbutton_push.s);
1403 				}
1404 
1405 				w->par_pushbutton_push.s = widget_strcpy(NULL, c[i].s);
1406 
1407 				break;
1408 			/* Slideswitch widget callbacks */
1409 			case WIDGET_CB_TYPE_SLIDESWITCH_SLIDE:
1410 				w->cb_slideswitch_slide = widget_cb_slideswitch_slide;
1411 
1412 				if(w->par_slideswitch_slide.s != NULL) {
1413 					(void) free(w->par_slideswitch_slide.s);
1414 				}
1415 
1416 				w->par_slideswitch_slide.s = widget_strcpy(NULL, c[i].s);
1417 
1418 				break;
1419 			/* Toggleswitch widget callbacks */
1420 			case WIDGET_CB_TYPE_TOGGLESWITCH_TOGGLE:
1421 				w->cb_toggleswitch_toggle = widget_cb_toggleswitch_toggle;
1422 
1423 				if(w->par_toggleswitch_toggle.s != NULL) {
1424 					(void) free(w->par_toggleswitch_toggle.s);
1425 				}
1426 
1427 				w->par_toggleswitch_toggle.s = widget_strcpy(NULL, c[i].s);
1428 
1429 				break;
1430 			/* Turnswitch widget callbacks */
1431 			case WIDGET_CB_TYPE_TURNSWITCH_TURN:
1432 				w->cb_turnswitch_turn = widget_cb_turnswitch_turn;
1433 
1434 				if(w->par_turnswitch_turn.s != NULL) {
1435 					(void) free(w->par_turnswitch_turn.s);
1436 				}
1437 
1438 				w->par_turnswitch_turn.s = widget_strcpy(NULL, c[i].s);
1439 
1440 				break;
1441 			/* Generic widget callbacks */
1442 			case WIDGET_CB_TYPE_KEYPRESS:
1443 				w->cb_generic_key_press = widget_cb_generic_key_press;
1444 
1445 				if(w->par_generic_key_press.s != NULL) {
1446 					(void) free(w->par_generic_key_press.s);
1447 				}
1448 
1449 				w->par_generic_key_press.s = widget_strcpy(NULL, c[i].s);
1450 
1451 				break;
1452 			case WIDGET_CB_TYPE_KEYRELEASE:
1453 				w->cb_generic_key_release = widget_cb_generic_key_release;
1454 
1455 				if(w->par_generic_key_release.s != NULL) {
1456 					(void) free(w->par_generic_key_release.s);
1457 				}
1458 
1459 				w->par_generic_key_release.s = widget_strcpy(NULL, c[i].s);
1460 
1461 				break;
1462 			case WIDGET_CB_TYPE_BUTTONPRESS:
1463 				w->cb_generic_button_press = widget_cb_generic_button_press;
1464 
1465 				if(w->par_generic_button_press.s != NULL) {
1466 					(void) free(w->par_generic_button_press.s);
1467 				}
1468 
1469 				w->par_generic_button_press.s = widget_strcpy(NULL, c[i].s);
1470 
1471 				break;
1472 			case WIDGET_CB_TYPE_BUTTONRELEASE:
1473 				w->cb_generic_button_release = widget_cb_generic_button_release;
1474 
1475 				if(w->par_generic_button_release.s != NULL) {
1476 					(void) free(w->par_generic_button_release.s);
1477 				}
1478 
1479 				w->par_generic_button_release.s = widget_strcpy(NULL, c[i].s);
1480 
1481 				break;
1482 			default:
1483 				(void) flush_error();
1484 
1485 				LOGWARN(
1486 					ERROR_SLIGHT, SUBSYSTEM,
1487 					_("Widget callback type %u is unknown, please check widget definitions"),
1488 					c[i].c
1489 				);
1490 
1491 				return(-1);
1492 		}
1493 	}
1494 
1495 	return(0);
1496 }
1497 
widget_init_stack_cb_delete(struct w_info * w,struct widget_cb * c)1498 static int widget_init_stack_cb_delete(struct w_info *w, struct widget_cb *c) {
1499 	unsigned int i;
1500 
1501 	w->d = 0;
1502 
1503 	if(c == NULL) return(0);
1504 
1505 	for(i = 0; ; i++) {
1506 		switch(c[i].c) {
1507 			case WIDGET_CB_TYPE_NONE:
1508 				return(0);
1509 			/* Pushbutton widget callbacks */
1510 			case WIDGET_CB_TYPE_PUSHBUTTON_PUSH:
1511 				w->cb_pushbutton_push = NULL;
1512 
1513 				if(w->par_pushbutton_push.s != NULL) {
1514 					(void) free(w->par_pushbutton_push.s);
1515 
1516 					w->par_pushbutton_push.s = NULL;
1517 				}
1518 
1519 				w->par_pushbutton_push.n = 0;
1520 				w->par_pushbutton_push.m = 0;
1521 				w->par_pushbutton_push.c = 0;
1522 
1523 				break;
1524 			/* Slideswitch widget callbacks */
1525 			case WIDGET_CB_TYPE_SLIDESWITCH_SLIDE:
1526 				w->cb_slideswitch_slide = NULL;
1527 
1528 				if(w->par_slideswitch_slide.s != NULL) {
1529 					(void) free(w->par_slideswitch_slide.s);
1530 
1531 					w->par_slideswitch_slide.s = NULL;
1532 				}
1533 
1534 				w->par_slideswitch_slide.n = 0;
1535 				w->par_slideswitch_slide.m = 0;
1536 				w->par_slideswitch_slide.c = 0;
1537 
1538 				break;
1539 			/* Toggleswitch widget callbacks */
1540 			case WIDGET_CB_TYPE_TOGGLESWITCH_TOGGLE:
1541 				w->cb_toggleswitch_toggle = NULL;
1542 
1543 				if(w->par_toggleswitch_toggle.s != NULL) {
1544 					(void) free(w->par_toggleswitch_toggle.s);
1545 
1546 					w->par_toggleswitch_toggle.s = NULL;
1547 				}
1548 
1549 				w->par_toggleswitch_toggle.n = 0;
1550 				w->par_toggleswitch_toggle.m = 0;
1551 				w->par_toggleswitch_toggle.c = 0;
1552 
1553 				break;
1554 			/* Turnswitch widget callbacks */
1555 			case WIDGET_CB_TYPE_TURNSWITCH_TURN:
1556 				w->cb_turnswitch_turn = NULL;
1557 
1558 				if(w->par_turnswitch_turn.s != NULL) {
1559 					(void) free(w->par_turnswitch_turn.s);
1560 
1561 					w->par_turnswitch_turn.s = NULL;
1562 				}
1563 
1564 				w->par_turnswitch_turn.n = 0;
1565 				w->par_turnswitch_turn.m = 0;
1566 				w->par_turnswitch_turn.c = 0;
1567 
1568 				break;
1569 			/* Generic widget callbacks */
1570 			case WIDGET_CB_TYPE_KEYPRESS:
1571 				w->cb_generic_key_press = NULL;
1572 
1573 				if(w->par_generic_key_press.s != NULL) {
1574 					(void) free(w->par_generic_key_press.s);
1575 
1576 					w->par_generic_key_press.s = NULL;
1577 				}
1578 
1579 				w->par_generic_key_press.n = 0;
1580 				w->par_generic_key_press.m = 0;
1581 				w->par_generic_key_press.c = 0;
1582 
1583 				break;
1584 			case WIDGET_CB_TYPE_KEYRELEASE:
1585 				w->cb_generic_key_release = NULL;
1586 
1587 				if(w->par_generic_key_release.s != NULL) {
1588 					(void) free(w->par_generic_key_release.s);
1589 
1590 					w->par_generic_key_release.s = NULL;
1591 				}
1592 
1593 				w->par_generic_key_release.n = 0;
1594 				w->par_generic_key_release.m = 0;
1595 				w->par_generic_key_release.c = 0;
1596 
1597 				break;
1598 			case WIDGET_CB_TYPE_BUTTONPRESS:
1599 				w->cb_generic_button_press = NULL;
1600 
1601 				if(w->par_generic_button_press.s != NULL) {
1602 					(void) free(w->par_generic_button_press.s);
1603 
1604 					w->par_generic_button_press.s = NULL;
1605 				}
1606 
1607 				w->par_generic_button_press.n = 0;
1608 				w->par_generic_button_press.m = 0;
1609 				w->par_generic_button_press.c = 0;
1610 
1611 				break;
1612 			case WIDGET_CB_TYPE_BUTTONRELEASE:
1613 				w->cb_generic_button_release = NULL;
1614 
1615 				if(w->par_generic_button_release.s != NULL) {
1616 					(void) free(w->par_generic_button_release.s);
1617 
1618 					w->par_generic_button_release.s = NULL;
1619 				}
1620 
1621 				w->par_generic_button_release.n = 0;
1622 				w->par_generic_button_release.m = 0;
1623 				w->par_generic_button_release.c = 0;
1624 
1625 				break;
1626 			default:
1627 				(void) flush_error();
1628 
1629 				LOGWARN(
1630 					ERROR_SLIGHT, SUBSYSTEM,
1631 					_("Widget callback type %u is unknown, please check widget definitions"),
1632 					c[i].c
1633 				);
1634 
1635 				return(-1);
1636 		}
1637 	}
1638 
1639 	return(0);
1640 }
1641 
widget_init_stack_bob_predraw(unsigned int p,unsigned int k,float f,struct t_img ** m_i,struct t_img ** m_s)1642 static int widget_init_stack_bob_predraw(unsigned int p, unsigned int k, float f, struct t_img **m_i, struct t_img **m_s) {
1643 	unsigned int i;
1644 
1645 	struct widget_predraw_it *t;
1646 	struct widget_predraw_op *u;
1647 
1648 	/* Check subtype as it may be user supplied value */
1649 	if(k >= WIDGET_GFX_TYPES) {
1650 		(void) widget_init_stack_bob_predraw_error(k);
1651 
1652 		return(-1);
1653 	}
1654 
1655 	if(f < -359.0) f = -359.0;
1656 	else if(f > 359.0) f = 359.0;
1657 
1658 	t = &widget_predraw[p].c_t[k];
1659 
1660 	/* Get widget image from predraw structure by its hue value */
1661 	for(i = 0; i < WIDGET_GFX_CACHE; i++) {
1662 		u = &t->c_o[i];
1663 
1664 		if(fabs(u->c_h - f) < CONST_FLOAT_EQUALS) break;
1665 
1666 		if(u->c_h < 0.0) {
1667 			u->c_h = f;
1668 
1669 			break;
1670 		}
1671 	}
1672 
1673 	/* Leave if all cache slots are taken */
1674 	if(i == WIDGET_GFX_CACHE) {
1675 		(void) flush_error();
1676 
1677 		LOGWARN(
1678 			ERROR_SLIGHT, SUBSYSTEM,
1679 			_("Failed to create widget because all cache slots are taken, please consider to increase WIDGET_GFX_CACHE")
1680 		);
1681 
1682 		return(-1);
1683 	}
1684 
1685 	/* Load widget image data if not loaded already */
1686 	if(u->a_i.p == NULL) {
1687 		if((t->f = widget_init_stack_bob_predraw_op(t->a, &u->a_i, &t->b_i, &t->m, &t->o_x, &t->o_y, &t->c, IS_YES)) == 0) {
1688 			return(-1);
1689 		}
1690 
1691 		/* Correct endianess and apply hue to image data if needed */
1692 		(void) widget_init_stack_bob_predraw_it(u->a_i.p + (t->a_w * t->a_h * t->c_f),
1693 			t->c, u->a_i.w, u->a_i.h, u->c_h);
1694 
1695 		(void) widget_init_stack_bob_predraw_it(t->b_i.p + (t->b_w * t->b_h * t->d_f),
1696 			t->c, t->b_i.w, t->b_i.h, 0.0);
1697 	}
1698 
1699 	/* Adjust possible frame offset to widget image data */
1700 	if(t->c_f != 0) {
1701 		u->a_i.p += (t->a_w * t->a_h * t->c_f);
1702 
1703 		t->c_f = 0;
1704 	}
1705 
1706 	*m_i = &u->a_i;
1707 
1708 	/* Adjust possible frame offset to shadow image data */
1709 	if(t->d_f != 0) {
1710 		t->b_i.p += (t->b_w * t->b_h * t->d_f);
1711 
1712 		t->d_f = 0;
1713 	}
1714 
1715 	*m_s = &t->b_i;
1716 
1717 	return(0);
1718 }
1719 
widget_init_stack_bob_predraw_op(char * a,struct t_img * t_a,struct t_img * t_b,uint8_t ** t_c,int * o_x,int * o_y,unsigned int * c,unsigned int w)1720 static unsigned int widget_init_stack_bob_predraw_op(char *a, struct t_img *t_a, struct t_img *t_b, uint8_t **t_c, int *o_x, int *o_y, unsigned int *c, unsigned int w) {
1721 	unsigned int i, f;
1722 
1723 	char *s, *p;
1724 
1725 	size_t t;
1726 
1727 	struct widget_header *h;
1728 
1729 	t = CONFIG_PATH_LENGTH;
1730 
1731 	APP_MALLOC_RET_VALUE(s, t + sizeof(char), 0);
1732 
1733 	for(i = 0; ; i++) {
1734 		if(c_d_t[i] == NULL) {
1735 			(void) flush_error();
1736 
1737 			LOGWARN(
1738 				ERROR_SLIGHT, SUBSYSTEM,
1739 				_("Failed to find %s from any of the widget directories, please check the installation"),
1740 				a
1741 			);
1742 
1743 			(void) free(s);
1744 
1745 			return(0);
1746 		}
1747 
1748 		if(conf_read_try(c_d_t[i], a, s, t) != 0) continue;
1749 
1750 		/* REMEMBER filehandle is not closed anywhere when opening whole file is succesful */
1751 		if((f = files_open(s, FILE_FLAG_SILENT, FILE_MODE_READ)) != 0) {
1752 			/* Either read whole file or just a header */
1753 			if(w == IS_YES) {
1754 				if((t = files_get_file_size(f)) == 0) {
1755 					(void) files_close(f);
1756 					(void) free(s);
1757 
1758 					return(0);
1759 				}
1760 			}
1761 			else t = sizeof(struct widget_header);
1762 
1763 			if(files_read(f, t) != 0) {
1764 				(void) files_close(f);
1765 				(void) free(s);
1766 
1767 				return(0);
1768 			}
1769 
1770 			break;
1771 		}
1772 	}
1773 
1774 	/* Check and initialize widget image data */
1775 	if((t_a->c = files_get_content(f)) == NULL) {
1776 		(void) files_close(f);
1777 		(void) free(s);
1778 
1779 		return(0);
1780 	}
1781 
1782 	t_a->t = files_get_content_size(f);
1783 
1784 	h = (struct widget_header *) t_a->c;
1785 
1786 	for(i = 0; i < WIDGET_FILE_TAG_SIZE; i++) {
1787 		if(t_a->t < sizeof(struct widget_header) || h->id[i] != endian_le_uint32(widget_header_tag[i])) {
1788 			(void) flush_error();
1789 
1790 			LOGWARN(
1791 				ERROR_SLIGHT, SUBSYSTEM,
1792 				_("Failed to identify widget file %s, please check the installation"),
1793 				s
1794 			);
1795 
1796 			(void) files_close(f);
1797 			(void) free(s);
1798 
1799 			return(0);
1800 		}
1801 	}
1802 
1803 	(void) free(s);
1804 
1805 	if(c != NULL) *(c) = (unsigned int) endian_be_uint32(h->frames);
1806 
1807 	*(o_x) = (int) endian_be_int32(h->offset_x);
1808 	*(o_y) = (int) endian_be_int32(h->offset_y);
1809 
1810 	t_a->w = (int32_t) endian_be_uint32(h->widget_width);
1811 	t_a->h = (int32_t) endian_be_uint32(h->widget_height);
1812 
1813 	t_a->b = sizeof(struct pixel_rgba_8) * 8;
1814 
1815 	p = (char *) t_a->c;
1816 	p += sizeof(struct widget_header) + endian_be_uint32(h->widget_data);
1817 
1818 	t_a->p = (struct pixel_rgba_8 *) p;
1819 
1820 	/* Initialize widget shadow image */
1821 	t_b->c = t_a->c;
1822 	t_b->t = t_a->t;
1823 
1824 	t_b->w = (int32_t) endian_be_uint32(h->shadow_width);
1825 	t_b->h = (int32_t) endian_be_uint32(h->shadow_height);
1826 
1827 	t_b->b = sizeof(struct pixel_rgba_8) * 8;
1828 
1829 	p = (char *) t_b->c;
1830 	p += sizeof(struct widget_header) + endian_be_uint32(h->shadow_data);
1831 
1832 	t_b->p = (struct pixel_rgba_8 *) p;
1833 
1834 	/* Initialize widget mouse mask if needed */
1835 	if(t_c != NULL) {
1836 		*(t_c) = (uint8_t *) t_a->c;
1837 		*(t_c) += sizeof(struct widget_header) + endian_be_uint32(h->masked_data);
1838 	}
1839 
1840 	return(f);
1841 }
1842 
widget_init_stack_bob_predraw_it(struct pixel_rgba_8 * p,unsigned int e,unsigned int w,unsigned int h,float f)1843 static void widget_init_stack_bob_predraw_it(struct pixel_rgba_8 *p, unsigned int e, unsigned int w, unsigned int h, float f) {
1844 	unsigned int i, j, k, l, n;
1845 
1846 	struct color_hsva c;
1847 #if defined(IS_BIGENDIAN)
1848 	/* Big-endian machine needs bytes reversed */
1849 	for(l = 0; l < e; l++) {
1850 		n = w * h * l;
1851 
1852 		for(i = 0; i < h; i++) {
1853 			k = n + (i * w);
1854 
1855 			for(j = 0; j < w; j++) {
1856 				p[k + j].pixel.p = endian_le_uint32(p[k + j].pixel.p);
1857 			}
1858 		}
1859 	}
1860 #endif
1861 	/* Apply hue to image data if needed */
1862 	if(fabs(f - 0.0) > CONST_FLOAT_EQUALS) {
1863 		for(l = 0; l < e; l++) {
1864 			n = w * h * l;
1865 
1866 			for(i = 0; i < h; i++) {
1867 				k = n + (i * w);
1868 
1869 				for(j = 0; j < w; j++) {
1870 					(void) color_rgba_to_hsva(&p[k + j], &c);
1871 
1872 					c.h += f;
1873 
1874 					if(c.h < 0.0) {
1875 						c.h = 359.0 + c.h;
1876 					}
1877 					else if(c.h > 359.0) c.h = c.h - 359.0;
1878 
1879 					(void) color_hsva_to_rgba(&c, &p[k + j]);
1880 				}
1881 			}
1882 		}
1883 	}
1884 }
1885 
widget_init_stack_bob_predraw_size(unsigned int p,unsigned int k,unsigned int * a_w,unsigned int * a_h,unsigned int * b_w,unsigned int * b_h)1886 static void widget_init_stack_bob_predraw_size(unsigned int p, unsigned int k, unsigned int *a_w, unsigned int *a_h, unsigned int *b_w, unsigned int *b_h) {
1887 	struct widget_predraw_it *t;
1888 
1889 	/* Check subtype as it may be user supplied value */
1890 	if(k >= WIDGET_GFX_TYPES) {
1891 		(void) widget_init_stack_bob_predraw_error(k);
1892 
1893 		if(a_w != NULL) *a_w = 0;
1894 		if(a_h != NULL) *a_h = 0;
1895 
1896 		if(b_w != NULL) *b_w = 0;
1897 		if(b_h != NULL) *b_h = 0;
1898 
1899 		return;
1900 	}
1901 
1902 	t = &widget_predraw[p].c_t[k];
1903 
1904 	/* Fetch widget data size from file if needed */
1905 	(void) widget_init_stack_bob_predraw_fetch(t);
1906 
1907 	if(a_w != NULL) *a_w = t->a_w;
1908 	if(a_h != NULL) *a_h = t->a_h;
1909 
1910 	if(b_w != NULL) *b_w = t->b_w;
1911 	if(b_h != NULL) *b_h = t->b_h;
1912 }
1913 
widget_init_stack_bob_predraw_offset(unsigned int p,unsigned int k,int * o_x,int * o_y)1914 static void widget_init_stack_bob_predraw_offset(unsigned int p, unsigned int k, int *o_x, int *o_y) {
1915 	struct widget_predraw_it *t;
1916 
1917 	/* Check subtype as it may be user supplied value */
1918 	if(k >= WIDGET_GFX_TYPES) {
1919 		(void) widget_init_stack_bob_predraw_error(k);
1920 
1921 		*o_x = 0;
1922 		*o_y = 0;
1923 
1924 		return;
1925 	}
1926 
1927 	t = &widget_predraw[p].c_t[k];
1928 
1929 	/* Fetch widget data size from file if needed */
1930 	(void) widget_init_stack_bob_predraw_fetch(t);
1931 
1932 	*o_x = t->o_x;
1933 	*o_y = t->o_y;
1934 }
1935 
widget_init_stack_bob_predraw_error(unsigned int k)1936 static void widget_init_stack_bob_predraw_error(unsigned int k) {
1937 	(void) flush_error();
1938 
1939 	LOGWARN(
1940 		ERROR_SLIGHT, SUBSYSTEM,
1941 		_("Widget subtype %u is out of range, please check widget parameters"),
1942 		k
1943 	);
1944 }
1945 
widget_init_stack_bob_predraw_fetch(struct widget_predraw_it * t)1946 static void widget_init_stack_bob_predraw_fetch(struct widget_predraw_it *t) {
1947 	unsigned int f;
1948 
1949 	struct t_img a, b;
1950 
1951 	if(t->a_w == 0) {
1952 		if((f = widget_init_stack_bob_predraw_op(t->a, &a, &b, NULL, &t->o_x, &t->o_y, &t->c, IS_NO)) == 0) {
1953 			t->a_w = 0;
1954 			t->a_h = 0;
1955 
1956 			t->b_w = 0;
1957 			t->b_h = 0;
1958 
1959 			return;
1960 		}
1961 
1962 		(void) files_close(f);
1963 
1964 		t->a_w = (unsigned int) a.w;
1965 		t->a_h = (unsigned int) a.h;
1966 
1967 		t->b_w = (unsigned int) b.w;
1968 		t->b_h = (unsigned int) b.h;
1969 	}
1970 }
1971 
widget_init_stack_bob_predraw_frame(unsigned int p,unsigned int k)1972 static unsigned int widget_init_stack_bob_predraw_frame(unsigned int p, unsigned int k) {
1973 	struct widget_predraw_it *t;
1974 
1975 	/* Check subtype as it may be user supplied value */
1976 	if(k >= WIDGET_GFX_TYPES) {
1977 		(void) widget_init_stack_bob_predraw_error(k);
1978 
1979 		return(0);
1980 	}
1981 
1982 	t = &widget_predraw[p].c_t[k];
1983 
1984 	/* Fetch widget data size from file if needed */
1985 	(void) widget_init_stack_bob_predraw_fetch(t);
1986 
1987 	return(t->c);
1988 }
1989 
widget_init_stack_bob_predraw_mask(unsigned int p,unsigned int k)1990 static uint8_t *widget_init_stack_bob_predraw_mask(unsigned int p, unsigned int k) {
1991 	struct widget_predraw_it *t;
1992 
1993 	/* Check subtype as it may be user supplied value */
1994 	if(k >= WIDGET_GFX_TYPES) {
1995 		(void) widget_init_stack_bob_predraw_error(k);
1996 
1997 		return(NULL);
1998 	}
1999 
2000 	t = &widget_predraw[p].c_t[k];
2001 
2002 	/* Fetch widget data size from file if needed */
2003 	(void) widget_init_stack_bob_predraw_fetch(t);
2004 
2005 	return(t->m);
2006 }
2007 
widget_init_stack_collision(struct w_stack * w,struct w_info * d,struct widget_id * n,struct widget_geometry * p)2008 static void widget_init_stack_collision(struct w_stack *w, struct w_info *d, struct widget_id *n, struct widget_geometry *p) {
2009 	unsigned int i;
2010 
2011 	struct w_info *c;
2012 
2013 	struct widget_type_block *w_bl;
2014 	struct widget_type_label *w_la;
2015 	struct widget_type_lamp *w_lm;
2016 	struct widget_type_led *w_le;
2017 	struct widget_type_pushbutton *w_pb;
2018 	struct widget_type_slideswitch *w_ss;
2019 	struct widget_type_toggleswitch *w_ts;
2020 	struct widget_type_turnswitch *w_tw;
2021 
2022 	for(i = 0; i < w->c; i++) {
2023 		c = w->a[i];
2024 
2025 		switch(c->c) {
2026 			case WIDGET_TYPE_BLOCK:
2027 				w_bl = (struct widget_type_block *) c->p;
2028 
2029 				(void) widget_init_stack_collision_op(d, c, &w_bl->e, &w_bl->p, n, p);
2030 
2031 				break;
2032 			case WIDGET_TYPE_LABEL:
2033 				w_la = (struct widget_type_label *) c->p;
2034 
2035 				(void) widget_init_stack_collision_op(d, c, &w_la->e, &w_la->p, n, p);
2036 
2037 				break;
2038 			case WIDGET_TYPE_LAMP:
2039 				w_lm = (struct widget_type_lamp *) c->p;
2040 
2041 				(void) widget_init_stack_collision_op(d, c, &w_lm->e, &w_lm->p, n, p);
2042 
2043 				break;
2044 			case WIDGET_TYPE_LED_1:
2045 			case WIDGET_TYPE_LED_2:
2046 			case WIDGET_TYPE_LED_3:
2047 				w_le = (struct widget_type_led *) c->p;
2048 
2049 				(void) widget_init_stack_collision_op(d, c, &w_le->e, &w_le->p, n, p);
2050 
2051 				break;
2052 			case WIDGET_TYPE_PUSHBUTTON_1:
2053 			case WIDGET_TYPE_PUSHBUTTON_2:
2054 			case WIDGET_TYPE_PUSHBUTTON_3:
2055 				w_pb = (struct widget_type_pushbutton *) c->p;
2056 
2057 				(void) widget_init_stack_collision_op(d, c, &w_pb->e, &w_pb->p, n, p);
2058 
2059 				break;
2060 			case WIDGET_TYPE_SLIDESWITCH:
2061 				w_ss = (struct widget_type_slideswitch *) c->p;
2062 
2063 				(void) widget_init_stack_collision_op(d, c, &w_ss->e, &w_ss->p, n, p);
2064 
2065 				break;
2066 			case WIDGET_TYPE_TOGGLESWITCH:
2067 				w_ts = (struct widget_type_toggleswitch *) c->p;
2068 
2069 				(void) widget_init_stack_collision_op(d, c, &w_ts->e, &w_ts->p, n, p);
2070 
2071 				break;
2072 			case WIDGET_TYPE_TURNSWITCH:
2073 				w_tw = (struct widget_type_turnswitch *) c->p;
2074 
2075 				(void) widget_init_stack_collision_op(d, c, &w_tw->e, &w_tw->p, n, p);
2076 
2077 				break;
2078 			default:
2079 				break;
2080 		}
2081 	}
2082 }
2083 
widget_init_stack_collision_op(struct w_info * d,struct w_info * c,struct widget_id * n,struct widget_geometry * a,struct widget_id * m,struct widget_geometry * b)2084 static void widget_init_stack_collision_op(struct w_info *d, struct w_info *c, struct widget_id *n, struct widget_geometry *a, struct widget_id *m, struct widget_geometry *b) {
2085 	int x, y;
2086 
2087 	/* Dont test collision against myself */
2088 	if(n->t == m->t) {
2089 		if(memcmp((const void *) n->s, (const void *) m->s, n->t) == 0) return;
2090 	}
2091 
2092 	x = widget_init_stack_collision_it(a->x, b->x, b->x + b->w) || \
2093 		widget_init_stack_collision_it(b->x, a->x, a->x + a->w);
2094 	y = widget_init_stack_collision_it(a->y, b->y, b->y + b->h) || \
2095 		widget_init_stack_collision_it(b->y, a->y, a->y + a->h);
2096 
2097 	/* Put widgets to collision array if they collide */
2098 	if(x && y != 0) {
2099 		(void) widget_init_stack_collision_at(&d->o, c);
2100 		(void) widget_init_stack_collision_at(&c->o, d);
2101 
2102 /* XXX MEMO printf("collision %s with %s : %p (%d), %p (%d) \n",
2103 	m->s, n->s, c->o.d[c->o.c - 1], c->o.c, d->o.d[d->o.c - 1], d->o.c); */
2104 
2105 	}
2106 }
2107 
widget_init_stack_collision_it(int v,int a,int b)2108 static int widget_init_stack_collision_it(int v, int a, int b) {
2109 	return((v >= a) && (v <= b));
2110 }
2111 
widget_init_stack_collision_at(struct w_collision * c,struct w_info * d)2112 static int widget_init_stack_collision_at(struct w_collision *c, struct w_info *d) {
2113 	struct w_info **t;
2114 
2115 	APP_REALLOC_RET_VALUE(t, c->d, sizeof(struct w_info *) * (c->c + 1), -1);
2116 
2117 	c->d[c->c++] = d;
2118 
2119 	return(0);
2120 }
2121 
widget_init_stack_def(struct w_stack * w)2122 void widget_init_stack_def(struct w_stack *w) {
2123 	w->a = NULL;
2124 	w->c = 0;
2125 
2126 	w->bb = NULL;
2127 	w->mb = NULL;
2128 
2129 	w->n.c = 0;
2130 	w->q.c = 0;
2131 	w->o.c = 0;
2132 }
2133 
widget_free_stack(struct w_stack * w)2134 void widget_free_stack(struct w_stack *w) {
2135 	unsigned int i;
2136 
2137 	/* Free widgets */
2138 	if(w->a != NULL) {
2139 		for(i = 0; i < w->c; i++) (void) widget_free_widget(w->a[i]);
2140 
2141 		(void) free(w->a);
2142 
2143 		w->a = NULL;
2144 		w->c = 0;
2145 	}
2146 
2147 	/* Free background buffers */
2148 	if(w->bb != NULL) {
2149 		(void) free(w->bb);
2150 
2151 		w->bb = NULL;
2152 	}
2153 
2154 	if(w->mb != NULL) {
2155 		(void) free(w->mb);
2156 
2157 		w->mb = NULL;
2158 	}
2159 }
2160 
widget_free_widget(struct w_info * d)2161 static void widget_free_widget(struct w_info *d) {
2162 	struct widget_id *e;
2163 	struct widget_title *f;
2164 
2165 	struct widget_type_background *w_ba;
2166 	struct widget_type_block *w_bl;
2167 	struct widget_type_slideswitch *w_ss;
2168 	struct widget_type_toggleswitch *w_ts;
2169 	struct widget_type_turnswitch *w_tw;
2170 
2171 	if(d == NULL) return;
2172 
2173 	switch(d->c) {
2174 		case WIDGET_TYPE_BACKGROUND:
2175 			w_ba = (struct widget_type_background *) d->p;
2176 
2177 			if(w_ba->s != NULL) (void) free(w_ba->s);
2178 
2179 			break;
2180 		case WIDGET_TYPE_BLOCK:
2181 			w_bl = (struct widget_type_block *) d->p;
2182 
2183 			if(w_bl->s != NULL) (void) free(w_bl->s);
2184 			if(w_bl->u != NULL) (void) free(w_bl->u);
2185 
2186 			break;
2187 		case WIDGET_TYPE_SLIDESWITCH:
2188 			w_ss = (struct widget_type_slideswitch *) d->p;
2189 
2190 			(void) widget_free_widget_scale(&w_ss->s);
2191 			(void) widget_free_widget_indicator(&w_ss->i);
2192 
2193 			break;
2194 		case WIDGET_TYPE_TOGGLESWITCH:
2195 			w_ts = (struct widget_type_toggleswitch *) d->p;
2196 
2197 			(void) widget_free_widget_scale(&w_ts->s);
2198 			(void) widget_free_widget_indicator(&w_ts->i);
2199 
2200 			break;
2201 		case WIDGET_TYPE_TURNSWITCH:
2202 			w_tw = (struct widget_type_turnswitch *) d->p;
2203 
2204 			(void) widget_free_widget_scale(&w_tw->s);
2205 			(void) widget_free_widget_indicator(&w_tw->i);
2206 
2207 			break;
2208 		default:
2209 			break;
2210 	}
2211 
2212 	if(d->f != NULL) {
2213 		f = (struct widget_title *) d->f;
2214 
2215 		if(f->f != 0) (void) fonts_close(f->f);
2216 	}
2217 
2218 	if(d->e != NULL) {
2219 		e = (struct widget_id *) d->e;
2220 
2221 		if(e->f != IS_NO && e->s != NULL) {
2222 			(void) free(e->s);
2223 		}
2224 
2225 		if(e->g != IS_NO) (void) free(d->p);
2226 	}
2227 
2228 	if(d->o.d != NULL) (void) free(d->o.d);
2229 	if(d->m_f != NULL) (void) free(d->m_f);
2230 
2231 	(void) widget_free_widget_par(d);
2232 
2233 	(void) free(d);
2234 }
2235 
widget_free_widget_scale(struct widget_scale * c)2236 static void widget_free_widget_scale(struct widget_scale *c) {
2237 	unsigned int i;
2238 
2239 	for(i = 0; i < c->k; i++) (void) fonts_close(c->t.p[i].f);
2240 
2241 	if(c->g != NULL) (void) free(c->g);
2242 	if(c->m != NULL) (void) free(c->m);
2243 
2244 	if(c->p.p != NULL) (void) free(c->p.p);
2245 	if(c->t.p != NULL) (void) free(c->t.p);
2246 }
2247 
widget_free_widget_indicator(struct widget_indicator * i)2248 static void widget_free_widget_indicator(struct widget_indicator *i) {
2249 	if(i->f != 0) (void) fonts_close(i->f);
2250 
2251 	if(i->fc != NULL) (void) free(i->fc);
2252 	if(i->fs != NULL) (void) free(i->fs);
2253 }
2254 
widget_free_widget_par(struct w_info * d)2255 static void widget_free_widget_par(struct w_info *d) {
2256 	if(d->par_pushbutton_push.s != NULL) (void) free(d->par_pushbutton_push.s);
2257 	if(d->par_slideswitch_slide.s != NULL) (void) free(d->par_slideswitch_slide.s);
2258 	if(d->par_toggleswitch_toggle.s != NULL) (void) free(d->par_toggleswitch_toggle.s);
2259 	if(d->par_turnswitch_turn.s != NULL) (void) free(d->par_turnswitch_turn.s);
2260 
2261 	if(d->par_generic_key_press.s != NULL) (void) free(d->par_generic_key_press.s);
2262 	if(d->par_generic_key_release.s != NULL) (void) free(d->par_generic_key_release.s);
2263 	if(d->par_generic_button_press.s != NULL) (void) free(d->par_generic_button_press.s);
2264 	if(d->par_generic_button_release.s != NULL) (void) free(d->par_generic_button_release.s);
2265 }
2266 
2267 /**
2268  * @brief Create new block widget.
2269  *
2270  * It is necessary to call widget_update_color()/widget_update_image() to set widget outlook,
2271  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2272  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2273  *
2274  * @param[in] w Widget stack info structure
2275  * @param[in] s Widget unique name
2276  * @param[in] x Widget x position in pixels
2277  * @param[in] y Widget y position in pixels
2278  * @param[in] e Widget width in pixels
2279  * @param[in] f Widget height in pixels
2280  *
2281  * @retval Zero on success
2282  * @retval Non-zero on failure
2283  *
2284  */
2285 
widget_create_block(struct w_stack * w,char * s,int x,int y,unsigned int e,unsigned int f)2286 int widget_create_block(struct w_stack *w, char *s, int x, int y, unsigned int e, unsigned int f) {
2287 	size_t u;
2288 
2289 	struct widget_type_block *p;
2290 
2291 	u = sizeof(struct widget_type_block);
2292 
2293 	if((p = (struct widget_type_block *) widget_create_op_alloc(u)) == NULL) {
2294 		return(-1);
2295 	}
2296 
2297 	/* Set defaults and create widget */
2298 	p->set = w->set;
2299 
2300 	p->s = NULL;
2301 
2302 	p->c.pixel.p = WIDGET_DEFAULT_COLOR;
2303 
2304 	p->u = NULL;
2305 
2306 	return(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, e, f, WIDGET_TYPE_BLOCK));
2307 }
2308 
2309 /**
2310  * @brief Create new label widget.
2311  *
2312  * It is necessary to call widget_update_label() to set widget label, and widget_refresh() afterwards
2313  * to update changes to window. New widget belongs to set whichever is active when widget is created.
2314  * See widget_change_set().
2315  *
2316  * @param[in] w Widget stack info structure
2317  * @param[in] s Widget unique name
2318  * @param[in] x Widget x position in pixels
2319  * @param[in] y Widget y position in pixels
2320  *
2321  * @retval Zero on success
2322  * @retval Non-zero on failure
2323  *
2324  */
2325 
widget_create_label(struct w_stack * w,char * s,int x,int y)2326 int widget_create_label(struct w_stack *w, char *s, int x, int y) {
2327 	size_t u;
2328 
2329 	struct w_info *d;
2330 	struct widget_type_label *p;
2331 
2332 	u = sizeof(struct widget_type_label);
2333 
2334 	if((p = (struct widget_type_label *) widget_create_op_alloc(u)) == NULL) {
2335 		return(-1);
2336 	}
2337 
2338 	/* Set defaults and create widget */
2339 	p->set = w->set;
2340 
2341 	p->t.s = NULL;
2342 	p->t.t = 0;
2343 
2344 	p->t.c = NULL;
2345 	p->t.e = NULL;
2346 
2347 	p->t.d = (unsigned int) c_font_dpi;
2348 	p->t.y = (unsigned int) c_font_size;
2349 
2350 	if(p->t.d == 0) p->t.d = (unsigned int) round(window_get_dpi_height());
2351 
2352 	p->t.r.pixel.p = WIDGET_DEFAULT_COLOR;
2353 
2354 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2355 	p->t.f = 0;
2356 
2357 	p->t.i.x = 0;
2358 	p->t.i.y = 0;
2359 	p->t.i.f = 0;
2360 
2361 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, 0, 0, WIDGET_TYPE_LABEL) != 0) {
2362 		return(-1);
2363 	}
2364 
2365 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2366 		return(-1);
2367 	}
2368 
2369 	/* Store widget_title structure to w_info as well */
2370 	d->f = (void *) &p->t;
2371 
2372 	return(0);
2373 }
2374 
2375 /**
2376  * @brief Create new lamp widget.
2377  *
2378  * It is necessary to call widget_update_label() to set widget label,
2379  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2380  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2381  *
2382  * @param[in] w Widget stack info structure
2383  * @param[in] s Widget unique name
2384  * @param[in] x Widget x position in pixels
2385  * @param[in] y Widget y position in pixels
2386  * @param[in] o Widget subtype
2387  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2388  * @param[in] o_x Widget title finetune x position offset in pixels
2389  * @param[in] o_y Widget title finetune y position offset in pixels
2390  *
2391  * @retval Zero on success
2392  * @retval Non-zero on failure
2393  *
2394  */
2395 
widget_create_lamp(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y)2396 int widget_create_lamp(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y) {
2397 	unsigned int a_w, a_h, b_w, b_h;
2398 
2399 	size_t u;
2400 
2401 	struct w_info *d;
2402 	struct widget_type_lamp *p;
2403 
2404 	u = sizeof(struct widget_type_lamp);
2405 
2406 	if((p = (struct widget_type_lamp *) widget_create_op_alloc(u)) == NULL) {
2407 		return(-1);
2408 	}
2409 
2410 	/* Set defaults and create widget */
2411 	p->set = w->set;
2412 
2413 	p->o = o;
2414 	p->k = k;
2415 
2416 	p->ox = o_x;
2417 	p->oy = o_y;
2418 
2419 	p->a = 0;
2420 	p->b = WIDGET_FRAME_LAMP_ANGLES;
2421 	p->c = 2;
2422 	p->d = 0;
2423 
2424 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2425 	p->t.f = 0;
2426 
2427 	p->t.i.x = 0;
2428 	p->t.i.y = 0;
2429 	p->t.i.f = 0;
2430 
2431 	(void) widget_init_stack_bob_predraw_size(WIDGET_GFX_LAMP,
2432 		o, &a_w, &a_h, &b_w, &b_h);
2433 
2434 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, WIDGET_TYPE_LAMP) != 0) {
2435 		return(-1);
2436 	}
2437 
2438 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2439 		return(-1);
2440 	}
2441 
2442 	/* Store widget_title structure to w_info as well */
2443 	d->f = (void *) &p->t;
2444 
2445 	return(0);
2446 }
2447 
2448 /**
2449  * @brief Create new led widgets.
2450  *
2451  * It is necessary to call widget_update_label() to set widget label,
2452  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2453  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2454  *
2455  * @param[in] w Widget stack info structure
2456  * @param[in] s Widget unique name
2457  * @param[in] x Widget x position in pixels
2458  * @param[in] y Widget y position in pixels
2459  * @param[in] o Widget subtype
2460  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2461  * @param[in] o_x Widget title finetune x position offset in pixels
2462  * @param[in] o_y Widget title finetune y position offset in pixels
2463  *
2464  * @retval Zero on success
2465  * @retval Non-zero on failure
2466  *
2467  */
2468 
widget_create_led_1(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y)2469 int widget_create_led_1(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y) {
2470 	return(widget_create_led_op(w, s, x, y, o, k, o_x, o_y,
2471 		WIDGET_GFX_LED_1, WIDGET_TYPE_LED_1));
2472 }
2473 
widget_create_led_2(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y)2474 int widget_create_led_2(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y) {
2475 	return(widget_create_led_op(w, s, x, y, o, k, o_x, o_y,
2476 		WIDGET_GFX_LED_2, WIDGET_TYPE_LED_2));
2477 }
2478 
widget_create_led_3(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y)2479 int widget_create_led_3(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y) {
2480 	return(widget_create_led_op(w, s, x, y, o, k, o_x, o_y,
2481 		WIDGET_GFX_LED_3, WIDGET_TYPE_LED_3));
2482 }
2483 
widget_create_led_op(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int g,unsigned int t)2484 static int widget_create_led_op(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int g, unsigned int t) {
2485 	unsigned int a_w, a_h, b_w, b_h;
2486 
2487 	size_t u;
2488 
2489 	struct w_info *d;
2490 	struct widget_type_led *p;
2491 
2492 	u = sizeof(struct widget_type_led);
2493 
2494 	if((p = (struct widget_type_led *) widget_create_op_alloc(u)) == NULL) {
2495 		return(-1);
2496 	}
2497 
2498 	/* Set defaults and create widget */
2499 	p->set = w->set;
2500 
2501 	p->o = o;
2502 	p->k = k;
2503 
2504 	p->ox = o_x;
2505 	p->oy = o_y;
2506 
2507 	p->a = 0;
2508 	p->b = WIDGET_FRAME_LED_ANGLES;
2509 	p->c = 2;
2510 	p->d = 0;
2511 
2512 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2513 	p->t.f = 0;
2514 
2515 	p->t.i.x = 0;
2516 	p->t.i.y = 0;
2517 	p->t.i.f = 0;
2518 
2519 	(void) widget_init_stack_bob_predraw_size(g, o, &a_w, &a_h, &b_w, &b_h);
2520 
2521 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, t) != 0) {
2522 		return(-1);
2523 	}
2524 
2525 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2526 		return(-1);
2527 	}
2528 
2529 	/* Store widget_title structure to w_info as well */
2530 	d->f = (void *) &p->t;
2531 
2532 	return(0);
2533 }
2534 
2535 /**
2536  * @brief Create new pushbutton widgets.
2537  *
2538  * It is necessary to call widget_update_label() to set widget label, widget_cb_add_*() to make it useable,
2539  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2540  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2541  *
2542  * @param[in] w Widget stack info structure
2543  * @param[in] s Widget unique name
2544  * @param[in] x Widget x position in pixels
2545  * @param[in] y Widget y position in pixels
2546  * @param[in] o Widget subtype
2547  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2548  * @param[in] o_x Widget title finetune x position offset in pixels
2549  * @param[in] o_y Widget title finetune y position offset in pixels
2550  * @param[in] z Widget state is sticky (IS_NO|IS_YES)
2551  *
2552  * @retval Zero on success
2553  * @retval Non-zero on failure
2554  *
2555  */
2556 
widget_create_pushbutton_1(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int z)2557 int widget_create_pushbutton_1(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int z) {
2558 	return(widget_create_pushbutton_op(w, s, x, y, o, k, o_x, o_y, z,
2559 		WIDGET_GFX_PUSHBUTTON_1, WIDGET_TYPE_PUSHBUTTON_1));
2560 }
2561 
widget_create_pushbutton_2(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int z)2562 int widget_create_pushbutton_2(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int z) {
2563 	return(widget_create_pushbutton_op(w, s, x, y, o, k, o_x, o_y, z,
2564 		WIDGET_GFX_PUSHBUTTON_2, WIDGET_TYPE_PUSHBUTTON_2));
2565 }
2566 
widget_create_pushbutton_3(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int z)2567 int widget_create_pushbutton_3(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int z) {
2568 	return(widget_create_pushbutton_op(w, s, x, y, o, k, o_x, o_y, z,
2569 		WIDGET_GFX_PUSHBUTTON_3, WIDGET_TYPE_PUSHBUTTON_3));
2570 }
2571 
widget_create_pushbutton_op(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int z,unsigned int g,unsigned int t)2572 static int widget_create_pushbutton_op(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int z, unsigned int g, unsigned int t) {
2573 	unsigned int a_w, a_h, b_w, b_h;
2574 
2575 	size_t u;
2576 
2577 	struct w_info *d;
2578 	struct widget_type_pushbutton *p;
2579 
2580 	u = sizeof(struct widget_type_pushbutton);
2581 
2582 	if((p = (struct widget_type_pushbutton *) widget_create_op_alloc(u)) == NULL) {
2583 		return(-1);
2584 	}
2585 
2586 	/* Set defaults and create widget */
2587 	p->set = w->set;
2588 
2589 	p->o = o;
2590 	p->k = k;
2591 
2592 	p->ox = o_x;
2593 	p->oy = o_y;
2594 
2595 	p->a = 0;
2596 	p->b = WIDGET_FRAME_PUSHBUTTON_ANGLES;
2597 	p->c = 2;
2598 	p->d = 0;
2599 
2600 	p->z = z;
2601 
2602 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2603 	p->t.f = 0;
2604 
2605 	p->t.i.x = 0;
2606 	p->t.i.y = 0;
2607 	p->t.i.f = 0;
2608 
2609 	(void) widget_init_stack_bob_predraw_size(g, o, &a_w, &a_h, &b_w, &b_h);
2610 
2611 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, t) != 0) {
2612 		return(-1);
2613 	}
2614 
2615 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2616 		return(-1);
2617 	}
2618 
2619 	/* Store widget_title structure to w_info as well */
2620 	d->f = (void *) &p->t;
2621 
2622 	return(0);
2623 }
2624 
2625 /**
2626  * @brief Create new slideswitch widget.
2627  *
2628  * It is necessary to call widget_update_label() to set widget label, widget_cb_add_*() to make it useable,
2629  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2630  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2631  *
2632  * @param[in] w Widget stack info structure
2633  * @param[in] s Widget unique name
2634  * @param[in] x Widget x position in pixels
2635  * @param[in] y Widget y position in pixels
2636  * @param[in] o Widget subtype
2637  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2638  * @param[in] o_x Widget title finetune x position offset in pixels
2639  * @param[in] o_y Widget title finetune y position offset in pixels
2640  * @param[in] b Widget slide length in pixels
2641  * @param[in] c Widget steps within slide length
2642  * @param[in] t Widget start step
2643  *
2644  * @retval Zero on success
2645  * @retval Non-zero on failure
2646  *
2647  */
2648 
widget_create_slideswitch(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int b,unsigned int c,unsigned int t)2649 int widget_create_slideswitch(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int b, unsigned int c, unsigned int t) {
2650 	unsigned int a_w, a_h;
2651 
2652 	size_t u;
2653 
2654 	struct pixel_rgba_8 b_c;
2655 
2656 	struct w_info *d;
2657 	struct widget_type_slideswitch *p;
2658 
2659 	u = sizeof(struct widget_type_slideswitch);
2660 
2661 	if((p = (struct widget_type_slideswitch *) widget_create_op_alloc(u)) == NULL) {
2662 		return(-1);
2663 	}
2664 
2665 	/* Set defaults and create widget */
2666 	p->set = w->set;
2667 
2668 	p->o = o;
2669 	p->k = k;
2670 
2671 	p->ox = o_x;
2672 	p->oy = o_y;
2673 
2674 	p->a = 0;
2675 	p->b = b;
2676 	p->c = c;
2677 	p->d = t;
2678 
2679 	p->g = IS_YES;
2680 
2681 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2682 	p->t.f = 0;
2683 
2684 	p->t.i.x = 0;
2685 	p->t.i.y = 0;
2686 	p->t.i.f = 0;
2687 
2688 	p->s.p.c = 0;
2689 	p->s.p.p = NULL;
2690 
2691 	p->s.t.c = 0;
2692 	p->s.t.p = NULL;
2693 
2694 	p->i.f = 0;
2695 	p->i.c = WIDGET_INDICATOR_MODE_DISABLE;
2696 
2697 	(void) widget_init_stack_bob_predraw_size(WIDGET_GFX_SLIDESWITCH,
2698 		o, &a_w, &a_h, NULL, NULL);
2699 
2700 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, WIDGET_TYPE_SLIDESWITCH) != 0) {
2701 		return(-1);
2702 	}
2703 
2704 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2705 		return(-1);
2706 	}
2707 
2708 	/* Allocate either vertical or horizontal container */
2709 	if(o % 2 == 0) {
2710 		p->p.w = a_w + p->b;
2711 		p->p.h = a_h;
2712 	}
2713 	else {
2714 		p->p.w = a_w;
2715 		p->p.h = a_h + p->b;
2716 	}
2717 
2718 	/* Store container geometry for positioning the title relative to it */
2719 	p->q.x = p->p.x;
2720 	p->q.y = p->p.y;
2721 	p->q.w = p->p.w;
2722 	p->q.h = p->p.h;
2723 
2724 	b_c.pixel.p = 0;
2725 
2726 	(void) widget_init_stack_bob_au(w, d, &p->p, &b_c, &b_c, 0);
2727 
2728 	if(widget_init_stack_bob_at(w, d, &p->t, &p->p, &p->q, WIDGET_GFX_SLIDESWITCH,
2729 		p->o, p->ch, p->k, p->a, p->b, p->c, p->d,
2730 		p->ox, p->oy, 0.0) != 0) return(-1);
2731 
2732 	/* Re-set slider current position and adjust its initial placement */
2733 	p->d = t;
2734 
2735 	if(p->o % 2 == 0) {
2736 		(void) widget_init_stack_bob_sl_h(w, d, p);
2737 
2738 		d->x = p->p.x + (unsigned int) round(maths_map((double) p->d,
2739 			0.0, (double) p->c, 0.0, (double) p->b));
2740 	}
2741 	else {
2742 		(void) widget_init_stack_bob_sl_v(w, d, p);
2743 
2744 		d->y = p->p.y + p->b - (unsigned int) round(maths_map((double) p->d,
2745 			0.0, (double) p->c, 0.0, (double) p->b));
2746 	}
2747 
2748 	/* Store widget_title structure to w_info as well */
2749 	d->f = (void *) &p->t;
2750 
2751 	return(0);
2752 }
2753 
2754 /**
2755  * @brief Create new toggleswitch widget.
2756  *
2757  * It is necessary to call widget_update_label() to set widget label, widget_cb_add_*() to make it useable,
2758  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2759  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2760  *
2761  * @param[in] w Widget stack info structure
2762  * @param[in] s Widget unique name
2763  * @param[in] x Widget x position in pixels
2764  * @param[in] y Widget y position in pixels
2765  * @param[in] o Widget subtype
2766  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2767  * @param[in] o_x Widget title finetune x position offset in pixels
2768  * @param[in] o_y Widget title finetune y position offset in pixels
2769  * @param[in] c Widget moveable steps between min and max positions
2770  * @param[in] t Widget start step
2771  *
2772  * @retval Zero on success
2773  * @retval Non-zero on failure
2774  *
2775  */
2776 
widget_create_toggleswitch(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int c,unsigned int t)2777 int widget_create_toggleswitch(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int c, unsigned int t) {
2778 	unsigned int a_w, a_h, b_w, b_h;
2779 
2780 	size_t u;
2781 
2782 	struct w_info *d;
2783 	struct widget_type_toggleswitch *p;
2784 
2785 	u = sizeof(struct widget_type_toggleswitch);
2786 
2787 	if((p = (struct widget_type_toggleswitch *) widget_create_op_alloc(u)) == NULL) {
2788 		return(-1);
2789 	}
2790 
2791 	/* Set defaults and create widget */
2792 	p->set = w->set;
2793 
2794 	p->o = o;
2795 	p->k = k;
2796 
2797 	p->ox = o_x;
2798 	p->oy = o_y;
2799 
2800 	p->a = 0;
2801 	p->b = WIDGET_FRAME_TOGGLESWITCH_ANGLES;
2802 	p->c = c;
2803 	p->d = t;
2804 
2805 	p->g = IS_YES;
2806 
2807 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2808 	p->t.f = 0;
2809 
2810 	p->t.i.x = 0;
2811 	p->t.i.y = 0;
2812 	p->t.i.f = 0;
2813 
2814 	p->s.p.c = 0;
2815 	p->s.p.p = NULL;
2816 
2817 	p->s.t.c = 0;
2818 	p->s.t.p = NULL;
2819 
2820 	p->i.f = 0;
2821 	p->i.c = WIDGET_INDICATOR_MODE_DISABLE;
2822 
2823 	(void) widget_init_stack_bob_predraw_size(WIDGET_GFX_TOGGLESWITCH,
2824 		o, &a_w, &a_h, &b_w, &b_h);
2825 
2826 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, WIDGET_TYPE_TOGGLESWITCH) != 0) {
2827 		return(-1);
2828 	}
2829 
2830 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2831 		return(-1);
2832 	}
2833 
2834 	/* Store widget_title structure to w_info as well */
2835 	d->f = (void *) &p->t;
2836 
2837 	return(0);
2838 }
2839 
2840 /**
2841  * @brief Create new turnswitch widget.
2842  *
2843  * It is necessary to call widget_update_label() to set widget label, widget_cb_add_*() to make it useable,
2844  * widget_enable() to enable widget, and widget_refresh() afterwards to update changes to window.
2845  * New widget belongs to set whichever is active when widget is created. See widget_change_set().
2846  *
2847  * @param[in] w Widget stack info structure
2848  * @param[in] s Widget unique name
2849  * @param[in] x Widget x position in pixels
2850  * @param[in] y Widget y position in pixels
2851  * @param[in] o Widget subtype
2852  * @param[in] k Widget title position (WIDGET_TITLE_POSITION_*)
2853  * @param[in] o_x Widget title finetune x position offset in pixels
2854  * @param[in] o_y Widget title finetune y position offset in pixels
2855  * @param[in] a Widget minimum position angle (-> 0)
2856  * @param[in] b Widget maximum position angle (<- 359)
2857  * @param[in] c Widget moveable steps between min and max position angles
2858  * @param[in] t Widget start step
2859  *
2860  * @retval Zero on success
2861  * @retval Non-zero on failure
2862  *
2863  */
2864 
widget_create_turnswitch(struct w_stack * w,char * s,int x,int y,unsigned int o,unsigned int k,int o_x,int o_y,unsigned int a,unsigned int b,unsigned int c,unsigned int t)2865 int widget_create_turnswitch(struct w_stack *w, char *s, int x, int y, unsigned int o, unsigned int k, int o_x, int o_y, unsigned int a, unsigned int b, unsigned int c, unsigned int t) {
2866 	unsigned int a_w, a_h, b_w, b_h;
2867 
2868 	size_t u;
2869 
2870 	struct w_info *d;
2871 	struct widget_type_turnswitch *p;
2872 
2873 	if(b >= WIDGET_FRAME_TURNSWITCH_ANGLES) {
2874 		(void) flush_error();
2875 
2876 		LOGWARN(
2877 			ERROR_SLIGHT, SUBSYSTEM,
2878 			_("Widget %s parameter %u is out of range, please check widget parameters"),
2879 			s, b
2880 		);
2881 
2882 		return(-1);
2883 	}
2884 
2885 	u = sizeof(struct widget_type_turnswitch);
2886 
2887 	if((p = (struct widget_type_turnswitch *) widget_create_op_alloc(u)) == NULL) {
2888 		return(-1);
2889 	}
2890 
2891 	/* Set defaults and create widget */
2892 	p->set = w->set;
2893 
2894 	p->o = o;
2895 	p->k = k;
2896 
2897 	p->ox = o_x;
2898 	p->oy = o_y;
2899 
2900 	p->a = a;
2901 	p->b = b;
2902 	p->c = c;
2903 	p->d = t;
2904 
2905 	p->g = IS_YES;
2906 
2907 	p->t.j = WIDGET_DEFAULT_JUSTIFICATION;
2908 	p->t.f = 0;
2909 
2910 	p->t.i.x = 0;
2911 	p->t.i.y = 0;
2912 	p->t.i.f = 0;
2913 
2914 	p->s.p.c = 0;
2915 	p->s.p.p = NULL;
2916 
2917 	p->s.t.c = 0;
2918 	p->s.t.p = NULL;
2919 
2920 	p->i.f = 0;
2921 	p->i.c = WIDGET_INDICATOR_MODE_DISABLE;
2922 
2923 	(void) widget_init_stack_bob_predraw_size(WIDGET_GFX_TURNSWITCH,
2924 		o, &a_w, &a_h, &b_w, &b_h);
2925 
2926 	if(widget_create_it(w, &p->e, &p->p, (void *) p, s, x, y, a_w, a_h, WIDGET_TYPE_TURNSWITCH) != 0) {
2927 		return(-1);
2928 	}
2929 
2930 	if((d = widget_get_info_by_name(w, s)) == NULL) {
2931 		return(-1);
2932 	}
2933 
2934 	/* Store widget_title structure to w_info as well */
2935 	d->f = (void *) &p->t;
2936 
2937 	return(0);
2938 }
2939 
widget_create_it(struct w_stack * w,struct widget_id * d,struct widget_geometry * g,void * p,char * s,int x,int y,unsigned int e,unsigned int f,unsigned int c)2940 static int widget_create_it(struct w_stack *w, struct widget_id *d, struct widget_geometry *g, void *p, char *s, int x, int y, unsigned int e, unsigned int f, unsigned int c) {
2941 	(void) widget_create_op_gm(g, x, y, e, f);
2942 
2943 	if(widget_create_op_id(d, s) != 0) {
2944 		(void) free(p);
2945 
2946 		return(-1);
2947 	}
2948 
2949 	if(widget_create_op(w, d, (void *) p, c) != 0) {
2950 		(void) free(d->s);
2951 		(void) free(p);
2952 
2953 		return(-1);
2954 	}
2955 
2956 /* XXX TODO check collision */
2957 
2958 	return(0);
2959 }
2960 
widget_create_op(struct w_stack * w,struct widget_id * e,void * p,unsigned int c)2961 static int widget_create_op(struct w_stack *w, struct widget_id *e, void *p, unsigned int c) {
2962 	struct w_info *d;
2963 
2964 	if(w->mb == NULL) {
2965 		/* Allocate mouse mask buffer for container window */
2966 		if(widget_init_stack_op(w) != 0) return(-1);
2967 	}
2968 
2969 	if((d = widget_init_stack_alloc(w, c, p)) == NULL) return(-1);
2970 
2971 	/* Store widget_id and widget_type_* structures to w_info as well */
2972 	d->e = (void *) e;
2973 	d->p = (void *) p;
2974 
2975 	/* Tag widget type structure as allocated */
2976 	e->g = IS_YES;
2977 
2978 	return(0);
2979 }
2980 
widget_create_op_id(struct widget_id * d,char * s)2981 static int widget_create_op_id(struct widget_id *d, char *s) {
2982 	if(s == NULL) return(-1);
2983 
2984 	d->t = str_len(s, STRING_ASCII);
2985 
2986 	APP_MALLOC_RET_VALUE(d->s, d->t + sizeof(char), -1);
2987 
2988 	(void) memcpy((void *) d->s, (const void *) s, d->t);
2989 
2990 	d->s[d->t] = 0;
2991 
2992 	/* Tag widget unique name as allocated */
2993 	d->f = IS_YES;
2994 
2995 	d->c = WIDGET_STATE_DISABLE;
2996 
2997 	return(0);
2998 }
2999 
widget_create_op_gm(struct widget_geometry * d,int x,int y,unsigned int w,unsigned int h)3000 static void widget_create_op_gm(struct widget_geometry *d, int x, int y, unsigned int w, unsigned int h) {
3001 	d->x = x;
3002 	d->y = y;
3003 	d->w = w;
3004 	d->h = h;
3005 }
3006 
widget_create_op_alloc(size_t t)3007 static void *widget_create_op_alloc(size_t t) {
3008 	void *r;
3009 
3010 	APP_MALLOC_RET_VALUE(r, t, NULL);
3011 
3012 	(void) memset((void *) r, 0, t);
3013 
3014 	return(r);
3015 }
3016 
3017 /**
3018  * @brief Delete existing widget.
3019  *
3020  * It is necessary to call widget_refresh() afterwards to update changes to window.
3021  *
3022  * @param[in] w Widget stack info structure
3023  * @param[in] s Widget name to delete
3024  *
3025  * @retval Zero on success
3026  * @retval Non-zero on failure
3027  *
3028  */
3029 
widget_delete(struct w_stack * w,char * s)3030 int widget_delete(struct w_stack *w, char *s) {
3031 	unsigned int i, j;
3032 
3033 	struct w_info *d;
3034 
3035 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3036 
3037 	/* Set this widget slot as null in widget stack array... */
3038 	for(i = 0; i < w->c; i++) {
3039 		if(w->a[i] == NULL) continue;
3040 
3041 		if(w->a[i]->m_id.c == d->m_id.c) {
3042 			w->a[i] = NULL;
3043 
3044 			break;
3045 		}
3046 	}
3047 
3048 	/* ...and get rid of it */
3049 	(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
3050 	(void) widget_init_stack_bob_rems(w, d);
3051 	(void) widget_free_widget(d);
3052 
3053 /* XXX TODO dont _free_widget here because 'd' can be in someone else's collision array */
3054 
3055 	/* Remove unused slots from widget structure array */
3056 	for(i = 0; i < w->c; i++) {
3057 		if(w->a[i] == NULL) {
3058 			for(j = i; j < w->c; j++) w->a[j] = w->a[j + 1];
3059 
3060 			--w->c;
3061 		}
3062 	}
3063 
3064 	return(0);
3065 }
3066 
3067 /**
3068  * @brief Disable enabled widget.
3069  *
3070  * It is necessary to call widget_refresh() afterwards to update changes to window.
3071  *
3072  * @param[in] w Widget stack info structure
3073  * @param[in] s Widget name to disable
3074  *
3075  * @retval Zero on success
3076  * @retval Non-zero on failure
3077  *
3078  */
3079 
widget_disable(struct w_stack * w,char * s)3080 int widget_disable(struct w_stack *w, char *s) {
3081 	struct w_info *d;
3082 
3083 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3084 
3085 	return(widget_state(w, d, WIDGET_STATE_DISABLE));
3086 }
3087 
3088 /**
3089  * @brief Enable disabled widget.
3090  *
3091  * It is necessary to call widget_refresh() afterwards to update changes to window.
3092  *
3093  * @param[in] w Widget stack info structure
3094  * @param[in] s Widget name to enable
3095  *
3096  * @retval Zero on success
3097  * @retval Non-zero on failure
3098  *
3099  */
3100 
widget_enable(struct w_stack * w,char * s)3101 int widget_enable(struct w_stack *w, char *s) {
3102 	struct w_info *d;
3103 
3104 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3105 
3106 	return(widget_state(w, d, WIDGET_STATE_ENABLE));
3107 }
3108 
widget_state(struct w_stack * w,struct w_info * d,unsigned int c)3109 static int widget_state(struct w_stack *w, struct w_info *d, unsigned int c) {
3110 	struct widget_type_background *w_ba;
3111 	struct widget_type_block *w_bl;
3112 	struct widget_type_label *w_la;
3113 	struct widget_type_lamp *w_lm;
3114 	struct widget_type_led *w_le;
3115 	struct widget_type_pushbutton *w_pb;
3116 	struct widget_type_slideswitch *w_ss;
3117 	struct widget_type_toggleswitch *w_ts;
3118 	struct widget_type_turnswitch *w_tw;
3119 
3120 	switch(d->c) {
3121 		case WIDGET_TYPE_BACKGROUND:
3122 			w_ba = (struct widget_type_background *) d->p;
3123 
3124 			if(widget_state_op(w, d, &w_ba->e.c, c, w_ba->s) != 0) return(-1);
3125 
3126 			break;
3127 		case WIDGET_TYPE_BLOCK:
3128 			w_bl = (struct widget_type_block *) d->p;
3129 
3130 			if(widget_state_op(w, d, &w_bl->e.c, c, w_bl->s) != 0) return(-1);
3131 
3132 			break;
3133 		case WIDGET_TYPE_LABEL:
3134 			w_la = (struct widget_type_label *) d->p;
3135 
3136 			if(widget_state_op(w, d, &w_la->e.c, c, NULL) != 0) return(-1);
3137 
3138 			break;
3139 		case WIDGET_TYPE_LAMP:
3140 			w_lm = (struct widget_type_lamp *) d->p;
3141 
3142 			if(widget_state_op(w, d, &w_lm->e.c, c, NULL) != 0) return(-1);
3143 
3144 			break;
3145 		case WIDGET_TYPE_LED_1:
3146 		case WIDGET_TYPE_LED_2:
3147 		case WIDGET_TYPE_LED_3:
3148 			w_le = (struct widget_type_led *) d->p;
3149 
3150 			if(widget_state_op(w, d, &w_le->e.c, c, NULL) != 0) return(-1);
3151 
3152 			break;
3153 		case WIDGET_TYPE_PUSHBUTTON_1:
3154 		case WIDGET_TYPE_PUSHBUTTON_2:
3155 		case WIDGET_TYPE_PUSHBUTTON_3:
3156 			w_pb = (struct widget_type_pushbutton *) d->p;
3157 
3158 			if(widget_state_op(w, d, &w_pb->e.c, c, NULL) != 0) return(-1);
3159 
3160 			break;
3161 		case WIDGET_TYPE_SLIDESWITCH:
3162 			w_ss = (struct widget_type_slideswitch *) d->p;
3163 
3164 			if(widget_state_op(w, d, &w_ss->e.c, c, NULL) != 0) return(-1);
3165 
3166 			break;
3167 		case WIDGET_TYPE_TOGGLESWITCH:
3168 			w_ts = (struct widget_type_toggleswitch *) d->p;
3169 
3170 			if(widget_state_op(w, d, &w_ts->e.c, c, NULL) != 0) return(-1);
3171 
3172 			break;
3173 		case WIDGET_TYPE_TURNSWITCH:
3174 			w_tw = (struct widget_type_turnswitch *) d->p;
3175 
3176 			if(widget_state_op(w, d, &w_tw->e.c, c, NULL) != 0) return(-1);
3177 
3178 			break;
3179 		default:
3180 			(void) flush_error();
3181 
3182 			LOGWARN(
3183 				ERROR_SLIGHT, SUBSYSTEM,
3184 				_("Widget type %u not supported by this action, please check widget definitions"),
3185 				d->c
3186 			);
3187 
3188 			return(-1);
3189 	}
3190 
3191 	return(0);
3192 }
3193 
widget_state_op(struct w_stack * w,struct w_info * d,unsigned int * c,unsigned int n,char * b)3194 static int widget_state_op(struct w_stack *w, struct w_info *d, unsigned int *c, unsigned int n, char *b) {
3195 	if(*c == n) return(0);
3196 
3197 	*c = n;
3198 
3199 	return(widget_state_it(w, d, n, b));
3200 }
3201 
widget_state_it(struct w_stack * w,struct w_info * d,unsigned int n,char * b)3202 static int widget_state_it(struct w_stack *w, struct w_info *d, unsigned int n, char *b) {
3203 	struct widget_title *t;
3204 
3205 	struct widget_type_slideswitch *w_ss;
3206 	struct widget_type_toggleswitch *w_ts;
3207 	struct widget_type_turnswitch *w_tw;
3208 
3209 	switch(n) {
3210 		case WIDGET_STATE_DISABLE:
3211 			t = (struct widget_title *) d->f;
3212 
3213 			switch(d->c) {
3214 				case WIDGET_TYPE_SLIDESWITCH:
3215 					w_ss = (struct widget_type_slideswitch *) d->p;
3216 
3217 					(void) widget_update_scale_op(w, d, &w_ss->s,
3218 						w_ss->s.b.left, w_ss->s.b.top, w_ss->s.b.s.width, w_ss->s.b.s.height);
3219 					(void) widget_update_indicator_op(w, d, &w_ss->i,
3220 						w_ss->i.ox, w_ss->i.oy, w_ss->i.ow, w_ss->i.oh);
3221 
3222 					break;
3223 				case WIDGET_TYPE_TOGGLESWITCH:
3224 					w_ts = (struct widget_type_toggleswitch *) d->p;
3225 
3226 					(void) widget_update_scale_op(w, d, &w_ts->s,
3227 						w_ts->s.b.left, w_ts->s.b.top, w_ts->s.b.s.width, w_ts->s.b.s.height);
3228 					(void) widget_update_indicator_op(w, d, &w_ts->i,
3229 						w_ts->i.ox, w_ts->i.oy, w_ts->i.ow, w_ts->i.oh);
3230 
3231 					break;
3232 				case WIDGET_TYPE_TURNSWITCH:
3233 					w_tw = (struct widget_type_turnswitch *) d->p;
3234 
3235 					(void) widget_update_scale_op(w, d, &w_tw->s,
3236 						w_tw->s.b.left, w_tw->s.b.top, w_tw->s.b.s.width, w_tw->s.b.s.height);
3237 					(void) widget_update_indicator_op(w, d, &w_tw->i,
3238 						w_tw->i.ox, w_tw->i.oy, w_tw->i.ow, w_tw->i.oh);
3239 
3240 					break;
3241 				default:
3242 					break;
3243 			}
3244 
3245 			(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
3246 			(void) widget_update_it(w, d, &t->b_8, t->i.x, t->i.y,
3247 				fonts_get_width(t->i.f), fonts_get_height(t->i.f));
3248 			(void) widget_init_stack_bob_text_close(t);
3249 			(void) widget_init_stack_bob_rems(w, d);
3250 
3251 			break;
3252 		case WIDGET_STATE_ENABLE:
3253 			switch(d->c) {
3254 				case WIDGET_TYPE_SLIDESWITCH:
3255 					w_ss = (struct widget_type_slideswitch *) d->p;
3256 
3257 					(void) widget_update_scale(w, d, &w_ss->s);
3258 					(void) widget_update_indicator(w, d, &w_ss->i,
3259 						&w_ss->q, w_ss->d, w_ss->k);
3260 
3261 					break;
3262 				case WIDGET_TYPE_TOGGLESWITCH:
3263 					w_ts = (struct widget_type_toggleswitch *) d->p;
3264 
3265 					(void) widget_update_scale(w, d, &w_ts->s);
3266 					(void) widget_update_indicator(w, d, &w_ts->i,
3267 						&w_ts->p, w_ts->d, w_ts->k);
3268 
3269 					break;
3270 				case WIDGET_TYPE_TURNSWITCH:
3271 					w_tw = (struct widget_type_turnswitch *) d->p;
3272 
3273 					(void) widget_update_scale(w, d, &w_tw->s);
3274 					(void) widget_update_indicator(w, d, &w_tw->i,
3275 						&w_tw->p, w_tw->d, w_tw->k);
3276 
3277 					break;
3278 				default:
3279 					break;
3280 			}
3281 
3282 			if(widget_init_stack_bob(w, d, w->set, b) != 0) return(-1);
3283 
3284 			break;
3285 		default:
3286 			return(-1);
3287 	}
3288 
3289 	return(0);
3290 }
3291 
3292 /**
3293  * @brief Change visible widget set.
3294  *
3295  * It is necessary to call widget_refresh() afterwards to update changes to window.
3296  *
3297  * @param[in] w Widget stack info structure
3298  * @param[in] s Widget set to change to
3299  *
3300  * @retval Previous widget set
3301  *
3302  */
3303 
widget_change_set(struct w_stack * w,unsigned int s)3304 unsigned int widget_change_set(struct w_stack *w, unsigned int s) {
3305 	unsigned int h, p;
3306 
3307 	struct w_info *d;
3308 
3309 	p = w->set;
3310 	h = 0;
3311 
3312 	while((d = widget_get_info_by_set(w, p, &h)) != NULL) {
3313 		(void) widget_state_it(w, d, WIDGET_STATE_DISABLE, NULL);
3314 	}
3315 
3316 	w->set = s;
3317 	h = 0;
3318 
3319 	while((d = widget_get_info_by_set(w, s, &h)) != NULL) {
3320 		(void) widget_state_it(w, d, WIDGET_STATE_ENABLE, NULL);
3321 	}
3322 
3323 	return(p);
3324 }
3325 
3326 /**
3327  * @brief Get widget current state/step/position.
3328  *
3329  * @param[in] w Widget stack info structure
3330  * @param[in] s Widget name to get the value
3331  * @param[out] c Current state/step/position
3332  *
3333  * @retval Zero on success
3334  * @retval Non-zero on failure
3335  *
3336  */
3337 
widget_step_get(struct w_stack * w,char * s,unsigned int * c)3338 int widget_step_get(struct w_stack *w, char *s, unsigned int *c) {
3339 	struct w_info *d;
3340 
3341 	struct widget_type_lamp *w_lm;
3342 	struct widget_type_led *w_le;
3343 	struct widget_type_pushbutton *w_pb;
3344 	struct widget_type_slideswitch *w_ss;
3345 	struct widget_type_toggleswitch *w_ts;
3346 	struct widget_type_turnswitch *w_tw;
3347 
3348 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3349 
3350 	switch(d->c) {
3351 		case WIDGET_TYPE_LAMP:
3352 			w_lm = (struct widget_type_lamp *) d->p;
3353 
3354 			*c = w_lm->d;
3355 
3356 			break;
3357 		case WIDGET_TYPE_LED_1:
3358 		case WIDGET_TYPE_LED_2:
3359 		case WIDGET_TYPE_LED_3:
3360 			w_le = (struct widget_type_led *) d->p;
3361 
3362 			*c = w_le->d;
3363 
3364 			break;
3365 		case WIDGET_TYPE_PUSHBUTTON_1:
3366 		case WIDGET_TYPE_PUSHBUTTON_2:
3367 		case WIDGET_TYPE_PUSHBUTTON_3:
3368 			w_pb = (struct widget_type_pushbutton *) d->p;
3369 
3370 			*c = w_pb->d;
3371 
3372 			break;
3373 		case WIDGET_TYPE_SLIDESWITCH:
3374 			w_ss = (struct widget_type_slideswitch *) d->p;
3375 
3376 			*c = w_ss->d;
3377 
3378 			break;
3379 		case WIDGET_TYPE_TOGGLESWITCH:
3380 			w_ts = (struct widget_type_toggleswitch *) d->p;
3381 
3382 			*c = w_ts->d;
3383 
3384 			break;
3385 		case WIDGET_TYPE_TURNSWITCH:
3386 			w_tw = (struct widget_type_turnswitch *) d->p;
3387 
3388 			*c = w_tw->d;
3389 
3390 			break;
3391 		default:
3392 			(void) flush_error();
3393 
3394 			LOGWARN(
3395 				ERROR_SLIGHT, SUBSYSTEM,
3396 				_("Widget type %u not supported by this action, please check widget definitions"),
3397 				d->c
3398 			);
3399 
3400 			return(-1);
3401 	}
3402 
3403 	return(0);
3404 }
3405 
3406 /**
3407  * @brief Get widget minimum state/step/position.
3408  *
3409  * @param[in] w Widget stack info structure
3410  * @param[in] s Widget name to get the value
3411  * @param[out] c Minimum state/step/position
3412  *
3413  * @retval Zero on success
3414  * @retval Non-zero on failure
3415  *
3416  */
3417 
widget_step_get_min(struct w_stack * w,char * s,unsigned int * c)3418 int widget_step_get_min(struct w_stack *w, char *s, unsigned int *c) {
3419 	struct w_info *d;
3420 
3421 	struct widget_type_lamp *w_lm;
3422 	struct widget_type_led *w_le;
3423 	struct widget_type_pushbutton *w_pb;
3424 	struct widget_type_slideswitch *w_ss;
3425 	struct widget_type_toggleswitch *w_ts;
3426 	struct widget_type_turnswitch *w_tw;
3427 
3428 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3429 
3430 	switch(d->c) {
3431 		case WIDGET_TYPE_LAMP:
3432 			w_lm = (struct widget_type_lamp *) d->p;
3433 
3434 			*c = w_lm->a;
3435 
3436 			break;
3437 		case WIDGET_TYPE_LED_1:
3438 		case WIDGET_TYPE_LED_2:
3439 		case WIDGET_TYPE_LED_3:
3440 			w_le = (struct widget_type_led *) d->p;
3441 
3442 			*c = w_le->a;
3443 
3444 			break;
3445 		case WIDGET_TYPE_PUSHBUTTON_1:
3446 		case WIDGET_TYPE_PUSHBUTTON_2:
3447 		case WIDGET_TYPE_PUSHBUTTON_3:
3448 			w_pb = (struct widget_type_pushbutton *) d->p;
3449 
3450 			*c = w_pb->a;
3451 
3452 			break;
3453 		case WIDGET_TYPE_SLIDESWITCH:
3454 			w_ss = (struct widget_type_slideswitch *) d->p;
3455 
3456 			*c = w_ss->a;
3457 
3458 			break;
3459 		case WIDGET_TYPE_TOGGLESWITCH:
3460 			w_ts = (struct widget_type_toggleswitch *) d->p;
3461 
3462 			*c = w_ts->a;
3463 
3464 			break;
3465 		case WIDGET_TYPE_TURNSWITCH:
3466 			w_tw = (struct widget_type_turnswitch *) d->p;
3467 
3468 			*c = w_tw->a;
3469 
3470 			break;
3471 		default:
3472 			(void) flush_error();
3473 
3474 			LOGWARN(
3475 				ERROR_SLIGHT, SUBSYSTEM,
3476 				_("Widget type %u not supported by this action, please check widget definitions"),
3477 				d->c
3478 			);
3479 
3480 			return(-1);
3481 	}
3482 
3483 	return(0);
3484 }
3485 
3486 /**
3487  * @brief Get widget maximum state/step/position.
3488  *
3489  * @param[in] w Widget stack info structure
3490  * @param[in] s Widget name to get the value
3491  * @param[out] c Maximum state/step/position
3492  *
3493  * @retval Zero on success
3494  * @retval Non-zero on failure
3495  *
3496  */
3497 
widget_step_get_max(struct w_stack * w,char * s,unsigned int * c)3498 int widget_step_get_max(struct w_stack *w, char *s, unsigned int *c) {
3499 	struct w_info *d;
3500 
3501 	struct widget_type_lamp *w_lm;
3502 	struct widget_type_led *w_le;
3503 	struct widget_type_pushbutton *w_pb;
3504 	struct widget_type_slideswitch *w_ss;
3505 	struct widget_type_toggleswitch *w_ts;
3506 	struct widget_type_turnswitch *w_tw;
3507 
3508 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3509 
3510 	switch(d->c) {
3511 		case WIDGET_TYPE_LAMP:
3512 			w_lm = (struct widget_type_lamp *) d->p;
3513 
3514 			*c = w_lm->b;
3515 
3516 			break;
3517 		case WIDGET_TYPE_LED_1:
3518 		case WIDGET_TYPE_LED_2:
3519 		case WIDGET_TYPE_LED_3:
3520 			w_le = (struct widget_type_led *) d->p;
3521 
3522 			*c = w_le->b;
3523 
3524 			break;
3525 		case WIDGET_TYPE_PUSHBUTTON_1:
3526 		case WIDGET_TYPE_PUSHBUTTON_2:
3527 		case WIDGET_TYPE_PUSHBUTTON_3:
3528 			w_pb = (struct widget_type_pushbutton *) d->p;
3529 
3530 			*c = w_pb->b;
3531 
3532 			break;
3533 		case WIDGET_TYPE_SLIDESWITCH:
3534 			w_ss = (struct widget_type_slideswitch *) d->p;
3535 
3536 			*c = w_ss->b;
3537 
3538 			break;
3539 		case WIDGET_TYPE_TOGGLESWITCH:
3540 			w_ts = (struct widget_type_toggleswitch *) d->p;
3541 
3542 			*c = w_ts->b;
3543 
3544 			break;
3545 		case WIDGET_TYPE_TURNSWITCH:
3546 			w_tw = (struct widget_type_turnswitch *) d->p;
3547 
3548 			*c = w_tw->b;
3549 
3550 			break;
3551 		default:
3552 			(void) flush_error();
3553 
3554 			LOGWARN(
3555 				ERROR_SLIGHT, SUBSYSTEM,
3556 				_("Widget type %u not supported by this action, please check widget definitions"),
3557 				d->c
3558 			);
3559 
3560 			return(-1);
3561 	}
3562 
3563 	return(0);
3564 }
3565 
3566 /**
3567  * @brief Set widget new state/step/position.
3568  *
3569  * It is necessary to call widget_refresh() afterwards to update changes to window.
3570  *
3571  * Note: widget must be enabled before calling this function, call widget_enable() if necessary.
3572  *
3573  * @param[in] w Widget stack info structure
3574  * @param[in] s Widget name to set
3575  * @param[in] c New state/step/position
3576  *
3577  * @retval Zero on success
3578  * @retval Non-zero on failure
3579  *
3580  */
3581 
widget_step_set(struct w_stack * w,char * s,unsigned int c)3582 int widget_step_set(struct w_stack *w, char *s, unsigned int c) {
3583 	unsigned int e;
3584 
3585 	struct w_info *d;
3586 
3587 	struct widget_type_lamp *w_lm;
3588 	struct widget_type_toggleswitch *w_ts;
3589 	struct widget_type_turnswitch *w_tw;
3590 
3591 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3592 
3593 	switch(d->c) {
3594 		case WIDGET_TYPE_LAMP:
3595 			w_lm = (struct widget_type_lamp *) d->p;
3596 
3597 			/* Lamp is allowed to set only on or off */
3598 			if(c >= WIDGET_FRAME_LAMP_ANGLES) c = WIDGET_FRAME_LAMP_ANGLES - 1;
3599 
3600 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_LAMP, w_lm->o);
3601 
3602 			(void) widget_step_set_op(w, d, NULL, NULL, c, w_lm->a, w_lm->b, w_lm->c, &w_lm->d,
3603 				NULL, 0, 0,
3604 				WIDGET_GFX_LAMP, w_lm->o, w_lm->ch,
3605 				(double) (e / WIDGET_FRAME_LAMP_ANGLES));
3606 
3607 			(void) widget_step_set_title(w, d, &w_lm->t);
3608 
3609 			break;
3610 		case WIDGET_TYPE_LED_1:
3611 			(void) widget_step_set_ld(w, d, c, WIDGET_GFX_LED_1);
3612 
3613 			break;
3614 		case WIDGET_TYPE_LED_2:
3615 			(void) widget_step_set_ld(w, d, c, WIDGET_GFX_LED_2);
3616 
3617 			break;
3618 		case WIDGET_TYPE_LED_3:
3619 			(void) widget_step_set_ld(w, d, c, WIDGET_GFX_LED_3);
3620 
3621 			break;
3622 		case WIDGET_TYPE_PUSHBUTTON_1:
3623 			(void) widget_step_set_pb(w, d, c, WIDGET_GFX_PUSHBUTTON_1);
3624 
3625 			break;
3626 		case WIDGET_TYPE_PUSHBUTTON_2:
3627 			(void) widget_step_set_pb(w, d, c, WIDGET_GFX_PUSHBUTTON_2);
3628 
3629 			break;
3630 		case WIDGET_TYPE_PUSHBUTTON_3:
3631 			(void) widget_step_set_pb(w, d, c, WIDGET_GFX_PUSHBUTTON_3);
3632 
3633 			break;
3634 		case WIDGET_TYPE_SLIDESWITCH:
3635 			(void) widget_step_set_ss(w, d, c);
3636 
3637 			break;
3638 		case WIDGET_TYPE_TOGGLESWITCH:
3639 			w_ts = (struct widget_type_toggleswitch *) d->p;
3640 
3641 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TOGGLESWITCH, w_ts->o);
3642 
3643 			(void) widget_step_set_op(w, d, &w_ts->s, &w_ts->i, c, w_ts->a, w_ts->b, w_ts->c, &w_ts->d,
3644 				&w_ts->p, w_ts->d, w_ts->k,
3645 				WIDGET_GFX_TOGGLESWITCH, w_ts->o, w_ts->ch,
3646 				(double) (e / WIDGET_FRAME_TOGGLESWITCH_ANGLES));
3647 
3648 			(void) widget_step_set_title(w, d, &w_ts->t);
3649 
3650 			break;
3651 		case WIDGET_TYPE_TURNSWITCH:
3652 			w_tw = (struct widget_type_turnswitch *) d->p;
3653 
3654 			/* For indicator to show right value, current step must be set here */
3655 			if(c > w_tw->c) return(0);
3656 
3657 			w_tw->d = c;
3658 
3659 			e = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TURNSWITCH, w_tw->o);
3660 
3661 			(void) widget_step_set_op(w, d, &w_tw->s, &w_tw->i, c, w_tw->a, w_tw->b, w_tw->c, &w_tw->d,
3662 				&w_tw->p, w_tw->d, w_tw->k,
3663 				WIDGET_GFX_TURNSWITCH, w_tw->o, w_tw->ch,
3664 				(double) (e / WIDGET_FRAME_TURNSWITCH_ANGLES));
3665 
3666 			(void) widget_step_set_title(w, d, &w_tw->t);
3667 
3668 			break;
3669 		default:
3670 			(void) flush_error();
3671 
3672 			LOGWARN(
3673 				ERROR_SLIGHT, SUBSYSTEM,
3674 				_("Widget type %u not supported by this action, please check widget definitions"),
3675 				d->c
3676 			);
3677 
3678 			return(-1);
3679 	}
3680 
3681 	return(0);
3682 }
3683 
widget_step_set_ld(struct w_stack * w,struct w_info * d,unsigned int c,unsigned int g)3684 static void widget_step_set_ld(struct w_stack *w, struct w_info *d, unsigned int c, unsigned int g) {
3685 	unsigned int e;
3686 
3687 	struct widget_type_led *w_le;
3688 
3689 	w_le = (struct widget_type_led *) d->p;
3690 
3691 	/* Led is allowed to set only on or off */
3692 	if(c >= WIDGET_FRAME_LED_ANGLES) c = WIDGET_FRAME_LED_ANGLES - 1;
3693 
3694 	e = widget_init_stack_bob_predraw_frame(g, w_le->o);
3695 
3696 	(void) widget_step_set_op(w, d, NULL, NULL, c, w_le->a, w_le->b, w_le->c, &w_le->d,
3697 		NULL, 0, 0,
3698 		g, w_le->o, w_le->ch, (double) (e / WIDGET_FRAME_LED_ANGLES));
3699 
3700 	(void) widget_step_set_title(w, d, &w_le->t);
3701 }
3702 
widget_step_set_pb(struct w_stack * w,struct w_info * d,unsigned int c,unsigned int g)3703 static void widget_step_set_pb(struct w_stack *w, struct w_info *d, unsigned int c, unsigned int g) {
3704 	unsigned int e;
3705 
3706 	struct widget_type_pushbutton *w_pb;
3707 
3708 	w_pb = (struct widget_type_pushbutton *) d->p;
3709 
3710 	/* Pushbutton is allowed to set only on or off */
3711 	if(c >= WIDGET_FRAME_PUSHBUTTON_ANGLES) c = WIDGET_FRAME_PUSHBUTTON_ANGLES - 1;
3712 
3713 	e = widget_init_stack_bob_predraw_frame(g, w_pb->o);
3714 
3715 	(void) widget_step_set_op(w, d, NULL, NULL, c, w_pb->a, w_pb->b, w_pb->c, &w_pb->d,
3716 		NULL, 0, 0,
3717 		g, w_pb->o, w_pb->ch, (double) (e / WIDGET_FRAME_PUSHBUTTON_ANGLES));
3718 
3719 	(void) widget_step_set_title(w, d, &w_pb->t);
3720 }
3721 
widget_step_set_ss(struct w_stack * w,struct w_info * d,unsigned int c)3722 static void widget_step_set_ss(struct w_stack *w, struct w_info *d, unsigned int c) {
3723 	struct t_img *m_i, *m_s;
3724 
3725 	struct widget_type_slideswitch *w_ss;
3726 
3727 	w_ss = (struct widget_type_slideswitch *) d->p;
3728 
3729 	if(c > w_ss->c) return;
3730 
3731 	w_ss->d = c;
3732 
3733 	/* Update widget pixel buffer */
3734 	if(widget_init_stack_bob_predraw(WIDGET_GFX_SLIDESWITCH, w_ss->o, w_ss->ch, &m_i, &m_s) != 0) {
3735 		return;
3736 	}
3737 
3738 	(void) widget_init_stack_bob_content(WIDGET_GFX_SLIDESWITCH,
3739 		w_ss->o, d, m_i->p, m_s->p, d->m_f, 0);
3740 
3741 	(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
3742 	(void) widget_update_scale(w, d, &w_ss->s);
3743 	(void) widget_update_indicator(w, d, &w_ss->i, &w_ss->q, w_ss->d, w_ss->k);
3744 
3745 	/* Move slider either verically or horizontally */
3746 	if(w_ss->o % 2 == 0) {
3747 		d->x = w_ss->p.x + (unsigned int) round(maths_map((double) w_ss->d,
3748 			0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
3749 	}
3750 	else {
3751 		d->y = w_ss->p.y + w_ss->b - (unsigned int) round(maths_map((double) w_ss->d,
3752 			0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
3753 	}
3754 
3755 	(void) widget_init_stack_bob_copy(w, d);
3756 	(void) widget_step_set_title(w, d, &w_ss->t);
3757 }
3758 
widget_step_set_op(struct w_stack * w,struct w_info * d,struct widget_scale * s,struct widget_indicator * i,unsigned int c,unsigned int c_a,unsigned int c_b,unsigned int c_c,unsigned int * c_d,struct widget_geometry * g,unsigned int i_c,unsigned int i_k,unsigned int a,unsigned int k,float f,double b)3759 static void widget_step_set_op(struct w_stack *w, struct w_info *d, struct widget_scale *s, struct widget_indicator *i, unsigned int c, unsigned int c_a, unsigned int c_b, unsigned int c_c, unsigned int *c_d, struct widget_geometry *g, unsigned int i_c, unsigned int i_k, unsigned int a, unsigned int k, float f, double b) {
3760 	struct t_img *m_i, *m_s;
3761 
3762 	if(c > c_c) return;
3763 
3764 	*c_d = c;
3765 
3766 	/* Update widget pixel buffer */
3767 	if(widget_init_stack_bob_predraw(a, k, f, &m_i, &m_s) != 0) return;
3768 
3769 	(void) widget_init_stack_bob_content(a, k, d, m_i->p, m_s->p, d->m_f,
3770 		widget_init_stack_bob_frame(c_a, c_b, c_c, *c_d, b));
3771 
3772 	(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
3773 	(void) widget_update_scale(w, d, s);
3774 	(void) widget_update_indicator(w, d, i, g, i_c, i_k);
3775 
3776 	(void) widget_init_stack_bob_copy(w, d);
3777 }
3778 
widget_step_set_title(struct w_stack * w,struct w_info * d,struct widget_title * t)3779 static void widget_step_set_title(struct w_stack *w, struct w_info *d, struct widget_title *t) {
3780 	(void) widget_update_it(w, d, &t->b_8, t->i.x, t->i.y,
3781 		fonts_get_width(t->f), fonts_get_height(t->f));
3782 	(void) widget_init_stack_bob_text(w, t);
3783 }
3784 
3785 /**
3786  * @brief Set widget new ranges.
3787  *
3788  * It is necessary to call widget_refresh() afterwards to update changes to window.
3789  *
3790  * Note: widget must be enabled before calling this function, call widget_enable() if necessary.
3791  *
3792  * @param[in] w Widget stack info structure
3793  * @param[in] s Widget name to set
3794  * @param[in] a New minimum position angle (-> 0)
3795  * @param[in] b New maximum position angle (<- 359)
3796  * @param[in] c New moveable steps between min and max position angles
3797  *
3798  * @retval Zero on success
3799  * @retval Non-zero on failure
3800  *
3801  */
3802 
widget_range_set(struct w_stack * w,char * s,unsigned int a,unsigned int b,unsigned int c)3803 int widget_range_set(struct w_stack *w, char *s, unsigned int a, unsigned int b, unsigned int c) {
3804 	struct w_info *d;
3805 
3806 	struct widget_type_turnswitch *w_tw;
3807 
3808 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3809 
3810 	switch(d->c) {
3811 		case WIDGET_TYPE_TURNSWITCH:
3812 			w_tw = (struct widget_type_turnswitch *) d->p;
3813 
3814 			w_tw->a = a;
3815 			w_tw->b = b;
3816 			w_tw->c = c;
3817 
3818 			if(w_tw->d > w_tw->c) w_tw->d = w_tw->c;
3819 
3820 			if(widget_step_set(w, s, w_tw->d) != 0) return(-1);
3821 
3822 			break;
3823 		default:
3824 			(void) flush_error();
3825 
3826 			LOGWARN(
3827 				ERROR_SLIGHT, SUBSYSTEM,
3828 				_("Widget type %u not supported by this action, please check widget definitions"),
3829 				d->c
3830 			);
3831 
3832 			return(-1);
3833 	}
3834 
3835 	return(0);
3836 }
3837 
3838 /**
3839  * @brief Set widget callback trigger mode.
3840  *
3841  * @param[in] w Widget stack info structure
3842  * @param[in] s Widget name to set
3843  * @param[in] g Widget callback trigger mode is continuous or not
3844  *
3845  * @retval Zero on success
3846  * @retval Non-zero on failure
3847  *
3848  */
3849 
widget_trigger_set(struct w_stack * w,char * s,unsigned int g)3850 int widget_trigger_set(struct w_stack *w, char *s, unsigned int g) {
3851 	struct w_info *d;
3852 
3853 	struct widget_type_slideswitch *w_ss;
3854 	struct widget_type_toggleswitch *w_ts;
3855 	struct widget_type_turnswitch *w_tw;
3856 
3857 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3858 
3859 	switch(d->c) {
3860 		case WIDGET_TYPE_SLIDESWITCH:
3861 			w_ss = (struct widget_type_slideswitch *) d->p;
3862 
3863 			w_ss->g = g;
3864 
3865 			break;
3866 		case WIDGET_TYPE_TOGGLESWITCH:
3867 			w_ts = (struct widget_type_toggleswitch *) d->p;
3868 
3869 			w_ts->g = g;
3870 
3871 			break;
3872 		case WIDGET_TYPE_TURNSWITCH:
3873 			w_tw = (struct widget_type_turnswitch *) d->p;
3874 
3875 			w_tw->g = g;
3876 
3877 			break;
3878 		default:
3879 			(void) flush_error();
3880 
3881 			LOGWARN(
3882 				ERROR_SLIGHT, SUBSYSTEM,
3883 				_("Widget type %u not supported by this action, please check widget definitions"),
3884 				d->c
3885 			);
3886 
3887 			return(-1);
3888 	}
3889 
3890 	return(0);
3891 }
3892 
3893 /**
3894  * @brief Set widget indicator.
3895  *
3896  * It is necessary to call widget_refresh() afterwards to update changes to window.
3897  *
3898  * @param[in] w Widget stack info structure
3899  * @param[in] s Widget name to set
3900  * @param[in] u Indicator character set, understandable by iconv(), or NULL to use default character set
3901  * @param[in] e Indicator font file
3902  * @param[in] y Indicator font size in 1/64 points
3903  * @param[in] p Indicator font resolution in dots per inch
3904  * @param[in] g Indicator mode (WIDGET_INDICATOR_MODE_*)
3905  * @param[in] o Indicator vertical offset in pixels
3906  * @param[in] r Indicator color
3907  *
3908  * @retval Zero on success
3909  * @retval Non-zero on failure
3910  *
3911  */
3912 
widget_indicator_set(struct w_stack * w,char * s,char * u,char * e,unsigned int y,unsigned int p,unsigned int g,int o,struct pixel_rgba_8 * r)3913 int widget_indicator_set(struct w_stack *w, char *s, char *u, char *e, unsigned int y, unsigned int p, unsigned int g, int o, struct pixel_rgba_8 *r) {
3914 	struct w_info *d;
3915 
3916 	struct widget_type_slideswitch *w_ss;
3917 	struct widget_type_toggleswitch *w_ts;
3918 	struct widget_type_turnswitch *w_tw;
3919 
3920 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
3921 
3922 	switch(d->c) {
3923 		case WIDGET_TYPE_SLIDESWITCH:
3924 			w_ss = (struct widget_type_slideswitch *) d->p;
3925 
3926 			(void) widget_indicator_set_at(&w_ss->i, u, e, y, p, o, r);
3927 			(void) widget_indicator_set_op(w, d, &w_ss->i, &w_ss->q, w_ss->d, w_ss->k, g);
3928 
3929 			break;
3930 		case WIDGET_TYPE_TOGGLESWITCH:
3931 			w_ts = (struct widget_type_toggleswitch *) d->p;
3932 
3933 			(void) widget_indicator_set_at(&w_ts->i, u, e, y, p, o, r);
3934 			(void) widget_indicator_set_op(w, d, &w_ts->i, &w_ts->p, w_ts->d, w_ts->k, g);
3935 
3936 			break;
3937 		case WIDGET_TYPE_TURNSWITCH:
3938 			w_tw = (struct widget_type_turnswitch *) d->p;
3939 
3940 			(void) widget_indicator_set_at(&w_tw->i, u, e, y, p, o, r);
3941 			(void) widget_indicator_set_op(w, d, &w_tw->i, &w_tw->p, w_tw->d, w_tw->k, g);
3942 
3943 			break;
3944 		default:
3945 			(void) flush_error();
3946 
3947 			LOGWARN(
3948 				ERROR_SLIGHT, SUBSYSTEM,
3949 				_("Widget type %u not supported by this action, please check widget definitions"),
3950 				d->c
3951 			);
3952 
3953 			return(-1);
3954 	}
3955 
3956 	return(0);
3957 }
3958 
widget_indicator_set_at(struct widget_indicator * i,char * u,char * e,unsigned int y,unsigned int p,int o,struct pixel_rgba_8 * r)3959 static void widget_indicator_set_at(struct widget_indicator *i, char *u, char *e, unsigned int y, unsigned int p, int o, struct pixel_rgba_8 *r) {
3960 	if(i->f != 0) (void) fonts_close(i->f);
3961 
3962 	if(u == NULL) u = CHARSET_DEFAULT;
3963 
3964 	i->f = 0;
3965 
3966 	i->fc = str_dup((const char *) u, STRING_ASCII);
3967 	i->fs = str_dup((const char *) e, STRING_ASCII);
3968 
3969 	i->fz = y;
3970 	i->fr = p;
3971 
3972 	i->fo = o;
3973 
3974 	i->r.pixel.p = r->pixel.p;
3975 }
3976 
widget_indicator_set_op(struct w_stack * w,struct w_info * d,struct widget_indicator * i,struct widget_geometry * p,unsigned int c,unsigned int k,unsigned int g)3977 static void widget_indicator_set_op(struct w_stack *w, struct w_info *d, struct widget_indicator *i, struct widget_geometry *p, unsigned int c, unsigned int k, unsigned int g) {
3978 	if(i->c == g) return;
3979 
3980 	switch(g) {
3981 		case WIDGET_INDICATOR_MODE_DISABLE:
3982 		case WIDGET_INDICATOR_MODE_ONDEMAND:
3983 			(void) widget_update_indicator_op(w, d, i, i->ox, i->oy, i->ow, i->oh);
3984 
3985 			i->c = g;
3986 
3987 			break;
3988 		case WIDGET_INDICATOR_MODE_ALWAYS:
3989 			(void) widget_update_indicator(w, d, i, p, c, k);
3990 
3991 			i->c = g;
3992 
3993 			break;
3994 		default:
3995 			break;
3996 	}
3997 }
3998 
3999 /**
4000  * @brief Update widget border.
4001  *
4002  * It is necessary to call widget_refresh() afterwards to update changes to window.
4003  *
4004  * @param[in] w Widget stack info structure
4005  * @param[in] s Widget name to update
4006  * @param[in] c New border color or NULL to use existing color
4007  * @param[in] h New border thickness or 0 to use existing thickness
4008  *
4009  * @retval Zero on success
4010  * @retval Non-zero on failure
4011  *
4012  */
4013 
widget_update_border(struct w_stack * w,char * s,struct pixel_rgba_8 * c,unsigned int h)4014 int widget_update_border(struct w_stack *w, char *s, struct pixel_rgba_8 *c, unsigned int h) {
4015 	struct w_info *d;
4016 
4017 	struct widget_type_block *w_bl;
4018 
4019 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
4020 
4021 	switch(d->c) {
4022 		case WIDGET_TYPE_BLOCK:
4023 			w_bl = (struct widget_type_block *) d->p;
4024 
4025 			if(c != NULL) w_bl->b.pixel.p = c->pixel.p;
4026 			if(h != 0) w_bl->d = h;
4027 
4028 			if(d->m_f != NULL) {
4029 				/* Restore image from storebuffer */
4030 				(void) memcpy((void *) d->m_f, (const void *) w_bl->u, d->t);
4031 
4032 				(void) widget_init_stack_bob_av_border(d, &w_bl->p, &w_bl->b, w_bl->d);
4033 				(void) widget_init_stack_bob_copy(w, d);
4034 			}
4035 			else {
4036 				if(widget_init_stack_bob_au(w, d, &w_bl->p, &w_bl->c, &w_bl->b, w_bl->d) != 0) {
4037 					return(-1);
4038 				}
4039 			}
4040 
4041 			break;
4042 		default:
4043 			(void) flush_error();
4044 
4045 			LOGWARN(
4046 				ERROR_SLIGHT, SUBSYSTEM,
4047 				_("Widget type %u not supported by this action, please check widget definitions"),
4048 				d->c
4049 			);
4050 
4051 			return(-1);
4052 	}
4053 
4054 	return(0);
4055 }
4056 
4057 /**
4058  * @brief Update widget content using solid color.
4059  *
4060  * It is necessary to call widget_refresh() afterwards to update changes to window.
4061  *
4062  * @param[in] w Widget stack info structure
4063  * @param[in] s Widget name to update
4064  * @param[in] c New content color or NULL to use existing color
4065  *
4066  * @retval Zero on success
4067  * @retval Non-zero on failure
4068  *
4069  */
4070 
widget_update_color(struct w_stack * w,char * s,struct pixel_rgba_8 * c)4071 int widget_update_color(struct w_stack *w, char *s, struct pixel_rgba_8 *c) {
4072 	struct pixel_rgba_8 *t;
4073 
4074 	struct w_info *d;
4075 	struct widget_type_block *w_bl;
4076 
4077 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
4078 
4079 	switch(d->c) {
4080 		case WIDGET_TYPE_BLOCK:
4081 			w_bl = (struct widget_type_block *) d->p;
4082 
4083 			(void) widget_update_op(w, d, w_bl->p.x, w_bl->p.y, w_bl->p.w, w_bl->p.h);
4084 
4085 			if(c != NULL) w_bl->c.pixel.p = c->pixel.p;
4086 
4087 			t = d->m_f;
4088 
4089 			if(widget_init_stack_bob_au(w, d, &w_bl->p, &w_bl->c, &w_bl->b, w_bl->d) != 0) {
4090 				d->m_f = t;
4091 
4092 				return(-1);
4093 			}
4094 
4095 			if(t != NULL) (void) free(t);
4096 
4097 			if(w_bl->u != NULL) {
4098 				(void) free(w_bl->u);
4099 
4100 				w_bl->u = NULL;
4101 			}
4102 
4103 			break;
4104 		default:
4105 			(void) flush_error();
4106 
4107 			LOGWARN(
4108 				ERROR_SLIGHT, SUBSYSTEM,
4109 				_("Widget type %u not supported by this action, please check widget definitions"),
4110 				d->c
4111 			);
4112 
4113 			return(-1);
4114 	}
4115 
4116 	return(0);
4117 }
4118 
4119 /**
4120  * @brief Update widget content using image buffer.
4121  *
4122  * It is necessary to call widget_refresh() afterwards to update changes to window.
4123  *
4124  * @param[in] w Widget stack info structure
4125  * @param[in] s Widget id to update
4126  * @param[in] p Source image buffer
4127  * @param[in] x Horizontal offset to source image buffer
4128  * @param[in] y Vertical offset to source image buffer
4129  * @param[in] e Source image buffer absolute width in pixels
4130  * @param[in] f Source image buffer absolute height in pixels
4131  *
4132  * @retval Zero on success
4133  * @retval Non-zero on failure
4134  *
4135  */
4136 
widget_update_image(struct w_stack * w,char * s,struct pixel_rgba_8 * p,int x,int y,unsigned int e,unsigned int f)4137 int widget_update_image(struct w_stack *w, char *s, struct pixel_rgba_8 *p, int x, int y, unsigned int e, unsigned int f) {
4138 	struct w_info *d;
4139 	struct widget_type_block *w_bl;
4140 
4141 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
4142 
4143 	switch(d->c) {
4144 		case WIDGET_TYPE_BLOCK:
4145 			w_bl = (struct widget_type_block *) d->p;
4146 
4147 			(void) widget_update_op(w, d, w_bl->p.x, w_bl->p.y, w_bl->p.w, w_bl->p.h);
4148 
4149 			/* Allocate widget pixel buffer only once */
4150 			if(d->m_f == NULL) {
4151 				if(widget_init_stack_bob_op(d, &w_bl->p) != 0) return(-1);
4152 			}
4153 
4154 			/* Adjust source pixel buffer offset if needed */
4155 			p += (y * e) + x;
4156 
4157 			if(widget_init_stack_bob_aw(w, d, &w_bl->p, p, e, f) != 0) return(-1);
4158 
4159 			/* Copy image to storebuffer */
4160 			if(w_bl->u == NULL) {
4161 				if((w_bl->u = widget_init_stack_bob_store(d->m_f, d->t)) == NULL) return(-1);
4162 			}
4163 			else (void) memcpy((void *) w_bl->u, (const void *) d->m_f, d->t);
4164 
4165 			(void) widget_init_stack_bob_av_border(d, &w_bl->p, &w_bl->b, w_bl->d);
4166 			(void) widget_init_stack_bob_copy(w, d);
4167 
4168 			break;
4169  		default:
4170 			(void) flush_error();
4171 
4172 			LOGWARN(
4173 				ERROR_SLIGHT, SUBSYSTEM,
4174 				_("Widget type %u not supported by this action, please check widget definitions"),
4175 				d->c
4176 			);
4177 
4178  			return(-1);
4179 	}
4180 
4181 	return(0);
4182 }
4183 
4184 /**
4185  * @brief Update widget content using image file.
4186  *
4187  * It is necessary to call widget_refresh() afterwards to update changes to window.
4188  *
4189  * @param[in] w Widget stack info structure
4190  * @param[in] s Widget name to update
4191  * @param[in] p Source image file name
4192  *
4193  * @retval Zero on success
4194  * @retval Non-zero on failure
4195  *
4196  */
4197 
widget_update_image_file(struct w_stack * w,char * s,char * p)4198 int widget_update_image_file(struct w_stack *w, char *s, char *p) {
4199 	struct t_img *r;
4200 	struct pixel_rgba_8 *t;
4201 
4202 	struct w_info *d;
4203 	struct widget_type_block *w_bl;
4204 
4205 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
4206 
4207 	switch(d->c) {
4208 		case WIDGET_TYPE_BLOCK:
4209 			w_bl = (struct widget_type_block *) d->p;
4210 
4211 			if((w_bl->s = widget_strcpy(w_bl->s, p)) == NULL) return(-1);
4212 
4213 			if((r = image_read(w_bl->s, 0)) == NULL) return(-1);
4214 
4215 			(void) widget_update_op(w, d, w_bl->p.x, w_bl->p.y, w_bl->p.w, w_bl->p.h);
4216 
4217 			t = d->m_f;
4218 
4219 			if(widget_init_stack_bob_av(w, d, &w_bl->p, r) != 0) {
4220 				d->m_f = t;
4221 
4222 				(void) image_free(r);
4223 
4224 				return(-1);
4225 			}
4226 
4227 			(void) image_free(r);
4228 
4229 			if(t != NULL) (void) free(t);
4230 
4231 			/* Copy image to storebuffer */
4232 			if(w_bl->u == NULL) {
4233 				if((w_bl->u = widget_init_stack_bob_store(d->m_f, d->t)) == NULL) return(-1);
4234 			}
4235 			else (void) memcpy((void *) w_bl->u, (const void *) d->m_f, d->t);
4236 
4237 			(void) widget_init_stack_bob_av_border(d, &w_bl->p, &w_bl->b, w_bl->d);
4238 			(void) widget_init_stack_bob_copy(w, d);
4239 
4240 			break;
4241  		default:
4242 			(void) flush_error();
4243 
4244 			LOGWARN(
4245 				ERROR_SLIGHT, SUBSYSTEM,
4246 				_("Widget type %u not supported by this action, please check widget definitions"),
4247 				d->c
4248 			);
4249 
4250  			return(-1);
4251 	}
4252 
4253 	return(0);
4254 }
4255 
4256 /**
4257  * @brief Update widget label.
4258  *
4259  * It is necessary to call widget_refresh() afterwards to update changes to window.
4260  *
4261  * @param[in] w Widget stack info structure
4262  * @param[in] s Widget name to update
4263  * @param[in] l New label or NULL to use existing label
4264  * @param[in] c Label new charset or NULL to use existing charset
4265  * @param[in] e Label new font file or NULL to use existing font
4266  * @param[in] y Label new font size in 1/64 points or 0 to use existing font size, or 0 to get size from resource file if size is not set already
4267  * @param[in] p Label new font resolution in dots per inch or 0 to use existing resolution
4268  * @param[in] j Label new justification or 0 to use existing justification
4269  * @param[in] r Label new color or NULL to use existing color
4270  *
4271  * @retval Zero on success
4272  * @retval Non-zero on failure
4273  *
4274  */
4275 
widget_update_label(struct w_stack * w,char * s,char * l,char * c,char * e,unsigned int y,unsigned int p,unsigned int j,struct pixel_rgba_8 * r)4276 int widget_update_label(struct w_stack *w, char *s, char *l, char *c, char *e, unsigned int y, unsigned int p, unsigned int j, struct pixel_rgba_8 *r) {
4277 	struct w_info *d;
4278 	struct widget_title *t;
4279 
4280 	struct widget_type_label *w_la;
4281 	struct widget_type_lamp *w_lm;
4282 	struct widget_type_led *w_le;
4283 	struct widget_type_pushbutton *w_pb;
4284 	struct widget_type_slideswitch *w_ss;
4285 	struct widget_type_toggleswitch *w_ts;
4286 	struct widget_type_turnswitch *w_tw;
4287 
4288 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
4289 
4290 	if(d->f == NULL) return(0);
4291 
4292 	t = (struct widget_title *) d->f;
4293 
4294 	if(l != NULL) {
4295 		t->s = l;
4296 		t->t = str_len(t->s, STRING_UTF8);
4297 	}
4298 	else if(t->s == NULL) return(-1);
4299 
4300 	if(c != NULL) t->c = c;
4301 	if(e != NULL) t->e = e;
4302 
4303 	if(y != 0) {
4304 		t->y = y;
4305 	}
4306 	else if(t->y == 0) {
4307 		t->y = (unsigned int) c_font_size;
4308 	}
4309 
4310 	if(p != 0) t->d = p;
4311 
4312 	if(j != WIDGET_TITLE_JUSTIFICATION_NONE) t->j = j;
4313 	if(r != NULL) t->r.pixel.p = r->pixel.p;
4314 
4315 	switch(d->c) {
4316 		case WIDGET_TYPE_LABEL:
4317 			w_la = (struct widget_type_label *) d->p;
4318 
4319 			(void) widget_update_it(w, d, &w_la->t.b_8, w_la->t.i.x, w_la->t.i.y,
4320 				fonts_get_width(w_la->t.f), fonts_get_height(w_la->t.f));
4321 
4322 			(void) widget_init_stack_bob_text_close(t);
4323 			(void) widget_init_stack_bob_rems(w, d);
4324 
4325 			if(widget_init_stack_bob_af(w, d, t, &w_la->p) != 0) {
4326 				return(-1);
4327 			}
4328 
4329 			(void) widget_init_stack_bob_apps(w, d, &d->m_id);
4330 
4331 			break;
4332 		case WIDGET_TYPE_LAMP:
4333 			w_lm = (struct widget_type_lamp *) d->p;
4334 
4335 			(void) widget_update_it(w, d, &w_lm->t.b_8, w_lm->t.i.x, w_lm->t.i.y,
4336 				fonts_get_width(w_lm->t.f), fonts_get_height(w_lm->t.f));
4337 
4338 			(void) widget_init_stack_bob_text_close(t);
4339 
4340 			if(widget_init_stack_bob_ag(w, d, t, &w_lm->p, w_lm->k, w_lm->ox, w_lm->oy) != 0) {
4341 				return(-1);
4342 			}
4343 
4344 			break;
4345 		case WIDGET_TYPE_LED_1:
4346 		case WIDGET_TYPE_LED_2:
4347 		case WIDGET_TYPE_LED_3:
4348 			w_le = (struct widget_type_led *) d->p;
4349 
4350 			(void) widget_update_it(w, d, &w_le->t.b_8, w_le->t.i.x, w_le->t.i.y,
4351 				fonts_get_width(w_le->t.f), fonts_get_height(w_le->t.f));
4352 
4353 			(void) widget_init_stack_bob_text_close(t);
4354 
4355 			if(widget_init_stack_bob_ag(w, d, t, &w_le->p, w_le->k, w_le->ox, w_le->oy) != 0) {
4356 				return(-1);
4357 			}
4358 
4359 			break;
4360 		case WIDGET_TYPE_PUSHBUTTON_1:
4361 		case WIDGET_TYPE_PUSHBUTTON_2:
4362 		case WIDGET_TYPE_PUSHBUTTON_3:
4363 			w_pb = (struct widget_type_pushbutton *) d->p;
4364 
4365 			(void) widget_update_it(w, d, &w_pb->t.b_8, w_pb->t.i.x, w_pb->t.i.y,
4366 				fonts_get_width(w_pb->t.f), fonts_get_height(w_pb->t.f));
4367 
4368 			(void) widget_init_stack_bob_text_close(t);
4369 
4370 			if(widget_init_stack_bob_ag(w, d, t, &w_pb->p, w_pb->k, w_pb->ox, w_pb->oy) != 0) {
4371 				return(-1);
4372 			}
4373 
4374 			break;
4375 		case WIDGET_TYPE_SLIDESWITCH:
4376 			w_ss = (struct widget_type_slideswitch *) d->p;
4377 
4378 			(void) widget_update_it(w, d, &w_ss->t.b_8, w_ss->t.i.x, w_ss->t.i.y,
4379 				fonts_get_width(w_ss->t.f), fonts_get_height(w_ss->t.f));
4380 
4381 			(void) widget_init_stack_bob_text_close(t);
4382 
4383 			if(widget_init_stack_bob_ag(w, d, t, &w_ss->q, w_ss->k, w_ss->ox, w_ss->oy) != 0) {
4384 				return(-1);
4385 			}
4386 
4387 			break;
4388 		case WIDGET_TYPE_TOGGLESWITCH:
4389 			w_ts = (struct widget_type_toggleswitch *) d->p;
4390 
4391 			(void) widget_update_it(w, d, &w_ts->t.b_8, w_ts->t.i.x, w_ts->t.i.y,
4392 				fonts_get_width(w_ts->t.f), fonts_get_height(w_ts->t.f));
4393 
4394 			(void) widget_init_stack_bob_text_close(t);
4395 
4396 			if(widget_init_stack_bob_ag(w, d, t, &w_ts->p, w_ts->k, w_ts->ox, w_ts->oy) != 0) {
4397 				return(-1);
4398 			}
4399 
4400 			break;
4401 		case WIDGET_TYPE_TURNSWITCH:
4402 			w_tw = (struct widget_type_turnswitch *) d->p;
4403 
4404 			(void) widget_update_it(w, d, &w_tw->t.b_8, w_tw->t.i.x, w_tw->t.i.y,
4405 				fonts_get_width(w_tw->t.f), fonts_get_height(w_tw->t.f));
4406 
4407 			(void) widget_init_stack_bob_text_close(t);
4408 
4409 			if(widget_init_stack_bob_ag(w, d, t, &w_tw->p, w_tw->k, w_tw->ox, w_tw->oy) != 0) {
4410 				return(-1);
4411 			}
4412 
4413 			break;
4414 		default:
4415 			(void) flush_error();
4416 
4417 			LOGWARN(
4418 				ERROR_SLIGHT, SUBSYSTEM,
4419 				_("Widget type %u not supported by this action, please check widget definitions"),
4420 				d->c
4421 			);
4422 
4423 			return(-1);
4424 	}
4425 
4426 	return(0);
4427 }
4428 
4429 /**
4430  * @brief Update widget scale with incidator bars.
4431  *
4432  * It is necessary to call widget_enable() before creating a scale, and widget_refresh() afterwards to update
4433  * changes to window. Parameters that accepts 'existing' fonts, colors or whatever must be provided when creating
4434  * scale for first time.
4435  *
4436  * @param[in] w Widget stack info structure
4437  * @param[in] s Widget name to update
4438  * @param[in] u Scale label array current character set, understandable by iconv(), or NULL to use default character set
4439  * @param[in] e Scale label new font file or NULL to use existing font
4440  * @param[in] y Scale label new font size in 1/64 points or 0 to use existing font size
4441  * @param[in] p Scale label new font resolution in dots per inch or 0 to use existing resolution
4442  * @param[in] l Scale label array or NULL to use numbers interpolated between a and b
4443  * @param[in] a Scale start value if scale label array is NULL
4444  * @param[in] b Scale end value if scale label array is NULL
4445  * @param[in] k Scale steps between widget min and max range
4446  * @param[in] r Scale new color or NULL to use existing color
4447  *
4448  * @retval Zero on success
4449  * @retval Non-zero on failure
4450  *
4451  */
4452 
widget_update_scale_bars(struct w_stack * w,char * s,char * u,char * e,unsigned int y,unsigned int p,char ** l,double a,double b,unsigned int k,struct pixel_rgba_8 * r)4453 int widget_update_scale_bars(struct w_stack *w, char *s, char *u, char *e, unsigned int y, unsigned int p, char **l, double a, double b, unsigned int k, struct pixel_rgba_8 *r) {
4454 	return(widget_update_scale_it(w, s, u, e, y, p, l, a, b, k, r, WIDGET_SCALE_TYPE_BARS));
4455 }
4456 
widget_update_scale_bars_line(struct w_stack * w,struct w_info * d,struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char * se,unsigned int sy,unsigned int sp,char ** l,double e,double f,unsigned int o,double v,double z,unsigned int k)4457 static int widget_update_scale_bars_line(struct w_stack *w, struct w_info *d, struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char *se, unsigned int sy, unsigned int sp, char **l, double e, double f, unsigned int o, double v, double z, unsigned int k) {
4458 	int t, u, x;
4459 	unsigned int i;
4460 	double a, b, n, s;
4461 
4462 	struct point_4 *t_a;
4463 	struct text_2 *t_b;
4464 
4465 	if(k < 2) return(-1);
4466 
4467 	/* Allocate enough line and text structures if needed */
4468 	if(c->t.c < k) {
4469 		for(i = 0; i < c->t.c; i++) (void) fonts_close(c->t.p[i].f);
4470 
4471 		APP_REALLOC_RET_VALUE(t_a, c->p.p, sizeof(struct point_4) * (k * 2), -1);
4472 		APP_REALLOC_RET_VALUE(t_b, c->t.p, sizeof(struct text_2) * k, -1);
4473 
4474 		for(i = 0; i < k; i++) c->t.p[i].f = 0;
4475 
4476 		c->p.c = k * 2;
4477 		c->t.c = k;
4478 	}
4479 
4480 	if(c->t.p[0].f == 0) {
4481 		if((c->t.p[0].f = widget_update_scale_font(se, sy, sp)) == 0) return(-1);
4482 	}
4483 
4484 	t = g->x + (g->w / 2);
4485 	u = g->y + (g->h / 2);
4486 
4487 	b = (f - e) / (double) (k - 1);
4488 	n = (z - v) / (double) (k - 1);
4489 
4490 	for(i = 0; i < k; i++) {
4491 		a = e + (b * (double) i);
4492 		x = 0;
4493 
4494 		if(k % 2 == 0) {
4495 			if(i == 0 || i == k - 1) x = 10;
4496 		}
4497 		else {
4498 			if(i == 0 || i == k - 1 || i == k / 2) x = 10;
4499 		}
4500 
4501 		if(o % 2 == 0) {
4502 			s = v + (n * (double) i);
4503 
4504 			(void) widget_update_scale_bars_line_h(g, c, r, m, l, t, u, x, i, k, a, s);
4505 		}
4506 		else {
4507 			s = v + (n * (double) i);
4508 			s = (v + (n * (double) (k - 1))) - s;
4509 
4510 			(void) widget_update_scale_bars_line_v(g, c, r, m, l, t, u, x, i, k, a, s);
4511 		}
4512 	}
4513 
4514 	/* Calculate scale bounding box */
4515 	c->b.left = c->b.top = 32767;
4516 	c->b.right = c->b.bottom = -32766;
4517 
4518 	for(i = 0; i < k; i++) {
4519 		if(c->p.p[i].x1 < c->b.left) c->b.left = c->p.p[i].x1;
4520 		if(c->p.p[i].x2 > c->b.right) c->b.right = c->p.p[i].x2;
4521 		if(c->p.p[i].y1 < c->b.top) c->b.top = c->p.p[i].y1;
4522 		if(c->p.p[i].y2 > c->b.bottom) c->b.bottom = c->p.p[i].y2;
4523 
4524 		if(c->p.p[i + k].x2 < c->b.left) c->b.left = c->p.p[i + k].x2;
4525 		if(c->p.p[i + k].x1 > c->b.right) c->b.right = c->p.p[i + k].x1;
4526 		if(c->p.p[i + k].y2 < c->b.top) c->b.top = c->p.p[i + k].y2;
4527 		if(c->p.p[i + k].y1 > c->b.bottom) c->b.bottom = c->p.p[i + k].y1;
4528 
4529 		if(c->t.p[i].x < c->b.left) c->b.left = c->t.p[i].x;
4530 		if(c->t.p[i].y < c->b.top) c->b.top = c->t.p[i].y;
4531 
4532 		if(c->t.p[i].x + (int) fonts_get_width(c->t.p[i].f) > c->b.right) {
4533 			c->b.right = c->t.p[i].x + fonts_get_width(c->t.p[i].f);
4534 		}
4535 
4536 		if(c->t.p[i].y + (int) fonts_get_height(c->t.p[i].f) > c->b.bottom) {
4537 			c->b.bottom = c->t.p[i].y + fonts_get_height(c->t.p[i].f);
4538 		}
4539 	}
4540 
4541 	if(c->b.left > c->b.right) {
4542 		c->b.left = c->b.top = 0;
4543 		c->b.right = c->b.bottom = 0;
4544 	}
4545 
4546 	/* Store item count for later use */
4547 	c->k = k;
4548 	c->c = WIDGET_SCALE_TYPE_BARS;
4549 
4550 	/* For first time the scale size is the whole widget area */
4551 	c->b.s.width = d->w + abs(d->x - c->b.left);
4552 	c->b.s.height = d->h + abs(d->y - c->b.top);
4553 
4554 	(void) widget_update_scale(w, d, c);
4555 
4556 	/* Store real scale size for later use */
4557 	c->b.s.width = c->b.right - c->b.left;
4558 	c->b.s.height = c->b.bottom - c->b.top;
4559 
4560 	return(0);
4561 }
4562 
widget_update_scale_bars_line_h(struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char ** l,int t,int u,int x,unsigned int i,unsigned int k,double a,double s)4563 static void widget_update_scale_bars_line_h(struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char **l, int t, int u, int x, unsigned int i, unsigned int k, double a, double s) {
4564 	size_t q;
4565 
4566 	struct pixel_rgb_8 p;
4567 
4568 	char t_s[32];
4569 
4570 	/* Calculate scale bar endpoints */
4571 	c->p.p[i].p.pixel.p = r->pixel.p;
4572 	c->p.p[i + k].p.pixel.p = r->pixel.p;
4573 
4574 	c->p.p[i].x1 = t + (int) round(a);
4575 	c->p.p[i].y1 = u + 4;
4576 	c->p.p[i].x2 = c->p.p[i].x1;
4577 	c->p.p[i].y2 = c->p.p[i].y1 + (g->h / 2) - 6 + x;
4578 
4579 	c->p.p[i + k].x1 = c->p.p[i].x1;
4580 	c->p.p[i + k].y1 = u - 5;
4581 	c->p.p[i + k].x2 = c->p.p[i].x1;
4582 	c->p.p[i + k].y2 = c->p.p[i + k].y1 - (g->h / 2) - (x - 6);
4583 
4584 	p.r = r->pixel.r;
4585 	p.g = r->pixel.g;
4586 	p.b = r->pixel.b;
4587 
4588 	/* Render scale bar label text */
4589 	if(c->t.p[i].f == 0) {
4590 		if((c->t.p[i].f = fonts_open_copy(c->t.p[0].f)) == 0) return;
4591 	}
4592 
4593 	if(l != NULL && l[i] != NULL) {
4594 		(void) fonts_render(c->t.p[i].f, m, l[i], str_len(l[i], STRING_UTF8), &p, 0);
4595 	}
4596 	else {
4597 		q = (size_t) snprintf(t_s, sizeof(t_s), "%g", s);
4598 
4599 		(void) fonts_render(c->t.p[i].f, m, t_s, q, &p, 1);
4600 	}
4601 
4602 	c->t.p[i].x = c->p.p[i].x2 - (fonts_get_width(c->t.p[i].f) / 2);
4603 	c->t.p[i].y = c->p.p[0].y2 + 10;
4604 }
4605 
widget_update_scale_bars_line_v(struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char ** l,int t,int u,int x,unsigned int i,unsigned int k,double a,double s)4606 static void widget_update_scale_bars_line_v(struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char **l, int t, int u, int x, unsigned int i, unsigned int k, double a, double s) {
4607 	size_t q;
4608 
4609 	struct pixel_rgb_8 p;
4610 
4611 	char t_s[32];
4612 
4613 	/* Calculate scale bar endpoints */
4614 	c->p.p[i].p.pixel.p = r->pixel.p;
4615 	c->p.p[i + k].p.pixel.p = r->pixel.p;
4616 
4617 	c->p.p[i].x1 = t + 4;
4618 	c->p.p[i].y1 = u + (int) round(a);
4619 	c->p.p[i].x2 = c->p.p[i].x1 + (g->w / 2) - 6 + x;
4620 	c->p.p[i].y2 = c->p.p[i].y1;
4621 
4622 	c->p.p[i + k].x1 = t - 5;
4623 	c->p.p[i + k].y1 = c->p.p[i].y1;
4624 	c->p.p[i + k].x2 = c->p.p[i + k].x1 - (g->w / 2) - (x - 6);
4625 	c->p.p[i + k].y2 = c->p.p[i].y1;
4626 
4627 	p.r = r->pixel.r;
4628 	p.g = r->pixel.g;
4629 	p.b = r->pixel.b;
4630 
4631 	/* Render scale bar label text */
4632 	if(c->t.p[i].f == 0) {
4633 		if((c->t.p[i].f = fonts_open_copy(c->t.p[0].f)) == 0) return;
4634 	}
4635 
4636 	if(l != NULL && l[i] != NULL) {
4637 		(void) fonts_render(c->t.p[i].f, m, l[i], str_len(l[i], STRING_UTF8), &p, 0);
4638 	}
4639 	else {
4640 		q = (size_t) snprintf(t_s, sizeof(t_s), "%g", s);
4641 
4642 		(void) fonts_render(c->t.p[i].f, m, t_s, q, &p, 1);
4643 	}
4644 
4645 	c->t.p[i].x = c->p.p[0].x2 + 10;
4646 	c->t.p[i].y = c->p.p[i].y2 - (fonts_get_height(c->t.p[i].f) / 2);
4647 }
4648 
widget_update_scale_bars_round(struct w_stack * w,struct w_info * d,struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char * se,unsigned int sy,unsigned int sp,char ** l,double e,double f,double v,double z,unsigned int k)4649 static int widget_update_scale_bars_round(struct w_stack *w, struct w_info *d, struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char *se, unsigned int sy, unsigned int sp, char **l, double e, double f, double v, double z, unsigned int k) {
4650 	int t, u, x, y;
4651 	unsigned int i;
4652 	double a, b, n, s;
4653 
4654 	size_t q;
4655 
4656 	struct position o, i_r, i_p[4];
4657 	struct pixel_rgb_8 p;
4658 
4659 	struct point_4 *t_a;
4660 	struct text_2 *t_b;
4661 
4662 	char t_s[32];
4663 
4664 	if(k < 2) return(-1);
4665 
4666 	/* Allocate enough line and text structures if needed */
4667 	if(c->p.c < k) {
4668 		for(i = 0; i < c->t.c; i++) (void) fonts_close(c->t.p[i].f);
4669 
4670 		APP_REALLOC_RET_VALUE(t_a, c->p.p, sizeof(struct point_4) * k, -1);
4671 		APP_REALLOC_RET_VALUE(t_b, c->t.p, sizeof(struct text_2) * k, -1);
4672 
4673 		for(i = 0; i < k; i++) c->t.p[i].f = 0;
4674 
4675 		c->p.c = k;
4676 		c->t.c = k;
4677 	}
4678 
4679 	if(c->t.p[0].f == 0) {
4680 		if((c->t.p[0].f = widget_update_scale_font(se, sy, sp)) == 0) return(-1);
4681 	}
4682 
4683 	t = g->x + (g->w / 2);
4684 	u = g->y + (g->h / 2);
4685 
4686 	b = (f - e) / (double) (k - 1);
4687 	n = (z - v) / (double) (k - 1);
4688 
4689 	for(i = 0; i < k; i++) {
4690 		a = e + (b * (double) i);
4691 
4692 		c->p.p[i].p.pixel.p = r->pixel.p;
4693 
4694 		/* Calculate scale bar endpoints */
4695 		s = sqrt((double) (g->w * g->h)) / 2.0;
4696 		s += s / WIDGET_SCALE_DISTANCE_FROM_EDGE;
4697 
4698 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
4699 
4700 		c->p.p[i].x1 = t + (int) round(o.x);
4701 		c->p.p[i].y1 = u + (int) round(o.y);
4702 
4703 		s = sqrt((double) (g->w * g->h)) / WIDGET_SCALE_DISTANCE_ENDPOINT;
4704 
4705 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
4706 
4707 		c->p.p[i].x2 = c->p.p[i].x1 + (int) round(o.x);
4708 		c->p.p[i].y2 = c->p.p[i].y1 + (int) round(o.y);
4709 
4710 		/* Calculate scale bar label coordinates */
4711 		s = (double) sy + WIDGET_SCALE_DISTANCE_FROM_RING;
4712 
4713 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
4714 
4715 		/* This kludge moves titles on the right side to little more right */
4716 		if(a > 179.0) o.x += (a / 50.0);
4717 
4718 		x = c->p.p[i].x2 + (int) round(o.x);
4719 		y = c->p.p[i].y2 + (int) round(o.y);
4720 
4721 		/* Render scale bar label text */
4722 		if(c->t.p[i].f == 0) {
4723 			if((c->t.p[i].f = fonts_open_copy(c->t.p[0].f)) == 0) return(-1);
4724 		}
4725 
4726 		p.r = r->pixel.r;
4727 		p.g = r->pixel.g;
4728 		p.b = r->pixel.b;
4729 
4730 		if(l != NULL && l[i] != NULL) {
4731 			(void) fonts_render(c->t.p[i].f, m, l[i], str_len(l[i], STRING_UTF8), &p, 0);
4732 		}
4733 		else {
4734 			q = (size_t) snprintf(t_s, sizeof(t_s), "%g", v + (n * (double) i));
4735 
4736 			(void) fonts_render(c->t.p[i].f, m, t_s, q, &p, 1);
4737 		}
4738 
4739 		/* Calculate final bar label position by its center point */
4740 		i_p[0].x = 0.0;
4741 		i_p[0].y = 0.0;
4742 		i_p[1].x = (double) fonts_get_width(c->t.p[i].f);
4743 		i_p[1].y = 0.0;
4744 		i_p[2].x = i_p[1].x;
4745 		i_p[2].y = (double) fonts_get_height(c->t.p[i].f);
4746 		i_p[3].x = 0.0;
4747 		i_p[3].y = i_p[2].y;
4748 
4749 		(void) coords_polygon_center(3, i_p, &i_r);
4750 
4751 		c->t.p[i].x = x - (int) round(i_r.x);
4752 		c->t.p[i].y = y - (int) round(i_r.y);
4753 	}
4754 
4755 	/* Calculate scale bounding box */
4756 	c->b.left = c->b.top = 32767;
4757 	c->b.right = c->b.bottom = -32766;
4758 
4759 	for(i = 0; i < k; i++) {
4760 		if(c->p.p[i].x1 < c->b.left) c->b.left = c->p.p[i].x1;
4761 		if(c->p.p[i].x2 > c->b.right) c->b.right = c->p.p[i].x2;
4762 		if(c->p.p[i].y1 < c->b.top) c->b.top = c->p.p[i].y1;
4763 		if(c->p.p[i].y2 > c->b.bottom) c->b.bottom = c->p.p[i].y2;
4764 
4765 		if(c->t.p[i].x < c->b.left) c->b.left = c->t.p[i].x;
4766 		if(c->t.p[i].y < c->b.top) c->b.top = c->t.p[i].y;
4767 
4768 		if(c->t.p[i].x + (int) fonts_get_width(c->t.p[i].f) > c->b.right) {
4769 			c->b.right = c->t.p[i].x + fonts_get_width(c->t.p[i].f);
4770 		}
4771 
4772 		if(c->t.p[i].y + (int) fonts_get_height(c->t.p[i].f) > c->b.bottom) {
4773 			c->b.bottom = c->t.p[i].y + fonts_get_height(c->t.p[i].f);
4774 		}
4775 	}
4776 
4777 	if(c->b.left > c->b.right) {
4778 		c->b.left = c->b.top = 0;
4779 		c->b.right = c->b.bottom = 0;
4780 	}
4781 
4782 	/* Store item count for later use */
4783 	c->k = k;
4784 	c->c = WIDGET_SCALE_TYPE_BARS;
4785 
4786 	/* For first time the scale size is the whole widget area */
4787 	c->b.s.width = d->w + abs(d->x - c->b.left);
4788 	c->b.s.height = d->h + abs(d->y - c->b.top);
4789 
4790 	(void) widget_update_scale(w, d, c);
4791 
4792 	/* Store real scale size for later use */
4793 	c->b.s.width = c->b.right - c->b.left;
4794 	c->b.s.height = c->b.bottom - c->b.top;
4795 
4796 	return(0);
4797 }
4798 
4799 /**
4800  * @brief Update widget scale with indicator dots.
4801  *
4802  * It is necessary to call widget_enable() before creating a scale, and widget_refresh() afterwards to update
4803  * changes to window. Parameters that accepts 'existing' fonts, colors or whatever must be provided when creating
4804  * scale for first time.
4805  *
4806  * @param[in] w Widget stack info structure
4807  * @param[in] s Widget name to update
4808  * @param[in] u Scale label array current character set, understandable by iconv(), or NULL to use default character set
4809  * @param[in] e Scale label new font file or NULL to use existing font
4810  * @param[in] y Scale label new font size in 1/64 points or 0 to use existing font size
4811  * @param[in] p Scale label new font resolution in dots per inch or 0 to use existing resolution
4812  * @param[in] l Scale label array or NULL to use numbers interpolated between a and b
4813  * @param[in] a Scale start value if scale label array is NULL
4814  * @param[in] b Scale end value if scale label array is NULL
4815  * @param[in] k Scale steps between widget min and max range
4816  * @param[in] r Scale new color or NULL to use existing color
4817  *
4818  * @retval Zero on success
4819  * @retval Non-zero on failure
4820  *
4821  */
4822 
widget_update_scale_dots(struct w_stack * w,char * s,char * u,char * e,unsigned int y,unsigned int p,char ** l,double a,double b,unsigned int k,struct pixel_rgba_8 * r)4823 int widget_update_scale_dots(struct w_stack *w, char *s, char *u, char *e, unsigned int y, unsigned int p, char **l, double a, double b, unsigned int k, struct pixel_rgba_8 *r) {
4824 	return(widget_update_scale_it(w, s, u, e, y, p, l, a, b, k, r, WIDGET_SCALE_TYPE_DOTS));
4825 }
4826 
widget_update_scale_dots_round(struct w_stack * w,struct w_info * d,struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char * se,unsigned int sy,unsigned int sp,char ** l,double e,double f,double v,double z,unsigned int k)4827 static int widget_update_scale_dots_round(struct w_stack *w, struct w_info *d, struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char *se, unsigned int sy, unsigned int sp, char **l, double e, double f, double v, double z, unsigned int k) {
4828 	int t, u, x, y;
4829 	unsigned int i;
4830 	double a, b, n, s;
4831 
4832 	size_t q;
4833 
4834 	struct position o, i_r, i_p[4];
4835 	struct pixel_rgb_8 p;
4836 
4837 	struct region_copy_8 *t_a;
4838 	struct text_2 *t_b;
4839 
4840 	char t_s[32];
4841 
4842 	if(k < 2) return(-1);
4843 
4844 	/* Allocate enough dot and text structures if needed */
4845 	if(c->m == NULL) {
4846 		q = (WIDGET_SCALE_DOT_WIDTH * WIDGET_SCALE_DOT_HEIGHT) * sizeof(struct pixel_rgba_8);
4847 
4848 		APP_MALLOC_RET_VALUE(c->m, q, -1);
4849 
4850 		(void) memset((void *) c->m, 0, q);
4851 	}
4852 
4853 	if(c->d != IS_YES) {
4854 		APP_REALLOC_RET_VALUE(t_a, c->g, sizeof(struct region_copy_8) * k, -1);
4855 
4856 		p.r = c->r.pixel.r;
4857 		p.g = c->r.pixel.g;
4858 		p.b = c->r.pixel.b;
4859 
4860 		(void) widget_update_scale_round_it(c, &p);
4861 
4862 		c->d = IS_YES;
4863 	}
4864 
4865 	if(c->t.c < k) {
4866 		for(i = 0; i < c->t.c; i++) (void) fonts_close(c->t.p[i].f);
4867 
4868 		APP_REALLOC_RET_VALUE(t_b, c->t.p, sizeof(struct text_2) * k, -1);
4869 
4870 		for(i = 0; i < k; i++) c->t.p[i].f = 0;
4871 
4872 		c->t.c = k;
4873 	}
4874 
4875 	if(c->t.p[0].f == 0) {
4876 		if((c->t.p[0].f = widget_update_scale_font(se, sy, sp)) == 0) return(-1);
4877 	}
4878 
4879 	t = g->x + (g->w / 2);
4880 	u = g->y + (g->h / 2);
4881 
4882 	b = (f - e) / (double) (k - 1);
4883 	n = (z - v) / (double) (k - 1);
4884 
4885 	o.x = 0.0;
4886 	o.y = 0.0;
4887 	o.z = -100.0;
4888 
4889 	for(i = 0; i < k; i++) {
4890 		a = e + (b * (double) i);
4891 
4892 		/* Calculate scale dot coordinates */
4893 		s = sqrt((double) (g->w * g->h)) / 2.0;
4894 		s += s / WIDGET_SCALE_DISTANCE_FROM_EDGE;
4895 
4896 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
4897 
4898 		c->g[i].dx = t + (int) round(o.x) - ((WIDGET_SCALE_DOT_WIDTH + 4) / 2);
4899 		c->g[i].dy = u + (int) round(o.y) - ((WIDGET_SCALE_DOT_HEIGHT + 4) / 2);
4900 
4901 		c->g[i].sx = 0;
4902 		c->g[i].sy = 0;
4903 
4904 		c->g[i].c.width = WIDGET_SCALE_DOT_WIDTH;
4905 		c->g[i].c.height = WIDGET_SCALE_DOT_HEIGHT;
4906 		c->g[i].s.width = WIDGET_SCALE_DOT_WIDTH;
4907 		c->g[i].s.height = WIDGET_SCALE_DOT_HEIGHT;
4908 
4909 		c->g[i].p = c->m;
4910 
4911 		/* Calculate scale dot label coordinates */
4912 		s = (double) sy + WIDGET_SCALE_DISTANCE_FROM_DOTS;
4913 
4914 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
4915 
4916 		/* This kludge moves titles on the right side to little more right */
4917 		if(a > 179.0) o.x += (a / 50.0);
4918 
4919 		x = c->g[i].dx + (int) round(o.x) + ((WIDGET_SCALE_DOT_WIDTH + 4) / 2);
4920 		y = c->g[i].dy + (int) round(o.y) + ((WIDGET_SCALE_DOT_HEIGHT + 4) / 2);
4921 
4922 		/* Render scale dot label text */
4923 		if(c->t.p[i].f == 0) {
4924 			if((c->t.p[i].f = fonts_open_copy(c->t.p[0].f)) == 0) return(-1);
4925 		}
4926 
4927 		p.r = r->pixel.r;
4928 		p.g = r->pixel.g;
4929 		p.b = r->pixel.b;
4930 
4931 		if(l != NULL && l[i] != NULL) {
4932 			(void) fonts_render(c->t.p[i].f, m, l[i], str_len(l[i], STRING_UTF8), &p, 0);
4933 		}
4934 		else {
4935 			q = (size_t) snprintf(t_s, sizeof(t_s), "%g", v + (n * (double) i));
4936 
4937 			(void) fonts_render(c->t.p[i].f, m, t_s, q, &p, 1);
4938 		}
4939 
4940 		/* Calculate final dot label position by its center point */
4941 		i_p[0].x = 0.0;
4942 		i_p[0].y = 0.0;
4943 		i_p[1].x = (double) fonts_get_width(c->t.p[i].f);
4944 		i_p[1].y = 0.0;
4945 		i_p[2].x = i_p[1].x;
4946 		i_p[2].y = (double) fonts_get_height(c->t.p[i].f);
4947 		i_p[3].x = 0.0;
4948 		i_p[3].y = i_p[2].y;
4949 
4950 		(void) coords_polygon_center(3, i_p, &i_r);
4951 
4952 		c->t.p[i].x = x - (int) round(i_r.x);
4953 		c->t.p[i].y = y - (int) round(i_r.y);
4954 	}
4955 
4956 	/* Calculate scale bounding box */
4957 	c->b.left = c->b.top = 32767;
4958 	c->b.right = c->b.bottom = -32766;
4959 
4960 	for(i = 0; i < k; i++) {
4961 		if(c->g[i].dx < c->b.left) c->b.left = c->g[i].dx;
4962 		if(c->g[i].dy < c->b.top) c->b.top = c->g[i].dy;
4963 
4964 		if(c->g[i].dx + (int) c->g[i].c.width > c->b.right) {
4965 			c->b.right = c->g[i].dx + (int) c->g[i].c.width;
4966 		}
4967 
4968 		if(c->g[i].dy + (int) c->g[i].c.height > c->b.bottom) {
4969 			c->b.bottom = c->g[i].dy + (int) c->g[i].c.height;
4970 		}
4971 
4972 		if(c->t.p[i].x < c->b.left) c->b.left = c->t.p[i].x;
4973 		if(c->t.p[i].y < c->b.top) c->b.top = c->t.p[i].y;
4974 
4975 		if(c->t.p[i].x + (int) fonts_get_width(c->t.p[i].f) > c->b.right) {
4976 			c->b.right = c->t.p[i].x + fonts_get_width(c->t.p[i].f);
4977 		}
4978 
4979 		if(c->t.p[i].y + (int) fonts_get_height(c->t.p[i].f) > c->b.bottom) {
4980 			c->b.bottom = c->t.p[i].y + fonts_get_height(c->t.p[i].f);
4981 		}
4982 	}
4983 
4984 	if(c->b.left > c->b.right) {
4985 		c->b.left = c->b.top = 0;
4986 		c->b.right = c->b.bottom = 0;
4987 	}
4988 
4989 	/* Store item count for later use */
4990 	c->k = k;
4991 	c->c = WIDGET_SCALE_TYPE_DOTS;
4992 
4993 	/* For first time the scale size is the whole widget area */
4994 	c->b.s.width = d->w + abs(d->x - c->b.left);
4995 	c->b.s.height = d->h + abs(d->y - c->b.top);
4996 
4997 	(void) widget_update_scale(w, d, c);
4998 
4999 	/* Store real scale size for later use */
5000 	c->b.s.width = c->b.right - c->b.left;
5001 	c->b.s.height = c->b.bottom - c->b.top;
5002 
5003 	return(0);
5004 }
5005 
5006 /**
5007  * @brief Update widget scale without extra indicators.
5008  *
5009  * It is necessary to call widget_enable() before creating a scale, and widget_refresh() afterwards to update
5010  * changes to window. Parameters that accepts 'existing' fonts, colors or whatever must be provided when creating
5011  * scale for first time.
5012  *
5013  * @param[in] w Widget stack info structure
5014  * @param[in] s Widget name to update
5015  * @param[in] u Scale label array current character set, understandable by iconv(), or NULL to use default character set
5016  * @param[in] e Scale label new font file or NULL to use existing font
5017  * @param[in] y Scale label new font size in 1/64 points or 0 to use existing font size
5018  * @param[in] p Scale label new font resolution in dots per inch or 0 to use existing resolution
5019  * @param[in] l Scale label array or NULL to use numbers interpolated between a and b
5020  * @param[in] a Scale start value if scale label array is NULL
5021  * @param[in] b Scale end value if scale label array is NULL
5022  * @param[in] k Scale steps between widget min and max range
5023  * @param[in] r Scale new color or NULL to use existing color
5024  *
5025  * @retval Zero on success
5026  * @retval Non-zero on failure
5027  *
5028  */
5029 
widget_update_scale_nude(struct w_stack * w,char * s,char * u,char * e,unsigned int y,unsigned int p,char ** l,double a,double b,unsigned int k,struct pixel_rgba_8 * r)5030 int widget_update_scale_nude(struct w_stack *w, char *s, char *u, char *e, unsigned int y, unsigned int p, char **l, double a, double b, unsigned int k, struct pixel_rgba_8 *r) {
5031 	return(widget_update_scale_it(w, s, u, e, y, p, l, a, b, k, r, WIDGET_SCALE_TYPE_NUDE));
5032 }
5033 
widget_update_scale_nude_round(struct w_stack * w,struct w_info * d,struct widget_geometry * g,struct widget_scale * c,struct pixel_rgba_8 * r,char * m,char * se,unsigned int sy,unsigned int sp,char ** l,double e,double f,double v,double z,unsigned int k)5034 static int widget_update_scale_nude_round(struct w_stack *w, struct w_info *d, struct widget_geometry *g, struct widget_scale *c, struct pixel_rgba_8 *r, char *m, char *se, unsigned int sy, unsigned int sp, char **l, double e, double f, double v, double z, unsigned int k) {
5035 	int t, u, x, y;
5036 	unsigned int i;
5037 	double a, b, n, s;
5038 
5039 	size_t q;
5040 
5041 	struct position o, i_r, i_p[4];
5042 	struct pixel_rgb_8 p;
5043 
5044 	struct text_2 *t_b;
5045 
5046 	char t_s[32];
5047 
5048 	if(k < 2) return(-1);
5049 
5050 	/* Allocate enough text structures if needed */
5051 	if(c->t.c < k) {
5052 		for(i = 0; i < c->t.c; i++) (void) fonts_close(c->t.p[i].f);
5053 
5054 		APP_REALLOC_RET_VALUE(t_b, c->t.p, sizeof(struct text_2) * k, -1);
5055 
5056 		for(i = 0; i < k; i++) c->t.p[i].f = 0;
5057 
5058 		c->t.c = k;
5059 	}
5060 
5061 	if(c->t.p[0].f == 0) {
5062 		if((c->t.p[0].f = widget_update_scale_font(se, sy, sp)) == 0) return(-1);
5063 	}
5064 
5065 	t = g->x + (g->w / 2);
5066 	u = g->y + (g->h / 2);
5067 
5068 	b = (f - e) / (double) (k - 1);
5069 	n = (z - v) / (double) (k - 1);
5070 
5071 	for(i = 0; i < k; i++) {
5072 		a = e + (b * (double) i);
5073 
5074 		/* Calculate scale label coordinates */
5075 		s = sqrt((double) (g->w * g->h)) / 2.0;
5076 		s += s / WIDGET_SCALE_DISTANCE_FROM_EDGE;
5077 
5078 		(void) coords_angle_distance_to_position(a + 90.0, s, &o);
5079 
5080 		x = t + (int) round(o.x);
5081 		y = u + (int) round(o.y);
5082 
5083 		/* Render scale label text */
5084 		if(c->t.p[i].f == 0) {
5085 			if((c->t.p[i].f = fonts_open_copy(c->t.p[0].f)) == 0) return(-1);
5086 		}
5087 
5088 		p.r = r->pixel.r;
5089 		p.g = r->pixel.g;
5090 		p.b = r->pixel.b;
5091 
5092 		if(l != NULL && l[i] != NULL) {
5093 			(void) fonts_render(c->t.p[i].f, m, l[i], str_len(l[i], STRING_UTF8), &p, 0);
5094 		}
5095 		else {
5096 			q = (size_t) snprintf(t_s, sizeof(t_s), "%g", v + (n * (double) i));
5097 
5098 			(void) fonts_render(c->t.p[i].f, m, t_s, q, &p, 1);
5099 		}
5100 
5101 		/* Calculate final label position by its center point */
5102 		i_p[0].x = 0.0;
5103 		i_p[0].y = 0.0;
5104 		i_p[1].x = (double) fonts_get_width(c->t.p[i].f);
5105 		i_p[1].y = 0.0;
5106 		i_p[2].x = i_p[1].x;
5107 		i_p[2].y = (double) fonts_get_height(c->t.p[i].f);
5108 		i_p[3].x = 0.0;
5109 		i_p[3].y = i_p[2].y;
5110 
5111 		(void) coords_polygon_center(3, i_p, &i_r);
5112 
5113 		c->t.p[i].x = x - (int) round(i_r.x);
5114 		c->t.p[i].y = y - (int) round(i_r.y);
5115 	}
5116 
5117 	/* Calculate scale bounding box */
5118 	c->b.left = c->b.top = 32767;
5119 	c->b.right = c->b.bottom = -32766;
5120 
5121 	for(i = 0; i < k; i++) {
5122 		if(c->t.p[i].x < c->b.left) c->b.left = c->t.p[i].x;
5123 		if(c->t.p[i].y < c->b.top) c->b.top = c->t.p[i].y;
5124 
5125 		if(c->t.p[i].x + (int) fonts_get_width(c->t.p[i].f) > c->b.right) {
5126 			c->b.right = c->t.p[i].x + fonts_get_width(c->t.p[i].f);
5127 		}
5128 
5129 		if(c->t.p[i].y + (int) fonts_get_height(c->t.p[i].f) > c->b.bottom) {
5130 			c->b.bottom = c->t.p[i].y + fonts_get_height(c->t.p[i].f);
5131 		}
5132 	}
5133 
5134 	if(c->b.left > c->b.right) {
5135 		c->b.left = c->b.top = 0;
5136 		c->b.right = c->b.bottom = 0;
5137 	}
5138 
5139 	/* Store item count for later use */
5140 	c->k = k;
5141 	c->c = WIDGET_SCALE_TYPE_NUDE;
5142 
5143 	/* For first time the scale size is the whole widget area */
5144 	c->b.s.width = d->w + abs(d->x - c->b.left);
5145 	c->b.s.height = d->h + abs(d->y - c->b.top);
5146 
5147 	(void) widget_update_scale(w, d, c);
5148 
5149 	/* Store real scale size for later use */
5150 	c->b.s.width = c->b.right - c->b.left;
5151 	c->b.s.height = c->b.bottom - c->b.top;
5152 
5153 	return(0);
5154 }
5155 
widget_update_scale_it(struct w_stack * w,char * s,char * u,char * e,unsigned int y,unsigned int p,char ** l,double a,double b,unsigned int k,struct pixel_rgba_8 * r,unsigned int t)5156 static int widget_update_scale_it(struct w_stack *w, char *s, char *u, char *e, unsigned int y, unsigned int p, char **l, double a, double b, unsigned int k, struct pixel_rgba_8 *r, unsigned int t) {
5157 	struct w_info *d;
5158 
5159 	struct widget_type_slideswitch *w_ss;
5160 	struct widget_type_toggleswitch *w_ts;
5161 	struct widget_type_turnswitch *w_tw;
5162 
5163 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
5164 
5165 	switch(d->c) {
5166 		case WIDGET_TYPE_SLIDESWITCH:
5167 			w_ss = (struct widget_type_slideswitch *) d->p;
5168 
5169 			if(r != NULL) {
5170 				w_ss->s.r.pixel.p = r->pixel.p;
5171 			}
5172 			else w_ss->s.r.pixel.p = w_ss->t.r.pixel.p;
5173 
5174 			switch(t) {
5175 				case WIDGET_SCALE_TYPE_BARS:
5176 					if(widget_update_scale_bars_line(w, d, &w_ss->p, &w_ss->s, &w_ss->s.r,
5177 						u, e, y, p, l,
5178 						(double) w_ss->a, (double) w_ss->b, w_ss->o, a, b, k) != 0) return(-1);
5179 
5180 					break;
5181 				default:
5182 					return(-1);
5183 			}
5184 
5185 			(void) widget_init_stack_bob_copy(w, d);
5186 			(void) widget_step_set_title(w, d, &w_ss->t);
5187 
5188 			break;
5189 		case WIDGET_TYPE_TOGGLESWITCH:
5190 			w_ts = (struct widget_type_toggleswitch *) d->p;
5191 
5192 			if(r != NULL) {
5193 				w_ts->s.r.pixel.p = r->pixel.p;
5194 			}
5195 			else w_ts->s.r.pixel.p = w_ts->t.r.pixel.p;
5196 
5197 /* XXX TODO scale for toggleswitch */
5198 
5199 			break;
5200 		case WIDGET_TYPE_TURNSWITCH:
5201 			w_tw = (struct widget_type_turnswitch *) d->p;
5202 
5203 			if(r != NULL) {
5204 				w_tw->s.r.pixel.p = r->pixel.p;
5205 			}
5206 			else w_tw->s.r.pixel.p = w_tw->t.r.pixel.p;
5207 
5208 			switch(t) {
5209 				case WIDGET_SCALE_TYPE_BARS:
5210 					if(widget_update_scale_bars_round(w, d, &w_tw->p, &w_tw->s, &w_tw->s.r,
5211 						u, e, y, p, l,
5212 						(double) w_tw->a, (double) w_tw->b, a, b, k) != 0) return(-1);
5213 
5214 					break;
5215 				case WIDGET_SCALE_TYPE_DOTS:
5216 					if(widget_update_scale_dots_round(w, d, &w_tw->p, &w_tw->s, &w_tw->s.r,
5217 						u, e, y, p, l,
5218 						(double) w_tw->a, (double) w_tw->b, a, b, k) != 0) return(-1);
5219 
5220 					break;
5221 				case WIDGET_SCALE_TYPE_NUDE:
5222 					if(widget_update_scale_nude_round(w, d, &w_tw->p, &w_tw->s, &w_tw->s.r,
5223 						u, e, y, p, l,
5224 						(double) w_tw->a, (double) w_tw->b, a, b, k) != 0) return(-1);
5225 
5226 					break;
5227 				default:
5228 					return(-1);
5229 			}
5230 
5231 			(void) widget_init_stack_bob_copy(w, d);
5232 			(void) widget_step_set_title(w, d, &w_tw->t);
5233 
5234 			break;
5235 		default:
5236 			(void) flush_error();
5237 
5238 			LOGWARN(
5239 				ERROR_SLIGHT, SUBSYSTEM,
5240 				_("Widget type %u not supported by this action, please check widget definitions"),
5241 				d->c
5242 			);
5243 
5244 			return(-1);
5245 	}
5246 
5247 	return(0);
5248 }
5249 
widget_update_scale_font(char * s,unsigned int t,unsigned int d)5250 static unsigned int widget_update_scale_font(char *s, unsigned int t, unsigned int d) {
5251 	unsigned int r;
5252 
5253 	char *f;
5254 
5255 	/* If font name was not supplied, get the default */
5256 	if(s == NULL || s[0] == 0) s = c_font_face;
5257 
5258 	if((f = window_get_default_font(s)) == NULL) return(0);
5259 
5260 	/* If font size and/or resolution was not supplied, use defaults */
5261 	if(d == 0) d = (unsigned int) c_font_dpi;
5262 	if(d == 0) d = (unsigned int) round(window_get_dpi_height());
5263 
5264 	if(t == 0) t = (unsigned int) c_font_size;
5265 
5266 	r = fonts_open(f, t, d);
5267 
5268 	(void) window_get_default_font_free(f);
5269 
5270 	return(r);
5271 }
5272 
widget_update_scale_round_it(struct widget_scale * c,struct pixel_rgb_8 * p)5273 static void widget_update_scale_round_it(struct widget_scale *c, struct pixel_rgb_8 *p) {
5274 	int i, j, k, a, b, e, x, y;
5275 	unsigned int u;
5276 
5277 	size_t t;
5278 
5279 	struct pixel_rgba_8 *r;
5280 
5281 	t = (WIDGET_SCALE_DOT_WIDTH * WIDGET_SCALE_DOT_HEIGHT) * sizeof(struct pixel_rgba_8);
5282 
5283 	APP_MALLOC_RET_VOID(r, t);
5284 
5285 	/* Prefill image completely with transparent dot color */
5286 	for(i = 0; i < WIDGET_SCALE_DOT_WIDTH * WIDGET_SCALE_DOT_HEIGHT; i++) {
5287 		r[i].pixel.r = p->r;
5288 		r[i].pixel.g = p->g;
5289 		r[i].pixel.b = p->b;
5290 
5291 		r[i].pixel.a = 0;
5292 	}
5293 
5294 	e = (WIDGET_SCALE_DOT_WIDTH / 2) - 4;
5295 	a = e * 2;
5296 	b = e * e;
5297 
5298 	/* Apply visibility on dot */
5299 	for(i = 0; i < b * 4; i++) {
5300 		x = (i % a) - e;
5301 		y = (i / a) - e;
5302 
5303 		if((x * x) + (y * y) <= b) {
5304 			k = ((WIDGET_SCALE_DOT_HEIGHT / 2) + y + 1) * WIDGET_SCALE_DOT_WIDTH;
5305 			k += (WIDGET_SCALE_DOT_WIDTH / 2) + x + 1;
5306 
5307 			r[k].pixel.a = 255;
5308 		}
5309 	}
5310 
5311 	/* Blur alpha channel a bit to make dot smoother */
5312 	for(i = 1; i < WIDGET_SCALE_DOT_HEIGHT - 1; i++) {
5313 		for(j = 1; j < WIDGET_SCALE_DOT_WIDTH - 1; j++) {
5314 			k = i * WIDGET_SCALE_DOT_WIDTH;
5315 
5316 			c->m[k + j].pixel.p = r[k + j].pixel.p;
5317 
5318 			u = (unsigned int) r[k + j].pixel.a + \
5319 				r[k + j - 1].pixel.a + \
5320 				r[k + j + 1].pixel.a + \
5321 				r[((i - 1) * WIDGET_SCALE_DOT_WIDTH) + j].pixel.a + \
5322 				r[((i + 1) * WIDGET_SCALE_DOT_WIDTH) + j].pixel.a;
5323 
5324 			u /= 5;
5325 
5326 			c->m[k + j].pixel.a = (uint8_t) u;
5327 		}
5328 	}
5329 
5330 	(void) free(r);
5331 }
5332 
widget_update_scale(struct w_stack * w,struct w_info * d,struct widget_scale * c)5333 static void widget_update_scale(struct w_stack *w, struct w_info *d, struct widget_scale *c) {
5334 	unsigned int i;
5335 
5336 	if(c == NULL || c->b.s.width == 0 || c->b.s.height == 0) return;
5337 
5338 	(void) widget_update_scale_op(w, d, c, c->b.left, c->b.top, c->b.s.width, c->b.s.height);
5339 
5340 	switch(c->c) {
5341 		case WIDGET_SCALE_TYPE_BARS:
5342 			(void) gui_draw_lines_aa(w->hnd, &c->p);
5343 
5344 			if(c->t.c > 0) (void) gui_draw_texts(w->hnd, &c->t);
5345 
5346 			break;
5347 		case WIDGET_SCALE_TYPE_DOTS:
5348 			for(i = 0; i < c->k; i++) (void) gui_draw_copy_alpha(w->hnd, &c->g[i]);
5349 
5350 			if(c->t.c > 0) (void) gui_draw_texts(w->hnd, &c->t);
5351 
5352 			break;
5353 		case WIDGET_SCALE_TYPE_NUDE:
5354 			if(c->t.c > 0) (void) gui_draw_texts(w->hnd, &c->t);
5355 
5356 			break;
5357 		default:
5358 			break;
5359 	}
5360 }
5361 
widget_update_scale_op(struct w_stack * w,struct w_info * d,struct widget_scale * c,int x,int y,unsigned int e,unsigned int f)5362 static void widget_update_scale_op(struct w_stack *w, struct w_info *d, struct widget_scale *c, int x, int y, unsigned int e, unsigned int f) {
5363 	if(c == NULL || e == 0 || f == 0) return;
5364 
5365 	(void) widget_update_it(w, d, &c->b_8, x, y, e, f);
5366 }
5367 
widget_update_indicator(struct w_stack * w,struct w_info * d,struct widget_indicator * i,struct widget_geometry * g,unsigned int c,unsigned int k)5368 static void widget_update_indicator(struct w_stack *w, struct w_info *d, struct widget_indicator *i, struct widget_geometry *g, unsigned int c, unsigned int k) {
5369 	size_t t;
5370 
5371 	struct pixel_rgb_8 p;
5372 
5373 	char t_s[32];
5374 
5375 	if(i == NULL || i->c == WIDGET_INDICATOR_MODE_DISABLE) return;
5376 
5377 	/* Allocate stuff if this is first go */
5378 	if(i->f == 0) {
5379 		if(widget_update_indicator_at(i, g, k) != 0) return;
5380 	}
5381 	else (void) widget_update_indicator_op(w, d, i, i->ox, i->oy, i->ow, i->oh);
5382 
5383 	if(i->i.x < i->ox) i->ox = i->i.x;
5384 	if(i->i.y < i->oy) i->oy = i->i.y;
5385 
5386 	t = (size_t) snprintf(t_s, sizeof(t_s), "%u", c);
5387 
5388 	p.r = i->r.pixel.r;
5389 	p.g = i->r.pixel.g;
5390 	p.b = i->r.pixel.b;
5391 
5392 	(void) fonts_render(i->f, i->fc, t_s, t, &p, 1);
5393 
5394 	(void) widget_update_indicator_x(i, g);
5395 	(void) widget_update_indicator_y(i, g, k, i->fo, fonts_get_height(i->f));
5396 
5397 	(void) gui_draw_text(w->hnd, &i->i);
5398 }
5399 
widget_update_indicator_x(struct widget_indicator * i,struct widget_geometry * g)5400 static void widget_update_indicator_x(struct widget_indicator *i, struct widget_geometry *g) {
5401 	i->i.x = g->x - (fonts_get_width(i->f) / 2) + (g->w / 2);
5402 }
5403 
widget_update_indicator_y(struct widget_indicator * i,struct widget_geometry * g,unsigned int k,int h,unsigned int f)5404 static void widget_update_indicator_y(struct widget_indicator *i, struct widget_geometry *g, unsigned int k, int h, unsigned int f) {
5405 	switch(k) {
5406 		case WIDGET_TITLE_POSITION_BELOW:
5407 			i->i.y = g->y - (h + f);
5408 
5409 			break;
5410 		default:
5411 			i->i.y = g->y + g->h + h;
5412 
5413 			break;
5414 	}
5415 }
5416 
widget_update_indicator_op(struct w_stack * w,struct w_info * d,struct widget_indicator * i,int x,int y,unsigned int e,unsigned int f)5417 static void widget_update_indicator_op(struct w_stack *w, struct w_info *d, struct widget_indicator *i, int x, int y, unsigned int e, unsigned int f) {
5418 	(void) widget_update_it(w, d, &i->b_8, x, y, e, f);
5419 }
5420 
widget_update_indicator_at(struct widget_indicator * i,struct widget_geometry * g,unsigned int k)5421 static int widget_update_indicator_at(struct widget_indicator *i, struct widget_geometry *g, unsigned int k) {
5422 	size_t t;
5423 
5424 	struct pixel_rgb_8 p;
5425 
5426 	char t_s[32];
5427 
5428 	if((i->f = widget_update_scale_font(i->fs, i->fz, i->fr)) == 0) {
5429 		return(-1);
5430 	}
5431 
5432 	i->ox = 32767;
5433 	i->oy = 32767;
5434 
5435 	t = (size_t) snprintf(t_s, sizeof(t_s), "@@@@@@@@@@@@");
5436 
5437 	p.r = i->r.pixel.r;
5438 	p.g = i->r.pixel.g;
5439 	p.b = i->r.pixel.b;
5440 
5441 	(void) fonts_render(i->f, i->fc, t_s, t, &p, 1);
5442 
5443 	i->ow = fonts_get_width(i->f);
5444 	i->oh = fonts_get_height(i->f);
5445 
5446 	(void) widget_update_indicator_x(i, g);
5447 	(void) widget_update_indicator_y(i, g, k, i->fo, fonts_get_height(i->f));
5448 
5449 	i->i.f = i->f;
5450 
5451 	return(0);
5452 }
5453 
widget_update_op(struct w_stack * w,struct w_info * d,int x,int y,unsigned int e,unsigned int f)5454 static void widget_update_op(struct w_stack *w, struct w_info *d, int x, int y, unsigned int e, unsigned int f) {
5455 	if(e == 0 || f == 0) return;
5456 
5457 	(void) widget_update_it(w, d, &d->b_8, x, y, e, f);
5458 }
5459 
widget_update_it(struct w_stack * w,struct w_info * d,struct region_copy_8 * b,int x,int y,unsigned int e,unsigned int f)5460 static void widget_update_it(struct w_stack *w, struct w_info *d, struct region_copy_8 *b, int x, int y, unsigned int e, unsigned int f) {
5461 	if(d->b == NULL) {
5462 		if((d->b = widget_get_info_by_id(w, (unsigned int) w->q.c)) == NULL) return;
5463 	}
5464 
5465 	b->sx = x;
5466 	b->sy = y;
5467 	b->dx = x;
5468 	b->dy = y;
5469 
5470 	b->c.width = e;
5471 	b->c.height = f;
5472 	b->s.width = d->b->w;
5473 	b->s.height = d->b->h;
5474 
5475 	b->p = w->bb;
5476 
5477 	(void) gui_draw_copy(w->hnd, b);
5478 }
5479 
5480 /**
5481  * @brief Add push-callback function to pushbutton widget.
5482  *
5483  * Possibly existing callback function will be replaced.
5484  *
5485  * @param[in] w Widget stack info structure
5486  * @param[in] s Widget unique name to add callback function
5487  * @param[in] f Ano-script callback function name
5488  *
5489  * @retval Zero on success
5490  * @retval Non-zero on failure
5491  *
5492  */
5493 
widget_cb_add_pushbutton_push(struct w_stack * w,char * s,char * f)5494 int widget_cb_add_pushbutton_push(struct w_stack *w, char *s, char *f) {
5495 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_PUSHBUTTON_PUSH));
5496 }
5497 
5498 /**
5499  * @brief Add slide-callback function to slideswitch widget.
5500  *
5501  * Possibly existing callback function will be replaced.
5502  *
5503  * @param[in] w Widget stack info structure
5504  * @param[in] s Widget unique name to add callback function
5505  * @param[in] f Ano-script callback function name
5506  *
5507  * @retval Zero on success
5508  * @retval Non-zero on failure
5509  *
5510  */
5511 
widget_cb_add_slideswitch_slide(struct w_stack * w,char * s,char * f)5512 int widget_cb_add_slideswitch_slide(struct w_stack *w, char *s, char *f) {
5513 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_SLIDESWITCH_SLIDE));
5514 }
5515 
5516 /**
5517  * @brief Add toggle-callback function to toggleswitch widget.
5518  *
5519  * Possibly existing callback function will be replaced.
5520  *
5521  * @param[in] w Widget stack info structure
5522  * @param[in] s Widget unique name to add callback function
5523  * @param[in] f Ano-script callback function name
5524  *
5525  * @retval Zero on success
5526  * @retval Non-zero on failure
5527  *
5528  */
5529 
widget_cb_add_toggleswitch_toggle(struct w_stack * w,char * s,char * f)5530 int widget_cb_add_toggleswitch_toggle(struct w_stack *w, char *s, char *f) {
5531 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_TOGGLESWITCH_TOGGLE));
5532 }
5533 
5534 /**
5535  * @brief Add turn-callback function to turnswitch widget.
5536  *
5537  * Possibly existing callback function will be replaced.
5538  *
5539  * @param[in] w Widget stack info structure
5540  * @param[in] s Widget unique name to add callback function
5541  * @param[in] f Ano-script callback function name
5542  *
5543  * @retval Zero on success
5544  * @retval Non-zero on failure
5545  *
5546  */
5547 
widget_cb_add_turnswitch_turn(struct w_stack * w,char * s,char * f)5548 int widget_cb_add_turnswitch_turn(struct w_stack *w, char *s, char *f) {
5549 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_TURNSWITCH_TURN));
5550 }
5551 
5552 /**
5553  * @brief Add generic key-press callback function to widget.
5554  *
5555  * Possibly existing callback function will be replaced.
5556  *
5557  * @param[in] w Widget stack info structure
5558  * @param[in] s Widget unique name to add callback function
5559  * @param[in] f Ano-script callback function name
5560  *
5561  * @retval Zero on success
5562  * @retval Non-zero on failure
5563  *
5564  */
5565 
widget_cb_add_key_press(struct w_stack * w,char * s,char * f)5566 int widget_cb_add_key_press(struct w_stack *w, char *s, char *f) {
5567 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_KEYPRESS));
5568 }
5569 
5570 /**
5571  * @brief Add generic key-release callback function to widget.
5572  *
5573  * Possibly existing callback function will be replaced.
5574  *
5575  * @param[in] w Widget stack info structure
5576  * @param[in] s Widget unique name to add callback function
5577  * @param[in] f Ano-script callback function name
5578  *
5579  * @retval Zero on success
5580  * @retval Non-zero on failure
5581  *
5582  */
5583 
widget_cb_add_key_release(struct w_stack * w,char * s,char * f)5584 int widget_cb_add_key_release(struct w_stack *w, char *s, char *f) {
5585 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_KEYRELEASE));
5586 }
5587 
5588 /**
5589  * @brief Add generic button-press callback function to widget.
5590  *
5591  * Possibly existing callback function will be replaced.
5592  *
5593  * @param[in] w Widget stack info structure
5594  * @param[in] s Widget unique name to add callback function
5595  * @param[in] f Ano-script callback function name
5596  *
5597  * @retval Zero on success
5598  * @retval Non-zero on failure
5599  *
5600  */
5601 
widget_cb_add_button_press(struct w_stack * w,char * s,char * f)5602 int widget_cb_add_button_press(struct w_stack *w, char *s, char *f) {
5603 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_BUTTONPRESS));
5604 }
5605 
5606 /**
5607  * @brief Add generic button-release callback function to widget.
5608  *
5609  * Possibly existing callback function will be replaced.
5610  *
5611  * @param[in] w Widget stack info structure
5612  * @param[in] s Widget unique name to add callback function
5613  * @param[in] f Ano-script callback function name
5614  *
5615  * @retval Zero on success
5616  * @retval Non-zero on failure
5617  *
5618  */
5619 
widget_cb_add_button_release(struct w_stack * w,char * s,char * f)5620 int widget_cb_add_button_release(struct w_stack *w, char *s, char *f) {
5621 	return(widget_cb_add_op(w, s, f, WIDGET_CB_TYPE_BUTTONRELEASE));
5622 }
5623 
widget_cb_add_op(struct w_stack * w,char * s,char * f,unsigned int c)5624 static int widget_cb_add_op(struct w_stack *w, char *s, char *f, unsigned int c) {
5625 	struct w_info *d;
5626 
5627 	struct widget_cb e[2];
5628 
5629 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
5630 
5631 	e[0].c = c;
5632 	e[0].s = f;
5633 	e[1].c = WIDGET_CB_TYPE_NONE;
5634 	e[1].s = NULL;
5635 
5636 	return(widget_init_stack_cb_add(d, e));
5637 }
5638 
5639 /**
5640  * @brief Delete push-callback function from pushbutton widget.
5641  *
5642  * @param[in] w Widget stack info structure
5643  * @param[in] s Widget unique name to delete callback function
5644  *
5645  * @retval Zero on success
5646  * @retval Non-zero on failure
5647  *
5648  */
5649 
widget_cb_delete_pushbutton_push(struct w_stack * w,char * s)5650 int widget_cb_delete_pushbutton_push(struct w_stack *w, char *s) {
5651 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_PUSHBUTTON_PUSH));
5652 }
5653 
5654 /**
5655  * @brief Delete slide-callback function from slideswitch widget.
5656  *
5657  * @param[in] w Widget stack info structure
5658  * @param[in] s Widget unique name to delete callback function
5659  *
5660  * @retval Zero on success
5661  * @retval Non-zero on failure
5662  *
5663  */
5664 
widget_cb_delete_slideswitch_slide(struct w_stack * w,char * s)5665 int widget_cb_delete_slideswitch_slide(struct w_stack *w, char *s) {
5666 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_SLIDESWITCH_SLIDE));
5667 }
5668 
5669 /**
5670  * @brief Delete toggle-callback function from toggleswitch widget.
5671  *
5672  * @param[in] w Widget stack info structure
5673  * @param[in] s Widget unique name to delete callback function
5674  *
5675  * @retval Zero on success
5676  * @retval Non-zero on failure
5677  *
5678  */
5679 
widget_cb_delete_toggleswitch_toggle(struct w_stack * w,char * s)5680 int widget_cb_delete_toggleswitch_toggle(struct w_stack *w, char *s) {
5681 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_TOGGLESWITCH_TOGGLE));
5682 }
5683 
5684 /**
5685  * @brief Delete turn-callback function from turnswitch widget.
5686  *
5687  * @param[in] w Widget stack info structure
5688  * @param[in] s Widget unique name to delete callback function
5689  *
5690  * @retval Zero on success
5691  * @retval Non-zero on failure
5692  *
5693  */
5694 
widget_cb_delete_turnswitch_turn(struct w_stack * w,char * s)5695 int widget_cb_delete_turnswitch_turn(struct w_stack *w, char *s) {
5696 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_TURNSWITCH_TURN));
5697 }
5698 
5699 /**
5700  * @brief Delete generic key-press callback function from widget.
5701  *
5702  * @param[in] w Widget stack info structure
5703  * @param[in] s Widget unique name to delete callback function
5704  *
5705  * @retval Zero on success
5706  * @retval Non-zero on failure
5707  *
5708  */
5709 
widget_cb_delete_key_press(struct w_stack * w,char * s)5710 int widget_cb_delete_key_press(struct w_stack *w, char *s) {
5711 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_KEYPRESS));
5712 }
5713 
5714 /**
5715  * @brief Delete generic key-release callback function from widget.
5716  *
5717  * @param[in] w Widget stack info structure
5718  * @param[in] s Widget unique name to delete callback function
5719  *
5720  * @retval Zero on success
5721  * @retval Non-zero on failure
5722  *
5723  */
5724 
widget_cb_delete_key_release(struct w_stack * w,char * s)5725 int widget_cb_delete_key_release(struct w_stack *w, char *s) {
5726 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_KEYRELEASE));
5727 }
5728 
5729 /**
5730  * @brief Delete generic button-press callback function from widget.
5731  *
5732  * @param[in] w Widget stack info structure
5733  * @param[in] s Widget unique name to delete callback function
5734  *
5735  * @retval Zero on success
5736  * @retval Non-zero on failure
5737  *
5738  */
5739 
widget_cb_delete_button_press(struct w_stack * w,char * s)5740 int widget_cb_delete_button_press(struct w_stack *w, char *s) {
5741 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_BUTTONPRESS));
5742 }
5743 
5744 /**
5745  * @brief Delete generic button-release callback function from widget.
5746  *
5747  * @param[in] w Widget stack info structure
5748  * @param[in] s Widget unique name to delete callback function
5749  *
5750  * @retval Zero on success
5751  * @retval Non-zero on failure
5752  *
5753  */
5754 
widget_cb_delete_button_release(struct w_stack * w,char * s)5755 int widget_cb_delete_button_release(struct w_stack *w, char *s) {
5756 	return(widget_cb_delete_op(w, s, WIDGET_CB_TYPE_BUTTONRELEASE));
5757 }
5758 
widget_cb_delete_op(struct w_stack * w,char * s,unsigned int c)5759 static int widget_cb_delete_op(struct w_stack *w, char *s, unsigned int c) {
5760 	struct w_info *d;
5761 
5762 	struct widget_cb e[2];
5763 
5764 	if((d = widget_get_info_by_name(w, s)) == NULL) return(-1);
5765 
5766 	e[0].c = c;
5767 	e[0].s = NULL;
5768 	e[1].c = WIDGET_CB_TYPE_NONE;
5769 	e[1].s = NULL;
5770 
5771 	return(widget_init_stack_cb_delete(d, e));
5772 }
5773 
5774 /**
5775  * @brief Refresh widget container window refreshing pending widget outlook changes.
5776  *
5777  * This call is necessary after any widget update.
5778  *
5779  * @param[in] w Widget stack info structure
5780  *
5781  */
5782 
widget_refresh(struct w_stack * w)5783 void widget_refresh(struct w_stack *w) {
5784 	(void) widget_refresh_op(w, 0, 0, 0, 0);
5785 }
5786 
widget_refresh_op(struct w_stack * w,int x,int y,unsigned int e,unsigned int f)5787 static void widget_refresh_op(struct w_stack *w, int x, int y, unsigned int e, unsigned int f) {
5788 	struct clip_2 c;
5789 
5790 	c.x = x;
5791 	c.y = y;
5792 	c.s.width = e;
5793 	c.s.height = f;
5794 
5795 	(void) gui_window_refresh(w->hnd, &c);
5796 }
5797 
widget_cb_move_gauge(struct w_stack * w,struct w_par * p,unsigned int * c)5798 char *widget_cb_move_gauge(struct w_stack *w, struct w_par *p, unsigned int *c) {
5799 	unsigned int i;
5800 
5801 	double f, g;
5802 
5803 	struct widget_type_slideswitch *w_ss;
5804 	struct widget_type_turnswitch *w_tw;
5805 
5806 	struct position a, b;
5807 
5808 	if(w->a == NULL) return(NULL);
5809 
5810 	a.x = (double) p->x;
5811 	a.y = (double) p->y;
5812 	a.z = 0.0;
5813 
5814 	b.z = 0.0;
5815 
5816 	for(i = 0; i < w->c; i++) {
5817 		if(w->a[i] == NULL) continue;
5818 
5819 		switch(w->a[i]->c) {
5820 			case WIDGET_TYPE_SLIDESWITCH:
5821 				w_ss = (struct widget_type_slideswitch *) w->a[i]->p;
5822 
5823 				/* Check if pointer is close enough */
5824 				if((p->x >= w_ss->q.x - WIDGET_SCALE_GAUGE_MARGIN &&
5825 					p->x <= (w_ss->q.x + w_ss->q.w) + WIDGET_SCALE_GAUGE_MARGIN) &&
5826 				(p->y >= w_ss->q.y - WIDGET_SCALE_GAUGE_MARGIN &&
5827 					p->y <= (w_ss->q.y + w_ss->q.h) + WIDGET_SCALE_GAUGE_MARGIN)) {
5828 
5829 					if(w_ss->o % 2 == 0) {
5830 						g = (double) (p->x - w_ss->q.x - (int) (w_ss->p.w / 2));
5831 						g = maths_clamp(g, (double) w_ss->a, (double) w_ss->b);
5832 					}
5833 					else {
5834 						g = (double) (p->y - w_ss->q.y - (int) (w_ss->p.h / 2));
5835 						g = maths_clamp(g, (double) w_ss->a, (double) w_ss->b);
5836 						g = (double) w_ss->b - g;
5837 					}
5838 
5839 					*c = (unsigned int) round(maths_map(g, (double) w_ss->a, (double) w_ss->b,
5840 						0.0, (double) w_ss->c));
5841 
5842 					return(w_ss->e.s);
5843 				}
5844 
5845 				break;
5846 			case WIDGET_TYPE_TURNSWITCH:
5847 				w_tw = (struct widget_type_turnswitch *) w->a[i]->p;
5848 
5849 				b.x = (double) (w_tw->p.x + (w_tw->p.w / 2));
5850 				b.y = (double) (w_tw->p.y + (w_tw->p.h / 2));
5851 
5852 				/* Check if pointer is close enough */
5853 				f = (sqrt(w_tw->p.w * w_tw->p.h) / 2.0) + WIDGET_SCALE_GAUGE_MARGIN;
5854 
5855 				if(coords_difference_2d(&a, &b) < f) {
5856 					a.x -= b.x;
5857 					a.y -= b.y;
5858 
5859 					/* Zero angle is south */
5860 					g = coords_position_to_angle(&a) + 270.0;
5861 
5862 					if(g > 359.0) g -= 360.0;
5863 
5864 					/* Map full round to widget min-max scale */
5865 					if(g < (double) w_tw->a) g = (double) w_tw->a;
5866 					if(g > (double) w_tw->b) g = (double) w_tw->b;
5867 
5868 					*c = (unsigned int) round(maths_map(g, (double) w_tw->a, (double) w_tw->b,
5869 						0.0, (double) w_tw->c));
5870 
5871 					return(w_tw->e.s);
5872 				}
5873 
5874 				break;
5875 			default:
5876 				break;
5877 		}
5878 	}
5879 
5880 	return(NULL);
5881 }
5882 
widget_cb_move_out(__UNUSED__ struct t_ctx * c,struct w_stack * w,struct w_info * d,__UNUSED__ struct w_par * p)5883 void widget_cb_move_out(__UNUSED__ struct t_ctx *c, struct w_stack *w, struct w_info *d, __UNUSED__ struct w_par *p) {
5884 	struct widget_type_slideswitch *w_ss;
5885 	struct widget_type_toggleswitch *w_ts;
5886 	struct widget_type_turnswitch *w_tw;
5887 
5888 	switch(d->c) {
5889 		case WIDGET_TYPE_SLIDESWITCH:
5890 			w_ss = (struct widget_type_slideswitch *) d->p;
5891 
5892 			if(w_ss->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5893 
5894 			(void) widget_update_indicator_op(w, d, &w_ss->i,
5895 				w_ss->i.ox, w_ss->i.oy, w_ss->i.ow, w_ss->i.oh);
5896 			(void) widget_refresh(w);
5897 
5898 			break;
5899 		case WIDGET_TYPE_TOGGLESWITCH:
5900 			w_ts = (struct widget_type_toggleswitch *) d->p;
5901 
5902 			if(w_ts->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5903 
5904 			(void) widget_update_indicator_op(w, d, &w_ts->i,
5905 				w_ts->i.ox, w_ts->i.oy, w_ts->i.ow, w_ts->i.oh);
5906 			(void) widget_refresh(w);
5907 
5908 			break;
5909 		case WIDGET_TYPE_TURNSWITCH:
5910 			w_tw = (struct widget_type_turnswitch *) d->p;
5911 
5912 			if(w_tw->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5913 
5914 			(void) widget_update_indicator_op(w, d, &w_tw->i,
5915 				w_tw->i.ox, w_tw->i.oy, w_tw->i.ow, w_tw->i.oh);
5916 			(void) widget_refresh(w);
5917 
5918 			break;
5919 		default:
5920 			break;
5921 	}
5922 }
5923 
widget_cb_move_over(__UNUSED__ struct t_ctx * c,struct w_stack * w,struct w_info * d,__UNUSED__ struct w_par * p)5924 void widget_cb_move_over(__UNUSED__ struct t_ctx *c, struct w_stack *w, struct w_info *d, __UNUSED__ struct w_par *p) {
5925 	struct widget_type_slideswitch *w_ss;
5926 	struct widget_type_toggleswitch *w_ts;
5927 	struct widget_type_turnswitch *w_tw;
5928 
5929 	switch(d->c) {
5930 		case WIDGET_TYPE_SLIDESWITCH:
5931 			w_ss = (struct widget_type_slideswitch *) d->p;
5932 
5933 			if(w_ss->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5934 
5935 			(void) widget_update_indicator(w, d, &w_ss->i, &w_ss->q, w_ss->d, w_ss->k);
5936 			(void) widget_refresh(w);
5937 
5938 			break;
5939 		case WIDGET_TYPE_TOGGLESWITCH:
5940 			w_ts = (struct widget_type_toggleswitch *) d->p;
5941 
5942 			if(w_ts->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5943 
5944 			(void) widget_update_indicator(w, d, &w_ts->i, &w_ts->p, w_ts->d, w_ts->k);
5945 			(void) widget_refresh(w);
5946 
5947 			break;
5948 		case WIDGET_TYPE_TURNSWITCH:
5949 			w_tw = (struct widget_type_turnswitch *) d->p;
5950 
5951 			if(w_tw->i.c != WIDGET_INDICATOR_MODE_ONDEMAND) break;
5952 
5953 			(void) widget_update_indicator(w, d, &w_tw->i, &w_tw->p, w_tw->d, w_tw->k);
5954 			(void) widget_refresh(w);
5955 
5956 			break;
5957 		default:
5958 			break;
5959 	}
5960 }
5961 
widget_push_cb_key_press(struct t_ctx * c,struct w_info * d,struct w_par * p)5962 void widget_push_cb_key_press(struct t_ctx *c, struct w_info *d, struct w_par *p) {
5963 	(void) callback_event_add(c, d->cb_generic_key_press, p, &d->par_generic_key_press);
5964 }
5965 
widget_push_cb_key_release(struct t_ctx * c,struct w_info * d,struct w_par * p)5966 void widget_push_cb_key_release(struct t_ctx *c, struct w_info *d, struct w_par *p) {
5967 	(void) callback_event_add(c, d->cb_generic_key_release, p, &d->par_generic_key_release);
5968 }
5969 
widget_push_cb_button_press(struct t_ctx * c,struct w_stack * w,struct w_info * d,struct w_par * p)5970 void widget_push_cb_button_press(struct t_ctx *c, struct w_stack *w, struct w_info *d, struct w_par *p) {
5971 	unsigned int r, s;
5972 
5973 	struct t_img *m_i, *m_s;
5974 
5975 	struct widget_id *e;
5976 
5977 	struct widget_type_block *w_bl;
5978 	struct widget_type_slideswitch *w_ss;
5979 	struct widget_type_toggleswitch *w_ts;
5980 	struct widget_type_turnswitch *w_tw;
5981 
5982 	/* If shift is pressed, swap button pairs */
5983 	if((p->state & window_get_mod_shift()) == window_get_mod_shift()) {
5984 		(void) widget_push_cb_button_swap(p);
5985 	}
5986 
5987 	switch(d->c) {
5988 		case WIDGET_TYPE_BLOCK:
5989 			w_bl = (struct widget_type_block *) d->p;
5990 
5991 			if(widget_push_cb_button_press_menu(c, w->hnd, p, w_bl->e.s, w_bl->e.t) == 0) {
5992 				return;
5993 			}
5994 
5995 			break;
5996 		case WIDGET_TYPE_PUSHBUTTON_1:
5997 			if(widget_push_cb_button_press_pb(c, w, d, p, WIDGET_GFX_PUSHBUTTON_1) != 0) {
5998 				return;
5999 			}
6000 
6001 			break;
6002 		case WIDGET_TYPE_PUSHBUTTON_2:
6003 			if(widget_push_cb_button_press_pb(c, w, d, p, WIDGET_GFX_PUSHBUTTON_2) != 0) {
6004 				return;
6005 			}
6006 
6007 			break;
6008 		case WIDGET_TYPE_PUSHBUTTON_3:
6009 			if(widget_push_cb_button_press_pb(c, w, d, p, WIDGET_GFX_PUSHBUTTON_3) != 0) {
6010 				return;
6011 			}
6012 
6013 			break;
6014 		case WIDGET_TYPE_SLIDESWITCH:
6015 			w_ss = (struct widget_type_slideswitch *) d->p;
6016 
6017 			/* No need to call actual button press or menu event if pointer was pressed on scale */
6018 			if(p->gsw == IS_NO) {
6019 				if(p->dragged == IS_YES) {
6020 					r = (unsigned int) round(p->drspeed / CONST_PI);
6021 				}
6022 				else r = 1;
6023 
6024 				if(widget_push_cb_button_press_menu(c, w->hnd, p, w_ss->e.s, w_ss->e.t) != 0) {
6025 					if(widget_push_cb_button_press_134567(p->button, w_ss->c, &w_ss->d, r) != 0) {
6026 						return;
6027 					}
6028 				}
6029 				else return;
6030 			}
6031 
6032 			/* Call widget callback if trigger mode is continuous */
6033 			if(w_ss->g == IS_YES) {
6034 				e = (struct widget_id *) &w_ss->e;
6035 
6036 				/* Put widget id and state info to callback parameter */
6037 				(void) dsl_cb_param_string_add(&d->par_slideswitch_slide, e->s, e->t, 0);
6038 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, (unsigned int) d->m_id.c, 1);
6039 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->a, 2);
6040 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->b, 3);
6041 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->c, 4);
6042 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->d, 5);
6043 
6044 				(void) callback_event_add(c, d->cb_slideswitch_slide,
6045 					p, &d->par_slideswitch_slide);
6046 			}
6047 
6048 			/* Update widget pixel buffer */
6049 			if(widget_init_stack_bob_predraw(WIDGET_GFX_SLIDESWITCH, w_ss->o, w_ss->ch, &m_i, &m_s) != 0) {
6050 				return;
6051 			}
6052 
6053 /* XXX TODO if(d->o.c != 0) printf("redraw also %d colliding widgets \n", d->o.c); */
6054 
6055 			(void) widget_init_stack_bob_content(WIDGET_GFX_SLIDESWITCH,
6056 				w_ss->o, d, m_i->p, m_s->p, d->m_f, 0);
6057 
6058 			(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
6059 			(void) widget_update_scale(w, d, &w_ss->s);
6060 			(void) widget_update_indicator(w, d, &w_ss->i, &w_ss->q, w_ss->d, w_ss->k);
6061 
6062 			/* Move slider either verically or horizontally */
6063 			if(w_ss->o % 2 == 0) {
6064 				d->x = w_ss->p.x + (unsigned int) round(maths_map((double) w_ss->d,
6065 					0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
6066 			}
6067 			else {
6068 				d->y = w_ss->p.y + w_ss->b - (unsigned int) round(maths_map((double) w_ss->d,
6069 					0.0, (double) w_ss->c, 0.0, (double) w_ss->b));
6070 			}
6071 
6072 			(void) widget_init_stack_bob_copy(w, d);
6073 			(void) widget_step_set_title(w, d, &w_ss->t);
6074 			(void) widget_refresh(w);
6075 
6076 			break;
6077 		case WIDGET_TYPE_TOGGLESWITCH:
6078 			if(p->dragged == IS_YES) return;
6079 
6080 			w_ts = (struct widget_type_toggleswitch *) d->p;
6081 
6082 			/* No need to call actual button press or menu event if pointer was pressed on scale */
6083 			if(p->gsw == IS_NO) {
6084 				if(widget_push_cb_button_press_menu(c, w->hnd, p, w_ts->e.s, w_ts->e.t) != 0) {
6085 					if(widget_push_cb_button_press_13(p->button, w_ts->c, &w_ts->d) != 0) {
6086 						return;
6087 					}
6088 				}
6089 				else return;
6090 			}
6091 
6092 			/* Call widget callback if trigger mode is continuous */
6093 			if(w_ts->g == IS_YES) {
6094 				e = (struct widget_id *) &w_ts->e;
6095 
6096 				/* Put widget id and state info to callback parameter */
6097 				(void) dsl_cb_param_string_add(&d->par_toggleswitch_toggle, e->s, e->t, 0);
6098 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, (unsigned int) d->m_id.c, 1);
6099 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->a, 2);
6100 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->b, 3);
6101 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->c, 4);
6102 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->d, 5);
6103 
6104 				(void) callback_event_add(c, d->cb_toggleswitch_toggle,
6105 					p, &d->par_toggleswitch_toggle);
6106 			}
6107 
6108 			/* Update widget pixel buffer */
6109 			if(widget_init_stack_bob_predraw(WIDGET_GFX_TOGGLESWITCH, w_ts->o, w_ts->ch, &m_i, &m_s) != 0) {
6110 				return;
6111 			}
6112 
6113 /* XXX TODO if(d->o.c != 0) printf("redraw also %d colliding widgets \n", d->o.c); */
6114 
6115 			s = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TOGGLESWITCH, w_ts->o);
6116 
6117 			(void) widget_init_stack_bob_content(WIDGET_GFX_TOGGLESWITCH,
6118 				w_ts->o, d, m_i->p, m_s->p, d->m_f,
6119 				widget_init_stack_bob_frame(w_ts->a, w_ts->b, w_ts->c, w_ts->d,
6120 				(double) (s / WIDGET_FRAME_TOGGLESWITCH_ANGLES)));
6121 
6122 			(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
6123 			(void) widget_update_scale(w, d, &w_ts->s);
6124 			(void) widget_update_indicator(w, d, &w_ts->i, &w_ts->p, w_ts->d, w_ts->k);
6125 
6126 			(void) widget_init_stack_bob_copy(w, d);
6127 			(void) widget_step_set_title(w, d, &w_ts->t);
6128 			(void) widget_refresh(w);
6129 
6130 			break;
6131 		case WIDGET_TYPE_TURNSWITCH:
6132 			w_tw = (struct widget_type_turnswitch *) d->p;
6133 
6134 			/* No need to call actual button press or menu event if pointer was pressed on scale */
6135 			if(p->gsw == IS_NO) {
6136 				if(p->dragged == IS_YES) {
6137 					r = (unsigned int) round(p->drspeed / CONST_PI);
6138 				}
6139 				else r = 1;
6140 
6141 				if(widget_push_cb_button_press_menu(c, w->hnd, p, w_tw->e.s, w_tw->e.t) != 0) {
6142 					if(widget_push_cb_button_press_134567(p->button, w_tw->c, &w_tw->d, r) != 0) {
6143 						return;
6144 					}
6145 				}
6146 				else return;
6147 			}
6148 
6149 			/* Call widget callback if trigger mode is continuous or event happened on scale */
6150 			if(w_tw->g == IS_YES || p->gsw == IS_YES) {
6151 				e = (struct widget_id *) &w_tw->e;
6152 
6153 				/* Put widget id and state info to callback parameter */
6154 				(void) dsl_cb_param_string_add(&d->par_turnswitch_turn, e->s, e->t, 0);
6155 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, (unsigned int) d->m_id.c, 1);
6156 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->a, 2);
6157 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->b, 3);
6158 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->c, 4);
6159 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->d, 5);
6160 
6161 				(void) callback_event_add(c, d->cb_turnswitch_turn,
6162 					p, &d->par_turnswitch_turn);
6163 			}
6164 			if(p->gsw == IS_YES) return;
6165 
6166 			/* Update widget pixel buffer */
6167 			if(widget_init_stack_bob_predraw(WIDGET_GFX_TURNSWITCH, w_tw->o, w_tw->ch, &m_i, &m_s) != 0) {
6168 				return;
6169 			}
6170 
6171 /* XXX TODO if(d->o.c != 0) printf("redraw also %d colliding widgets \n", d->o.c); */
6172 
6173 			s = widget_init_stack_bob_predraw_frame(WIDGET_GFX_TURNSWITCH, w_tw->o);
6174 
6175 			(void) widget_init_stack_bob_content(WIDGET_GFX_TURNSWITCH,
6176 				w_tw->o, d, m_i->p, m_s->p, d->m_f,
6177 				widget_init_stack_bob_frame(w_tw->a, w_tw->b, w_tw->c, w_tw->d,
6178 				(double) (s / WIDGET_FRAME_TURNSWITCH_ANGLES)));
6179 
6180 			(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
6181 			(void) widget_update_scale(w, d, &w_tw->s);
6182 			(void) widget_update_indicator(w, d, &w_tw->i, &w_tw->p, w_tw->d, w_tw->k);
6183 
6184 			(void) widget_init_stack_bob_copy(w, d);
6185 			(void) widget_step_set_title(w, d, &w_tw->t);
6186 			(void) widget_refresh(w);
6187 
6188 			break;
6189 		default:
6190 			break;
6191 	}
6192 
6193 	(void) callback_event_add(c, d->cb_generic_button_press, p, &d->par_generic_button_press);
6194 }
6195 
widget_push_cb_button_press_pb(struct t_ctx * c,struct w_stack * w,struct w_info * d,struct w_par * p,unsigned int g)6196 static int widget_push_cb_button_press_pb(struct t_ctx *c, struct w_stack *w, struct w_info *d, struct w_par *p, unsigned int g) {
6197 	unsigned int s;
6198 
6199 	struct t_img *m_i, *m_s;
6200 
6201 	struct widget_id *e;
6202 	struct widget_type_pushbutton *w_pb;
6203 
6204 	if(p->dragged == IS_YES) return(-1);
6205 
6206 	w_pb = (struct widget_type_pushbutton *) d->p;
6207 
6208 	/* No need to call actual button press or menu event if pointer was pressed on scale */
6209 	if(p->gsw == IS_NO) {
6210 		if(widget_push_cb_button_press_menu(c, w->hnd, p, w_pb->e.s, w_pb->e.t) != 0) {
6211 			if(widget_push_cb_button_toggle_13(p->button, &w_pb->d) != 0) {
6212 				return(-1);
6213 			}
6214 		}
6215 		else return(-1);
6216 	}
6217 
6218 	e = (struct widget_id *) &w_pb->e;
6219 
6220 	/* Put widget id and state info to callback parameter */
6221 	(void) dsl_cb_param_string_add(&d->par_pushbutton_push, e->s, e->t, 0);
6222 	(void) dsl_cb_param_uint_add(&d->par_pushbutton_push, (unsigned int) d->m_id.c, 1);
6223 	(void) dsl_cb_param_uint_add(&d->par_pushbutton_push, w_pb->a, 2);
6224 	(void) dsl_cb_param_uint_add(&d->par_pushbutton_push, w_pb->b, 3);
6225 	(void) dsl_cb_param_uint_add(&d->par_pushbutton_push, w_pb->c, 4);
6226 	(void) dsl_cb_param_uint_add(&d->par_pushbutton_push, w_pb->d, 5);
6227 
6228 	(void) callback_event_add(c, d->cb_pushbutton_push,
6229 		p, &d->par_pushbutton_push);
6230 
6231 	/* Update widget pixel buffer */
6232 	if(widget_init_stack_bob_predraw(g, w_pb->o, w_pb->ch, &m_i, &m_s) != 0) {
6233 		return(-1);
6234 	}
6235 
6236 	s = widget_init_stack_bob_predraw_frame(g, w_pb->o);
6237 
6238 	(void) widget_init_stack_bob_content(g, w_pb->o, d, m_i->p, m_s->p, d->m_f,
6239 		widget_init_stack_bob_frame(w_pb->a, w_pb->b, w_pb->c, w_pb->d,
6240 		(double) (s / WIDGET_FRAME_PUSHBUTTON_ANGLES)));
6241 
6242 	(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
6243 	(void) widget_init_stack_bob_copy(w, d);
6244 	(void) widget_step_set_title(w, d, &w_pb->t);
6245 	(void) widget_refresh(w);
6246 
6247 	return(0);
6248 }
6249 
widget_push_cb_button_release(struct t_ctx * c,struct w_stack * w,struct w_info * d,struct w_par * p)6250 void widget_push_cb_button_release(struct t_ctx *c, struct w_stack *w, struct w_info *d, struct w_par *p) {
6251 	struct widget_id *e;
6252 
6253 	struct widget_type_slideswitch *w_ss;
6254 	struct widget_type_toggleswitch *w_ts;
6255 	struct widget_type_turnswitch *w_tw;
6256 
6257 	/* If shift is pressed, swap button pairs */
6258 	if((p->state & window_get_mod_shift()) == window_get_mod_shift()) {
6259 		(void) widget_push_cb_button_swap(p);
6260 	}
6261 
6262 	switch(d->c) {
6263 		case WIDGET_TYPE_PUSHBUTTON_1:
6264 			if(widget_push_cb_button_release_pb(w, d, p, WIDGET_GFX_PUSHBUTTON_1) != 0) {
6265 				return;
6266 			}
6267 
6268 			break;
6269 		case WIDGET_TYPE_PUSHBUTTON_2:
6270 			if(widget_push_cb_button_release_pb(w, d, p, WIDGET_GFX_PUSHBUTTON_2) != 0) {
6271 				return;
6272 			}
6273 
6274 			break;
6275 		case WIDGET_TYPE_PUSHBUTTON_3:
6276 			if(widget_push_cb_button_release_pb(w, d, p, WIDGET_GFX_PUSHBUTTON_3) != 0) {
6277 				return;
6278 			}
6279 
6280 			break;
6281 		case WIDGET_TYPE_SLIDESWITCH:
6282 			w_ss = (struct widget_type_slideswitch *) d->p;
6283 
6284 			/* Call widget callback if trigger mode is non-continuous */
6285 			if(w_ss->g != IS_YES) {
6286 				e = (struct widget_id *) &w_ss->e;
6287 
6288 				/* Put widget id and state info to callback parameter */
6289 				(void) dsl_cb_param_string_add(&d->par_slideswitch_slide, e->s, e->t, 0);
6290 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, (unsigned int) d->m_id.c, 1);
6291 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->a, 2);
6292 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->b, 3);
6293 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->c, 4);
6294 				(void) dsl_cb_param_uint_add(&d->par_slideswitch_slide, w_ss->d, 5);
6295 
6296 				(void) callback_event_add(c, d->cb_slideswitch_slide,
6297 					p, &d->par_slideswitch_slide);
6298 			}
6299 
6300 			break;
6301 		case WIDGET_TYPE_TOGGLESWITCH:
6302 			w_ts = (struct widget_type_toggleswitch *) d->p;
6303 
6304 			/* Call widget callback if trigger mode is non-continuous */
6305 			if(w_ts->g != IS_YES) {
6306 				e = (struct widget_id *) &w_ts->e;
6307 
6308 				/* Put widget id and state info to callback parameter */
6309 				(void) dsl_cb_param_string_add(&d->par_toggleswitch_toggle, e->s, e->t, 0);
6310 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, (unsigned int) d->m_id.c, 1);
6311 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->a, 2);
6312 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->b, 3);
6313 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->c, 4);
6314 				(void) dsl_cb_param_uint_add(&d->par_toggleswitch_toggle, w_ts->d, 5);
6315 
6316 				(void) callback_event_add(c, d->cb_toggleswitch_toggle,
6317 					p, &d->par_toggleswitch_toggle);
6318 			}
6319 
6320 			break;
6321 		case WIDGET_TYPE_TURNSWITCH:
6322 			w_tw = (struct widget_type_turnswitch *) d->p;
6323 
6324 			/* Call widget callback if trigger mode is non-continuous */
6325 			if(w_tw->g != IS_YES) {
6326 				e = (struct widget_id *) &w_tw->e;
6327 
6328 				/* Put widget id and state info to callback parameter */
6329 				(void) dsl_cb_param_string_add(&d->par_turnswitch_turn, e->s, e->t, 0);
6330 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, (unsigned int) d->m_id.c, 1);
6331 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->a, 2);
6332 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->b, 3);
6333 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->c, 4);
6334 				(void) dsl_cb_param_uint_add(&d->par_turnswitch_turn, w_tw->d, 5);
6335 
6336 				(void) callback_event_add(c, d->cb_turnswitch_turn,
6337 					p, &d->par_turnswitch_turn);
6338 			}
6339 
6340 			break;
6341 		default:
6342 			break;
6343 	}
6344 
6345 	(void) callback_event_add(c, d->cb_generic_button_release, p, &d->par_generic_button_release);
6346 }
6347 
widget_push_cb_button_release_pb(struct w_stack * w,struct w_info * d,struct w_par * p,unsigned int g)6348 static int widget_push_cb_button_release_pb(struct w_stack *w, struct w_info *d, struct w_par *p, unsigned int g) {
6349 	unsigned int s;
6350 
6351 	struct t_img *m_i, *m_s;
6352 
6353 	struct widget_type_pushbutton *w_pb;
6354 
6355 	w_pb = (struct widget_type_pushbutton *) d->p;
6356 
6357 	/* Do nothing here if button is sticky */
6358 	if(w_pb->z == IS_YES) return(-1);
6359 
6360 	if(widget_push_cb_button_clear_13(p->button, &w_pb->d) != 0) {
6361 		return(-1);
6362 	}
6363 
6364 	/* Update widget pixel buffer */
6365 	if(widget_init_stack_bob_predraw(g, w_pb->o, w_pb->ch, &m_i, &m_s) != 0) {
6366 		return(-1);
6367 	}
6368 
6369 	s = widget_init_stack_bob_predraw_frame(g, w_pb->o);
6370 
6371 	(void) widget_init_stack_bob_content(g, w_pb->o, d, m_i->p, m_s->p, d->m_f,
6372 		widget_init_stack_bob_frame(w_pb->a, w_pb->b, w_pb->c, w_pb->d,
6373 		(double) (s / WIDGET_FRAME_PUSHBUTTON_ANGLES)));
6374 
6375 	(void) widget_update_op(w, d, d->x, d->y, d->w, d->h);
6376 	(void) widget_init_stack_bob_copy(w, d);
6377 	(void) widget_step_set_title(w, d, &w_pb->t);
6378 	(void) widget_refresh(w);
6379 
6380 	return(0);
6381 }
6382 
widget_push_cb_button_clear_13(unsigned int p,unsigned int * d)6383 static int widget_push_cb_button_clear_13(unsigned int p, unsigned int *d) {
6384 	switch(p) {
6385 		case 1:
6386 		case 3:
6387 			*d = 0;
6388 
6389 			break;
6390 		default:
6391 			return(-1);
6392 	}
6393 
6394 	return(0);
6395 }
6396 
widget_push_cb_button_toggle_13(unsigned int p,unsigned int * d)6397 static int widget_push_cb_button_toggle_13(unsigned int p, unsigned int *d) {
6398 	switch(p) {
6399 		case 1:
6400 		case 3:
6401 			*d ^= 1;
6402 
6403 			break;
6404 		default:
6405 			return(-1);
6406 	}
6407 
6408 	return(0);
6409 }
6410 
widget_push_cb_button_press_13(unsigned int p,unsigned int c,unsigned int * d)6411 static int widget_push_cb_button_press_13(unsigned int p, unsigned int c, unsigned int *d) {
6412 	switch(p) {
6413 		case 1:
6414 			if(*d >= c) return(-1);
6415 
6416 			++(*d);
6417 
6418 			break;
6419 		case 3:
6420 			if(*d == 0) return(-1);
6421 
6422 			--(*d);
6423 
6424 			break;
6425 		default:
6426 			return(-1);
6427 	}
6428 
6429 	return(0);
6430 }
6431 
widget_push_cb_button_press_134567(unsigned int p,unsigned int c,unsigned int * d,unsigned int s)6432 static int widget_push_cb_button_press_134567(unsigned int p, unsigned int c, unsigned int *d, unsigned int s) {
6433 	if(s == 0) return(-1);
6434 
6435 	switch(p) {
6436 		case 1:
6437 		case 5:
6438 		case 6:
6439 			if(*d >= c) return(-1);
6440 
6441 			if(*d + s >= c) s = c - *d;
6442 
6443 			*d += s;
6444 
6445 			break;
6446 		case 3:
6447 		case 4:
6448 		case 7:
6449 			if(*d == 0) return(-1);
6450 
6451 			if(s > *d) s = *d;
6452 
6453 			*d -= s;
6454 
6455 			break;
6456 		default:
6457 			return(-1);
6458 	}
6459 
6460 	return(0);
6461 }
6462 
widget_push_cb_button_press_menu(struct t_ctx * c,unsigned int v,struct w_par * p,char * s,size_t t)6463 static int widget_push_cb_button_press_menu(struct t_ctx *c, unsigned int v, struct w_par *p, char *s, size_t t) {
6464 #if ! defined(PROG_DISABLE_MENU) && defined(PROG_HAS_X11)
6465 	/* Widget menu opens with mouse button 2, or with any other button with ctrl pressed */
6466 	switch(p->button) {
6467 		case 2:
6468 			break;
6469 		default:
6470 			if((p->state & window_get_mod_ctrl()) == window_get_mod_ctrl()) {
6471 				break;
6472 			}
6473 
6474 			return(-1);
6475 	}
6476 
6477 	return(menu_init_stack_by_name(c, s, t, v));
6478 #else
6479 	(void) c;
6480 	(void) v;
6481 	(void) p;
6482 	(void) s;
6483 	(void) t;
6484 
6485 	return(-1);
6486 #endif
6487 }
6488 
widget_push_cb_button_swap(struct w_par * p)6489 static void widget_push_cb_button_swap(struct w_par *p) {
6490 	switch(p->button) {
6491 		case 1:
6492 			p->button = 3;
6493 
6494 			break;
6495 		case 3:
6496 			p->button = 1;
6497 
6498 			break;
6499 		case 4:
6500 			p->button = 5;
6501 
6502 			break;
6503 		case 5:
6504 			p->button = 4;
6505 
6506 			break;
6507 		case 6:
6508 			p->button = 7;
6509 
6510 			break;
6511 		case 7:
6512 			p->button = 6;
6513 
6514 			break;
6515 		default:
6516 			break;
6517 	}
6518 }
6519 
widget_get_drag_by_widget(struct w_info * d)6520 int widget_get_drag_by_widget(struct w_info *d) {
6521 	switch(d->c) {
6522 		case WIDGET_TYPE_SLIDESWITCH:
6523 		case WIDGET_TYPE_TURNSWITCH:
6524 			return(IS_YES);
6525 		default:
6526 			break;
6527 	}
6528 
6529 	return(IS_NO);
6530 }
6531 
widget_get_scale_by_id(struct w_stack * w,unsigned int h)6532 int widget_get_scale_by_id(struct w_stack *w, unsigned int h) {
6533 	unsigned int i;
6534 
6535 	struct widget_type_slideswitch *w_ss;
6536 	struct widget_type_toggleswitch *w_ts;
6537 	struct widget_type_turnswitch *w_tw;
6538 
6539 	for(i = 0; i < w->c; i++) {
6540 		if(w->a[i] == NULL) continue;
6541 
6542 		if((unsigned int) w->a[i]->m_id.c == h) {
6543 			switch(w->a[i]->c) {
6544 				case WIDGET_TYPE_SLIDESWITCH:
6545 					w_ss = (struct widget_type_slideswitch *) w->a[i]->p;
6546 
6547 					if(w_ss->s.c != WIDGET_SCALE_TYPE_NONE) return(IS_YES);
6548 
6549 					break;
6550 				case WIDGET_TYPE_TOGGLESWITCH:
6551 					w_ts = (struct widget_type_toggleswitch *) w->a[i]->p;
6552 
6553 					if(w_ts->s.c != WIDGET_SCALE_TYPE_NONE) return(IS_YES);
6554 
6555 					break;
6556 				case WIDGET_TYPE_TURNSWITCH:
6557 					w_tw = (struct widget_type_turnswitch *) w->a[i]->p;
6558 
6559 					if(w_tw->s.c != WIDGET_SCALE_TYPE_NONE) return(IS_YES);
6560 
6561 					break;
6562 				default:
6563 					break;
6564 			}
6565 
6566 			break;
6567 		}
6568 	}
6569 
6570 	return(IS_NO);
6571 }
6572 
widget_get_info_by_id(struct w_stack * w,unsigned int h)6573 struct w_info *widget_get_info_by_id(struct w_stack *w, unsigned int h) {
6574 	unsigned int i;
6575 
6576 	for(i = 0; i < w->c; i++) {
6577 		if(w->a[i] == NULL) continue;
6578 
6579 		if((unsigned int) w->a[i]->m_id.c == h) return(w->a[i]);
6580 	}
6581 
6582 	return(NULL);
6583 }
6584 
widget_get_info_by_name(struct w_stack * w,char * s)6585 struct w_info *widget_get_info_by_name(struct w_stack *w, char *s) {
6586 	unsigned int i;
6587 
6588 	size_t t;
6589 
6590 	struct widget_type_background *w_ba;
6591 	struct widget_type_block *w_bl;
6592 	struct widget_type_label *w_la;
6593 	struct widget_type_lamp *w_lm;
6594 	struct widget_type_led *w_le;
6595 	struct widget_type_pushbutton *w_pb;
6596 	struct widget_type_slideswitch *w_ss;
6597 	struct widget_type_toggleswitch *w_ts;
6598 	struct widget_type_turnswitch *w_tw;
6599 
6600 	if(s == NULL) return(NULL);
6601 
6602 	t = str_len(s, STRING_ASCII);
6603 
6604 	for(i = 0; i < w->c; i++) {
6605 		if(w->a[i] == NULL) continue;
6606 
6607 		switch(w->a[i]->c) {
6608 			case WIDGET_TYPE_BACKGROUND:
6609 				w_ba = (struct widget_type_background *) w->a[i]->p;
6610 
6611 				if(widget_get_info_by_name_op(&w_ba->e, s, t) == 0) {
6612 					return(w->a[i]);
6613 				}
6614 
6615 				break;
6616 			case WIDGET_TYPE_BLOCK:
6617 				w_bl = (struct widget_type_block *) w->a[i]->p;
6618 
6619 				if(widget_get_info_by_name_op(&w_bl->e, s, t) == 0) {
6620 					return(w->a[i]);
6621 				}
6622 
6623 				break;
6624 			case WIDGET_TYPE_LABEL:
6625 				w_la = (struct widget_type_label *) w->a[i]->p;
6626 
6627 				if(widget_get_info_by_name_op(&w_la->e, s, t) == 0) {
6628 					return(w->a[i]);
6629 				}
6630 
6631 				break;
6632 			case WIDGET_TYPE_LAMP:
6633 				w_lm = (struct widget_type_lamp *) w->a[i]->p;
6634 
6635 				if(widget_get_info_by_name_op(&w_lm->e, s, t) == 0) {
6636 					return(w->a[i]);
6637 				}
6638 
6639 				break;
6640 			case WIDGET_TYPE_LED_1:
6641 			case WIDGET_TYPE_LED_2:
6642 			case WIDGET_TYPE_LED_3:
6643 				w_le = (struct widget_type_led *) w->a[i]->p;
6644 
6645 				if(widget_get_info_by_name_op(&w_le->e, s, t) == 0) {
6646 					return(w->a[i]);
6647 				}
6648 
6649 				break;
6650 			case WIDGET_TYPE_PUSHBUTTON_1:
6651 			case WIDGET_TYPE_PUSHBUTTON_2:
6652 			case WIDGET_TYPE_PUSHBUTTON_3:
6653 				w_pb = (struct widget_type_pushbutton *) w->a[i]->p;
6654 
6655 				if(widget_get_info_by_name_op(&w_pb->e, s, t) == 0) {
6656 					return(w->a[i]);
6657 				}
6658 
6659 				break;
6660 			case WIDGET_TYPE_SLIDESWITCH:
6661 				w_ss = (struct widget_type_slideswitch *) w->a[i]->p;
6662 
6663 				if(widget_get_info_by_name_op(&w_ss->e, s, t) == 0) {
6664 					return(w->a[i]);
6665 				}
6666 
6667 				break;
6668 			case WIDGET_TYPE_TOGGLESWITCH:
6669 				w_ts = (struct widget_type_toggleswitch *) w->a[i]->p;
6670 
6671 				if(widget_get_info_by_name_op(&w_ts->e, s, t) == 0) {
6672 					return(w->a[i]);
6673 				}
6674 
6675 				break;
6676 			case WIDGET_TYPE_TURNSWITCH:
6677 				w_tw = (struct widget_type_turnswitch *) w->a[i]->p;
6678 
6679 				if(widget_get_info_by_name_op(&w_tw->e, s, t) == 0) {
6680 					return(w->a[i]);
6681 				}
6682 
6683 				break;
6684 			default:
6685 				break;
6686 		}
6687 	}
6688 
6689 	(void) flush_error();
6690 
6691 	LOGWARN(
6692 		ERROR_SLIGHT, SUBSYSTEM,
6693 		_("Widget %s does not exist, please check widget definitions"),
6694 		s
6695 	);
6696 
6697 	return(NULL);
6698 }
6699 
widget_get_info_by_name_op(struct widget_id * w,char * s,size_t t)6700 static int widget_get_info_by_name_op(struct widget_id *w, char *s, size_t t) {
6701 	if(w->t == t) {
6702 		if(memcmp((const void *) w->s, (const void *) s, t) == 0) {
6703 			return(0);
6704 		}
6705 	}
6706 
6707 	return(-1);
6708 }
6709 
widget_get_info_by_set(struct w_stack * w,unsigned int s,unsigned int * h)6710 static struct w_info *widget_get_info_by_set(struct w_stack *w, unsigned int s, unsigned int *h) {
6711 	unsigned int i, r;
6712 
6713 	struct widget_type_background *w_ba;
6714 	struct widget_type_block *w_bl;
6715 	struct widget_type_label *w_la;
6716 	struct widget_type_lamp *w_lm;
6717 	struct widget_type_led *w_le;
6718 	struct widget_type_pushbutton *w_pb;
6719 	struct widget_type_slideswitch *w_ss;
6720 	struct widget_type_toggleswitch *w_ts;
6721 	struct widget_type_turnswitch *w_tw;
6722 
6723 	for(i = *h; i < w->c; i++) {
6724 		if(w->a[i] == NULL) continue;
6725 
6726 		r = 0;
6727 
6728 		switch(w->a[i]->c) {
6729 			case WIDGET_TYPE_BACKGROUND:
6730 				w_ba = (struct widget_type_background *) w->a[i]->p;
6731 
6732 				if(w_ba->e.c == WIDGET_STATE_ENABLE) r = w_ba->set;
6733 
6734 				break;
6735 			case WIDGET_TYPE_BLOCK:
6736 				w_bl = (struct widget_type_block *) w->a[i]->p;
6737 
6738 				if(w_bl->e.c == WIDGET_STATE_ENABLE) r = w_bl->set;
6739 
6740 				break;
6741 			case WIDGET_TYPE_LABEL:
6742 				w_la = (struct widget_type_label *) w->a[i]->p;
6743 
6744 				if(w_la->e.c == WIDGET_STATE_ENABLE) r = w_la->set;
6745 
6746 				break;
6747 			case WIDGET_TYPE_LAMP:
6748 				w_lm = (struct widget_type_lamp *) w->a[i]->p;
6749 
6750 				if(w_lm->e.c == WIDGET_STATE_ENABLE) r = w_lm->set;
6751 
6752 				break;
6753 			case WIDGET_TYPE_LED_1:
6754 			case WIDGET_TYPE_LED_2:
6755 			case WIDGET_TYPE_LED_3:
6756 				w_le = (struct widget_type_led *) w->a[i]->p;
6757 
6758 				if(w_le->e.c == WIDGET_STATE_ENABLE) r = w_le->set;
6759 
6760 				break;
6761 			case WIDGET_TYPE_PUSHBUTTON_1:
6762 			case WIDGET_TYPE_PUSHBUTTON_2:
6763 			case WIDGET_TYPE_PUSHBUTTON_3:
6764 				w_pb = (struct widget_type_pushbutton *) w->a[i]->p;
6765 
6766 				if(w_pb->e.c == WIDGET_STATE_ENABLE) r = w_pb->set;
6767 
6768 				break;
6769 			case WIDGET_TYPE_SLIDESWITCH:
6770 				w_ss = (struct widget_type_slideswitch *) w->a[i]->p;
6771 
6772 				if(w_ss->e.c == WIDGET_STATE_ENABLE) r = w_ss->set;
6773 
6774 				break;
6775 			case WIDGET_TYPE_TOGGLESWITCH:
6776 				w_ts = (struct widget_type_toggleswitch *) w->a[i]->p;
6777 
6778 				if(w_ts->e.c == WIDGET_STATE_ENABLE) r = w_ts->set;
6779 
6780 				break;
6781 			case WIDGET_TYPE_TURNSWITCH:
6782 				w_tw = (struct widget_type_turnswitch *) w->a[i]->p;
6783 
6784 				if(w_tw->e.c == WIDGET_STATE_ENABLE) r = w_tw->set;
6785 
6786 				break;
6787 			default:
6788 				break;
6789 		}
6790 
6791 		if(r != 0 && r == s) {
6792 			*h = i + 1;
6793 
6794 			return(w->a[i]);
6795 		}
6796 	}
6797 
6798 	return(NULL);
6799 }
6800 
widget_strcpy(char * d,char * s)6801 static char *widget_strcpy(char *d, char *s) {
6802 	char *n;
6803 
6804 	size_t t;
6805 
6806 	if(s != NULL) {
6807 		t = str_len(s, STRING_ASCII);
6808 
6809 		APP_MALLOC_RET_VALUE(n, t + sizeof(char), d);
6810 
6811 		if(d != NULL) (void) free(d);
6812 
6813 		(void) memcpy((void *) n, (const void *) s, t);
6814 
6815 		n[t] = 0;
6816 
6817 		return(n);
6818 	}
6819 
6820 	return(d);
6821 }
6822 
widget_get_default_widget_path(unsigned int i)6823 const char *widget_get_default_widget_path(unsigned int i) {
6824 	return(c_d_t[i]);
6825 }
6826 #endif
6827