- Rearrange reactos.dff according to rosapps rearrange.
[reactos.git] / rosapps / applications / mc / src / dlg.c
1 /* Dlg box features module for the Midnight Commander
2 Copyright (C) 1994, 1995 Radek Doulik, Miguel de Icaza
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <config.h>
20 /* "$Id$" */
21 #include <string.h>
22 #include <stdio.h>
23 #include <malloc.h>
24 #include <ctype.h>
25 #include "tty.h"
26 #include <stdarg.h>
27 #include "mad.h"
28 #include "x.h"
29 #include "util.h"
30 #include "menu.h"
31 #include "global.h"
32 #include "win.h"
33 #include "color.h"
34 #include "mouse.h"
35 #include "help.h"
36 #include "key.h" /* For mi_getch() */
37 #include "dlg.h"
38 #include "dialog.h" /* For push_refresh() and pop_refresh() */
39 #include "layout.h"
40 #include "main.h"
41
42 /* This is the current frame, used to group Tk packings */
43 char *the_frame = "";
44
45 #define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)
46
47 /* Primitive way to check if the the current dialog is our dialog */
48 /* This is needed by async routines like load_prompt */
49 Dlg_head *current_dlg = 0;
50
51 /* A hook list for idle events */
52 Hook *idle_hook = 0;
53
54 #ifndef PORT_HAS_SET_IDLE
55 # define x_set_idle(d,x)
56 #endif
57
58 #ifndef PORT_HAS_DIALOG_STOP
59 # define x_dialog_stop(d)
60 #endif
61
62 static void slow_box (Dlg_head *h, int y, int x, int ys, int xs)
63 {
64 move (h->y+y, h->x+x);
65 hline (' ', xs);
66 vline (' ', ys);
67 move (h->y+y, h->x+x+xs-1);
68 vline (' ', ys);
69 move (h->y+y+ys-1, h->x+x);
70 hline (' ', xs);
71 }
72
73 /* draw box in window */
74 void draw_box (Dlg_head *h, int y, int x, int ys, int xs)
75 {
76 extern int slow_terminal;
77
78 if (slow_terminal){
79 slow_box (h, y, x, ys, xs);
80 return;
81 }
82
83 #ifndef HAVE_SLANG
84 waddc (h, y, x, ACS_ULCORNER);
85 hline (ACS_HLINE, xs - 2);
86 waddc (h, y + ys - 1, x, ACS_LLCORNER);
87 hline (ACS_HLINE, xs - 2);
88
89 waddc (h, y, x + xs - 1, ACS_URCORNER);
90 waddc (h, y + ys - 1, x + xs - 1, ACS_LRCORNER);
91
92 move (h->y+y+1, h->x+x);
93 vline (ACS_VLINE, ys - 2);
94 move (h->y+y+1, h->x+x+xs-1);
95 vline (ACS_VLINE, ys - 2);
96 #else
97 SLsmg_draw_box (h->y+y, h->x+x, ys, xs);
98 #endif
99 }
100
101 /* draw box in window */
102 void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs)
103 {
104 #ifndef HAVE_SLANG
105 draw_box (h, y, x, ys, xs);
106 #else
107 SLsmg_draw_double_box (h->y+y, h->x+x, ys, xs);
108 #endif
109 }
110
111 void widget_erase (Widget *w)
112 {
113 int x, y;
114
115 for (y = 0; y < w->lines; y++){
116 widget_move (w, y, 0);
117 for (x = 0; x < w->cols; x++)
118 addch (' ');
119 }
120 }
121
122 void dlg_erase (Dlg_head *h)
123 {
124 int x, y;
125
126 for (y = 0; y < h->lines; y++){
127 move (y+h->y, h->x); /* FIXME: should test if ERR */
128 for (x = 0; x < h->cols; x++){
129 addch (' ');
130 }
131 }
132 }
133
134 void init_widget (Widget *w, int y, int x, int lines, int cols,
135 int (*callback)(Dlg_head *, void *, int, int),
136 destroy_fn destroy, mouse_h mouse_handler, char *tkname)
137 {
138 w->x = x;
139 w->y = y;
140 w->cols = cols;
141 w->lines = lines;
142 w->color = -1;
143 w->callback = callback;
144 w->destroy = destroy;
145 w->mouse = mouse_handler;
146 w->wdata = 0;
147 w->wcontainer = 0;
148 w->frame = "";
149 w->parent = 0;
150 w->tkname = tkname;
151
152 if (tkname && *tkname == 0){
153 fprintf (stderr, "Got a null string for the tkname\n");
154 abort ();
155 }
156 /* Almost all widgets want to put the cursor in a suitable place */
157 w->options = W_WANT_CURSOR;
158 }
159
160 int default_proc (Dlg_head *h, int Msg, int Par)
161 {
162 switch (Msg){
163
164 case WIDGET_HOTKEY: /* Didn't use the key */
165 return 0;
166
167 case WIDGET_INIT: /* We could tell if something went wrong */
168 return 1;
169
170 case WIDGET_KEY:
171 return 0; /* Didn't use the key */
172
173 case WIDGET_FOCUS: /* We accept FOCUSes */
174 if (h->current)
175 x_focus_widget (h->current);
176 return 1;
177
178 case WIDGET_UNFOCUS: /* We accept loose FOCUSes */
179 if (h->current)
180 x_unfocus_widget (h->current);
181 return 1;
182
183 case WIDGET_DRAW:
184 return 1;
185
186 case WIDGET_DESTROY:
187 return 1;
188
189 case WIDGET_CURSOR:
190 /* Move the cursor to the default widget position */
191 return 1;
192
193 case WIDGET_IDLE:
194 return 1;
195 }
196 printf ("Internal error: unhandled message: %d\n", Msg);
197 return 1;
198 }
199
200 int default_dlg_callback (Dlg_head *h, int id, int msg)
201 {
202 if (msg == DLG_IDLE){
203 dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
204 }
205 return 0;
206 }
207
208 #ifdef HAVE_X
209 int midnight_callback (struct Dlg_head *h, int id, int msg);
210 #endif
211 Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
212 int *color_set,
213 int (*callback) (struct Dlg_head *, int, int),
214 char *help_ctx, char *name,
215 int flags)
216 {
217 Dlg_head *new_d;
218
219 if (flags & DLG_CENTER){
220 y1 = (LINES-lines)/2;
221 x1 = (COLS-cols)/2;
222 }
223 if ((flags & DLG_TRYUP) && (y1 > 3))
224 y1 -= 2;
225
226 new_d = (Dlg_head *) malloc (sizeof (Dlg_head));
227 new_d->current = NULL;
228 new_d->count = 0;
229 new_d->direction = DIR_FORWARD;
230 new_d->color = color_set;
231 new_d->help_ctx = help_ctx;
232 new_d->callback = callback ? callback : default_dlg_callback;
233 new_d->send_idle_msg = 0;
234 new_d->x = x1;
235 new_d->y = y1;
236 new_d->title = 0;
237 new_d->cols = cols;
238 new_d->lines = lines;
239 new_d->refresh_pushed = 0;
240 new_d->has_menubar = 0;
241 new_d->name = name;
242 new_d->raw = 0;
243 new_d->grided = 0;
244 new_d->initfocus = NULL;
245 new_d->running = 0;
246 #ifdef HAVE_X
247 if (callback != midnight_callback)
248 new_d->wdata = xtoolkit_create_dialog (new_d, flags);
249 else
250 new_d->wdata = xtoolkit_get_main_dialog (new_d);
251 #endif
252 return (new_d);
253 }
254
255 void set_idle_proc (Dlg_head *d, int state)
256 {
257 d->send_idle_msg = state;
258 x_set_idle (d, state);
259 }
260
261 /* add component to dialog buffer */
262 int add_widgetl (Dlg_head *where, void *what, WLay layout)
263 {
264 Widget_Item *back;
265 Widget *widget = (Widget *) what;
266
267 /* Only used by Tk */
268 widget->frame = the_frame;
269
270 widget->layout = layout;
271 /* Don't accept 0 widgets, this could be from widgets that could not */
272 /* initialize properly */
273 if (!what)
274 return 0;
275
276 widget->x += where->x;
277 widget->y += where->y;
278
279 if (where->running){
280 Widget_Item *point = where->current;
281
282 where->current = (Widget_Item *) malloc (sizeof (Widget_Item));
283
284 if (point){
285 where->current->next = point->next;
286 where->current->prev = point;
287 point->next->prev = where->current;
288 point->next = where->current;
289 } else {
290 where->current->next = where->current;
291 where->first = where->current;
292 where->current->prev = where->first;
293 where->last = where->current;
294 where->first->next = where->last;
295 }
296 } else {
297 back = where->current;
298 where->current = (Widget_Item *) malloc (sizeof (Widget_Item));
299 if (back){
300 back->prev = where->current;
301 where->current->next = back;
302 } else {
303 where->current->next = where->current;
304 where->first = where->current;
305 }
306
307 where->current->prev = where->first;
308 where->last = where->current;
309 where->first->next = where->last;
310
311 }
312 where->current->dlg_id = where->count;
313 where->current->widget = what;
314 where->current->widget->parent = where;
315
316 where->count++;
317
318 /* If the widget is inserted in a running dialog */
319 if (where->running){
320 send_message (where, widget, WIDGET_INIT, 0);
321 send_message (where, widget, WIDGET_DRAW, 0);
322 #ifdef HAVE_GNOME
323 x_add_widget (where, where->current);
324 #endif
325 }
326 return (where->count - 1);
327 }
328
329 int remove_widget (Dlg_head *h, void *what)
330 {
331 Widget_Item *first, *p;
332
333 first = p = h->current;
334
335 do {
336 if (p->widget == what){
337 /* Remove links to this Widget_Item */
338 p->prev->next = p->next;
339 p->next->prev = p->prev;
340
341 /* Make sure h->current is always valid */
342 if (p == h->current){
343 h->current = h->current->next;
344 if (h->current == p)
345 h->current = 0;
346 }
347 h->count--;
348 free (p);
349 return 1;
350 }
351 p = p->next;
352 } while (p != first);
353 return 0;
354 }
355
356 int destroy_widget (Widget *w)
357 {
358 send_message (w->parent, w, WIDGET_DESTROY, 0);
359 if (w->destroy)
360 w->destroy (w);
361 free (w);
362 return 1;
363 }
364
365 int add_widget (Dlg_head *where, void *what)
366 {
367 return add_widgetl (where, what, XV_WLAY_DONTCARE);
368 }
369
370 int send_message (Dlg_head *h, Widget *w, int msg, int par)
371 {
372 return (*(w->callback))(h, w, msg, par);
373 }
374
375 /* broadcast a message to all the widgets in a dialog that have
376 * the options set to flags.
377 */
378 void dlg_broadcast_msg_to (Dlg_head *h, int message, int reverse, int flags)
379 {
380 Widget_Item *p, *first;
381
382 if (!h->current)
383 return;
384
385 if (reverse)
386 first = p = h->current->prev;
387 else
388 /* FIXME: On XView the layout for the widget->next widget is
389 invoked, and we should change the buttons order on query_dialog
390 in order to use the HAVE_X part of the statement */
391 #ifdef HAVE_X
392 first = p = h->current;
393 #else
394 first = p = h->current->next;
395 #endif
396 do {
397 /* if (p->widget->options & flags) */
398 send_message (h, p->widget, message, 0);
399
400 if (reverse)
401 p = p->prev;
402 else
403 p = p->next;
404 } while (first != p);
405 }
406
407 /* broadcast a message to all the widgets in a dialog */
408 void dlg_broadcast_msg (Dlg_head *h, int message, int reverse)
409 {
410 dlg_broadcast_msg_to (h, message, reverse, ~0);
411 }
412
413 int dlg_focus (Dlg_head *h)
414 {
415 if (send_message (h, h->current->widget, WIDGET_FOCUS, 0)){
416 (*h->callback) (h, h->current->dlg_id, DLG_FOCUS);
417 return 1;
418 }
419 return 0;
420 }
421
422 int dlg_unfocus (Dlg_head *h)
423 {
424 if (send_message (h, h->current->widget, WIDGET_UNFOCUS, 0)){
425 (*h->callback) (h, h->current->dlg_id, DLG_UNFOCUS);
426 return 1;
427 }
428 return 0;
429 }
430
431 static void select_a_widget (Dlg_head *h, int down)
432 {
433 int direction = h->direction;
434
435 if (!down)
436 direction = !direction;
437
438 do {
439 if (direction)
440 h->current = h->current->next;
441 else
442 h->current = h->current->prev;
443
444 (*h->callback) (h, h->current->dlg_id, DLG_ONE_DOWN);
445 } while (!dlg_focus (h));
446 }
447
448 /* Return true if the windows overlap */
449 int dlg_overlap (Widget *a, Widget *b)
450 {
451 if ((b->x >= a->x + a->cols)
452 || (a->x >= b->x + b->cols)
453 || (b->y >= a->y + a->lines)
454 || (a->y >= b->y + b->lines))
455 return 0;
456 return 1;
457 }
458
459
460 /* Searches a widget, uses the callback as a signature in the dialog h */
461 Widget *find_widget_type (Dlg_head *h, callback_fn signature)
462 {
463 Widget *w;
464 Widget_Item *item;
465 int i;
466
467 if (!h)
468 return 0;
469
470 w = 0;
471 for (i = 0, item = h->current; i < h->count; i++, item = item->next){
472 if (item->widget->callback == signature){
473 w = item->widget;
474 break;
475 }
476 }
477 return w;
478 }
479
480 void dlg_one_up (Dlg_head *h)
481 {
482 Widget_Item *old;
483
484 old = h->current;
485 /* If it accepts unFOCUSion */
486 if (!dlg_unfocus(h))
487 return;
488
489 select_a_widget (h, 0);
490 if (dlg_overlap (old->widget, h->current->widget)){
491 send_message (h, h->current->widget, WIDGET_DRAW, 0);
492 send_message (h, h->current->widget, WIDGET_FOCUS, 0);
493 }
494 }
495
496 void dlg_one_down (Dlg_head *h)
497 {
498 Widget_Item *old;
499
500 old = h->current;
501 if (!dlg_unfocus (h))
502 return;
503
504 select_a_widget (h, 1);
505 if (dlg_overlap (old->widget, h->current->widget)){
506 send_message (h, h->current->widget, WIDGET_DRAW, 0);
507 send_message (h, h->current->widget, WIDGET_FOCUS, 0);
508 }
509 }
510
511 int dlg_select_widget (Dlg_head *h, void *w)
512 {
513 if (dlg_unfocus (h)){
514 while (h->current->widget != w)
515 h->current = h->current->next;
516 while (!dlg_focus (h))
517 h->current = h->current->next;
518
519 return 1;
520 }
521 return 0;
522 }
523
524 int send_message_to (Dlg_head *h, Widget *w, int msg, int par)
525 {
526 Widget_Item *p = h->current;
527 int v, i;
528
529 v = 0;
530 for (i = 0; i < h->count; i++){
531 if (w == (void *) p->widget){
532 v = send_message (h, p->widget, msg, par);
533 break;
534 }
535 p = p->next;
536 }
537 return v;
538 }
539
540 #define callback(h) (h->current->widget->callback)
541
542 void update_cursor (Dlg_head *h)
543 {
544 if (!h->current)
545 return;
546 if (h->current->widget->options & W_WANT_CURSOR)
547 send_message (h, h->current->widget, WIDGET_CURSOR, 0);
548 else {
549 Widget_Item *p = h->current;
550
551 do {
552 if (p->widget->options & W_WANT_CURSOR)
553 if ((*p->widget->callback)(h, p->widget, WIDGET_CURSOR, 0)){
554 x_focus_widget (p);
555 break;
556 }
557 p = p->next;
558 } while (h->current != p);
559 }
560 }
561
562 /* Redraw the widgets in reverse order, leaving the current widget
563 * as the last one
564 */
565 void dlg_redraw (Dlg_head *h)
566 {
567 (h->callback)(h, 0, DLG_DRAW);
568
569 dlg_broadcast_msg (h, WIDGET_DRAW, 1);
570
571 update_cursor (h);
572 }
573
574 void dlg_refresh (void *parameter)
575 {
576 dlg_redraw ((Dlg_head *) parameter);
577 }
578
579 void dlg_stop (Dlg_head *h)
580 {
581 h->running = 0;
582 x_dialog_stop (h);
583 }
584
585 static INLINE void dialog_handle_key (Dlg_head *h, int d_key)
586 {
587 char *hlpfile;
588
589 switch (d_key){
590 case KEY_LEFT:
591 case KEY_UP:
592 dlg_one_up (h);
593 break;
594
595 case KEY_RIGHT:
596 case KEY_DOWN:
597 dlg_one_down (h);
598 break;
599
600 case KEY_F(1):
601 hlpfile = concat_dir_and_file (mc_home, "mc.hlp");
602 interactive_display (hlpfile, h->help_ctx);
603 free (hlpfile);
604 do_refresh ();
605 break;
606
607 case XCTRL('z'):
608 suspend_cmd ();
609 /* Fall through */
610
611 case XCTRL('l'):
612 #ifndef HAVE_SLANG
613 /* Use this if the refreshes fail */
614 clr_scr ();
615 do_refresh ();
616 #else
617 touchwin (stdscr);
618 #endif
619 mc_refresh ();
620 doupdate ();
621 break;
622
623 case '\n':
624 case KEY_ENTER:
625 h->ret_value = B_ENTER;
626 h->running = 0;
627 x_dialog_stop (h);
628 break;
629
630 case ESC_CHAR:
631 case KEY_F (10):
632 case XCTRL ('c'):
633 case XCTRL ('g'):
634 h->ret_value = B_CANCEL;
635 dlg_stop (h);
636 break;
637 }
638 }
639
640 static int dlg_try_hotkey (Dlg_head *h, int d_key)
641 {
642 Widget_Item *hot_cur;
643 Widget_Item *previous;
644 int handled, c;
645 extern input_event ();
646
647 /*
648 * Explanation: we don't send letter hotkeys to other widgets if
649 * the currently selected widget is an input line
650 */
651
652 if (h->current->widget->options & W_IS_INPUT){
653 if(d_key < 255 && isalpha(d_key))
654 return 0;
655 }
656
657 /* If it's an alt key, send the message */
658 c = d_key & ~ALT(0);
659 if (d_key & ALT(0) && c < 255 && isalpha(c))
660 d_key = tolower(c);
661
662 #ifdef _OS_NT
663 /* .ado: fix problem with file_permission under Win95 */
664 if (d_key == 0) return 0;
665 #endif
666
667 handled = 0;
668 if (h->current->widget->options & W_WANT_HOTKEY)
669 handled = callback (h) (h, h->current->widget, WIDGET_HOTKEY, d_key);
670
671 /* If not used, send hotkey to other widgets */
672 if (handled)
673 return handled;
674
675 hot_cur = h->current;
676
677 /* send it to all widgets */
678 do {
679 if (hot_cur->widget->options & W_WANT_HOTKEY)
680 handled |= (*hot_cur->widget->callback)
681 (h, hot_cur->widget, WIDGET_HOTKEY, d_key);
682
683 if (!handled)
684 hot_cur = hot_cur->next;
685 } while (h->current != hot_cur && !handled);
686
687 if (!handled)
688 return 0;
689
690 (*h->callback) (h, 0, DLG_HOTKEY_HANDLED);
691 previous = h->current;
692 if (!dlg_unfocus (h))
693 return handled;
694
695 h->current = hot_cur;
696 if (!dlg_focus (h)){
697 h->current = previous;
698 dlg_focus (h);
699 }
700 return handled;
701 }
702
703 void dlg_key_event (Dlg_head *h, int d_key)
704 {
705 int handled;
706
707 /* TAB used to cycle */
708 if (!h->raw && (d_key == '\t' || d_key == KEY_BTAB))
709 if (d_key == '\t')
710 dlg_one_down (h);
711 else
712 dlg_one_up (h);
713 else {
714
715 /* first can dlg_callback handle the key */
716 handled = (*h->callback) (h, d_key, DLG_KEY);
717
718 /* next try the hotkey */
719 if (!handled)
720 handled = dlg_try_hotkey (h, d_key);
721
722 /* not used - then try widget_callback */
723 if (!handled)
724 handled |= callback (h)(h, h->current->widget, WIDGET_KEY, d_key);
725
726 /* not used- try to use the unhandled case */
727 if (!handled)
728 handled |= (*h->callback) (h, d_key, DLG_UNHANDLED_KEY);
729
730 if (!handled)
731 dialog_handle_key (h, d_key);
732 (*h->callback) (h, d_key, DLG_POST_KEY);
733 }
734 }
735
736 static INLINE int dlg_mouse_event (Dlg_head *h, Gpm_Event *event)
737 {
738 Widget_Item *item;
739 Widget_Item *starting_widget = h->current;
740 Gpm_Event new_event;
741 int x = event->x;
742 int y = event->y;
743 int ret_value;
744
745 /* kludge for the menubar: start at h->first, not current */
746 /* Must be carefull in the insertion order to the dlg list */
747 if (y == 1 && h->has_menubar)
748 starting_widget = h->first;
749
750 item = starting_widget;
751 do {
752 Widget *widget = item->widget;
753
754 item = item->next;
755
756 if (!((x > widget->x) && (x <= widget->x+widget->cols)
757 && (y > widget->y) && (y <= widget->y+widget->lines)))
758 continue;
759
760 new_event = *event;
761 new_event.x -= widget->x;
762 new_event.y -= widget->y;
763
764 ret_value = widget->mouse ? (*widget->mouse) (&new_event, widget) :
765 MOU_NORMAL;
766
767 return ret_value;
768 } while (item != starting_widget);
769 return 0;
770 }
771
772 /* Run dialog routines */
773
774 /* Init the process */
775 void init_dlg (Dlg_head *h)
776 {
777 int refresh_mode;
778
779 tk_end_frame ();
780
781 /* Initialize dialog manager and widgets */
782 (*h->callback) (h, 0, DLG_INIT);
783 dlg_broadcast_msg (h, WIDGET_INIT, 0);
784
785 if (h->x == 0 && h->y == 0 && h->cols == COLS && h->lines == LINES)
786 refresh_mode = REFRESH_COVERS_ALL;
787 else
788 refresh_mode = REFRESH_COVERS_PART;
789 push_refresh (dlg_refresh, h, refresh_mode);
790 h->refresh_pushed = 1;
791
792 /* Initialize direction */
793 if (!h->direction)
794 h->current = h->first;
795
796 if (h->initfocus != NULL)
797 h->current = h->initfocus;
798
799 h->previous_dialog = current_dlg;
800 current_dlg = h;
801
802 /* Initialize the mouse status */
803 h->mouse_status = 0;
804
805 /* Redraw the screen */
806 dlg_redraw (h);
807
808 while (!dlg_focus (h))
809 h->current = h->current->next;
810
811 h->ret_value = 0;
812 h->running = 1;
813 x_init_dlg (h);
814 }
815
816 /* Shutdown the run_dlg */
817 void dlg_run_done (Dlg_head *h)
818 {
819 (*h->callback) (h, h->current->dlg_id, DLG_END);
820 current_dlg = (Dlg_head *) h->previous_dialog;
821 if (current_dlg)
822 x_focus_widget (current_dlg->current);
823 }
824
825 void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event)
826 {
827 if (key == EV_NONE){
828 if (got_interrupt ())
829 key = XCTRL('g');
830 else
831 return;
832 }
833
834 if (key == EV_MOUSE)
835 h->mouse_status = dlg_mouse_event (h, event);
836 else
837 dlg_key_event (h, key);
838 }
839
840 #ifndef PORT_HAS_FRONTEND_RUN_DLG
841 static inline void
842 frontend_run_dlg (Dlg_head *h)
843 {
844 int d_key;
845 Gpm_Event event;
846
847 event.x = -1;
848 while (h->running) {
849 #if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
850 /* It does not work with ncurses before 1.9.9g, it will break */
851 if (winch_flag)
852 change_screen_size ();
853 #endif
854 if (is_idle ()){
855 if (idle_hook)
856 execute_hooks (idle_hook);
857
858 while (h->send_idle_msg && is_idle ()){
859 (*h->callback) (h, 0, DLG_IDLE);
860 }
861 }
862
863 update_cursor (h);
864 (*h->callback)(h, 0, DLG_PRE_EVENT);
865
866 /* Clear interrupt flag */
867 got_interrupt ();
868 d_key = get_event (&event, h->mouse_status == MOU_REPEAT, 1);
869
870 dlg_process_event (h, d_key, &event);
871 }
872 }
873 #endif /* PORT_HAS_FRONTEND_RUN_DLG */
874
875 /* Standard run dialog routine
876 * We have to keep this routine small so that we can duplicate it's
877 * behavior on complex routines like the file routines, this way,
878 * they can call the dlg_process_event without rewriting all the code
879 */
880 void run_dlg (Dlg_head *h)
881 {
882 init_dlg (h);
883 frontend_run_dlg (h);
884 dlg_run_done (h);
885 }
886
887 void
888 destroy_dlg (Dlg_head *h)
889 {
890 int i;
891 Widget_Item *c;
892
893 if (h->refresh_pushed)
894 pop_refresh ();
895
896 x_destroy_dlg_start (h);
897 dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
898 c = h->current;
899 for (i = 0; i < h->count; i++){
900 if (c->widget->destroy)
901 c->widget->destroy (c->widget);
902 c = c->next;
903 free (h->current->widget);
904 free (h->current);
905 h->current = c;
906 }
907 if (h->title)
908 free (h->title);
909 x_destroy_dlg (h);
910 free (h);
911 if (refresh_list)
912 do_refresh ();
913 }
914
915 int std_callback (Dlg_head *h, int Msg, int Par)
916 {
917 return 0;
918 }
919
920 void widget_set_size (Widget *widget, int y, int x, int lines, int cols)
921 {
922 widget->x = x;
923 widget->y = y;
924 widget->cols = cols;
925 widget->lines = lines;
926 }
927
928 /* Replace widget old for widget new in the h dialog */
929 void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new)
930 {
931 Widget_Item *p = h->current;
932 int should_focus = 0;
933
934 do {
935 if (p->widget == old){
936
937 if (old == h->current->widget)
938 should_focus = 1;
939
940 /* We found the widget */
941 /* First kill the widget */
942 new->focused = old->focused;
943 new->parent = h;
944 send_message_to (h, old, WIDGET_DESTROY, 0);
945 (*old->destroy) (old);
946
947 /* We insert the new widget */
948 p->widget = new;
949 send_message_to (h, new, WIDGET_INIT, 0);
950 if (should_focus){
951 if (dlg_focus (h) == 0)
952 select_a_widget (h, 1);
953 }
954 send_message_to (h, new, WIDGET_DRAW, 0);
955 break;
956 }
957 p = p->next;
958 } while (p != h->current);
959 }
960
961 void widget_redraw (Dlg_head *h, Widget_Item *w)
962 {
963 Widget_Item *save = h->current;
964
965 h->current = w;
966 (*w->widget->callback)(h, h->current->widget, WIDGET_DRAW, 0);
967 h->current = save;
968 }
969
970 /* Returns the index of h->current from h->first */
971 int dlg_item_number (Dlg_head *h)
972 {
973 Widget_Item *p;
974 int i = 0;
975
976 p = h->first;
977
978 do {
979 if (p == h->current)
980 return i;
981 i++;
982 p = p->next;
983 } while (p != h->first);
984 fprintf (stderr, "Internal error: current not in dialog list\n\r");
985 exit (1);
986 }
987
988 int dlg_select_nth_widget (Dlg_head *h, int n)
989 {
990 Widget_Item *w;
991 int i;
992
993 w = h->first;
994 for (i = 0; i < n; i++)
995 w = w->next;
996
997 return dlg_select_widget (h, w->widget);
998 }
999
1000 #ifdef HAVE_TK
1001 /* Frames must include a trailing dot */
1002 static void tk_frame_proc (Dlg_head *h, char *frame, int new_frame)
1003 {
1004 char *s = strdup (frame);
1005
1006 if (frame [strlen (frame)-1] != '.'){
1007 fprintf (stderr, "Invalid frame name\n");
1008 exit (1);
1009 }
1010 s [strlen (frame)-1] = 0;
1011 the_frame = frame;
1012
1013 if (new_frame)
1014 tk_evalf ("frame %s.%s", (char *)h->wdata, s);
1015 }
1016
1017 /* If passed a null string, it returns */
1018 void tk_new_frame (Dlg_head *h, char *frame)
1019 {
1020 if (!*frame)
1021 return;
1022 tk_frame_proc (h, frame, 1);
1023 }
1024
1025 void tk_frame (Dlg_head *h, char *frame)
1026 {
1027 tk_frame_proc (h, frame, 0);
1028 }
1029
1030 void tk_end_frame ()
1031 {
1032 the_frame = "";
1033 }
1034 #else
1035 void tk_new_frame (Dlg_head *h, char *x)
1036 {
1037 }
1038
1039 void tk_frame (Dlg_head *h, char *x)
1040 {
1041 }
1042
1043 void tk_end_frame (void)
1044 {
1045 }
1046 #endif
1047
1048 #ifndef PORT_HAS_DIALOG_TITLE
1049 void
1050 x_set_dialog_title (Dlg_head *h, char *title)
1051 {
1052 h->title = strdup(title);
1053 }
1054 #endif
1055