2 * $Id: timebox.c,v 1.54 2013/03/17 15:03:41 tom Exp $
4 * timebox.c -- implements the timebox dialog
6 * Copyright 2001-2012,2013 Thomas E. Dickey
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License, version 2.1
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to
19 * Free Software Foundation, Inc.
20 * 51 Franklin St., Fifth Floor
21 * Boston, MA 02110, USA.
33 #define MIN_HIGH (ONE_HIGH + BTN_HIGH + (4 * MARGIN))
34 #define MIN_WIDE ((3 * (ONE_WIDE + 2 * MARGIN)) + 2 + (2 * MARGIN))
56 next_or_previous(int key
)
74 * Draw the hour-of-month selection box
80 dlg_draw_box(data
->parent
,
81 data
->y
- MARGIN
, data
->x
- MARGIN
,
82 data
->height
+ (2 * MARGIN
), data
->width
+ (2 * MARGIN
),
83 menubox_border_attr
, menubox_border2_attr
);
85 (void) wattrset(data
->window
, item_attr
);
86 wprintw(data
->window
, "%02d", data
->value
);
91 init_object(BOX
* data
,
94 int width
, int height
,
95 int period
, int value
,
100 data
->parent
= parent
;
104 data
->height
= height
;
105 data
->period
= period
;
106 data
->value
= value
% period
;
108 data
->window
= derwin(data
->parent
,
109 data
->height
, data
->width
,
111 if (data
->window
== 0)
113 (void) keypad(data
->window
, TRUE
);
115 dlg_mouse_setbase(getbegx(parent
), getbegy(parent
));
116 dlg_mouse_mkregion(y
, x
, height
, width
, code
);
122 CleanupResult(int code
, WINDOW
*dialog
, char *prompt
, DIALOG_VARS
* save_vars
)
124 dlg_del_window(dialog
);
125 dlg_mouse_free_regions();
127 dlg_restore_vars(save_vars
);
132 #define DrawObject(data) draw_cell(data)
135 * Display a dialog box for entering a date
138 dialog_timebox(const char *title
,
139 const char *subtitle
,
147 static DLG_KEYS_BINDING binding
[] = {
148 DLG_KEYS_DATA( DLGK_DELETE_RIGHT
,KEY_DC
),
151 DLG_KEYS_DATA( DLGK_ENTER
, ' ' ),
152 DLG_KEYS_DATA( DLGK_FIELD_FIRST
,KEY_HOME
),
153 DLG_KEYS_DATA( DLGK_FIELD_LAST
, KEY_END
),
154 DLG_KEYS_DATA( DLGK_FIELD_LAST
, KEY_LL
),
155 DLG_KEYS_DATA( DLGK_FIELD_NEXT
, CHR_NEXT
),
156 DLG_KEYS_DATA( DLGK_FIELD_NEXT
, KEY_RIGHT
),
157 DLG_KEYS_DATA( DLGK_FIELD_NEXT
, TAB
),
158 DLG_KEYS_DATA( DLGK_FIELD_PREV
, CHR_BACKSPACE
),
159 DLG_KEYS_DATA( DLGK_FIELD_PREV
, CHR_PREVIOUS
),
160 DLG_KEYS_DATA( DLGK_FIELD_PREV
, KEY_BTAB
),
161 DLG_KEYS_DATA( DLGK_FIELD_PREV
, KEY_LEFT
),
162 DLG_KEYS_DATA( DLGK_ITEM_NEXT
, '+'),
163 DLG_KEYS_DATA( DLGK_ITEM_NEXT
, KEY_DOWN
),
164 DLG_KEYS_DATA( DLGK_ITEM_NEXT
, KEY_NEXT
),
165 DLG_KEYS_DATA( DLGK_ITEM_NEXT
, KEY_NPAGE
),
166 DLG_KEYS_DATA( DLGK_ITEM_PREV
, '-' ),
167 DLG_KEYS_DATA( DLGK_ITEM_PREV
, KEY_PPAGE
),
168 DLG_KEYS_DATA( DLGK_ITEM_PREV
, KEY_PREVIOUS
),
169 DLG_KEYS_DATA( DLGK_ITEM_PREV
, KEY_UP
),
175 int old_height
= height
;
176 int old_width
= width
;
178 BOX hr_box
, mn_box
, sc_box
;
179 int key
= 0, key2
, fkey
;
181 int result
= DLG_EXIT_UNKNOWN
;
183 time_t now_time
= time((time_t *) 0);
185 int state
= dlg_default_button();
186 const char **buttons
= dlg_ok_labels();
187 char *prompt
= dlg_strclone(subtitle
);
188 char buffer
[MAX_LEN
];
189 DIALOG_VARS save_vars
;
191 now_time
= time((time_t *) 0);
192 current
= *localtime(&now_time
);
194 dlg_save_vars(&save_vars
);
195 dialog_vars
.separate_output
= TRUE
;
203 dlg_auto_size(title
, prompt
, &height
, &width
, 0, 0);
205 if (width
< MIN_WIDE
)
207 dlg_button_layout(buttons
, &width
);
208 dlg_print_size(height
, width
);
209 dlg_ctl_size(height
, width
);
211 dialog
= dlg_new_window(height
, width
,
212 dlg_box_y_ordinate(height
),
213 dlg_box_x_ordinate(width
));
215 if (hour
>= 24 || minute
>= 60 || second
>= 60) {
216 return CleanupResult(DLG_EXIT_ERROR
, dialog
, prompt
, &save_vars
);
219 dlg_register_window(dialog
, "timebox", binding
);
220 dlg_register_buttons(dialog
, "timebox", buttons
);
222 dlg_draw_box2(dialog
, 0, 0, height
, width
, dialog_attr
, border_attr
, border2_attr
);
223 dlg_draw_bottom_box2(dialog
, border_attr
, border2_attr
, dialog_attr
);
224 dlg_draw_title(dialog
, title
);
225 dlg_draw_helpline(dialog
, FALSE
);
227 (void) wattrset(dialog
, dialog_attr
);
228 dlg_print_autowrap(dialog
, prompt
, height
, width
);
230 /* compute positions of hour, month and year boxes */
231 memset(&hr_box
, 0, sizeof(hr_box
));
232 memset(&mn_box
, 0, sizeof(mn_box
));
233 memset(&sc_box
, 0, sizeof(sc_box
));
235 if (init_object(&hr_box
,
237 (width
- MIN_WIDE
+ 1) / 2 + MARGIN
,
238 (height
- MIN_HIGH
+ MARGIN
),
242 hour
>= 0 ? hour
: current
.tm_hour
,
244 || DrawObject(&hr_box
) < 0) {
245 return CleanupResult(DLG_EXIT_ERROR
, dialog
, prompt
, &save_vars
);
248 mvwprintw(dialog
, hr_box
.y
, hr_box
.x
+ ONE_WIDE
+ MARGIN
, ":");
249 if (init_object(&mn_box
,
251 hr_box
.x
+ (ONE_WIDE
+ 2 * MARGIN
+ 1),
256 minute
>= 0 ? minute
: current
.tm_min
,
258 || DrawObject(&mn_box
) < 0) {
259 return CleanupResult(DLG_EXIT_ERROR
, dialog
, prompt
, &save_vars
);
262 mvwprintw(dialog
, mn_box
.y
, mn_box
.x
+ ONE_WIDE
+ MARGIN
, ":");
263 if (init_object(&sc_box
,
265 mn_box
.x
+ (ONE_WIDE
+ 2 * MARGIN
+ 1),
270 second
>= 0 ? second
: current
.tm_sec
,
272 || DrawObject(&sc_box
) < 0) {
273 return CleanupResult(DLG_EXIT_ERROR
, dialog
, prompt
, &save_vars
);
276 dlg_trace_win(dialog
);
277 while (result
== DLG_EXIT_UNKNOWN
) {
278 BOX
*obj
= (state
== sHR
? &hr_box
279 : (state
== sMN
? &mn_box
:
280 (state
== sSC
? &sc_box
: 0)));
282 button
= (state
< 0) ? 0 : state
;
283 dlg_draw_buttons(dialog
, height
- 2, 0, buttons
, button
, FALSE
, width
);
285 dlg_set_focus(dialog
, obj
->window
);
287 key
= dlg_mouse_wgetch(dialog
, &fkey
);
288 if (dlg_result_key(key
, fkey
, &result
))
291 if ((key2
= dlg_char_to_button(key
, buttons
)) >= 0) {
294 /* handle function-keys */
297 case DLGK_MOUSE('H'):
300 case DLGK_MOUSE('M'):
303 case DLGK_MOUSE('S'):
307 result
= dlg_ok_buttoncode(button
);
309 case DLGK_FIELD_PREV
:
310 state
= dlg_prev_ok_buttonindex(state
, sHR
);
312 case DLGK_FIELD_NEXT
:
313 state
= dlg_next_ok_buttonindex(state
, sHR
);
315 case DLGK_FIELD_FIRST
:
318 (void) DrawObject(obj
);
321 case DLGK_FIELD_LAST
:
332 (void) DrawObject(obj
);
335 case DLGK_DELETE_RIGHT
:
338 (void) DrawObject(obj
);
347 minute
= mn_box
.value
;
348 second
= sc_box
.value
;
351 dlg_del_window(dialog
);
353 dlg_mouse_free_regions();
357 if (is_DLGK_MOUSE(key
)) {
358 result
= dlg_ok_buttoncode(key
- M_EVENT
);
360 result
= DLG_EXIT_OK
;
361 } else if (obj
!= 0) {
362 int step
= next_or_previous(key
);
365 while (obj
->value
< 0)
366 obj
->value
+= obj
->period
;
367 obj
->value
%= obj
->period
;
368 (void) DrawObject(obj
);
373 } else if (isdigit(key
)) {
375 int digit
= (key
- '0');
376 int value
= (obj
->value
* 10) + digit
;
377 if (value
< obj
->period
) {
379 (void) DrawObject(obj
);
390 #define DefaultFormat(dst, src) \
391 sprintf(dst, "%02d:%02d:%02d", \
392 hr_box.value, mn_box.value, sc_box.value)
394 #if defined(HAVE_STRFTIME)
395 if (dialog_vars
.time_format
!= 0) {
397 time_t now
= time((time_t *) 0);
398 struct tm
*parts
= localtime(&now
);
400 parts
->tm_sec
= sc_box
.value
;
401 parts
->tm_min
= mn_box
.value
;
402 parts
->tm_hour
= hr_box
.value
;
403 used
= strftime(buffer
,
405 dialog_vars
.time_format
,
407 if (used
== 0 || *buffer
== '\0')
408 DefaultFormat(buffer
, hr_box
);
411 DefaultFormat(buffer
, hr_box
);
413 dlg_add_result(buffer
);
415 dlg_add_last_key(-1);
417 return CleanupResult(result
, dialog
, prompt
, &save_vars
);