xref: /freebsd-src/contrib/bsddialog/lib/timebox.c (revision 263660c061ac76d449cbca7bdd0db2ecdfad76d9)
1c76f0793SBaptiste Daroussin /*-
2c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3c76f0793SBaptiste Daroussin  *
4*263660c0SAlfonso Siciliano  * Copyright (c) 2021-2022 Alfonso Sabato Siciliano
5c76f0793SBaptiste Daroussin  *
6c76f0793SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7c76f0793SBaptiste Daroussin  * modification, are permitted provided that the following conditions
8c76f0793SBaptiste Daroussin  * are met:
9c76f0793SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11c76f0793SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12c76f0793SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13c76f0793SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14c76f0793SBaptiste Daroussin  *
15c76f0793SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c76f0793SBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c76f0793SBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c76f0793SBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c76f0793SBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c76f0793SBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c76f0793SBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c76f0793SBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c76f0793SBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c76f0793SBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c76f0793SBaptiste Daroussin  * SUCH DAMAGE.
26c76f0793SBaptiste Daroussin  */
27c76f0793SBaptiste Daroussin 
28f499134dSBaptiste Daroussin #include <sys/param.h>
29f499134dSBaptiste Daroussin 
30d93b4d32SBaptiste Daroussin #include <ctype.h>
31*263660c0SAlfonso Siciliano #include <curses.h>
32f499134dSBaptiste Daroussin #include <string.h>
33f499134dSBaptiste Daroussin 
34c76f0793SBaptiste Daroussin #include "bsddialog.h"
35f499134dSBaptiste Daroussin #include "bsddialog_theme.h"
36*263660c0SAlfonso Siciliano #include "lib_util.h"
37c76f0793SBaptiste Daroussin 
38*263660c0SAlfonso Siciliano #define MINWDATE   23 /* 3 windows and their borders */
39*263660c0SAlfonso Siciliano #define MINWTIME   14 /* 3 windows and their borders */
40f499134dSBaptiste Daroussin 
41f499134dSBaptiste Daroussin extern struct bsddialog_theme t;
42f499134dSBaptiste Daroussin 
43f499134dSBaptiste Daroussin static int
44f499134dSBaptiste Daroussin datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
45*263660c0SAlfonso Siciliano     int *w, int minw, const char *text, struct buttons bs)
46f499134dSBaptiste Daroussin {
47*263660c0SAlfonso Siciliano 	int htext, wtext;
48f499134dSBaptiste Daroussin 
49*263660c0SAlfonso Siciliano 	if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
50*263660c0SAlfonso Siciliano 		if (text_size(conf, rows, cols, text, &bs, 3, minw, &htext,
51*263660c0SAlfonso Siciliano 		    &wtext) != 0)
52*263660c0SAlfonso Siciliano 			return (BSDDIALOG_ERROR);
53f499134dSBaptiste Daroussin 	}
54f499134dSBaptiste Daroussin 
55*263660c0SAlfonso Siciliano 	if (cols == BSDDIALOG_AUTOSIZE)
56*263660c0SAlfonso Siciliano 		*w = widget_min_width(conf, htext,minw, &bs);
57f499134dSBaptiste Daroussin 
58*263660c0SAlfonso Siciliano 	if (rows == BSDDIALOG_AUTOSIZE)
59*263660c0SAlfonso Siciliano 		*h = widget_min_height(conf, htext, 3 /* windows */, true);
60*263660c0SAlfonso Siciliano 
61*263660c0SAlfonso Siciliano 	return (0);
62f499134dSBaptiste Daroussin }
63f499134dSBaptiste Daroussin 
64f499134dSBaptiste Daroussin static int
65*263660c0SAlfonso Siciliano datetime_checksize(int rows, int cols, int minw, struct buttons bs)
66f499134dSBaptiste Daroussin {
67f499134dSBaptiste Daroussin 	int mincols;
68f499134dSBaptiste Daroussin 
69f499134dSBaptiste Daroussin 	mincols = VBORDERS;
70f499134dSBaptiste Daroussin 	mincols += bs.nbuttons * bs.sizebutton;
71f499134dSBaptiste Daroussin 	mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
72f499134dSBaptiste Daroussin 	mincols = MAX(minw, mincols);
73f499134dSBaptiste Daroussin 
74f499134dSBaptiste Daroussin 	if (cols < mincols)
75f499134dSBaptiste Daroussin 		RETURN_ERROR("Few cols for this timebox/datebox");
76f499134dSBaptiste Daroussin 
77*263660c0SAlfonso Siciliano 	if (rows < 7) /* 2 button + 2 borders + 3 windows */
78*263660c0SAlfonso Siciliano 		RETURN_ERROR("Few rows for this timebox/datebox, at least 7");
79f499134dSBaptiste Daroussin 
80*263660c0SAlfonso Siciliano 	return (0);
81f499134dSBaptiste Daroussin }
82f499134dSBaptiste Daroussin 
83*263660c0SAlfonso Siciliano int
84*263660c0SAlfonso Siciliano bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
85*263660c0SAlfonso Siciliano     int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss)
86c76f0793SBaptiste Daroussin {
87f499134dSBaptiste Daroussin 	bool loop;
88*263660c0SAlfonso Siciliano 	int i, input, output, y, x, h, w, sel;
89*263660c0SAlfonso Siciliano 	WINDOW *widget, *textpad, *shadow;
90*263660c0SAlfonso Siciliano 	struct buttons bs;
91c76f0793SBaptiste Daroussin 	struct myclockstruct {
92c76f0793SBaptiste Daroussin 		unsigned int max;
93f499134dSBaptiste Daroussin 		unsigned int value;
94c76f0793SBaptiste Daroussin 		WINDOW *win;
95f499134dSBaptiste Daroussin 	};
96c76f0793SBaptiste Daroussin 
97f499134dSBaptiste Daroussin 	if (hh == NULL || mm == NULL || ss == NULL)
98f499134dSBaptiste Daroussin 		RETURN_ERROR("hh / mm / ss cannot be NULL");
99c76f0793SBaptiste Daroussin 
100f499134dSBaptiste Daroussin 	struct myclockstruct c[3] = {
101f499134dSBaptiste Daroussin 		{23, *hh, NULL},
102f499134dSBaptiste Daroussin 		{59, *mm, NULL},
103f499134dSBaptiste Daroussin 		{59, *ss, NULL}
104f499134dSBaptiste Daroussin 	};
105f499134dSBaptiste Daroussin 
106f499134dSBaptiste Daroussin 	for (i = 0 ; i < 3; i++) {
107f499134dSBaptiste Daroussin 		if (c[i].value > c[i].max)
108f499134dSBaptiste Daroussin 			c[i].value = c[i].max;
109f499134dSBaptiste Daroussin 	}
110c76f0793SBaptiste Daroussin 
111*263660c0SAlfonso Siciliano 	get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
112c76f0793SBaptiste Daroussin 
113f499134dSBaptiste Daroussin 	if (set_widget_size(conf, rows, cols, &h, &w) != 0)
114*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
115*263660c0SAlfonso Siciliano 	if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text,
116*263660c0SAlfonso Siciliano 	    bs) != 0)
117*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
118*263660c0SAlfonso Siciliano 	if (datetime_checksize(h, w, MINWTIME, bs) != 0)
119*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
120f499134dSBaptiste Daroussin 	if (set_widget_position(conf, &y, &x, h, w) != 0)
121*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
122f499134dSBaptiste Daroussin 
123*263660c0SAlfonso Siciliano 	if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
124*263660c0SAlfonso Siciliano 	    true) != 0)
125*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
126f499134dSBaptiste Daroussin 
127*263660c0SAlfonso Siciliano 	pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
128*263660c0SAlfonso Siciliano 	doupdate();
129f499134dSBaptiste Daroussin 
130f499134dSBaptiste Daroussin 	c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 7, 3, 4, LOWERED);
131f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 - 3, ':');
132f499134dSBaptiste Daroussin 	c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 2, 3, 4, LOWERED);
133f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 + 2, ':');
134f499134dSBaptiste Daroussin 	c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 3, 3, 4, LOWERED);
135f499134dSBaptiste Daroussin 
136f499134dSBaptiste Daroussin 	wrefresh(widget);
137f499134dSBaptiste Daroussin 
138c76f0793SBaptiste Daroussin 	sel = 0;
139c76f0793SBaptiste Daroussin 	curs_set(2);
140f499134dSBaptiste Daroussin 	loop = true;
141c76f0793SBaptiste Daroussin 	while (loop) {
142c76f0793SBaptiste Daroussin 		for (i = 0; i < 3; i++) {
143f499134dSBaptiste Daroussin 			mvwprintw(c[i].win, 1, 1, "%2d", c[i].value);
144c76f0793SBaptiste Daroussin 			wrefresh(c[i].win);
145c76f0793SBaptiste Daroussin 		}
146c76f0793SBaptiste Daroussin 		wmove(c[sel].win, 1, 2);
147c76f0793SBaptiste Daroussin 		wrefresh(c[sel].win);
148c76f0793SBaptiste Daroussin 
149c76f0793SBaptiste Daroussin 		input = getch();
150c76f0793SBaptiste Daroussin 		switch(input) {
151f499134dSBaptiste Daroussin 		case KEY_ENTER:
152c76f0793SBaptiste Daroussin 		case 10: /* Enter */
153c76f0793SBaptiste Daroussin 			output = bs.value[bs.curr];
1548c4f4028SBaptiste Daroussin 			if (output == BSDDIALOG_OK) {
155f499134dSBaptiste Daroussin 				*hh = c[0].value;
156f499134dSBaptiste Daroussin 				*mm = c[1].value;
157f499134dSBaptiste Daroussin 				*ss = c[2].value;
158c76f0793SBaptiste Daroussin 			}
159c76f0793SBaptiste Daroussin 			loop = false;
160c76f0793SBaptiste Daroussin 			break;
161c76f0793SBaptiste Daroussin 		case 27: /* Esc */
162*263660c0SAlfonso Siciliano 			if (conf->key.enable_esc) {
163c76f0793SBaptiste Daroussin 				output = BSDDIALOG_ESC;
164c76f0793SBaptiste Daroussin 				loop = false;
165*263660c0SAlfonso Siciliano 			}
166c76f0793SBaptiste Daroussin 			break;
167c76f0793SBaptiste Daroussin 		case '\t': /* TAB */
168*263660c0SAlfonso Siciliano 			bs.curr = (bs.curr + 1) % bs.nbuttons;
169*263660c0SAlfonso Siciliano 			draw_buttons(widget, bs, true);
170*263660c0SAlfonso Siciliano 			wrefresh(widget);
171c76f0793SBaptiste Daroussin 			break;
172c76f0793SBaptiste Daroussin 		case KEY_LEFT:
173*263660c0SAlfonso Siciliano 			sel = sel == 0 ? 2 : (sel - 1);
174c76f0793SBaptiste Daroussin 			break;
175c76f0793SBaptiste Daroussin 		case KEY_RIGHT:
176*263660c0SAlfonso Siciliano 			sel = (sel + 1) % 3;
177c76f0793SBaptiste Daroussin 			break;
178c76f0793SBaptiste Daroussin 		case KEY_UP:
179*263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value < c[sel].max ?
180*263660c0SAlfonso Siciliano 			    c[sel].value + 1 : 0;
181c76f0793SBaptiste Daroussin 			break;
182c76f0793SBaptiste Daroussin 		case KEY_DOWN:
183*263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value > 0 ?
184*263660c0SAlfonso Siciliano 			    c[sel].value - 1 : c[sel].max;
185c76f0793SBaptiste Daroussin 			break;
186f499134dSBaptiste Daroussin 		case KEY_F(1):
1878c4f4028SBaptiste Daroussin 			if (conf->f1_file == NULL && conf->f1_message == NULL)
188f499134dSBaptiste Daroussin 				break;
189f499134dSBaptiste Daroussin 			curs_set(0);
190f499134dSBaptiste Daroussin 			if (f1help(conf) != 0)
191*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
192f499134dSBaptiste Daroussin 			curs_set(2);
193*263660c0SAlfonso Siciliano 			/* No break, screen size can change */
194f499134dSBaptiste Daroussin 		case KEY_RESIZE:
195*263660c0SAlfonso Siciliano 			/* Important for decreasing screen */
196f499134dSBaptiste Daroussin 			hide_widget(y, x, h, w, conf->shadow);
197f499134dSBaptiste Daroussin 			refresh();
198f499134dSBaptiste Daroussin 
199f499134dSBaptiste Daroussin 			if (set_widget_size(conf, rows, cols, &h, &w) != 0)
200*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
201*263660c0SAlfonso Siciliano 			if (datetime_autosize(conf, rows, cols, &h, &w,
202*263660c0SAlfonso Siciliano 			    MINWTIME, text, bs) != 0)
203*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
204*263660c0SAlfonso Siciliano 			if (datetime_checksize(h, w, MINWTIME, bs) != 0)
205*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
206f499134dSBaptiste Daroussin 			if (set_widget_position(conf, &y, &x, h, w) != 0)
207*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
208f499134dSBaptiste Daroussin 
209*263660c0SAlfonso Siciliano 			if (update_dialog(conf, shadow, widget, y, x, h, w,
210*263660c0SAlfonso Siciliano 			    textpad, text, &bs, true) != 0)
211*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
212f499134dSBaptiste Daroussin 
213*263660c0SAlfonso Siciliano 			doupdate();
214f499134dSBaptiste Daroussin 
215f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 - 3, ':');
216f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 + 2, ':');
217f499134dSBaptiste Daroussin 			wrefresh(widget);
218f499134dSBaptiste Daroussin 
219f499134dSBaptiste Daroussin 			prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
220f499134dSBaptiste Daroussin 
221f499134dSBaptiste Daroussin 			wclear(c[0].win);
222f499134dSBaptiste Daroussin 			mvwin(c[0].win, y + h - 6, x + w/2 - 7);
223f499134dSBaptiste Daroussin 			draw_borders(conf, c[0].win, 3, 4, LOWERED);
224f499134dSBaptiste Daroussin 			wrefresh(c[0].win);
225f499134dSBaptiste Daroussin 
226f499134dSBaptiste Daroussin 			wclear(c[1].win);
227f499134dSBaptiste Daroussin 			mvwin(c[1].win, y + h - 6, x + w/2 - 2);
228f499134dSBaptiste Daroussin 			draw_borders(conf, c[1].win, 3, 4, LOWERED);
229f499134dSBaptiste Daroussin 			wrefresh(c[1].win);
230f499134dSBaptiste Daroussin 
231f499134dSBaptiste Daroussin 			wclear(c[2].win);
232f499134dSBaptiste Daroussin 			mvwin(c[2].win, y + h - 6, x + w/2 + 3);
233f499134dSBaptiste Daroussin 			draw_borders(conf, c[2].win, 3, 4, LOWERED);
234f499134dSBaptiste Daroussin 			wrefresh(c[2].win);
235f499134dSBaptiste Daroussin 
236f499134dSBaptiste Daroussin 			/* Important to avoid grey lines expanding screen */
237f499134dSBaptiste Daroussin 			refresh();
238f499134dSBaptiste Daroussin 			break;
239f499134dSBaptiste Daroussin 		default:
240*263660c0SAlfonso Siciliano 			if (shortcut_buttons(input, &bs)) {
241*263660c0SAlfonso Siciliano 				output = bs.value[bs.curr];
242f499134dSBaptiste Daroussin 				loop = false;
243f499134dSBaptiste Daroussin 			}
244c76f0793SBaptiste Daroussin 		}
245c76f0793SBaptiste Daroussin 	}
246c76f0793SBaptiste Daroussin 
247c76f0793SBaptiste Daroussin 	curs_set(0);
248c76f0793SBaptiste Daroussin 
249c76f0793SBaptiste Daroussin 	for (i = 0; i < 3; i++)
250c76f0793SBaptiste Daroussin 		delwin(c[i].win);
251*263660c0SAlfonso Siciliano 	end_dialog(conf, shadow, widget, textpad);
252c76f0793SBaptiste Daroussin 
253*263660c0SAlfonso Siciliano 	return (output);
254c76f0793SBaptiste Daroussin }
255c76f0793SBaptiste Daroussin 
256f499134dSBaptiste Daroussin int
257*263660c0SAlfonso Siciliano bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
258*263660c0SAlfonso Siciliano     int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
259c76f0793SBaptiste Daroussin {
260f499134dSBaptiste Daroussin 	bool loop;
261*263660c0SAlfonso Siciliano 	int i, input, output, y, x, h, w, sel;
262*263660c0SAlfonso Siciliano 	WINDOW *widget, *textpad, *shadow;
263*263660c0SAlfonso Siciliano 	struct buttons bs;
264c76f0793SBaptiste Daroussin 	struct calendar {
265f499134dSBaptiste Daroussin 		int max;
266f499134dSBaptiste Daroussin 		int value;
267c76f0793SBaptiste Daroussin 		WINDOW *win;
268c76f0793SBaptiste Daroussin 		unsigned int x;
269f499134dSBaptiste Daroussin 	};
270c76f0793SBaptiste Daroussin 	struct month {
271c76f0793SBaptiste Daroussin 		char *name;
272c76f0793SBaptiste Daroussin 		unsigned int days;
273c76f0793SBaptiste Daroussin 	};
274c76f0793SBaptiste Daroussin 
275f499134dSBaptiste Daroussin 	if (yy == NULL || mm == NULL || dd == NULL)
276f499134dSBaptiste Daroussin 		RETURN_ERROR("yy / mm / dd cannot be NULL");
277c76f0793SBaptiste Daroussin 
278f499134dSBaptiste Daroussin 	struct calendar c[3] = {
279f499134dSBaptiste Daroussin 		{9999, *yy, NULL, 4 },
280f499134dSBaptiste Daroussin 		{12,   *mm, NULL, 9 },
281f499134dSBaptiste Daroussin 		{31,   *dd, NULL, 2 }
282f499134dSBaptiste Daroussin 	};
283c76f0793SBaptiste Daroussin 
284f499134dSBaptiste Daroussin 	struct month m[12] = {
285f499134dSBaptiste Daroussin 		{ "January", 31 }, { "February", 28 }, { "March",     31 },
286f499134dSBaptiste Daroussin 		{ "April",   30 }, { "May",      31 }, { "June",      30 },
287f499134dSBaptiste Daroussin 		{ "July",    31 }, { "August",   31 }, { "September", 30 },
288f499134dSBaptiste Daroussin 		{ "October", 31 }, { "November", 30 }, { "December",  31 }
289f499134dSBaptiste Daroussin 	};
290f499134dSBaptiste Daroussin 
291f499134dSBaptiste Daroussin #define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
292f499134dSBaptiste Daroussin 
293f499134dSBaptiste Daroussin 	for (i = 0 ; i < 3; i++) {
294f499134dSBaptiste Daroussin 		if (c[i].value > c[i].max)
295f499134dSBaptiste Daroussin 			c[i].value = c[i].max;
296f499134dSBaptiste Daroussin 		if (c[i].value < 1)
297f499134dSBaptiste Daroussin 			c[i].value = 1;
298f499134dSBaptiste Daroussin 	}
299f499134dSBaptiste Daroussin 	c[2].max = m[c[1].value -1].days;
300f499134dSBaptiste Daroussin 	if (c[1].value == 2 && ISLEAF(c[0].value))
301f499134dSBaptiste Daroussin 		c[2].max = 29;
302f499134dSBaptiste Daroussin 	if (c[2].value > c[2].max)
303f499134dSBaptiste Daroussin 		c[2].value = c[2].max;
304c76f0793SBaptiste Daroussin 
305*263660c0SAlfonso Siciliano 	get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
306c76f0793SBaptiste Daroussin 
307f499134dSBaptiste Daroussin 	if (set_widget_size(conf, rows, cols, &h, &w) != 0)
308*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
309*263660c0SAlfonso Siciliano 	if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text,
310*263660c0SAlfonso Siciliano 	    bs) != 0)
311*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
312*263660c0SAlfonso Siciliano 	if (datetime_checksize(h, w, MINWDATE, bs) != 0)
313*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
314f499134dSBaptiste Daroussin 	if (set_widget_position(conf, &y, &x, h, w) != 0)
315*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
316f499134dSBaptiste Daroussin 
317*263660c0SAlfonso Siciliano 	if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
318*263660c0SAlfonso Siciliano 	    true) != 0)
319*263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
320f499134dSBaptiste Daroussin 
321*263660c0SAlfonso Siciliano 	pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
322*263660c0SAlfonso Siciliano 	doupdate();
323f499134dSBaptiste Daroussin 
324f499134dSBaptiste Daroussin 	c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 11, 3, 6, LOWERED);
325f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 - 5, '/');
326f499134dSBaptiste Daroussin 	c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 4, 3, 11, LOWERED);
327f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 + 7, '/');
328f499134dSBaptiste Daroussin 	c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 8, 3, 4, LOWERED);
329f499134dSBaptiste Daroussin 
330f499134dSBaptiste Daroussin 	wrefresh(widget);
331f499134dSBaptiste Daroussin 
332c76f0793SBaptiste Daroussin 	sel = 2;
333c76f0793SBaptiste Daroussin 	curs_set(2);
334f499134dSBaptiste Daroussin 	loop = true;
335c76f0793SBaptiste Daroussin 	while (loop) {
336f499134dSBaptiste Daroussin 		mvwprintw(c[0].win, 1, 1, "%4d", c[0].value);
337f499134dSBaptiste Daroussin 		mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name);
338f499134dSBaptiste Daroussin 		mvwprintw(c[2].win, 1, 1, "%2d", c[2].value);
339c76f0793SBaptiste Daroussin 		for (i = 0; i < 3; i++) {
340c76f0793SBaptiste Daroussin 			wrefresh(c[i].win);
341c76f0793SBaptiste Daroussin 		}
342c76f0793SBaptiste Daroussin 		wmove(c[sel].win, 1, c[sel].x);
343c76f0793SBaptiste Daroussin 		wrefresh(c[sel].win);
344c76f0793SBaptiste Daroussin 
345c76f0793SBaptiste Daroussin 		input = getch();
346c76f0793SBaptiste Daroussin 		switch(input) {
347f499134dSBaptiste Daroussin 		case KEY_ENTER:
348f499134dSBaptiste Daroussin 		case 10: /* Enter */
349f499134dSBaptiste Daroussin 			output = bs.value[bs.curr];
3508c4f4028SBaptiste Daroussin 			if (output == BSDDIALOG_OK) {
351f499134dSBaptiste Daroussin 				*yy = c[0].value;
352f499134dSBaptiste Daroussin 				*mm = c[1].value;
353f499134dSBaptiste Daroussin 				*dd = c[2].value;
354c76f0793SBaptiste Daroussin 			}
355c76f0793SBaptiste Daroussin 			loop = false;
356c76f0793SBaptiste Daroussin 			break;
357f499134dSBaptiste Daroussin 		case 27: /* Esc */
358*263660c0SAlfonso Siciliano 			if (conf->key.enable_esc) {
359c76f0793SBaptiste Daroussin 				output = BSDDIALOG_ESC;
360c76f0793SBaptiste Daroussin 				loop = false;
361*263660c0SAlfonso Siciliano 			}
362c76f0793SBaptiste Daroussin 			break;
363f499134dSBaptiste Daroussin 		case '\t': /* TAB */
364*263660c0SAlfonso Siciliano 			bs.curr = (bs.curr + 1) % bs.nbuttons;
365*263660c0SAlfonso Siciliano 			draw_buttons(widget, bs, true);
366*263660c0SAlfonso Siciliano 			wrefresh(widget);
367c76f0793SBaptiste Daroussin 			break;
368c76f0793SBaptiste Daroussin 		case KEY_LEFT:
369*263660c0SAlfonso Siciliano 			sel = sel == 0 ? 2 : (sel - 1);
370c76f0793SBaptiste Daroussin 			break;
371c76f0793SBaptiste Daroussin 		case KEY_RIGHT:
372*263660c0SAlfonso Siciliano 			sel = (sel + 1) % 3;
373c76f0793SBaptiste Daroussin 			break;
374c76f0793SBaptiste Daroussin 		case KEY_UP:
375*263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value > 1 ?
376*263660c0SAlfonso Siciliano 			    c[sel].value - 1 : c[sel].max ;
377f499134dSBaptiste Daroussin 			/* if mount change */
378f499134dSBaptiste Daroussin 			c[2].max = m[c[1].value -1].days;
379f499134dSBaptiste Daroussin 			/* if year change */
380f499134dSBaptiste Daroussin 			if (c[1].value == 2 && ISLEAF(c[0].value))
381f499134dSBaptiste Daroussin 				c[2].max = 29;
382f499134dSBaptiste Daroussin 			/* set new day */
383f499134dSBaptiste Daroussin 			if (c[2].value > c[2].max)
384f499134dSBaptiste Daroussin 				c[2].value = c[2].max;
385c76f0793SBaptiste Daroussin 			break;
386c76f0793SBaptiste Daroussin 		case KEY_DOWN:
387*263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value < c[sel].max ?
388*263660c0SAlfonso Siciliano 			    c[sel].value + 1 : 1;
389f499134dSBaptiste Daroussin 			/* if mount change */
390f499134dSBaptiste Daroussin 			c[2].max = m[c[1].value -1].days;
391f499134dSBaptiste Daroussin 			/* if year change */
392f499134dSBaptiste Daroussin 			if (c[1].value == 2 && ISLEAF(c[0].value))
393f499134dSBaptiste Daroussin 				c[2].max = 29;
394f499134dSBaptiste Daroussin 			/* set new day */
395f499134dSBaptiste Daroussin 			if (c[2].value > c[2].max)
396f499134dSBaptiste Daroussin 				c[2].value = c[2].max;
397c76f0793SBaptiste Daroussin 			break;
398f499134dSBaptiste Daroussin 		case KEY_F(1):
3998c4f4028SBaptiste Daroussin 			if (conf->f1_file == NULL && conf->f1_message == NULL)
400f499134dSBaptiste Daroussin 				break;
401f499134dSBaptiste Daroussin 			curs_set(0);
402f499134dSBaptiste Daroussin 			if (f1help(conf) != 0)
403*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
404f499134dSBaptiste Daroussin 			curs_set(2);
405*263660c0SAlfonso Siciliano 			/* No break, screen size can change */
406f499134dSBaptiste Daroussin 		case KEY_RESIZE:
407*263660c0SAlfonso Siciliano 			/* Important for decreasing screen */
408f499134dSBaptiste Daroussin 			hide_widget(y, x, h, w, conf->shadow);
409f499134dSBaptiste Daroussin 			refresh();
410f499134dSBaptiste Daroussin 
411f499134dSBaptiste Daroussin 			if (set_widget_size(conf, rows, cols, &h, &w) != 0)
412*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
413*263660c0SAlfonso Siciliano 			if (datetime_autosize(conf, rows, cols, &h, &w,
414*263660c0SAlfonso Siciliano 			    MINWDATE, text, bs) != 0)
415*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
416*263660c0SAlfonso Siciliano 			if (datetime_checksize(h, w, MINWDATE, bs) != 0)
417*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
418f499134dSBaptiste Daroussin 			if (set_widget_position(conf, &y, &x, h, w) != 0)
419*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
420f499134dSBaptiste Daroussin 
421*263660c0SAlfonso Siciliano 			if (update_dialog(conf, shadow, widget, y, x, h, w,
422*263660c0SAlfonso Siciliano 			    textpad, text, &bs, true) != 0)
423*263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
424*263660c0SAlfonso Siciliano 			doupdate();
425f499134dSBaptiste Daroussin 
426f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 - 5, '/');
427f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 + 7, '/');
428f499134dSBaptiste Daroussin 			wrefresh(widget);
429f499134dSBaptiste Daroussin 
430f499134dSBaptiste Daroussin 			prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
431f499134dSBaptiste Daroussin 
432f499134dSBaptiste Daroussin 			wclear(c[0].win);
433f499134dSBaptiste Daroussin 			mvwin(c[0].win, y + h - 6, x + w/2 - 11);
434f499134dSBaptiste Daroussin 			draw_borders(conf, c[0].win, 3, 6, LOWERED);
435f499134dSBaptiste Daroussin 			wrefresh(c[0].win);
436f499134dSBaptiste Daroussin 
437f499134dSBaptiste Daroussin 			wclear(c[1].win);
438f499134dSBaptiste Daroussin 			mvwin(c[1].win, y + h - 6, x + w/2 - 4);
439f499134dSBaptiste Daroussin 			draw_borders(conf, c[1].win, 3, 11, LOWERED);
440f499134dSBaptiste Daroussin 			wrefresh(c[1].win);
441f499134dSBaptiste Daroussin 
442f499134dSBaptiste Daroussin 			wclear(c[2].win);
443f499134dSBaptiste Daroussin 			mvwin(c[2].win, y + h - 6, x + w/2 + 8);
444f499134dSBaptiste Daroussin 			draw_borders(conf, c[2].win, 3, 4, LOWERED);
445f499134dSBaptiste Daroussin 			wrefresh(c[2].win);
446f499134dSBaptiste Daroussin 
447f499134dSBaptiste Daroussin 			/* Important to avoid grey lines expanding screen */
448f499134dSBaptiste Daroussin 			refresh();
449f499134dSBaptiste Daroussin 			break;
450f499134dSBaptiste Daroussin 		default:
451*263660c0SAlfonso Siciliano 			if (shortcut_buttons(input, &bs)) {
452*263660c0SAlfonso Siciliano 				output = bs.value[bs.curr];
453f499134dSBaptiste Daroussin 				loop = false;
454f499134dSBaptiste Daroussin 			}
455c76f0793SBaptiste Daroussin 		}
456c76f0793SBaptiste Daroussin 	}
457c76f0793SBaptiste Daroussin 
458c76f0793SBaptiste Daroussin 	curs_set(0);
459c76f0793SBaptiste Daroussin 
460c76f0793SBaptiste Daroussin 	for (i = 0; i < 3; i++)
461c76f0793SBaptiste Daroussin 		delwin(c[i].win);
462*263660c0SAlfonso Siciliano 	end_dialog(conf, shadow, widget, textpad);
463c76f0793SBaptiste Daroussin 
464*263660c0SAlfonso Siciliano 	return (output);
465c76f0793SBaptiste Daroussin }