* Makefile.in: Converted to ...
[midnight-commander.git] / src / dlg.c
blob7802109b5d2bb23a9c00bc2c8da1e7b0de2e331c
1 /* Dlg box features module for the Midnight Commander
2 Copyright (C) 1994, 1995 Radek Doulik, Miguel de Icaza
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
20 /* "$Id$" */
21 #include <string.h>
22 #include <stdio.h>
23 #include <ctype.h>
24 #include "tty.h"
25 #include <stdarg.h>
26 #include "global.h"
27 #include "x.h"
28 #include "menu.h"
29 #include "win.h"
30 #include "color.h"
31 #include "mouse.h"
32 #include "help.h"
33 #include "key.h" /* For mi_getch() */
34 #include "dlg.h"
35 #include "dialog.h" /* For push_refresh() and pop_refresh() */
36 #include "layout.h"
37 #include "main.h"
39 /* This is the current frame, used to group Tk packings */
40 char *the_frame = "";
42 #define waddc(w,y1,x1,c) move (w->y+y1, w->x+x1); addch (c)
44 /* Primitive way to check if the the current dialog is our dialog */
45 /* This is needed by async routines like load_prompt */
46 Dlg_head *current_dlg = 0;
48 /* A hook list for idle events */
49 Hook *idle_hook = 0;
51 #ifndef HAVE_X
52 # define x_set_idle(d,x)
53 # define x_dialog_stop(d)
54 #endif /* HAVE_X */
56 #ifdef HAVE_X
57 void widget_erase (Widget *w)
61 void dlg_erase (Dlg_head *h)
64 #else
65 static void slow_box (Dlg_head *h, int y, int x, int ys, int xs)
67 move (h->y+y, h->x+x);
68 hline (' ', xs);
69 vline (' ', ys);
70 move (h->y+y, h->x+x+xs-1);
71 vline (' ', ys);
72 move (h->y+y+ys-1, h->x+x);
73 hline (' ', xs);
76 /* draw box in window */
77 void draw_box (Dlg_head *h, int y, int x, int ys, int xs)
79 extern int slow_terminal;
81 if (slow_terminal){
82 slow_box (h, y, x, ys, xs);
83 return;
86 #ifndef HAVE_SLANG
87 waddc (h, y, x, ACS_ULCORNER);
88 hline (ACS_HLINE, xs - 2);
89 waddc (h, y + ys - 1, x, ACS_LLCORNER);
90 hline (ACS_HLINE, xs - 2);
92 waddc (h, y, x + xs - 1, ACS_URCORNER);
93 waddc (h, y + ys - 1, x + xs - 1, ACS_LRCORNER);
95 move (h->y+y+1, h->x+x);
96 vline (ACS_VLINE, ys - 2);
97 move (h->y+y+1, h->x+x+xs-1);
98 vline (ACS_VLINE, ys - 2);
99 #else
100 SLsmg_draw_box (h->y+y, h->x+x, ys, xs);
101 #endif
104 /* draw box in window */
105 void draw_double_box (Dlg_head *h, int y, int x, int ys, int xs)
107 #ifndef HAVE_SLANG
108 draw_box (h, y, x, ys, xs);
109 #else
110 SLsmg_draw_double_box (h->y+y, h->x+x, ys, xs);
111 #endif
114 void widget_erase (Widget *w)
116 int x, y;
118 for (y = 0; y < w->lines; y++){
119 widget_move (w, y, 0);
120 for (x = 0; x < w->cols; x++)
121 addch (' ');
125 void dlg_erase (Dlg_head *h)
127 int x, y;
129 for (y = 0; y < h->lines; y++){
130 move (y+h->y, h->x); /* FIXME: should test if ERR */
131 for (x = 0; x < h->cols; x++){
132 addch (' ');
136 #endif /* HAVE_X */
138 void init_widget (Widget *w, int y, int x, int lines, int cols,
139 int (*callback)(Dlg_head *, void *, int, int),
140 destroy_fn destroy, mouse_h mouse_handler, char *tkname)
142 w->x = x;
143 w->y = y;
144 w->cols = cols;
145 w->lines = lines;
146 w->color = -1;
147 w->callback = callback;
148 w->destroy = destroy;
149 w->mouse = mouse_handler;
150 w->wdata = 0;
151 w->wcontainer = 0;
152 w->frame = "";
153 w->parent = 0;
154 w->tkname = tkname;
156 if (tkname && *tkname == 0){
157 fprintf (stderr, "Got a null string for the tkname\n");
158 abort ();
160 /* Almost all widgets want to put the cursor in a suitable place */
161 w->options = W_WANT_CURSOR;
164 int default_proc (Dlg_head *h, int Msg, int Par)
166 switch (Msg){
168 case WIDGET_HOTKEY: /* Didn't use the key */
169 return 0;
171 case WIDGET_INIT: /* We could tell if something went wrong */
172 return 1;
174 case WIDGET_KEY:
175 return 0; /* Didn't use the key */
177 case WIDGET_FOCUS: /* We accept FOCUSes */
178 if (h->current)
179 x_focus_widget (h->current);
180 return 1;
182 case WIDGET_UNFOCUS: /* We accept loose FOCUSes */
183 if (h->current)
184 x_unfocus_widget (h->current);
185 return 1;
187 case WIDGET_DRAW:
188 return 1;
190 case WIDGET_DESTROY:
191 return 1;
193 case WIDGET_CURSOR:
194 /* Move the cursor to the default widget position */
195 return 1;
197 case WIDGET_IDLE:
198 return 1;
200 printf ("Internal error: unhandled message: %d\n", Msg);
201 return 1;
204 int default_dlg_callback (Dlg_head *h, int id, int msg)
206 if (msg == DLG_IDLE){
207 dlg_broadcast_msg_to (h, WIDGET_IDLE, 0, W_WANT_IDLE);
209 return 0;
212 #ifdef HAVE_X
213 int midnight_callback (struct Dlg_head *h, int id, int msg);
214 #endif
215 Dlg_head *create_dlg (int y1, int x1, int lines, int cols,
216 int *color_set,
217 int (*callback) (struct Dlg_head *, int, int),
218 char *help_ctx, char *name,
219 int flags)
221 Dlg_head *new_d;
223 #ifndef HAVE_X
224 if (flags & DLG_CENTER){
225 y1 = (LINES-lines)/2;
226 x1 = (COLS-cols)/2;
228 #endif
230 if ((flags & DLG_TRYUP) && (y1 > 3))
231 y1 -= 2;
233 new_d = g_new0 (Dlg_head, 1);
234 new_d->direction = DIR_FORWARD;
235 new_d->color = color_set;
236 new_d->help_ctx = help_ctx;
237 new_d->callback = callback ? callback : default_dlg_callback;
238 new_d->x = x1;
239 new_d->y = y1;
240 new_d->cols = cols;
241 new_d->lines = lines;
242 new_d->name = name;
243 #ifdef HAVE_X
244 if (callback != midnight_callback)
245 new_d->wdata = xtoolkit_create_dialog (new_d, flags);
246 else
247 new_d->wdata = xtoolkit_get_main_dialog (new_d);
248 #endif
249 return (new_d);
252 void set_idle_proc (Dlg_head *d, int state)
254 d->send_idle_msg = state;
255 x_set_idle (d, state);
258 /* add component to dialog buffer */
259 int add_widget (Dlg_head *where, void *what)
261 Widget_Item *back;
262 Widget *widget = (Widget *) what;
264 /* Only used by Tk */
265 widget->frame = the_frame;
267 /* Don't accept 0 widgets, this could be from widgets that could not */
268 /* initialize properly */
269 if (!what)
270 return 0;
272 widget->x += where->x;
273 widget->y += where->y;
275 if (where->running){
276 Widget_Item *point = where->current;
278 where->current = g_new (Widget_Item, 1);
280 if (point){
281 where->current->next = point->next;
282 where->current->prev = point;
283 point->next->prev = where->current;
284 point->next = where->current;
285 } else {
286 where->current->next = where->current;
287 where->first = where->current;
288 where->current->prev = where->first;
289 where->last = where->current;
290 where->first->next = where->last;
292 } else {
293 back = where->current;
294 where->current = g_new (Widget_Item, 1);
295 if (back){
296 back->prev = where->current;
297 where->current->next = back;
298 } else {
299 where->current->next = where->current;
300 where->first = where->current;
303 where->current->prev = where->first;
304 where->last = where->current;
305 where->first->next = where->last;
308 where->current->dlg_id = where->count;
309 where->current->widget = what;
310 where->current->widget->parent = where;
312 where->count++;
314 /* If the widget is inserted in a running dialog */
315 if (where->running){
316 send_message (where, widget, WIDGET_INIT, 0);
317 send_message (where, widget, WIDGET_DRAW, 0);
318 #ifdef HAVE_GNOME
319 x_add_widget (where, where->current);
320 #endif
322 return (where->count - 1);
325 int remove_widget (Dlg_head *h, void *what)
327 Widget_Item *first, *p;
329 if (!h->current)
330 return 0;
332 first = p = h->current;
334 do {
335 if (p->widget == what){
336 /* Remove links to this Widget_Item */
337 p->prev->next = p->next;
338 p->next->prev = p->prev;
340 /* Make sure h->current is always valid */
341 if (p == h->current){
342 h->current = h->current->next;
343 if (h->current == p)
344 h->current = 0;
346 h->count--;
347 g_free (p);
348 return 1;
350 p = p->next;
351 } while (p != first);
352 return 0;
355 int destroy_widget (Widget *w)
357 send_message (w->parent, w, WIDGET_DESTROY, 0);
358 if (w->destroy)
359 w->destroy (w);
360 g_free (w);
361 return 1;
364 int send_message (Dlg_head *h, Widget *w, int msg, int par)
366 return (*(w->callback))(h, w, msg, par);
369 /* broadcast a message to all the widgets in a dialog that have
370 * the options set to flags.
372 void dlg_broadcast_msg_to (Dlg_head *h, int message, int reverse, int flags)
374 Widget_Item *p, *first, *wi;
375 #ifdef HAVE_GNOME
376 int was_panel;
377 #endif
379 if (!h->current)
380 return;
382 if (reverse)
383 first = p = h->current->prev;
384 else
385 /* FIXME: On XView the layout for the widget->next widget is
386 invoked, and we should change the buttons order on query_dialog
387 in order to use the HAVE_X part of the statement */
388 #ifdef HAVE_X
389 first = p = h->current;
390 #else
391 first = p = h->current->next;
392 #endif
394 #ifdef HAVE_GNOME
395 was_panel = FALSE;
396 #endif
397 do {
398 wi = p;
399 if (reverse)
400 p = p->prev;
401 else
402 p = p->next;
403 /* if (p->widget->options & flags) */
404 #ifdef HAVE_GNOME
405 if (is_a_panel (wi->widget))
406 was_panel |= TRUE;
407 #endif
408 send_message (h, wi->widget, message, 0);
409 } while (first != p);
410 #ifdef HAVE_GNOME
411 if (was_panel && message == WIDGET_INIT)
412 h->current = h->current->prev;
413 #endif
416 /* broadcast a message to all the widgets in a dialog */
417 void dlg_broadcast_msg (Dlg_head *h, int message, int reverse)
419 dlg_broadcast_msg_to (h, message, reverse, ~0);
422 int dlg_focus (Dlg_head *h)
424 if (!h->current)
425 return 0;
427 if (send_message (h, h->current->widget, WIDGET_FOCUS, 0)){
428 (*h->callback) (h, h->current->dlg_id, DLG_FOCUS);
429 return 1;
431 return 0;
434 int dlg_unfocus (Dlg_head *h)
436 if (!h->current)
437 return 0;
439 if (send_message (h, h->current->widget, WIDGET_UNFOCUS, 0)){
440 (*h->callback) (h, h->current->dlg_id, DLG_UNFOCUS);
441 return 1;
443 return 0;
446 static void select_a_widget (Dlg_head *h, int down)
448 int direction = h->direction;
450 if (!h->current)
451 return;
453 if (!down)
454 direction = !direction;
456 do {
457 if (direction)
458 h->current = h->current->next;
459 else
460 h->current = h->current->prev;
462 (*h->callback) (h, h->current->dlg_id, DLG_ONE_DOWN);
463 } while (!dlg_focus (h));
466 /* Return true if the windows overlap */
467 int dlg_overlap (Widget *a, Widget *b)
469 if ((b->x >= a->x + a->cols)
470 || (a->x >= b->x + b->cols)
471 || (b->y >= a->y + a->lines)
472 || (a->y >= b->y + b->lines))
473 return 0;
474 return 1;
478 /* Searches a widget, uses the callback as a signature in the dialog h */
479 Widget *find_widget_type (Dlg_head *h, callback_fn signature)
481 Widget *w;
482 Widget_Item *item;
483 int i;
485 if (!h)
486 return 0;
487 if (!h->current)
488 return 0;
490 w = 0;
491 for (i = 0, item = h->current; i < h->count; i++, item = item->next){
492 if (item->widget->callback == signature){
493 w = item->widget;
494 break;
497 return w;
500 void dlg_one_up (Dlg_head *h)
502 Widget_Item *old;
504 old = h->current;
506 if (!old)
507 return;
509 /* If it accepts unFOCUSion */
510 if (!dlg_unfocus(h))
511 return;
513 select_a_widget (h, 0);
514 if (dlg_overlap (old->widget, h->current->widget)){
515 send_message (h, h->current->widget, WIDGET_DRAW, 0);
516 send_message (h, h->current->widget, WIDGET_FOCUS, 0);
520 void dlg_one_down (Dlg_head *h)
522 Widget_Item *old;
524 old = h->current;
525 if (!old)
526 return;
528 if (!dlg_unfocus (h))
529 return;
531 select_a_widget (h, 1);
532 if (dlg_overlap (old->widget, h->current->widget)){
533 send_message (h, h->current->widget, WIDGET_DRAW, 0);
534 send_message (h, h->current->widget, WIDGET_FOCUS, 0);
538 int dlg_select_widget (Dlg_head *h, void *w)
540 if (!h->current)
541 return 0;
543 if (dlg_unfocus (h)){
544 while (h->current->widget != w)
545 h->current = h->current->next;
546 while (!dlg_focus (h))
547 h->current = h->current->next;
549 return 1;
551 return 0;
554 int send_message_to (Dlg_head *h, Widget *w, int msg, int par)
556 Widget_Item *p = h->current;
557 int v, i;
559 if (!h->current)
560 return 0;
562 v = 0;
563 for (i = 0; i < h->count; i++){
564 if (w == (void *) p->widget){
565 v = send_message (h, p->widget, msg, par);
566 break;
568 p = p->next;
570 return v;
573 #define callback(h) (h->current->widget->callback)
575 void update_cursor (Dlg_head *h)
577 if (!h->current)
578 return;
579 if (h->current->widget->options & W_WANT_CURSOR)
580 send_message (h, h->current->widget, WIDGET_CURSOR, 0);
581 else {
582 Widget_Item *p = h->current;
584 do {
585 if (p->widget->options & W_WANT_CURSOR)
586 if ((*p->widget->callback)(h, p->widget, WIDGET_CURSOR, 0)){
587 x_focus_widget (p);
588 break;
590 p = p->next;
591 } while (h->current != p);
595 /* Redraw the widgets in reverse order, leaving the current widget
596 * as the last one
598 void dlg_redraw (Dlg_head *h)
600 (h->callback)(h, 0, DLG_DRAW);
602 dlg_broadcast_msg (h, WIDGET_DRAW, 1);
604 update_cursor (h);
607 void dlg_refresh (void *parameter)
609 dlg_redraw ((Dlg_head *) parameter);
612 void dlg_stop (Dlg_head *h)
614 h->running = 0;
615 x_dialog_stop (h);
618 static INLINE void dialog_handle_key (Dlg_head *h, int d_key)
620 switch (d_key){
621 case KEY_LEFT:
622 case KEY_UP:
623 dlg_one_up (h);
624 break;
626 case KEY_RIGHT:
627 case KEY_DOWN:
628 dlg_one_down (h);
629 break;
631 case KEY_F(1):
632 interactive_display (NULL, h->help_ctx);
633 do_refresh ();
634 break;
636 #ifndef HAVE_X
637 case XCTRL('z'):
638 suspend_cmd ();
639 /* Fall through */
641 case XCTRL('l'):
642 #ifndef HAVE_SLANG
643 /* Use this if the refreshes fail */
644 clr_scr ();
645 do_refresh ();
646 #else
647 touchwin (stdscr);
648 #endif /* HAVE_SLANG */
649 mc_refresh ();
650 doupdate ();
651 #endif /* !HAVE_X */
652 break;
654 case '\n':
655 case KEY_ENTER:
656 h->ret_value = B_ENTER;
657 h->running = 0;
658 x_dialog_stop (h);
659 break;
661 case ESC_CHAR:
662 case KEY_F (10):
663 case XCTRL ('c'):
664 case XCTRL ('g'):
665 h->ret_value = B_CANCEL;
666 dlg_stop (h);
667 break;
671 static int dlg_try_hotkey (Dlg_head *h, int d_key)
673 Widget_Item *hot_cur;
674 Widget_Item *previous;
675 int handled, c;
677 if (!h->current)
678 return 0;
681 * Explanation: we don't send letter hotkeys to other widgets if
682 * the currently selected widget is an input line
685 if (h->current->widget->options & W_IS_INPUT){
686 if(d_key < 255 && isalpha(d_key))
687 return 0;
690 /* If it's an alt key, send the message */
691 c = d_key & ~ALT(0);
692 if (d_key & ALT(0) && c < 255 && isalpha(c))
693 d_key = tolower(c);
695 #ifdef _OS_NT
696 /* .ado: fix problem with file_permission under Win95 */
697 if (d_key == 0) return 0;
698 #endif
700 handled = 0;
701 if (h->current->widget->options & W_WANT_HOTKEY)
702 handled = callback (h) (h, h->current->widget, WIDGET_HOTKEY, d_key);
704 /* If not used, send hotkey to other widgets */
705 if (handled)
706 return handled;
708 hot_cur = h->current;
710 /* send it to all widgets */
711 do {
712 if (hot_cur->widget->options & W_WANT_HOTKEY)
713 handled |= (*hot_cur->widget->callback)
714 (h, hot_cur->widget, WIDGET_HOTKEY, d_key);
716 if (!handled)
717 hot_cur = hot_cur->next;
718 } while (h->current != hot_cur && !handled);
720 if (!handled)
721 return 0;
723 (*h->callback) (h, 0, DLG_HOTKEY_HANDLED);
724 previous = h->current;
725 if (!dlg_unfocus (h))
726 return handled;
728 h->current = hot_cur;
729 if (!dlg_focus (h)){
730 h->current = previous;
731 dlg_focus (h);
733 return handled;
736 int dlg_key_event (Dlg_head *h, int d_key)
738 int handled;
740 if (!h->current)
741 return 0;
743 /* TAB used to cycle */
744 if (!h->raw && (d_key == '\t' || d_key == KEY_BTAB))
745 if (d_key == '\t')
746 dlg_one_down (h);
747 else
748 dlg_one_up (h);
749 else {
751 /* first can dlg_callback handle the key */
752 handled = (*h->callback) (h, d_key, DLG_KEY);
754 /* next try the hotkey */
755 if (!handled)
756 handled = dlg_try_hotkey (h, d_key);
758 /* not used - then try widget_callback */
759 if (!handled)
760 handled |= callback (h)(h, h->current->widget, WIDGET_KEY, d_key);
762 /* not used- try to use the unhandled case */
763 if (!handled)
764 handled |= (*h->callback) (h, d_key, DLG_UNHANDLED_KEY);
766 if (!handled)
767 dialog_handle_key (h, d_key);
768 (*h->callback) (h, d_key, DLG_POST_KEY);
770 return handled;
772 return 1;
775 static INLINE int dlg_mouse_event (Dlg_head *h, Gpm_Event *event)
777 Widget_Item *item;
778 Widget_Item *starting_widget = h->current;
779 Gpm_Event new_event;
780 int x = event->x;
781 int y = event->y;
782 int ret_value;
784 /* kludge for the menubar: start at h->first, not current */
785 /* Must be carefull in the insertion order to the dlg list */
786 if (y == 1 && h->has_menubar)
787 starting_widget = h->first;
789 item = starting_widget;
790 do {
791 Widget *widget = item->widget;
793 item = item->next;
795 if (!((x > widget->x) && (x <= widget->x+widget->cols)
796 && (y > widget->y) && (y <= widget->y+widget->lines)))
797 continue;
799 new_event = *event;
800 new_event.x -= widget->x;
801 new_event.y -= widget->y;
803 ret_value = widget->mouse ? (*widget->mouse) (&new_event, widget) :
804 MOU_NORMAL;
806 return ret_value;
807 } while (item != starting_widget);
808 return 0;
811 /* Run dialog routines */
813 /* Init the process */
814 void init_dlg (Dlg_head *h)
816 int refresh_mode;
818 /* Initialize dialog manager and widgets */
819 (*h->callback) (h, 0, DLG_INIT);
820 dlg_broadcast_msg (h, WIDGET_INIT, 0);
822 #ifdef HAVE_X
823 refresh_mode = REFRESH_COVERS_PART;
824 #else
825 if (h->x == 0 && h->y == 0 && h->cols == COLS && h->lines == LINES)
826 refresh_mode = REFRESH_COVERS_ALL;
827 else
828 refresh_mode = REFRESH_COVERS_PART;
830 #endif
831 push_refresh (dlg_refresh, h, refresh_mode);
832 h->refresh_pushed = 1;
834 /* Initialize direction */
835 if (!h->direction)
836 h->current = h->first;
838 if (h->initfocus != NULL)
839 h->current = h->initfocus;
841 h->previous_dialog = current_dlg;
842 current_dlg = h;
844 /* Initialize the mouse status */
845 h->mouse_status = 0;
847 /* Redraw the screen */
848 dlg_redraw (h);
850 while (!dlg_focus (h) && h->current)
851 h->current = h->current->next;
853 h->ret_value = 0;
854 h->running = 1;
855 x_init_dlg (h);
858 /* Shutdown the run_dlg */
859 void dlg_run_done (Dlg_head *h)
861 if (h->current)
862 (*h->callback) (h, h->current->dlg_id, DLG_END);
864 current_dlg = (Dlg_head *) h->previous_dialog;
865 if (current_dlg){
868 * Special case for the GNOME desktop:
869 * The desktop will not have any widgets
871 if (current_dlg->current)
872 x_focus_widget (current_dlg->current);
876 void dlg_process_event (Dlg_head *h, int key, Gpm_Event *event)
878 if (key == EV_NONE){
879 if (got_interrupt ())
880 key = XCTRL('g');
881 else
882 return;
885 if (key == EV_MOUSE)
886 h->mouse_status = dlg_mouse_event (h, event);
887 else
888 dlg_key_event (h, key);
891 #ifndef HAVE_X
892 static inline void
893 frontend_run_dlg (Dlg_head *h)
895 int d_key;
896 Gpm_Event event;
898 event.x = -1;
899 while (h->running) {
900 #if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4
901 /* It does not work with ncurses before 1.9.9g, it will break */
902 if (winch_flag)
903 change_screen_size ();
904 #endif
905 if (is_idle ()){
906 if (idle_hook)
907 execute_hooks (idle_hook);
909 while (h->send_idle_msg && is_idle ()){
910 (*h->callback) (h, 0, DLG_IDLE);
914 update_cursor (h);
915 (*h->callback)(h, 0, DLG_PRE_EVENT);
917 /* Clear interrupt flag */
918 got_interrupt ();
919 d_key = get_event (&event, h->mouse_status == MOU_REPEAT, 1);
921 dlg_process_event (h, d_key, &event);
924 #endif /* HAVE_X */
926 /* Standard run dialog routine
927 * We have to keep this routine small so that we can duplicate it's
928 * behavior on complex routines like the file routines, this way,
929 * they can call the dlg_process_event without rewriting all the code
931 void run_dlg (Dlg_head *h)
933 init_dlg (h);
934 #ifdef HAVE_X
935 gtkrundlg_event (h);
936 #else
937 frontend_run_dlg (h);
938 #endif /* !HAVE_X */
939 dlg_run_done (h);
942 void
943 destroy_dlg (Dlg_head *h)
945 int i;
946 Widget_Item *c;
948 if (h->refresh_pushed)
949 pop_refresh ();
951 x_destroy_dlg_start (h);
952 dlg_broadcast_msg (h, WIDGET_DESTROY, 0);
953 c = h->current;
954 for (i = 0; i < h->count; i++){
955 if (c->widget->destroy)
956 c->widget->destroy (c->widget);
957 c = c->next;
958 if (h->current){
959 g_free (h->current->widget);
960 g_free (h->current);
962 h->current = c;
964 if (h->title)
965 g_free (h->title);
966 x_destroy_dlg (h);
967 g_free (h);
969 #ifndef HAVE_X
970 if (refresh_list)
971 do_refresh ();
972 #endif
975 int std_callback (Dlg_head *h, int Msg, int Par)
977 return 0;
980 void widget_set_size (Widget *widget, int y, int x, int lines, int cols)
982 widget->x = x;
983 widget->y = y;
984 widget->cols = cols;
985 widget->lines = lines;
988 /* Replace widget old for widget new in the h dialog */
989 void dlg_replace_widget (Dlg_head *h, Widget *old, Widget *new)
991 Widget_Item *p = h->current;
992 int should_focus = 0;
994 if (!h->current)
995 return;
997 do {
998 if (p->widget == old){
1000 if (old == h->current->widget)
1001 should_focus = 1;
1003 /* We found the widget */
1004 /* First kill the widget */
1005 new->focused = old->focused;
1006 new->parent = h;
1007 send_message_to (h, old, WIDGET_DESTROY, 0);
1008 (*old->destroy) (old);
1010 /* We insert the new widget */
1011 p->widget = new;
1012 send_message_to (h, new, WIDGET_INIT, 0);
1013 if (should_focus){
1014 if (dlg_focus (h) == 0)
1015 select_a_widget (h, 1);
1017 send_message_to (h, new, WIDGET_DRAW, 0);
1018 break;
1020 p = p->next;
1021 } while (p != h->current);
1024 void widget_redraw (Dlg_head *h, Widget_Item *w)
1026 Widget_Item *save = h->current;
1028 if (!h->current)
1029 return;
1031 h->current = w;
1032 (*w->widget->callback)(h, h->current->widget, WIDGET_DRAW, 0);
1033 h->current = save;
1036 /* Returns the index of h->current from h->first */
1037 int dlg_item_number (Dlg_head *h)
1039 Widget_Item *p;
1040 int i = 0;
1042 p = h->first;
1044 do {
1045 if (p == h->current)
1046 return i;
1047 i++;
1048 p = p->next;
1049 } while (p != h->first);
1050 fprintf (stderr, "Internal error: current not in dialog list\n\r");
1051 exit (1);
1054 int dlg_select_nth_widget (Dlg_head *h, int n)
1056 Widget_Item *w;
1057 int i;
1059 w = h->first;
1060 for (i = 0; i < n; i++)
1061 w = w->next;
1063 return dlg_select_widget (h, w->widget);
1066 #ifndef HAVE_X
1067 void
1068 x_set_dialog_title (Dlg_head *h, const char *title)
1070 h->title = g_strdup (title);
1072 #endif /* !HAVE_X */