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