1 /* MikMod module player
2 (c) 1998 - 2000 Miodrag Vallat and others - see file AUTHORS for
3 complete list.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23 $Id: mwidget.c,v 1.1.1.1 2004/01/16 02:07:33 raph Exp $
24
25 Widget and Dialog creation functions
26
27 ==============================================================================*/
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35
36 #include "display.h"
37 #include "player.h"
38 #include "mwindow.h"
39 #include "mwidget.h"
40 #include "keys.h"
41 #include "mutilities.h"
42
43 #define STR_WIDTH_MAX 70
44 #define STR_WIDTH_MIN 20
45 #define INT_WIDTH_MAX 11
46
47 #define LIST_WIDTH_DEFAULT 60
48 #define LIST_WIDTH_MIN 15
49 #define LIST_HEIGHT_DEFAULT 20
50 #define LIST_HEIGHT_MIN 5
51
52 #define WWIN(w) ((w)->w.d->win)
53
base_attr(DIALOG * d,ATTRS attrs)54 static ATTRS base_attr (DIALOG *d, ATTRS attrs)
55 {
56 if (d->attrs >= 0) return d->attrs;
57 return attrs;
58 }
59
label_free(WID_LABEL * w)60 static void label_free(WID_LABEL *w)
61 {
62 free(w->msg);
63 free(w);
64 }
65
label_paint(WID_LABEL * w)66 static void label_paint(WID_LABEL *w)
67 {
68 char *start, *pos;
69 int y = w->w.y;
70
71 win_attrset(base_attr(w->w.d,ATTR_DLG_LABEL));
72 start = w->msg;
73 for (pos = w->msg; *pos; pos++) {
74 if (*pos == '\n') {
75 *pos = '\0';
76 win_print(WWIN(w),w->w.x, y, start);
77 *pos = '\n';
78 start = pos + 1;
79 y++;
80 }
81 }
82 win_print(WWIN(w),w->w.x, y, start);
83 }
84
label_handle_event(WID_LABEL * w,WID_EVENT event,int ch)85 static int label_handle_event(WID_LABEL *w, WID_EVENT event, int ch)
86 {
87 return 0;
88 }
89
label_get_size(WID_LABEL * w,int * width,int * height)90 static void label_get_size(WID_LABEL *w, int *width, int *height)
91 {
92 char *pos;
93 int x = 0;
94
95 *width = 0;
96 *height = 0;
97 for (pos = w->msg; *pos; pos++) {
98 if (*pos == '\n') {
99 (*height)++;
100 if (x > *width)
101 *width = x;
102 x = -1;
103 }
104 x++;
105 }
106 if (x > *width)
107 *width = x;
108 (*height)++;
109 }
110
str_free(WID_STR * w)111 static void str_free(WID_STR *w)
112 {
113 free(w->input);
114 free(w);
115 }
116
str_paint(WID_STR * w)117 static void str_paint(WID_STR *w)
118 {
119 char hl[2] = " ", ch = ' ', *pos = &w->input[w->start];
120 int dx = 0, len;
121
122 win_attrset(ATTR_DLG_STR_TEXT);
123 if (w->w.has_focus) {
124 hl[0] = ch = w->input[w->cur_pos];
125 if (!hl[0])
126 hl[0] = ' ';
127 w->input[w->cur_pos] = '\0';
128 if (*pos)
129 win_print(WWIN(w),w->w.x, w->w.y, pos);
130 dx = strlen(pos);
131 win_attrset(ATTR_DLG_STR_CURSOR);
132 win_print(WWIN(w),w->w.x + dx, w->w.y, hl);
133 win_attrset(ATTR_DLG_STR_TEXT);
134 pos += dx;
135 dx++;
136 *pos = ch;
137 if (*pos)
138 pos++;
139 }
140 len = strlen(pos);
141 if (len + dx > w->w.width) {
142 ch = w->input[w->w.width + w->start];
143 w->input[w->w.width + w->start] = '\0';
144 }
145 win_print(WWIN(w),w->w.x + dx, w->w.y, pos);
146 if (len + dx > w->w.width)
147 w->input[w->w.width + w->start] = ch;
148 else if (len + dx < w->w.width) {
149 dx += len;
150 for (len = 0; len < w->w.width - dx; len++)
151 storage[len] = ' ';
152 storage[len] = '\0';
153 win_print(WWIN(w),w->w.x + dx, w->w.y, storage);
154 }
155 }
156
handle_focus(WIDGET * w,int ret,int from_activate)157 static int handle_focus(WIDGET *w, int ret, int from_activate)
158 {
159 if (ret && (ret != EVENT_HANDLED) && w->handle_focus) {
160 return w->handle_focus((WIDGET *) w, ret);
161 } else {
162 if (ret == FOCUS_ACTIVATE) {
163 ret = from_activate;
164 if (ret == EVENT_HANDLED)
165 dialog_close(w->d);
166 }
167 return ret;
168 }
169 }
170
input_handle_event(WID_STR * w,WID_EVENT event,int ch,BOOL int_input)171 static int input_handle_event(WID_STR *w, WID_EVENT event,
172 int ch, BOOL int_input)
173 {
174 char *pos;
175 int i;
176
177 if (event == WID_HOTKEY)
178 return 0;
179 if (event == WID_GET_FOCUS)
180 return EVENT_HANDLED;
181 if ((event == WID_KEY) && w->w.handle_key) {
182 i = w->w.handle_key((WIDGET *) w, ch);
183 if (i)
184 return i;
185 }
186
187 switch (ch) {
188 case KEY_UP:
189 return handle_focus((WIDGET*)w, FOCUS_PREV, 0);
190 case KEY_TAB:
191 case KEY_DOWN:
192 return handle_focus((WIDGET*)w, FOCUS_NEXT, 0);
193 case KEY_LEFT:
194 case CTRL_B:
195 if (w->cur_pos > 0)
196 w->cur_pos--;
197 break;
198 case KEY_RIGHT:
199 case CTRL_F:
200 if (w->cur_pos < strlen(w->input))
201 w->cur_pos++;
202 break;
203 case KEY_HOME:
204 case KEY_PPAGE:
205 case CTRL_A:
206 w->cur_pos = 0;
207 break;
208 #ifdef KEY_END
209 case KEY_END:
210 #endif
211 case KEY_NPAGE:
212 case CTRL_E:
213 w->cur_pos = strlen(w->input);
214 break;
215 case CTRL_K:
216 w->input[w->cur_pos] = '\0';
217 break;
218 case CTRL_U:
219 w->cur_pos = 0;
220 w->input[w->cur_pos] = '\0';
221 break;
222 case KEY_DC:
223 case CTRL_D:
224 #ifdef KEY_ASCII_DEL
225 case KEY_ASCII_DEL:
226 #endif
227 if (w->cur_pos < strlen(w->input))
228 for (pos = &w->input[w->cur_pos]; *pos; pos++)
229 *pos = *(pos + 1);
230 break;
231 case KEY_BACKSPACE:
232 #ifdef KEY_ASCII_BS
233 case KEY_ASCII_BS:
234 #endif
235 if (w->cur_pos > 0) {
236 for (pos = &w->input[w->cur_pos - 1]; *pos; pos++)
237 *pos = *(pos + 1);
238 w->cur_pos--;
239 }
240 break;
241 case KEY_ENTER:
242 case '\r':
243 return handle_focus((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_NEXT);
244 default:
245 if (ch >= 256 || ch < ' ')
246 return 0;
247
248 if ((int_input && isdigit(ch)) || !int_input) {
249 i = strlen(w->input);
250 if (i < w->length) {
251 for (; i >= w->cur_pos; i--)
252 w->input[i + 1] = w->input[i];
253 w->input[w->cur_pos] = ch;
254 w->cur_pos++;
255 }
256 }
257 }
258 if (w->cur_pos < w->start)
259 w->start = w->cur_pos;
260 if (w->cur_pos >= w->start + w->w.width)
261 w->start = w->cur_pos - w->w.width + 1;
262 str_paint(w);
263 return EVENT_HANDLED;
264 }
265
str_handle_event(WID_STR * w,WID_EVENT event,int ch)266 static int str_handle_event(WID_STR *w, WID_EVENT event, int ch)
267 {
268 return input_handle_event(w, event, ch, 0);
269 }
270
str_get_size(WID_STR * w,int * width,int * height)271 static void str_get_size(WID_STR *w, int *width, int *height)
272 {
273 if (*width > w->w.def_width)
274 *width = w->w.def_width;
275 if (*width > w->length)
276 *width = w->length + 1;
277 if (*width < STR_WIDTH_MIN)
278 *width = STR_WIDTH_MIN;
279
280 w->start = w->cur_pos - *width + 1;
281 if (w->start < 0)
282 w->start = 0;
283
284 *height = 1;
285 }
286
int_free(WID_INT * w)287 static void int_free(WID_INT *w)
288 {
289 free(w->input);
290 free(w);
291 }
292
int_paint(WID_INT * w)293 static void int_paint(WID_INT *w)
294 {
295 str_paint((WID_STR *) w);
296 }
297
int_handle_event(WID_INT * w,WID_EVENT event,int ch)298 static BOOL int_handle_event(WID_INT *w, WID_EVENT event, int ch)
299 {
300 return input_handle_event((WID_STR *) w, event, ch, 1);
301 }
302
int_get_size(WID_INT * w,int * width,int * height)303 static void int_get_size(WID_INT *w, int *width, int *height)
304 {
305 *width = w->w.def_width;
306 *height = 1;
307 }
308
button_free(WID_BUTTON * w)309 static void button_free(WID_BUTTON *w)
310 {
311 free(w->button);
312 free(w);
313 }
314
button_paint(WID_BUTTON * w)315 static void button_paint(WID_BUTTON *w)
316 {
317 int cur, x, cnt_hl = 0;
318 char *pos, *hl_pos, *start, hl[2];
319 BOOL end;
320
321 for (pos = w->button; *pos; pos++)
322 if (*pos == '&')
323 cnt_hl++;
324 x = (w->w.d->win->width - 1 - w->w.x -
325 ((int)strlen(w->button) + 5 * w->cnt - 1 - cnt_hl)) / 2;
326 cur = 0;
327 hl_pos = NULL;
328 hl[1] = '\0';
329 start = w->button;
330 end = 0;
331 for (pos = w->button; !end; pos++) {
332 end = !(*pos);
333 if ((*pos == '|') || (*pos == '\0')) {
334 *pos = '\0';
335 if ((w->active != cur) || (!w->w.has_focus))
336 win_attrset(ATTR_DLG_BUT_INACTIVE);
337 else
338 win_attrset(ATTR_DLG_BUT_ACTIVE);
339 win_print(WWIN(w),w->w.x + x, w->w.y, "[ ");
340 if ((w->active != cur) || (!w->w.has_focus))
341 win_attrset(ATTR_DLG_BUT_ITEXT);
342 else
343 win_attrset(ATTR_DLG_BUT_ATEXT);
344 win_print(WWIN(w),w->w.x + x + 2, w->w.y, start);
345 x += strlen(start) + 2;
346 if (hl_pos) {
347 if ((w->active != cur) || (!w->w.has_focus))
348 win_attrset(ATTR_DLG_BUT_IHOTKEY);
349 else
350 win_attrset(ATTR_DLG_BUT_AHOTKEY);
351 win_print(WWIN(w),w->w.x + x, w->w.y, hl);
352 if ((w->active != cur) || (!w->w.has_focus))
353 win_attrset(ATTR_DLG_BUT_ITEXT);
354 else
355 win_attrset(ATTR_DLG_BUT_ATEXT);
356 win_print(WWIN(w),w->w.x + x + 1, w->w.y, hl_pos);
357 *(hl_pos - 2) = '&';
358 x += strlen(hl_pos) + 1;
359 hl_pos = NULL;
360 }
361 if ((w->active != cur) || (!w->w.has_focus))
362 win_attrset(ATTR_DLG_BUT_INACTIVE);
363 else
364 win_attrset(ATTR_DLG_BUT_ACTIVE);
365 win_print(WWIN(w),w->w.x + x, w->w.y, " ]");
366 x += 4;
367 *pos = '|';
368 start = pos + 1;
369 cur++;
370 }
371 if (*pos == '&') {
372 *pos = '\0';
373 pos++;
374 hl_pos = pos + 1;
375 hl[0] = *pos;
376 }
377 }
378 *(pos-1) = '\0';
379 }
380
button_handle_event(WID_BUTTON * w,WID_EVENT event,int ch)381 static BOOL button_handle_event(WID_BUTTON *w, WID_EVENT event, int ch)
382 {
383 int cur;
384 char *pos;
385
386 if (event == WID_GET_FOCUS) {
387 if (ch < 0)
388 w->active = w->cnt - 1;
389 else
390 w->active = 0;
391 return EVENT_HANDLED;
392 }
393 if ((event == WID_KEY) && (w->w.handle_key)) {
394 cur = w->w.handle_key((WIDGET *) w, ch);
395 if (cur)
396 return cur;
397 }
398 if ((ch < 256) && (isalpha(ch)))
399 ch = toupper(ch);
400 switch (ch) {
401 case KEY_UP:
402 case KEY_LEFT:
403 if (event == WID_KEY) {
404 w->active--;
405 if (w->active < 0)
406 return handle_focus ((WIDGET*)w, FOCUS_PREV, 0);
407 button_paint(w);
408 }
409 break;
410 case KEY_DOWN:
411 case KEY_RIGHT:
412 case KEY_TAB:
413 if (event == WID_KEY) {
414 w->active++;
415 if (w->active >= w->cnt)
416 return handle_focus ((WIDGET*)w, FOCUS_NEXT, 0);
417 button_paint(w);
418 }
419 break;
420 case KEY_ENTER:
421 case '\r':
422 if (event == WID_KEY)
423 return handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, EVENT_HANDLED);
424 break;
425 default:
426 cur = 0;
427 for (pos = w->button; *pos; pos++) {
428 if (*pos == '|')
429 cur++;
430 if (*pos == '&' && (toupper((int)*(pos+1)) == ch)) {
431 w->active = cur;
432 button_paint(w);
433 return handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, EVENT_HANDLED);
434 }
435 }
436 return 0;
437 }
438 return EVENT_HANDLED;
439 }
440
button_get_size(WID_BUTTON * w,int * width,int * height)441 static void button_get_size(WID_BUTTON *w, int *width, int *height)
442 {
443 char *pos;
444 int hl_cnt = 0;
445
446 w->cnt = 1;
447 for (pos = w->button; *pos; pos++) {
448 if (*pos == '&')
449 hl_cnt++;
450 if (*pos == '|')
451 w->cnt++;
452 }
453 *width = strlen(w->button) + 5 * w->cnt - 1 - hl_cnt;
454 *height = 1;
455 }
456
list_free(WID_LIST * w)457 static void list_free(WID_LIST *w)
458 {
459 int i;
460 for (i=0; i<w->cnt; i++)
461 free (w->entries[i]);
462 free (w->entries);
463 if (w->title) free (w->title);
464 free (w);
465 }
466
list_paint(WID_LIST * w)467 static void list_paint(WID_LIST *w)
468 {
469 int i,x,visible;
470 char ch;
471
472 x = w->w.x+w->w.width-1;
473 visible = w->w.height-2;
474
475 win_attrset(base_attr(w->w.d,ATTR_DLG_FRAME));
476 win_box (WWIN(w),w->w.x, w->w.y, x, w->w.y+w->w.height-1);
477 if (w->title) {
478 if (strlen(w->title) > w->w.width-2) {
479 ch = w->title[w->w.width-2];
480 w->title[w->w.width-2] = '\0';
481 win_print (WWIN(w),w->w.x+1, w->w.y, w->title);
482 w->title[w->w.width-2] = ch;
483 } else
484 win_print (WWIN(w),w->w.x+1, w->w.y, w->title);
485 }
486
487 if (w->first > 0)
488 win_print (WWIN(w),x, w->w.y+1, "^");
489 else
490 win_print (WWIN(w),x, w->w.y+1, "-");
491 if (w->first+visible < w->cnt)
492 win_print (WWIN(w),x, w->w.y+w->w.height-2, "v");
493 else
494 win_print (WWIN(w),x, w->w.y+w->w.height-2, "-");
495 if (visible>2) {
496 i = 0;
497 if (w->cnt > 1)
498 i = w->cur*(visible-3)/(w->cnt-1);
499 win_print (WWIN(w),x, w->w.y+i+2, "*");
500 }
501
502 for (i=w->first; i<visible+w->first; i++) {
503 storage[0] = '\0';
504 if (i == w->cur) {
505 if (w->w.has_focus)
506 win_attrset(ATTR_DLG_LIST_FOCUS);
507 else
508 win_attrset(ATTR_DLG_LIST_NOFOCUS);
509 } else
510 win_attrset(base_attr(w->w.d,ATTR_DLG_FRAME));
511 if (i < w->cnt) {
512 strncpy (storage,w->entries[i],w->w.width-2);
513 storage[w->w.width-2] = '\0';
514 }
515 for (x=strlen(storage); x<w->w.width-2; x++)
516 storage[x] = ' ';
517 storage[w->w.width-2] = '\0';
518 win_print (WWIN(w),w->w.x+1, w->w.y+i-w->first+1, storage);
519 }
520 }
521
list_handle_event(WID_LIST * w,WID_EVENT event,int ch)522 static int list_handle_event(WID_LIST *w, WID_EVENT event, int ch)
523 {
524 int i, old_cur;
525
526 if (event == WID_HOTKEY)
527 return 0;
528 if (event == WID_GET_FOCUS)
529 return EVENT_HANDLED;
530 if ((event == WID_KEY) && w->w.handle_key) {
531 i = w->w.handle_key((WIDGET *) w, ch);
532 if (i)
533 return i;
534 }
535 old_cur = w->cur;
536 switch (ch) {
537 case KEY_UP:
538 if (w->cur>0) w->cur--;
539 break;
540 case KEY_DOWN:
541 if (w->cur<w->cnt-1) w->cur++;
542 break;
543 case KEY_PPAGE:
544 w->cur -= w->w.height-3;
545 if (w->cur<0) w->cur = 0;
546 break;
547 case KEY_NPAGE:
548 w->cur += w->w.height-3;
549 if (w->cur>=w->cnt)
550 w->cur = w->cnt>0 ? w->cnt-1 : 0;
551 break;
552 case KEY_HOME:
553 w->cur = 0;
554 break;
555 #ifdef KEY_END
556 case KEY_END:
557 w->cur = w->cnt-1;
558 break;
559 #endif
560 case KEY_LEFT:
561 return handle_focus((WIDGET*)w, FOCUS_PREV, 0);
562 case KEY_RIGHT:
563 case KEY_TAB:
564 return handle_focus((WIDGET*)w, FOCUS_NEXT, 0);
565 case KEY_ENTER:
566 case '\r':
567 return handle_focus((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
568 default:
569 return 0;
570 }
571 if (w->cur < w->first)
572 w->first = w->cur;
573 if (w->cur >= w->first + w->w.height-2)
574 w->first = w->cur - w->w.height + 3;
575 list_paint(w);
576 if (w->sel_mode == WID_SEL_BROWSE && old_cur != w->cur)
577 return handle_focus((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
578
579 return EVENT_HANDLED;
580 }
581
list_get_size(WID_LIST * w,int * width,int * height)582 static void list_get_size(WID_LIST *w, int *width, int *height)
583 {
584 if (*width > w->w.def_width)
585 *width = w->w.def_width;
586 if (*width < LIST_WIDTH_MIN)
587 *width = LIST_WIDTH_MIN;
588
589 if (*height > w->w.def_height)
590 *height = w->w.def_height;
591 if (*height < LIST_HEIGHT_MIN)
592 *height = LIST_HEIGHT_MIN;
593 }
594
check_toggle_paint(WID_CHECK * w,BOOL toggle)595 static void check_toggle_paint(WID_CHECK *w, BOOL toggle)
596 {
597 char *start, *pos, *hl_pos, hl[2], end;
598 char marker[] = " x", help[STORAGELEN];
599 int cur = 0, x, xx;
600
601 hl_pos = NULL;
602 hl[1] = '\0';
603 if (toggle)
604 strcpy (help,"[ ] ");
605 else {
606 strcpy (help,"( ) ");
607 marker[1] = '*';
608 }
609 help[w->w.width] = '\0';
610 start = w->button;
611
612 pos = w->button-1;
613 do {
614 pos++;
615 if ((*pos == '|') || (*pos == '\0')) {
616 end = *pos;
617 *pos = '\0';
618 if ((w->active != cur) || (!w->w.has_focus))
619 win_attrset(ATTR_DLG_BUT_ITEXT);
620 else
621 win_attrset(ATTR_DLG_BUT_ATEXT);
622 help[1] = marker[BTST(w->selected,1<<cur)];
623 strcpy (&help[4],start);
624 x = strlen(start) + 4;
625 if (hl_pos) {
626 win_print(WWIN(w),w->w.x, w->w.y+cur, help);
627 if ((w->active != cur) || (!w->w.has_focus))
628 win_attrset(ATTR_DLG_BUT_IHOTKEY);
629 else
630 win_attrset(ATTR_DLG_BUT_AHOTKEY);
631 win_print(WWIN(w),w->w.x + x, w->w.y+cur, hl);
632 x++;
633 if ((w->active != cur) || (!w->w.has_focus))
634 win_attrset(ATTR_DLG_BUT_ITEXT);
635 else
636 win_attrset(ATTR_DLG_BUT_ATEXT);
637 strcpy (&help[x],hl_pos);
638 xx = x+strlen(hl_pos);
639 if (xx != w->w.width)
640 memset (&help[xx],' ',w->w.width-xx);
641 win_print(WWIN(w),w->w.x + x, w->w.y+cur, &help[x]);
642 *(hl_pos - 2) = '&';
643 hl_pos = NULL;
644 } else {
645 if (x != w->w.width)
646 memset (&help[x],' ',w->w.width-x);
647 win_print(WWIN(w),w->w.x, w->w.y+cur, help);
648 }
649 *pos = end;
650 start = pos + 1;
651 cur++;
652 } else if (*pos == '&') {
653 *pos = '\0';
654 pos++;
655 hl_pos = pos + 1;
656 hl[0] = *pos;
657 }
658 } while (*pos);
659 }
660
check_toggle_handle_event(WID_CHECK * w,WID_EVENT event,int ch,BOOL toggle)661 static BOOL check_toggle_handle_event(WID_CHECK *w, WID_EVENT event,
662 int ch, BOOL toggle)
663 {
664 static WID_EVENT last = WID_KEY;
665 int cur;
666 char *pos;
667
668 if (event == WID_GET_FOCUS) {
669 if (last != WID_HOTKEY) { /* active entry was already set */
670 if (ch < 0)
671 w->active = w->cnt - 1;
672 else
673 w->active = 0;
674 }
675 return EVENT_HANDLED;
676 }
677 last = event;
678 if ((event == WID_KEY) && (w->w.handle_key)) {
679 cur = w->w.handle_key((WIDGET *) w, ch);
680 if (cur)
681 return cur;
682 }
683 if ((ch < 256) && (isalpha(ch)))
684 ch = toupper(ch);
685 switch (ch) {
686 case KEY_UP:
687 case KEY_LEFT:
688 if (event == WID_KEY) {
689 w->active--;
690 if (w->active < 0)
691 return handle_focus ((WIDGET*)w, FOCUS_PREV, 0);
692 check_toggle_paint(w,toggle);
693 }
694 break;
695 case KEY_DOWN:
696 case KEY_RIGHT:
697 case KEY_TAB:
698 if (event == WID_KEY) {
699 w->active++;
700 if (w->active >= w->cnt)
701 return handle_focus ((WIDGET*)w, FOCUS_NEXT, 0);
702 check_toggle_paint(w,toggle);
703 }
704 break;
705 case KEY_ENTER:
706 case '\r':
707 if (event == WID_KEY) {
708 cur = handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, 0);
709 if (cur && cur!=FOCUS_ACTIVATE && cur!=FOCUS_DONT)
710 return cur;
711 if (toggle)
712 w->selected ^= 1<<w->active;
713 else
714 w->selected = 1<<w->active;
715 check_toggle_paint(w,toggle);
716 }
717 break;
718 default:
719 cur = 0;
720 for (pos = w->button; *pos; pos++) {
721 if (*pos == '|')
722 cur++;
723 if (*pos == '&' && (toupper((int)*(pos+1)) == ch)) {
724 w->active = cur;
725 check_toggle_paint(w,toggle);
726 cur = handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
727 if (cur!=FOCUS_ACTIVATE && cur!=FOCUS_DONT)
728 return cur;
729 if (toggle)
730 w->selected ^= 1<<w->active;
731 else
732 w->selected = 1<<w->active;
733 check_toggle_paint(w,toggle);
734 return cur;
735 }
736 }
737 return 0;
738 }
739 return EVENT_HANDLED;
740 }
741
check_free(WID_CHECK * w)742 static void check_free(WID_CHECK *w)
743 {
744 free(w->button);
745 free(w);
746 }
747
check_paint(WID_CHECK * w)748 static void check_paint(WID_CHECK *w)
749 {
750 check_toggle_paint(w, 0);
751 }
752
check_handle_event(WID_CHECK * w,WID_EVENT event,int ch)753 static BOOL check_handle_event(WID_CHECK *w, WID_EVENT event, int ch)
754 {
755 return check_toggle_handle_event(w, event, ch, 0);
756 }
757
check_get_size(WID_CHECK * w,int * width,int * height)758 static void check_get_size(WID_CHECK *w, int *width, int *height)
759 {
760 char *pos;
761 int x = 0, hl_cnt = 0;
762
763 *width = 0;
764 *height = 0;
765 w->cnt = 0;
766 for (pos = w->button; *pos; pos++) {
767 if (*pos == '&')
768 hl_cnt++;
769 if (*pos == '|') {
770 w->cnt++;
771 (*height)++;
772 x += 4 - hl_cnt;
773 if (x > *width)
774 *width = x;
775 hl_cnt = 0;
776 x = -1;
777 }
778 x++;
779 }
780 w->cnt++;
781 (*height)++;
782 x += 4 - hl_cnt;
783 if (x > *width)
784 *width = x;
785 }
786
toggle_free(WID_TOGGLE * w)787 static void toggle_free(WID_TOGGLE *w)
788 {
789 free(w->button);
790 free(w);
791 }
792
toggle_paint(WID_TOGGLE * w)793 static void toggle_paint(WID_TOGGLE *w)
794 {
795 check_toggle_paint((WID_CHECK *) w, 1);
796 }
797
toggle_handle_event(WID_TOGGLE * w,WID_EVENT event,int ch)798 static BOOL toggle_handle_event(WID_TOGGLE *w, WID_EVENT event, int ch)
799 {
800 return check_toggle_handle_event((WID_CHECK *) w, event, ch, 1);
801 }
802
toggle_get_size(WID_TOGGLE * w,int * width,int * height)803 static void toggle_get_size(WID_TOGGLE *w, int *width, int *height)
804 {
805 check_get_size((WID_CHECK *) w, width, height);
806 }
807
colorsel_free(WID_COLORSEL * w)808 static void colorsel_free(WID_COLORSEL *w)
809 {
810 free(w);
811 }
812
colorsel_paint(WID_COLORSEL * w)813 static void colorsel_paint(WID_COLORSEL *w)
814 {
815 int y = w->w.y, x = w->w.x;
816 int act_x = (w->active & COLOR_BMASK) >> COLOR_BSHIFT;
817 int act_y = (w->active & COLOR_FMASK) >> COLOR_FSHIFT;
818 ATTRS border[COLOR_CNT+2][COLOR_CNT*3+2], b[12], attr;
819
820 win_attrset(base_attr(w->w.d, ATTR_DLG_FRAME));
821 win_box (WWIN(w), w->w.x, w->w.y, w->w.x+COLOR_CNT*3+1, w->w.y+COLOR_CNT+1);
822
823 attr = (win_get_theme_color(ATTR_DLG_FRAME) & COLOR_BMASK) >> COLOR_BSHIFT;
824 for (x=0; x<COLOR_CNT*3+2; x++)
825 border[0][x] = border[COLOR_CNT+1][x] = attr;
826 for (y=1; y<COLOR_CNT+1; y++)
827 border[y][0] = border[y][COLOR_CNT*3+1] = attr;
828
829 for (y=0; y<COLOR_CNT; y++) {
830 for (x=0; x<COLOR_CNT; x++) {
831 border[y+1][x*3+1] = border[y+1][x*3+2] = border[y+1][x*3+3] = x;
832 win_set_color ((x << COLOR_BSHIFT) + (y << COLOR_FSHIFT));
833 win_print (WWIN(w),w->w.x+x*3+1, w->w.y+y+1, " X ");
834 }
835 }
836 {
837 ATTRS hotkey = w->w.has_focus ? ATTR_DLG_BUT_AHOTKEY:ATTR_DLG_BUT_IHOTKEY;
838 ATTRS text = w->w.has_focus ? ATTR_DLG_BUT_ATEXT:ATTR_DLG_BUT_ITEXT;
839 char key[2] = " ";
840 const char *pat[2] = {".......< h h >",
841 "..^h hv"};
842 int p, h = 0;
843
844 for (p=0; p<2; p++) {
845 for (x=0; x<strlen(pat[p]); x++) {
846 if (pat[p][x] != '.') {
847 border[x*p][x*(1-p)] =
848 (win_get_theme_color(text) & COLOR_BMASK) >> COLOR_BSHIFT;
849 win_attrset (text);
850 key[0] = pat[p][x];
851 if (pat[p][x] == 'h') {
852 if (w->hkeys[h]) {
853 border[x*p][x*(1-p)] =
854 (win_get_theme_color(hotkey) & COLOR_BMASK) >> COLOR_BSHIFT;
855 win_attrset (hotkey);
856 key[0] = w->hkeys[h];
857 }
858 h++;
859 }
860 win_print (WWIN(w), w->w.x+x*(1-p), w->w.y+x*p, key);
861 }
862 }
863 }
864 }
865
866 for (x=0; x<5; x++) {
867 b[x] = border[act_y][act_x*3+x];
868 b[10-x] = border[act_y+2][act_x*3+x];
869 }
870 b[5] = border[act_y+1][act_x*3+4];
871 b[11] = border[act_y+1][act_x*3];
872
873 win_set_forground (COLOR_BLACK_F);
874 win_box_color (WWIN(w),w->w.x+act_x*3, w->w.y+act_y,
875 w->w.x+act_x*3+4, w->w.y+act_y+2, b);
876 }
877
colorsel_handle_event(WID_COLORSEL * w,WID_EVENT event,int ch)878 static int colorsel_handle_event(WID_COLORSEL *w, WID_EVENT event, int ch)
879 {
880 int act_x = (w->active & COLOR_BMASK) >> COLOR_BSHIFT;
881 int act_y = (w->active & COLOR_FMASK) >> COLOR_FSHIFT;
882 int i, old_act_x = act_x, old_act_y = act_y;
883
884 if (event == WID_GET_FOCUS)
885 return EVENT_HANDLED;
886 if (event == WID_KEY && w->w.handle_key) {
887 i = w->w.handle_key((WIDGET *) w, ch);
888 if (i)
889 return i;
890 }
891 if (ch < 256 && isalpha(ch))
892 ch = toupper(ch);
893 switch (ch) {
894 case KEY_UP:
895 if (event == WID_KEY && act_y>0)
896 act_y--;
897 break;
898 case KEY_LEFT:
899 if (event == WID_KEY && act_x>0)
900 act_x--;
901 break;
902 case KEY_DOWN:
903 if (event == WID_KEY && act_y<COLOR_CNT-1)
904 act_y++;
905 break;
906 case KEY_RIGHT:
907 if (event == WID_KEY && act_x<COLOR_CNT-1)
908 act_x++;
909 break;
910 case KEY_ENTER:
911 case '\r':
912 if (event == WID_KEY)
913 return handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
914 break;
915 case KEY_TAB:
916 if (event == WID_KEY)
917 return handle_focus ((WIDGET*)w, FOCUS_NEXT, 0);
918 break;
919 default:
920 if (strchr (w->hkeys, ch)) {
921 if (ch == w->hkeys[0])
922 if (act_x>0) act_x--;
923 if (ch == w->hkeys[1])
924 if (act_x<COLOR_CNT-1) act_x++;
925 if (ch == w->hkeys[2])
926 if (act_y>0) act_y--;
927 if (ch == w->hkeys[3])
928 if (act_y<COLOR_CNT-1) act_y++;
929 w->active = (act_x << COLOR_BSHIFT) + (act_y << COLOR_FSHIFT);
930 colorsel_paint(w);
931
932 i = handle_focus ((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
933 if (i != FOCUS_ACTIVATE && i != FOCUS_DONT)
934 return i;
935
936 colorsel_paint(w);
937 return i;
938 }
939 return 0;
940 }
941 w->active = (act_x << COLOR_BSHIFT) + (act_y << COLOR_FSHIFT);
942 colorsel_paint (w);
943 if (w->sel_mode == WID_SEL_BROWSE && (old_act_x != act_x || old_act_y != act_y))
944 return handle_focus((WIDGET*)w, FOCUS_ACTIVATE, FOCUS_ACTIVATE);
945
946 return EVENT_HANDLED;
947 }
948
colorsel_get_size(WID_COLORSEL * w,int * width,int * height)949 static void colorsel_get_size(WID_COLORSEL *w, int *width, int *height)
950 {
951 *width = 26;
952 *height = 10;
953 }
954
dialog_add(DIALOG * d,WIDGET * w)955 static void dialog_add(DIALOG *d, WIDGET *w)
956 {
957 d->widget = (WIDGET **) realloc(d->widget, (d->cnt + 1) * sizeof(WIDGET *));
958 d->widget[d->cnt] = w;
959 d->cnt++;
960 }
961
widget_init(WIDGET * w,DIALOG * d,BOOL focus,int spacing)962 static void widget_init(WIDGET *w, DIALOG *d, BOOL focus, int spacing)
963 {
964 w->x = w->y = w->width = w->height = 1;
965 w->def_width = w->def_height = -1;
966 w->spacing = spacing;
967 w->can_focus = focus;
968 w->has_focus = 0;
969 w->d = d;
970 w->handle_key = w->handle_focus = NULL;
971 w->w_free = w->w_paint = NULL;
972 w->w_handle_event = NULL;
973 w->w_get_size = NULL;
974 w->data = NULL;
975 }
976
wid_label_add(DIALOG * d,int spacing,const char * msg)977 WIDGET *wid_label_add(DIALOG *d, int spacing, const char *msg)
978 {
979 WID_LABEL *w = (WID_LABEL *) malloc(sizeof(WID_LABEL));
980
981 widget_init((WIDGET *) w, d, 0, spacing);
982 w->w.type = TYPE_LABEL;
983 w->w.w_free = (freeFunc) label_free;
984 w->w.w_paint = (paintFunc) label_paint;
985 w->w.w_handle_event = (handleEventFunc) label_handle_event;
986 w->w.w_get_size = (getSizeFunc) label_get_size;
987
988 w->msg = strdup(msg);
989 dialog_add(d, (WIDGET *) w);
990 return (WIDGET *) w;
991 }
992
wid_label_set_label(WID_LABEL * w,const char * label)993 void wid_label_set_label (WID_LABEL *w, const char *label)
994 {
995 if (w->msg) free (w->msg);
996 w->msg = strdup (label);
997 }
998
wid_str_add(DIALOG * d,int spacing,const char * input,int length)999 WIDGET *wid_str_add(DIALOG *d, int spacing, const char *input, int length)
1000 {
1001 int i;
1002 WID_STR *w = (WID_STR *) malloc(sizeof(WID_STR));
1003
1004 widget_init((WIDGET *) w, d, 1, spacing);
1005 w->w.type = TYPE_STR;
1006 w->w.w_free = (freeFunc) str_free;
1007 w->w.w_paint = (paintFunc) str_paint;
1008 w->w.w_handle_event = (handleEventFunc) str_handle_event;
1009 w->w.w_get_size = (getSizeFunc) str_get_size;
1010
1011 w->length = length;
1012 w->w.def_width = STR_WIDTH_MAX;
1013
1014 w->input = (char *) malloc(length + 1);
1015
1016 i = MIN(strlen(input), length);
1017 strncpy(w->input, input, i);
1018 w->input[i] = '\0';
1019 w->cur_pos = strlen(w->input);
1020
1021 dialog_add(d, (WIDGET *) w);
1022 return (WIDGET *) w;
1023 }
1024
wid_str_set_input(WID_STR * w,const char * input,int length)1025 void wid_str_set_input (WID_STR *w, const char *input, int length)
1026 {
1027 if (length>=0) {
1028 if (w->input) free (w->input);
1029 if (length) w->input = (char *) malloc(length + 1);
1030 w->length = length;
1031 }
1032 if (w->length == 0) {
1033 w->input = NULL;
1034 w->cur_pos = w->start = 0;
1035 } else {
1036 int i = MIN (strlen(input), w->length);
1037 strncpy (w->input, input, i);
1038 w->input[i] = '\0';
1039 if (w->cur_pos > strlen(w->input))
1040 w->cur_pos = strlen(w->input);
1041
1042 if (w->cur_pos < w->start)
1043 w->start = w->cur_pos;
1044 if (w->cur_pos >= w->start + w->w.width)
1045 w->start = w->cur_pos - w->w.width + 1;
1046 }
1047 }
1048
wid_int_add(DIALOG * d,int spacing,int value,int length)1049 WIDGET *wid_int_add(DIALOG *d, int spacing, int value, int length)
1050 {
1051 WID_INT *w = (WID_INT *) malloc(sizeof(WID_INT));
1052
1053 widget_init((WIDGET *) w, d, 1, spacing);
1054 w->w.type = TYPE_INT;
1055 w->w.w_free = (freeFunc) int_free;
1056 w->w.w_paint = (paintFunc) int_paint;
1057 w->w.w_handle_event = (handleEventFunc) int_handle_event;
1058 w->w.w_get_size = (getSizeFunc) int_get_size;
1059
1060 w->start = 0;
1061 w->length = length;
1062 w->w.def_width = INT_WIDTH_MAX;
1063
1064 w->input = (char *) malloc(w->length + 1);
1065 sprintf(w->input, "%d", value);
1066 w->cur_pos = strlen(w->input);
1067
1068 dialog_add(d, (WIDGET *) w);
1069 return (WIDGET *) w;
1070 }
1071
wid_int_set_input(WID_INT * w,int value,int length)1072 void wid_int_set_input (WID_INT *w, int value, int length)
1073 {
1074 char val[20];
1075 sprintf(val, "%d", value);
1076 wid_str_set_input ((WID_STR*)w, val,length);
1077 }
1078
wid_button_add(DIALOG * d,int spacing,const char * button,int active)1079 WIDGET *wid_button_add(DIALOG *d, int spacing, const char *button, int active)
1080 {
1081 WID_BUTTON *w = (WID_BUTTON *) malloc(sizeof(WID_BUTTON));
1082
1083 widget_init((WIDGET *) w, d, 1, spacing);
1084 w->w.type = TYPE_BUTTON;
1085 w->w.w_free = (freeFunc) button_free;
1086 w->w.w_paint = (paintFunc) button_paint;
1087 w->w.w_handle_event = (handleEventFunc) button_handle_event;
1088 w->w.w_get_size = (getSizeFunc) button_get_size;
1089
1090 w->button = strdup(button);
1091 w->active = active;
1092 dialog_add(d, (WIDGET *) w);
1093 return (WIDGET *) w;
1094 }
1095
wid_list_add(DIALOG * d,int spacing,const char ** entries,int cnt)1096 WIDGET *wid_list_add(DIALOG *d, int spacing, const char **entries, int cnt)
1097 {
1098 WID_LIST *w = (WID_LIST *) malloc(sizeof(WID_LIST));
1099
1100 widget_init((WIDGET *) w, d, 1, spacing);
1101 w->w.type = TYPE_LIST;
1102
1103 w->title = NULL;
1104 w->entries = NULL;
1105 w->sel_mode = WID_SEL_SINGLE;
1106 w->cnt = w->cur = w->first = 0;
1107 w->w.def_width = LIST_WIDTH_DEFAULT;
1108 w->w.def_height = LIST_HEIGHT_DEFAULT;
1109 wid_list_set_entries (w,entries,-1,cnt);
1110
1111 w->w.w_free = (freeFunc) list_free;
1112 w->w.w_paint = (paintFunc) list_paint;
1113 w->w.w_handle_event = (handleEventFunc) list_handle_event;
1114 w->w.w_get_size = (getSizeFunc) list_get_size;
1115
1116 dialog_add(d, (WIDGET *) w);
1117 return (WIDGET *) w;
1118 }
1119
wid_list_set_title(WID_LIST * w,const char * title)1120 void wid_list_set_title (WID_LIST *w, const char *title)
1121 {
1122 if (w->title) free (w->title);
1123 w->title = strdup (title);
1124 }
1125
wid_list_set_entries(WID_LIST * w,const char ** entries,int cur,int cnt)1126 void wid_list_set_entries (WID_LIST *w, const char **entries, int cur, int cnt)
1127 {
1128 int i;
1129
1130 if (w->entries) {
1131 for (i=0; i<w->cnt; i++)
1132 free (w->entries[i]);
1133 free (w->entries);
1134 w->entries = NULL;
1135 }
1136 w->cnt = cnt;
1137 if (cur>=0) {
1138 w->cur = cur;
1139 w->first = cur>0 ? cur-1:0;
1140 }
1141 if (w->cur >= cnt) w->cur = cnt>0 ? cnt-1:0;
1142 if (w->first > w->cur) w->first = w->cur>0 ? w->cur-1:0;
1143
1144 if (cnt>0) {
1145 w->entries = (char **) malloc(sizeof(char*) * cnt);
1146 for (i=0; i<cnt; i++)
1147 w->entries[i] = strdup(entries[i]);
1148 }
1149 }
1150
wid_list_set_active(WID_LIST * w,int cur)1151 void wid_list_set_active (WID_LIST *w, int cur)
1152 {
1153 if (cur>=0 && cur < w->cnt) {
1154 w->cur = cur;
1155
1156 if (w->cur < w->first)
1157 w->first = w->cur;
1158 if (w->cur >= w->first + w->w.height-2)
1159 w->first = w->cur - w->w.height + 3;
1160 }
1161 }
1162
wid_list_set_selection_mode(WID_LIST * w,WID_SEL_MODE mode)1163 void wid_list_set_selection_mode (WID_LIST *w, WID_SEL_MODE mode)
1164 {
1165 w->sel_mode = mode;
1166 }
1167
wid_check_add(DIALOG * d,int spacing,const char * button,int active,int selected)1168 WIDGET *wid_check_add(DIALOG *d, int spacing, const char *button, int active, int selected)
1169 {
1170 WID_CHECK *w = (WID_CHECK *) malloc(sizeof(WID_CHECK));
1171
1172 widget_init((WIDGET *) w, d, 1, spacing);
1173 w->w.type = TYPE_CHECK;
1174 w->w.w_free = (freeFunc) check_free;
1175 w->w.w_paint = (paintFunc) check_paint;
1176 w->w.w_handle_event = (handleEventFunc) check_handle_event;
1177 w->w.w_get_size = (getSizeFunc) check_get_size;
1178
1179 w->button = strdup(button);
1180 w->active = active;
1181 w->selected = selected;
1182 dialog_add(d, (WIDGET *) w);
1183 return (WIDGET *) w;
1184 }
1185
wid_check_set_selected(WID_CHECK * w,int selected)1186 void wid_check_set_selected(WID_CHECK *w, int selected)
1187 {
1188 w->selected = selected;
1189 }
1190
wid_toggle_add(DIALOG * d,int spacing,const char * button,int active,int selected)1191 WIDGET *wid_toggle_add(DIALOG *d, int spacing, const char *button, int active, int selected)
1192 {
1193 WID_TOGGLE *w = (WID_TOGGLE *) malloc(sizeof(WID_TOGGLE));
1194
1195 widget_init((WIDGET *) w, d, 1, spacing);
1196 w->w.type = TYPE_TOGGLE;
1197 w->w.w_free = (freeFunc) toggle_free;
1198 w->w.w_paint = (paintFunc) toggle_paint;
1199 w->w.w_handle_event = (handleEventFunc) toggle_handle_event;
1200 w->w.w_get_size = (getSizeFunc) toggle_get_size;
1201
1202 w->button = strdup(button);
1203 w->active = active;
1204 w->selected = selected;
1205 dialog_add(d, (WIDGET *) w);
1206 return (WIDGET *) w;
1207 }
1208
wid_toggle_set_selected(WID_TOGGLE * w,int selected)1209 void wid_toggle_set_selected(WID_TOGGLE *w, int selected)
1210 {
1211 w->selected = selected;
1212 }
1213
wid_colorsel_add(DIALOG * d,int spacing,const char * hotkeys,int active)1214 WIDGET *wid_colorsel_add(DIALOG *d, int spacing, const char *hotkeys, int active)
1215 {
1216 WID_COLORSEL *w = (WID_COLORSEL *) malloc(sizeof(WID_COLORSEL));
1217 int i;
1218
1219 widget_init((WIDGET *) w, d, 1, spacing);
1220 w->w.type = TYPE_COLORSEL;
1221 w->w.w_free = (freeFunc) colorsel_free;
1222 w->w.w_paint = (paintFunc) colorsel_paint;
1223 w->w.w_handle_event = (handleEventFunc) colorsel_handle_event;
1224 w->w.w_get_size = (getSizeFunc) colorsel_get_size;
1225
1226 w->active = active;
1227 if (hotkeys && *hotkeys) {
1228 strcpy (w->hkeys, hotkeys);
1229 w->hkeys[4] = '\0';
1230 for (i=0; i<strlen(w->hkeys); i++)
1231 w->hkeys[i] = toupper(w->hkeys[i]);
1232 } else
1233 memset (&w->hkeys, 0, 5);
1234 w->sel_mode = WID_SEL_SINGLE;
1235 dialog_add(d, (WIDGET *) w);
1236 return (WIDGET *) w;
1237 }
1238
wid_colorsel_set_active(WID_COLORSEL * w,int active)1239 void wid_colorsel_set_active(WID_COLORSEL *w, int active)
1240 {
1241 w->active = active;
1242 }
1243
wid_set_size(WIDGET * w,int width,int height)1244 void wid_set_size (WIDGET *w, int width, int height)
1245 {
1246 if (width>=0) w->def_width = width;
1247 if (height>=0) w->def_height = height;
1248 }
1249
wid_set_func(WIDGET * w,handleKeyFunc key,handleFocusFunc focus,void * data)1250 void wid_set_func(WIDGET *w, handleKeyFunc key, handleFocusFunc focus,
1251 void *data)
1252 {
1253 w->handle_key = key;
1254 w->handle_focus = focus;
1255 w->data = data;
1256 }
1257
wid_repaint(WIDGET * w)1258 void wid_repaint (WIDGET *w)
1259 {
1260 if (w->w_paint) w->w_paint (w);
1261 }
1262
dialog_repaint(MWINDOW * win)1263 BOOL dialog_repaint(MWINDOW *win)
1264 {
1265 DIALOG *d = (DIALOG *) win->data;
1266 int i = 0;
1267
1268 win_attrset(base_attr(d,ATTR_DLG_FRAME));
1269 win_clear(win);
1270 for (i = 0; i < d->cnt; i++)
1271 d->widget[i]->w_paint(d->widget[i]);
1272
1273 return 1;
1274 }
1275
dialog_close(DIALOG * d)1276 void dialog_close(DIALOG *d)
1277 {
1278 int i;
1279
1280 for (i = 0; i < d->cnt; i++)
1281 d->widget[i]->w_free(d->widget[i]);
1282 if (d->cnt)
1283 free(d->widget);
1284 win_close(d->win);
1285 free(d);
1286 }
1287
dialog_handle_key(MWINDOW * win,int ch)1288 static BOOL dialog_handle_key(MWINDOW *win, int ch)
1289 {
1290 DIALOG *d = (DIALOG *) win->data;
1291 int ret, i;
1292
1293 /* Handle keys common for all widgets here */
1294 #if defined(__OS2__)||defined(__EMX__)||defined(__DJGPP__)||defined(_WIN32)
1295 if (ch == KEY_ESC) {
1296 dialog_close(d);
1297 return 1;
1298 }
1299 #endif
1300
1301 ret = d->widget[d->active]->w_handle_event(d->widget[d->active], WID_KEY,ch);
1302 if (!ret) {
1303 /* KEY not handled -> try the hotkeys */
1304 for (i = 0; !ret && i < d->cnt; i++) {
1305 ret = d->widget[i]->w_handle_event(d->widget[i], WID_HOTKEY, ch);
1306 if (ret == FOCUS_ACTIVATE) {
1307 d->widget[d->active]->has_focus = 0;
1308 d->widget[i]->has_focus = 1;
1309 d->active = i;
1310 d->widget[d->active]->w_handle_event(d->widget[d->active],
1311 WID_GET_FOCUS, ret);
1312 dialog_repaint(win);
1313 }
1314 }
1315 } else if (ret < EVENT_HANDLED) {
1316 /* FOCUS_{NEXT|PREV} */
1317 d->widget[d->active]->has_focus = 0;
1318 do {
1319 d->active += ret;
1320 if (d->active < 0)
1321 d->active = d->cnt - 1;
1322 else if (d->active >= d->cnt)
1323 d->active = 0;
1324 } while (!d->widget[d->active]->can_focus);
1325 d->widget[d->active]->has_focus = 1;
1326 d->widget[d->active]->w_handle_event(d->widget[d->active],
1327 WID_GET_FOCUS, ret);
1328 dialog_repaint(win);
1329 }
1330 return !!ret;
1331 }
1332
1333 /* Return size of column of widgets which starts at widget start */
column_dim(DIALOG * d,int start,int * width,int * height)1334 static void column_dim (DIALOG *d, int start, int *width, int *height)
1335 {
1336 int i;
1337
1338 *width = d->widget[start]->width;
1339 i = start+1;
1340 while (i<d->cnt && d->widget[i]->spacing>0) {
1341 if (d->widget[i]->width > *width)
1342 *width = d->widget[i]->width;
1343 i++;
1344 };
1345 *height = d->widget[i-1]->y+d->widget[i-1]->height-d->widget[start]->y;
1346 }
1347
1348 /* Layout the dialog widgets and return the calculated size and position
1349 of the dialog window (which must be still opened).
1350 initial = true: the the focus of the widgets is changed */
dialog_layout(DIALOG * d,int initial,int * w_x,int * w_y,int * w_width,int * w_height)1351 static void dialog_layout(DIALOG *d, int initial,
1352 int *w_x, int *w_y, int *w_width, int *w_height)
1353 {
1354 int m_y, m_width = 0, m_height = 0, i, x, y, width, height;
1355 int spacing, c_spacing = 1, c_height, c_width;
1356 BOOL focus = 1;
1357
1358 i = 0;
1359 width = 1;
1360 height = c_width = c_height = m_height = m_width = 0;
1361 while (i < d->cnt) { /* Init all widgets(position and focus) */
1362 spacing = d->widget[i]->spacing;
1363 if (i==0 || spacing<0)
1364 c_spacing = (spacing == 0 ? 1:abs(spacing));
1365
1366 x = 999; y = 999;
1367 d->widget[i]->w_get_size(d->widget[i], &x, &y);
1368 d->widget[i]->width = x;
1369 d->widget[i]->height = y;
1370
1371 if (spacing>0) {
1372 c_height += spacing-1;
1373 d->widget[i]->x = width;
1374 d->widget[i]->y = m_height+c_height;
1375 if (x>c_width) c_width = x;
1376 } else if (spacing==0) {
1377 if (c_height>height) height = c_height;
1378 c_height = c_spacing-1;
1379 width += c_width + 1;
1380
1381 d->widget[i]->x = width;
1382 d->widget[i]->y = m_height+c_height;
1383
1384 c_width = x;
1385 } else {
1386 width += c_width + 1;
1387 if (width > m_width) m_width = width;
1388 if (c_height>height) height = c_height;
1389 m_height += height;
1390 c_height = -spacing-1;
1391 height = 0;
1392 width = 1;
1393
1394 d->widget[i]->x = width;
1395 d->widget[i]->y = m_height+c_height;
1396
1397 c_width = x;
1398 }
1399 c_height += y;
1400
1401 if (initial) {
1402 if (d->widget[i]->can_focus) {
1403 d->widget[i]->has_focus = focus;
1404 if (focus)
1405 d->active = i;
1406 focus = 0;
1407 } else
1408 d->widget[i]->has_focus = 0;
1409 }
1410 i++;
1411 }
1412 width += c_width+1;
1413 if (width > m_width) m_width = width;
1414 if (c_height>height) height = c_height;
1415 m_height += height;
1416
1417 width = m_width;
1418 height = m_height;
1419 win_get_size_max(&m_y, &m_width, &m_height);
1420 if (width > m_width-2 || height > m_height-2) {
1421 /* preferred size of widgets was to big, try to reduce the size */
1422 int dx = width-m_width+2, dy = height-m_height+2, free_x,
1423 old_width = width, old_height = height,
1424 i_start, m_c_height, m_c_height_old, c_height_old, c_width_old, m_x;
1425
1426 m_width = m_height = 0;
1427 i = 0;
1428 while (i < d->cnt) { /* reinit all widget positions */
1429 spacing = abs(d->widget[i]->spacing);
1430 m_height += (spacing == 0 ? 0:spacing-1);
1431 width = 1;
1432
1433 /* get height of highest column in row */
1434 x = i;
1435 do {
1436 x++;
1437 } while (x<d->cnt && d->widget[x]->spacing>=0);
1438 if (x<d->cnt)
1439 m_c_height_old = d->widget[x]->y+d->widget[x]->spacing - d->widget[i]->y+1;
1440 else
1441 m_c_height_old = old_height - d->widget[i]->y;
1442
1443 /* get max x coordinate of last column in row */
1444 m_x = 0;
1445 do {
1446 x--;
1447 if ((d->widget[x]->x+d->widget[x]->width - 1) > m_x)
1448 m_x = d->widget[x]->x+d->widget[x]->width - 1;
1449 } while (x>0 && d->widget[x]->spacing>0);
1450 /* free space on right side of last column in row */
1451 free_x = old_width-1-m_x;
1452 m_c_height = 0;
1453
1454 /* for all columns in one row */
1455 do {
1456 c_height = c_width = 0;
1457 i_start = i;
1458 column_dim (d, i_start, &c_width_old, &c_height_old);
1459 /* for all widgets in one column */
1460 do {
1461 x = d->widget[i]->width - dx + free_x;
1462 y = d->widget[i]->height - dy + m_c_height_old-c_height_old;
1463 d->widget[i]->w_get_size(d->widget[i], &x, &y);
1464
1465 if (i>0 && d->widget[i]->spacing > 0)
1466 c_height += d->widget[i]->spacing-1;
1467 d->widget[i]->x = width;
1468 d->widget[i]->y = m_height + c_height;
1469 d->widget[i]->width = x;
1470 d->widget[i]->height = y;
1471 if (x>c_width) c_width = x;
1472 c_height += y;
1473
1474 y = c_width_old;
1475 column_dim (d, i_start, &c_width_old, &c_height_old);
1476 free_x += y - c_width_old;
1477
1478 i++;
1479 } while ((i < d->cnt) && (d->widget[i]->spacing > 0));
1480
1481 width += c_width +1;
1482 if (c_height > m_c_height)
1483 m_c_height = c_height;
1484 } while ((i < d->cnt) && (d->widget[i]->spacing >= 0));
1485 if (width > m_width)
1486 m_width = width;
1487 m_height += m_c_height;
1488 }
1489 width = m_width;
1490 height = m_height;
1491 win_get_size_max(&m_y, &m_width, &m_height);
1492 }
1493 m_width -= 2;
1494 m_height -= 2;
1495
1496 *w_x = (m_width - width) / 2 + 1;
1497 if (*w_x < 1)
1498 *w_x = 1;
1499 *w_y = (m_height - height) / 2 + m_y +1;
1500 if (*w_y <= m_y)
1501 *w_y = m_y+1;
1502 *w_width = (width>m_width ? m_width:width);
1503 *w_height = (height>m_height ? m_height:height);
1504 }
1505
dialog_handle_resize(MWINDOW * win,int dx,int dy)1506 static void dialog_handle_resize(MWINDOW *win, int dx, int dy)
1507 {
1508 DIALOG *d = (DIALOG *) win->data;
1509 int x,y,width,height;
1510
1511 dialog_layout (d,0,&x,&y,&width,&height);
1512 win->x = x;
1513 win->y = y;
1514 win->width = width;
1515 win->height = height;
1516 }
1517
dialog_open(DIALOG * d,const char * title)1518 void dialog_open(DIALOG *d, const char *title)
1519 {
1520 int x,y,width,height;
1521
1522 dialog_layout (d,1,&x,&y,&width,&height);
1523
1524 if (!title)
1525 title = "Dialog";
1526 win_open(x, y, width, height, 1, title, base_attr(d,ATTR_DLG_FRAME));
1527 win_set_repaint(dialog_repaint);
1528 win_set_handle_key(dialog_handle_key);
1529 win_set_resize(0, dialog_handle_resize);
1530 win_set_data((void *)d);
1531
1532 d->win = win_get_window();
1533 dialog_repaint(d->win);
1534 }
1535
1536 /* set attribute which is used for DLG_FRAME and DLG_LABEL,
1537 works only before dialog_open() */
dialog_set_attr(DIALOG * d,ATTRS attrs)1538 void dialog_set_attr (DIALOG *d, ATTRS attrs)
1539 {
1540 d->attrs = attrs;
1541 }
1542
dialog_new(void)1543 DIALOG *dialog_new(void)
1544 {
1545 DIALOG *d = (DIALOG *) malloc(sizeof(DIALOG));
1546
1547 d->active = 0;
1548 d->cnt = 0;
1549 d->attrs = ATTR_NONE;
1550 d->win = NULL;
1551 d->widget = NULL;
1552 return d;
1553 }
1554
1555 /* ex:set ts=4: */
1556