2 Widget based utility functions.
4 Copyright (C) 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
5 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
6 The Free Software Foundation, Inc.
9 Miguel de Icaza, 1994, 1995, 1996
10 Radek Doulik, 1994, 1995
12 Andrej Borsenkow, 1995
13 Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2011, 2012
15 This file is part of the Midnight Commander.
17 The Midnight Commander is free software: you can redistribute it
18 and/or modify it under the terms of the GNU General Public License as
19 published by the Free Software Foundation, either version 3 of the License,
20 or (at your option) any later version.
22 The Midnight Commander is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 * \brief Source: quick dialog engine
38 #include <stdio.h> /* fprintf() */
40 #include "lib/global.h"
41 #include "lib/strutil.h" /* str_term_width1() */
42 #include "lib/util.h" /* tilde_expand() */
43 #include "lib/widget.h"
45 /*** global variables ****************************************************************************/
47 /*** file scope macro definitions ****************************************************************/
50 #define I18N(x) (x = x != NULL && *x != '\0' ? _(x) : x)
52 #define I18N(x) (x = x)
55 /*** file scope type declarations ****************************************************************/
60 quick_widget_t
*quick_widget
;
61 } quick_widget_item_t
;
63 /*** file scope variables ************************************************************************/
65 /* --------------------------------------------------------------------------------------------- */
66 /*** file scope functions ************************************************************************/
67 /* --------------------------------------------------------------------------------------------- */
70 quick_create_input (int y
, int x
, const quick_widget_t
* qw
)
74 in
= input_new (y
, x
, input_get_default_colors (), 8, qw
->u
.input
.text
, qw
->u
.input
.histname
,
75 INPUT_COMPLETE_DEFAULT
);
76 in
->is_password
= (qw
->u
.input
.flags
== 1);
77 if ((qw
->u
.input
.flags
& 2) != 0)
78 in
->completion_flags
|= INPUT_COMPLETE_CD
;
79 if ((qw
->u
.input
.flags
& 4) != 0)
80 in
->strip_password
= TRUE
;
85 /* --------------------------------------------------------------------------------------------- */
88 quick_create_labeled_input (GArray
* widgets
, int *y
, int x
, quick_widget_t
* quick_widget
,
91 quick_widget_item_t in
, label
;
93 label
.quick_widget
= g_new0 (quick_widget_t
, 1);
94 label
.quick_widget
->widget_type
= quick_label
;
95 label
.quick_widget
->options
= quick_widget
->options
;
96 /* FIXME: this should be turned in depend of label_location */
97 label
.quick_widget
->pos_flags
= quick_widget
->pos_flags
;
99 switch (quick_widget
->u
.input
.label_location
)
101 case input_label_above
:
102 label
.widget
= WIDGET (label_new (*y
, x
, I18N (quick_widget
->u
.input
.label_text
)));
103 *y
+= label
.widget
->lines
- 1;
104 g_array_append_val (widgets
, label
);
106 in
.widget
= WIDGET (quick_create_input (++(*y
), x
, quick_widget
));
107 in
.quick_widget
= quick_widget
;
108 g_array_append_val (widgets
, in
);
110 *width
= max (label
.widget
->cols
, in
.widget
->cols
);
113 case input_label_left
:
114 label
.widget
= WIDGET (label_new (*y
, x
, I18N (quick_widget
->u
.input
.label_text
)));
115 g_array_append_val (widgets
, label
);
117 in
.widget
= WIDGET (quick_create_input (*y
, x
+ label
.widget
->cols
+ 1, quick_widget
));
118 in
.quick_widget
= quick_widget
;
119 g_array_append_val (widgets
, in
);
121 *width
= label
.widget
->cols
+ in
.widget
->cols
+ 1;
124 case input_label_right
:
125 in
.widget
= WIDGET (quick_create_input (*y
, x
, quick_widget
));
126 in
.quick_widget
= quick_widget
;
127 g_array_append_val (widgets
, in
);
131 (*y
, x
+ in
.widget
->cols
+ 1, I18N (quick_widget
->u
.input
.label_text
)));
132 g_array_append_val (widgets
, label
);
134 *width
= label
.widget
->cols
+ in
.widget
->cols
+ 1;
137 case input_label_below
:
138 in
.widget
= WIDGET (quick_create_input (*y
, x
, quick_widget
));
139 in
.quick_widget
= quick_widget
;
140 g_array_append_val (widgets
, in
);
142 label
.widget
= WIDGET (label_new (++(*y
), x
, I18N (quick_widget
->u
.input
.label_text
)));
143 *y
+= label
.widget
->lines
- 1;
144 g_array_append_val (widgets
, label
);
146 *width
= max (label
.widget
->cols
, in
.widget
->cols
);
153 INPUT (in
.widget
)->label
= LABEL (label
.widget
);
154 /* cross references */
155 label
.quick_widget
->u
.label
.input
= in
.quick_widget
;
156 in
.quick_widget
->u
.input
.label
= label
.quick_widget
;
159 /* --------------------------------------------------------------------------------------------- */
160 /*** public functions ****************************************************************************/
161 /* --------------------------------------------------------------------------------------------- */
164 quick_dialog_skip (quick_dialog_t
* quick_dlg
, int nskip
)
168 int x
, y
; /* current positions */
169 int y1
= 0; /* bottom of 1st column in case of two columns */
170 int y2
= -1; /* start of two columns */
171 int width1
= 0; /* width of single column */
172 int width2
= 0; /* width of each of two columns */
173 gboolean have_groupbox
= FALSE
;
174 gboolean two_columns
= FALSE
;
175 gboolean put_buttons
= FALSE
;
177 /* x position of 1st column is 3 */
179 /* x position of 2nd column is 4 and it will be fixed later, after creation of all widgets */
184 quick_widget_t
*quick_widget
;
189 len
= str_term_width1 (I18N (quick_dlg
->title
)) + 6;
190 quick_dlg
->cols
= max (quick_dlg
->cols
, len
);
196 widgets
= g_array_sized_new (FALSE
, FALSE
, sizeof (quick_widget_item_t
), 8);
198 for (quick_widget
= quick_dlg
->widgets
; quick_widget
->widget_type
!= quick_end
; quick_widget
++)
200 quick_widget_item_t item
= { NULL
, quick_widget
};
203 switch (quick_widget
->widget_type
)
208 (++y
, x
, *quick_widget
->u
.checkbox
.state
,
209 I18N (quick_widget
->u
.checkbox
.text
)));
210 g_array_append_val (widgets
, item
);
211 width
= item
.widget
->cols
;
215 width2
= max (width2
, width
);
217 width1
= max (width1
, width
);
222 item
.widget
= WIDGET (button_new (++y
, x
, quick_widget
->u
.button
.action
,
223 quick_widget
->u
.button
.action
== B_ENTER
?
224 DEFPUSH_BUTTON
: NORMAL_BUTTON
,
225 I18N (quick_widget
->u
.button
.text
),
226 quick_widget
->u
.button
.callback
));
227 g_array_append_val (widgets
, item
);
228 width
= item
.widget
->cols
;
232 width2
= max (width2
, width
);
234 width1
= max (width1
, width
);
238 *quick_widget
->u
.input
.result
= NULL
;
240 if (quick_widget
->u
.input
.label_location
!= input_label_none
)
241 quick_create_labeled_input (widgets
, &y
, x
, quick_widget
, &width
);
244 item
.widget
= WIDGET (quick_create_input (y
, x
, quick_widget
));
245 g_array_append_val (widgets
, item
);
246 width
= item
.widget
->cols
;
251 width2
= max (width2
, width
);
253 width1
= max (width1
, width
);
257 item
.widget
= WIDGET (label_new (++y
, x
, I18N (quick_widget
->u
.label
.text
)));
258 g_array_append_val (widgets
, item
);
259 y
+= item
.widget
->lines
- 1;
260 width
= item
.widget
->cols
;
264 width2
= max (width2
, width
);
266 width1
= max (width1
, width
);
274 /* create the copy of radio_items to avoid mwmory leak */
275 items
= g_new (char *, quick_widget
->u
.radio
.count
+ 1);
276 for (i
= 0; i
< (size_t) quick_widget
->u
.radio
.count
; i
++)
277 items
[i
] = g_strdup (_(quick_widget
->u
.radio
.items
[i
]));
280 r
= radio_new (++y
, x
, quick_widget
->u
.radio
.count
, (const char **) items
);
281 r
->pos
= r
->sel
= *quick_widget
->u
.radio
.value
;
283 item
.widget
= WIDGET (r
);
284 g_array_append_val (widgets
, item
);
285 y
+= item
.widget
->lines
- 1;
286 width
= item
.widget
->cols
;
290 width2
= max (width2
, width
);
292 width1
= max (width1
, width
);
296 case quick_start_groupbox
:
297 I18N (quick_widget
->u
.groupbox
.title
);
298 len
= str_term_width1 (quick_widget
->u
.groupbox
.title
);
299 g
= groupbox_new (++y
, x
, 1, len
+ 4, quick_widget
->u
.groupbox
.title
);
300 item
.widget
= WIDGET (g
);
301 g_array_append_val (widgets
, item
);
302 have_groupbox
= TRUE
;
305 case quick_stop_groupbox
:
308 Widget
*w
= WIDGET (g
);
311 w
->lines
= y
+ 1 - w
->y
;
314 g_array_append_val (widgets
, item
);
318 case quick_separator
:
320 if (quick_widget
->u
.separator
.line
)
322 item
.widget
= WIDGET (hline_new (y
, x
, 1));
323 g_array_append_val (widgets
, item
);
327 case quick_start_columns
:
329 g_array_append_val (widgets
, item
);
333 case quick_next_column
:
339 case quick_stop_columns
:
342 g_array_append_val (widgets
, item
);
347 /* start put several buttons in bottom line */
348 if (quick_widget
->u
.separator
.space
)
352 if (quick_widget
->u
.separator
.line
)
353 item
.widget
= WIDGET (hline_new (y
, 1, -1));
356 g_array_append_val (widgets
, item
);
358 /* several buttons in bottom line */
361 for (; quick_widget
->widget_type
== quick_button
; quick_widget
++)
363 item
.widget
= WIDGET (button_new (y
, x
++, quick_widget
->u
.button
.action
,
364 quick_widget
->u
.button
.action
== B_ENTER
?
365 DEFPUSH_BUTTON
: NORMAL_BUTTON
,
366 I18N (quick_widget
->u
.button
.text
),
367 quick_widget
->u
.button
.callback
));
368 item
.quick_widget
= quick_widget
;
369 g_array_append_val (widgets
, item
);
370 blen
+= item
.widget
->cols
+ 1;
373 /* stop dialog build here */
375 quick_widget
->widget_type
= quick_end
;
384 /* adjust dialog width */
385 quick_dlg
->cols
= max (quick_dlg
->cols
, blen
+ 6);
397 len
= width2
* 2 + 7;
399 len
= max (len
, width1
+ 6);
402 quick_dlg
->cols
= max (quick_dlg
->cols
, len
);
403 width1
= quick_dlg
->cols
- 6;
404 width2
= (quick_dlg
->cols
- 7) / 2;
406 if (quick_dlg
->x
== -1 || quick_dlg
->y
== -1)
407 dd
= create_dlg (TRUE
, 0, 0, y
+ 3, quick_dlg
->cols
,
408 dialog_colors
, quick_dlg
->callback
, quick_dlg
->mouse
, quick_dlg
->help
,
409 quick_dlg
->title
, DLG_CENTER
| DLG_TRYUP
);
411 dd
= create_dlg (TRUE
, quick_dlg
->y
, quick_dlg
->x
, y
+ 3, quick_dlg
->cols
,
412 dialog_colors
, quick_dlg
->callback
, quick_dlg
->mouse
, quick_dlg
->help
,
413 quick_dlg
->title
, DLG_NONE
);
415 /* add widgets into the dialog */
416 x2
= x1
+ width2
+ 1;
419 x
= (WIDGET (dd
)->cols
- blen
) / 2;
421 for (i
= 0; i
< widgets
->len
; i
++)
423 quick_widget_item_t
*item
;
426 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
427 column_width
= two_columns
? width2
: width1
;
429 /* adjust widget width and x position */
430 switch (item
->quick_widget
->widget_type
)
434 quick_widget_t
*input
= item
->quick_widget
->u
.label
.input
;
436 if (input
!= NULL
&& input
->u
.input
.label_location
== input_label_right
)
438 /* location of this label will be adjusted later */
445 if (item
->widget
->x
!= x1
)
446 item
->widget
->x
= x2
;
448 item
->widget
->x
+= 2;
454 if (item
->widget
->x
!= x1
)
455 item
->widget
->x
= x2
;
457 item
->widget
->x
+= 2;
462 x
+= item
->widget
->cols
+ 1;
468 Widget
*label
= WIDGET (INPUT (item
->widget
)->label
);
469 int width
= column_width
;
474 switch (item
->quick_widget
->u
.input
.label_location
)
476 case input_label_left
:
477 /* label was adjusted before; adjust input line */
478 item
->widget
->x
= label
->x
+ label
->cols
+ 1 - WIDGET (label
->owner
)->x
;
479 item
->widget
->cols
= width
- label
->cols
- 1;
482 case input_label_right
:
484 item
->widget
->x
+ item
->widget
->cols
+ 1 - WIDGET (item
->widget
->owner
)->x
;
485 item
->widget
->cols
= width
- label
->cols
- 1;
489 if (item
->widget
->x
!= x1
)
490 item
->widget
->x
= x2
;
492 item
->widget
->x
+= 2;
493 item
->widget
->cols
= width
;
497 /* forced update internal variables of inpuit line */
498 input_set_origin (INPUT (item
->widget
), item
->widget
->x
, item
->widget
->cols
);
502 case quick_start_groupbox
:
503 g
= GROUPBOX (item
->widget
);
504 if (item
->widget
->x
!= x1
)
505 item
->widget
->x
= x2
;
506 item
->widget
->cols
= column_width
;
509 case quick_stop_groupbox
:
513 case quick_separator
:
514 if (item
->widget
!= NULL
)
518 Widget
*wg
= WIDGET (g
);
520 HLINE (item
->widget
)->auto_adjust_cols
= FALSE
;
521 item
->widget
->x
= wg
->x
+ 1 - WIDGET (wg
->owner
)->x
;
522 item
->widget
->cols
= wg
->cols
;
524 else if (two_columns
)
526 HLINE (item
->widget
)->auto_adjust_cols
= FALSE
;
527 if (item
->widget
->x
!= x1
)
528 item
->widget
->x
= x2
;
530 item
->widget
->cols
= column_width
+ 2;
533 HLINE (item
->widget
)->auto_adjust_cols
= TRUE
;
537 case quick_start_columns
:
541 case quick_stop_columns
:
546 /* several buttons in bottom line */
554 if (item
->widget
!= NULL
)
558 /* add widget into dialog */
559 item
->widget
->options
|= item
->quick_widget
->options
; /* FIXME: cannot reset flags, setup only */
560 id
= add_widget_autopos (dd
, item
->widget
, item
->quick_widget
->pos_flags
, NULL
);
561 if (item
->quick_widget
->id
!= NULL
)
562 *item
->quick_widget
->id
= id
;
568 dd
->current
= g_list_next (dd
->current
);
569 if (dd
->current
== NULL
)
570 dd
->current
= dd
->widgets
;
573 return_val
= run_dlg (dd
);
575 /* Get the data if we found something interesting */
576 if (return_val
!= B_CANCEL
)
577 for (i
= 0; i
< widgets
->len
; i
++)
579 quick_widget_item_t
*item
;
581 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
583 switch (item
->quick_widget
->widget_type
)
586 *item
->quick_widget
->u
.checkbox
.state
= CHECK (item
->widget
)->state
& C_BOOL
;
590 if ((quick_widget
->u
.input
.flags
& 2) != 0)
591 *item
->quick_widget
->u
.input
.result
=
592 tilde_expand (INPUT (item
->widget
)->buffer
);
594 *item
->quick_widget
->u
.input
.result
= g_strdup (INPUT (item
->widget
)->buffer
);
598 *item
->quick_widget
->u
.radio
.value
= RADIO (item
->widget
)->sel
;
608 /* destroy input labels created before */
609 for (i
= 0; i
< widgets
->len
; i
++)
611 quick_widget_item_t
*item
;
613 item
= &g_array_index (widgets
, quick_widget_item_t
, i
);
614 if (item
->quick_widget
->widget_type
== quick_input
)
615 g_free (item
->quick_widget
->u
.input
.label
);
618 g_array_free (widgets
, TRUE
);
623 /* --------------------------------------------------------------------------------------------- */