xref: /freebsd/contrib/bsddialog/lib/timebox.c (revision bce40c0242b167a541cc051b6b0dbcc5f3d04319)
1c76f0793SBaptiste Daroussin /*-
2c76f0793SBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3c76f0793SBaptiste Daroussin  *
4263660c0SAlfonso 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>
31263660c0SAlfonso Siciliano #include <curses.h>
32f499134dSBaptiste Daroussin #include <string.h>
33f499134dSBaptiste Daroussin 
34c76f0793SBaptiste Daroussin #include "bsddialog.h"
35263660c0SAlfonso Siciliano #include "lib_util.h"
36c76f0793SBaptiste Daroussin 
37263660c0SAlfonso Siciliano #define MINWDATE   23 /* 3 windows and their borders */
38263660c0SAlfonso Siciliano #define MINWTIME   14 /* 3 windows and their borders */
39f499134dSBaptiste Daroussin 
40f499134dSBaptiste Daroussin static int
41f499134dSBaptiste Daroussin datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
42263660c0SAlfonso Siciliano     int *w, int minw, const char *text, struct buttons bs)
43f499134dSBaptiste Daroussin {
44263660c0SAlfonso Siciliano 	int htext, wtext;
45f499134dSBaptiste Daroussin 
46263660c0SAlfonso Siciliano 	if (cols == BSDDIALOG_AUTOSIZE || rows == BSDDIALOG_AUTOSIZE) {
47263660c0SAlfonso Siciliano 		if (text_size(conf, rows, cols, text, &bs, 3, minw, &htext,
48263660c0SAlfonso Siciliano 		    &wtext) != 0)
49263660c0SAlfonso Siciliano 			return (BSDDIALOG_ERROR);
50f499134dSBaptiste Daroussin 	}
51f499134dSBaptiste Daroussin 
52263660c0SAlfonso Siciliano 	if (cols == BSDDIALOG_AUTOSIZE)
53263660c0SAlfonso Siciliano 		*w = widget_min_width(conf, htext,minw, &bs);
54f499134dSBaptiste Daroussin 
55263660c0SAlfonso Siciliano 	if (rows == BSDDIALOG_AUTOSIZE)
56263660c0SAlfonso Siciliano 		*h = widget_min_height(conf, htext, 3 /* windows */, true);
57263660c0SAlfonso Siciliano 
58263660c0SAlfonso Siciliano 	return (0);
59f499134dSBaptiste Daroussin }
60f499134dSBaptiste Daroussin 
61f499134dSBaptiste Daroussin static int
62263660c0SAlfonso Siciliano datetime_checksize(int rows, int cols, int minw, struct buttons bs)
63f499134dSBaptiste Daroussin {
64f499134dSBaptiste Daroussin 	int mincols;
65f499134dSBaptiste Daroussin 
66f499134dSBaptiste Daroussin 	mincols = VBORDERS;
67*bce40c02SAlfonso S. Siciliano 	mincols += buttons_width(bs);
68f499134dSBaptiste Daroussin 	mincols = MAX(minw, mincols);
69f499134dSBaptiste Daroussin 
70f499134dSBaptiste Daroussin 	if (cols < mincols)
71f499134dSBaptiste Daroussin 		RETURN_ERROR("Few cols for this timebox/datebox");
72f499134dSBaptiste Daroussin 
73263660c0SAlfonso Siciliano 	if (rows < 7) /* 2 button + 2 borders + 3 windows */
74263660c0SAlfonso Siciliano 		RETURN_ERROR("Few rows for this timebox/datebox, at least 7");
75f499134dSBaptiste Daroussin 
76263660c0SAlfonso Siciliano 	return (0);
77f499134dSBaptiste Daroussin }
78f499134dSBaptiste Daroussin 
79263660c0SAlfonso Siciliano int
80263660c0SAlfonso Siciliano bsddialog_timebox(struct bsddialog_conf *conf, const char* text, int rows,
81263660c0SAlfonso Siciliano     int cols, unsigned int *hh, unsigned int *mm, unsigned int *ss)
82c76f0793SBaptiste Daroussin {
83*bce40c02SAlfonso S. Siciliano 	bool loop, focusbuttons;
84263660c0SAlfonso Siciliano 	int i, input, output, y, x, h, w, sel;
85263660c0SAlfonso Siciliano 	WINDOW *widget, *textpad, *shadow;
86263660c0SAlfonso Siciliano 	struct buttons bs;
87c76f0793SBaptiste Daroussin 	struct myclockstruct {
88c76f0793SBaptiste Daroussin 		unsigned int max;
89f499134dSBaptiste Daroussin 		unsigned int value;
90c76f0793SBaptiste Daroussin 		WINDOW *win;
91f499134dSBaptiste Daroussin 	};
92c76f0793SBaptiste Daroussin 
93f499134dSBaptiste Daroussin 	if (hh == NULL || mm == NULL || ss == NULL)
94f499134dSBaptiste Daroussin 		RETURN_ERROR("hh / mm / ss cannot be NULL");
95c76f0793SBaptiste Daroussin 
96f499134dSBaptiste Daroussin 	struct myclockstruct c[3] = {
97f499134dSBaptiste Daroussin 		{23, *hh, NULL},
98f499134dSBaptiste Daroussin 		{59, *mm, NULL},
99f499134dSBaptiste Daroussin 		{59, *ss, NULL}
100f499134dSBaptiste Daroussin 	};
101f499134dSBaptiste Daroussin 
102f499134dSBaptiste Daroussin 	for (i = 0 ; i < 3; i++) {
103f499134dSBaptiste Daroussin 		if (c[i].value > c[i].max)
104f499134dSBaptiste Daroussin 			c[i].value = c[i].max;
105f499134dSBaptiste Daroussin 	}
106c76f0793SBaptiste Daroussin 
107263660c0SAlfonso Siciliano 	get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
108c76f0793SBaptiste Daroussin 
109f499134dSBaptiste Daroussin 	if (set_widget_size(conf, rows, cols, &h, &w) != 0)
110263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
111263660c0SAlfonso Siciliano 	if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text,
112263660c0SAlfonso Siciliano 	    bs) != 0)
113263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
114263660c0SAlfonso Siciliano 	if (datetime_checksize(h, w, MINWTIME, bs) != 0)
115263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
116f499134dSBaptiste Daroussin 	if (set_widget_position(conf, &y, &x, h, w) != 0)
117263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
118f499134dSBaptiste Daroussin 
119263660c0SAlfonso Siciliano 	if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
120263660c0SAlfonso Siciliano 	    true) != 0)
121263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
122f499134dSBaptiste Daroussin 
123263660c0SAlfonso Siciliano 	pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
124263660c0SAlfonso Siciliano 	doupdate();
125f499134dSBaptiste Daroussin 
126f499134dSBaptiste Daroussin 	c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 7, 3, 4, LOWERED);
127f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 - 3, ':');
128f499134dSBaptiste Daroussin 	c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 2, 3, 4, LOWERED);
129f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 + 2, ':');
130f499134dSBaptiste Daroussin 	c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 3, 3, 4, LOWERED);
131f499134dSBaptiste Daroussin 
132f499134dSBaptiste Daroussin 	wrefresh(widget);
133f499134dSBaptiste Daroussin 
134*bce40c02SAlfonso S. Siciliano 	loop = focusbuttons = true;
135c76f0793SBaptiste Daroussin 	while (loop) {
136c76f0793SBaptiste Daroussin 		for (i = 0; i < 3; i++) {
137f499134dSBaptiste Daroussin 			mvwprintw(c[i].win, 1, 1, "%2d", c[i].value);
138c76f0793SBaptiste Daroussin 			wrefresh(c[i].win);
139c76f0793SBaptiste Daroussin 		}
140*bce40c02SAlfonso S. Siciliano 
141*bce40c02SAlfonso S. Siciliano 		if (focusbuttons == false) {
142c76f0793SBaptiste Daroussin 			wmove(c[sel].win, 1, 2);
143c76f0793SBaptiste Daroussin 			wrefresh(c[sel].win);
144*bce40c02SAlfonso S. Siciliano 		}
145c76f0793SBaptiste Daroussin 
146c76f0793SBaptiste Daroussin 		input = getch();
147c76f0793SBaptiste Daroussin 		switch(input) {
148f499134dSBaptiste Daroussin 		case KEY_ENTER:
149c76f0793SBaptiste Daroussin 		case 10: /* Enter */
150*bce40c02SAlfonso S. Siciliano 			if (focusbuttons == false)
151*bce40c02SAlfonso S. Siciliano 				break;
152c76f0793SBaptiste Daroussin 			output = bs.value[bs.curr];
153c76f0793SBaptiste Daroussin 			loop = false;
154c76f0793SBaptiste Daroussin 			break;
155c76f0793SBaptiste Daroussin 		case 27: /* Esc */
156263660c0SAlfonso Siciliano 			if (conf->key.enable_esc) {
157c76f0793SBaptiste Daroussin 				output = BSDDIALOG_ESC;
158c76f0793SBaptiste Daroussin 				loop = false;
159263660c0SAlfonso Siciliano 			}
160c76f0793SBaptiste Daroussin 			break;
161*bce40c02SAlfonso S. Siciliano 		case KEY_RIGHT:
162c76f0793SBaptiste Daroussin 		case '\t': /* TAB */
163*bce40c02SAlfonso S. Siciliano 			if (focusbuttons) {
164*bce40c02SAlfonso S. Siciliano 				bs.curr++;
165*bce40c02SAlfonso S. Siciliano 				focusbuttons = bs.curr < (int)bs.nbuttons ?
166*bce40c02SAlfonso S. Siciliano 				    true : false;
167*bce40c02SAlfonso S. Siciliano 				if (focusbuttons == false) {
168*bce40c02SAlfonso S. Siciliano 					curs_set(1);
169*bce40c02SAlfonso S. Siciliano 					sel = 0;
170*bce40c02SAlfonso S. Siciliano 				}
171*bce40c02SAlfonso S. Siciliano 			} else {
172*bce40c02SAlfonso S. Siciliano 				sel++;
173*bce40c02SAlfonso S. Siciliano 				focusbuttons = sel > 2 ? true : false;
174*bce40c02SAlfonso S. Siciliano 				if (focusbuttons) {
175*bce40c02SAlfonso S. Siciliano 					curs_set(0);
176*bce40c02SAlfonso S. Siciliano 					bs.curr = 0;
177*bce40c02SAlfonso S. Siciliano 				}
178*bce40c02SAlfonso S. Siciliano 			}
179263660c0SAlfonso Siciliano 			draw_buttons(widget, bs, true);
180263660c0SAlfonso Siciliano 			wrefresh(widget);
181c76f0793SBaptiste Daroussin 			break;
182c76f0793SBaptiste Daroussin 		case KEY_LEFT:
183*bce40c02SAlfonso S. Siciliano 			if (focusbuttons) {
184*bce40c02SAlfonso S. Siciliano 				bs.curr--;
185*bce40c02SAlfonso S. Siciliano 				focusbuttons = bs.curr < 0 ? false : true;
186*bce40c02SAlfonso S. Siciliano 				if (focusbuttons == false) {
187*bce40c02SAlfonso S. Siciliano 					curs_set(1);
188*bce40c02SAlfonso S. Siciliano 					sel = 2;
189*bce40c02SAlfonso S. Siciliano 				}
190*bce40c02SAlfonso S. Siciliano 			} else {
191*bce40c02SAlfonso S. Siciliano 				sel--;
192*bce40c02SAlfonso S. Siciliano 				focusbuttons = sel < 0 ? true : false;
193*bce40c02SAlfonso S. Siciliano 				if (focusbuttons) {
194*bce40c02SAlfonso S. Siciliano 					curs_set(0);
195*bce40c02SAlfonso S. Siciliano 					bs.curr = (int)bs.nbuttons - 1;
196*bce40c02SAlfonso S. Siciliano 				}
197*bce40c02SAlfonso S. Siciliano 			}
198*bce40c02SAlfonso S. Siciliano 			draw_buttons(widget, bs, true);
199*bce40c02SAlfonso S. Siciliano 			wrefresh(widget);
200c76f0793SBaptiste Daroussin 			break;
201c76f0793SBaptiste Daroussin 		case KEY_UP:
202*bce40c02SAlfonso S. Siciliano 			if (focusbuttons)
203c76f0793SBaptiste Daroussin 				break;
204263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value > 0 ?
205263660c0SAlfonso Siciliano 			    c[sel].value - 1 : c[sel].max;
206c76f0793SBaptiste Daroussin 			break;
207*bce40c02SAlfonso S. Siciliano 		case KEY_DOWN:
208*bce40c02SAlfonso S. Siciliano 			if (focusbuttons)
209*bce40c02SAlfonso S. Siciliano 				break;
210*bce40c02SAlfonso S. Siciliano 			c[sel].value = c[sel].value < c[sel].max ?
211*bce40c02SAlfonso S. Siciliano 			    c[sel].value + 1 : 0;
212*bce40c02SAlfonso S. Siciliano 			break;
213f499134dSBaptiste Daroussin 		case KEY_F(1):
214*bce40c02SAlfonso S. Siciliano 			if (conf->key.f1_file == NULL &&
215*bce40c02SAlfonso S. Siciliano 			    conf->key.f1_message == NULL)
216f499134dSBaptiste Daroussin 				break;
217f499134dSBaptiste Daroussin 			curs_set(0);
218f499134dSBaptiste Daroussin 			if (f1help(conf) != 0)
219263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
220*bce40c02SAlfonso S. Siciliano 			curs_set(1);
221263660c0SAlfonso Siciliano 			/* No break, screen size can change */
222f499134dSBaptiste Daroussin 		case KEY_RESIZE:
223263660c0SAlfonso Siciliano 			/* Important for decreasing screen */
224f499134dSBaptiste Daroussin 			hide_widget(y, x, h, w, conf->shadow);
225f499134dSBaptiste Daroussin 			refresh();
226f499134dSBaptiste Daroussin 
227f499134dSBaptiste Daroussin 			if (set_widget_size(conf, rows, cols, &h, &w) != 0)
228263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
229263660c0SAlfonso Siciliano 			if (datetime_autosize(conf, rows, cols, &h, &w,
230263660c0SAlfonso Siciliano 			    MINWTIME, text, bs) != 0)
231263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
232263660c0SAlfonso Siciliano 			if (datetime_checksize(h, w, MINWTIME, bs) != 0)
233263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
234f499134dSBaptiste Daroussin 			if (set_widget_position(conf, &y, &x, h, w) != 0)
235263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
236f499134dSBaptiste Daroussin 
237263660c0SAlfonso Siciliano 			if (update_dialog(conf, shadow, widget, y, x, h, w,
238263660c0SAlfonso Siciliano 			    textpad, text, &bs, true) != 0)
239263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
240f499134dSBaptiste Daroussin 
241263660c0SAlfonso Siciliano 			doupdate();
242f499134dSBaptiste Daroussin 
243f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 - 3, ':');
244f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 + 2, ':');
245f499134dSBaptiste Daroussin 			wrefresh(widget);
246f499134dSBaptiste Daroussin 
247f499134dSBaptiste Daroussin 			prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
248f499134dSBaptiste Daroussin 
249f499134dSBaptiste Daroussin 			wclear(c[0].win);
250f499134dSBaptiste Daroussin 			mvwin(c[0].win, y + h - 6, x + w/2 - 7);
251f499134dSBaptiste Daroussin 			draw_borders(conf, c[0].win, 3, 4, LOWERED);
252f499134dSBaptiste Daroussin 			wrefresh(c[0].win);
253f499134dSBaptiste Daroussin 
254f499134dSBaptiste Daroussin 			wclear(c[1].win);
255f499134dSBaptiste Daroussin 			mvwin(c[1].win, y + h - 6, x + w/2 - 2);
256f499134dSBaptiste Daroussin 			draw_borders(conf, c[1].win, 3, 4, LOWERED);
257f499134dSBaptiste Daroussin 			wrefresh(c[1].win);
258f499134dSBaptiste Daroussin 
259f499134dSBaptiste Daroussin 			wclear(c[2].win);
260f499134dSBaptiste Daroussin 			mvwin(c[2].win, y + h - 6, x + w/2 + 3);
261f499134dSBaptiste Daroussin 			draw_borders(conf, c[2].win, 3, 4, LOWERED);
262f499134dSBaptiste Daroussin 			wrefresh(c[2].win);
263f499134dSBaptiste Daroussin 
264f499134dSBaptiste Daroussin 			/* Important to avoid grey lines expanding screen */
265f499134dSBaptiste Daroussin 			refresh();
266f499134dSBaptiste Daroussin 			break;
267f499134dSBaptiste Daroussin 		default:
268263660c0SAlfonso Siciliano 			if (shortcut_buttons(input, &bs)) {
269263660c0SAlfonso Siciliano 				output = bs.value[bs.curr];
270f499134dSBaptiste Daroussin 				loop = false;
271f499134dSBaptiste Daroussin 			}
272c76f0793SBaptiste Daroussin 		}
273c76f0793SBaptiste Daroussin 	}
274c76f0793SBaptiste Daroussin 
275*bce40c02SAlfonso S. Siciliano 	if (output == BSDDIALOG_OK) {
276*bce40c02SAlfonso S. Siciliano 		*hh = c[0].value;
277*bce40c02SAlfonso S. Siciliano 		*mm = c[1].value;
278*bce40c02SAlfonso S. Siciliano 		*ss = c[2].value;
279*bce40c02SAlfonso S. Siciliano 	}
280*bce40c02SAlfonso S. Siciliano 
281c76f0793SBaptiste Daroussin 	curs_set(0);
282c76f0793SBaptiste Daroussin 
283c76f0793SBaptiste Daroussin 	for (i = 0; i < 3; i++)
284c76f0793SBaptiste Daroussin 		delwin(c[i].win);
285263660c0SAlfonso Siciliano 	end_dialog(conf, shadow, widget, textpad);
286c76f0793SBaptiste Daroussin 
287263660c0SAlfonso Siciliano 	return (output);
288c76f0793SBaptiste Daroussin }
289c76f0793SBaptiste Daroussin 
290f499134dSBaptiste Daroussin int
291263660c0SAlfonso Siciliano bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
292263660c0SAlfonso Siciliano     int cols, unsigned int *yy, unsigned int *mm, unsigned int *dd)
293c76f0793SBaptiste Daroussin {
294*bce40c02SAlfonso S. Siciliano 	bool loop, focusbuttons;
295263660c0SAlfonso Siciliano 	int i, input, output, y, x, h, w, sel;
296263660c0SAlfonso Siciliano 	WINDOW *widget, *textpad, *shadow;
297263660c0SAlfonso Siciliano 	struct buttons bs;
298c76f0793SBaptiste Daroussin 	struct calendar {
299f499134dSBaptiste Daroussin 		int max;
300f499134dSBaptiste Daroussin 		int value;
301c76f0793SBaptiste Daroussin 		WINDOW *win;
302c76f0793SBaptiste Daroussin 		unsigned int x;
303f499134dSBaptiste Daroussin 	};
304c76f0793SBaptiste Daroussin 	struct month {
305*bce40c02SAlfonso S. Siciliano 		const char *name;
306c76f0793SBaptiste Daroussin 		unsigned int days;
307c76f0793SBaptiste Daroussin 	};
308c76f0793SBaptiste Daroussin 
309f499134dSBaptiste Daroussin 	if (yy == NULL || mm == NULL || dd == NULL)
310f499134dSBaptiste Daroussin 		RETURN_ERROR("yy / mm / dd cannot be NULL");
311c76f0793SBaptiste Daroussin 
312f499134dSBaptiste Daroussin 	struct calendar c[3] = {
313f499134dSBaptiste Daroussin 		{9999, *yy, NULL, 4 },
314f499134dSBaptiste Daroussin 		{12,   *mm, NULL, 9 },
315f499134dSBaptiste Daroussin 		{31,   *dd, NULL, 2 }
316f499134dSBaptiste Daroussin 	};
317c76f0793SBaptiste Daroussin 
318f499134dSBaptiste Daroussin 	struct month m[12] = {
319f499134dSBaptiste Daroussin 		{ "January", 31 }, { "February", 28 }, { "March",     31 },
320f499134dSBaptiste Daroussin 		{ "April",   30 }, { "May",      31 }, { "June",      30 },
321f499134dSBaptiste Daroussin 		{ "July",    31 }, { "August",   31 }, { "September", 30 },
322f499134dSBaptiste Daroussin 		{ "October", 31 }, { "November", 30 }, { "December",  31 }
323f499134dSBaptiste Daroussin 	};
324f499134dSBaptiste Daroussin 
325f499134dSBaptiste Daroussin #define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
326f499134dSBaptiste Daroussin 
327f499134dSBaptiste Daroussin 	for (i = 0 ; i < 3; i++) {
328f499134dSBaptiste Daroussin 		if (c[i].value > c[i].max)
329f499134dSBaptiste Daroussin 			c[i].value = c[i].max;
330f499134dSBaptiste Daroussin 		if (c[i].value < 1)
331f499134dSBaptiste Daroussin 			c[i].value = 1;
332f499134dSBaptiste Daroussin 	}
333f499134dSBaptiste Daroussin 	c[2].max = m[c[1].value -1].days;
334f499134dSBaptiste Daroussin 	if (c[1].value == 2 && ISLEAF(c[0].value))
335f499134dSBaptiste Daroussin 		c[2].max = 29;
336f499134dSBaptiste Daroussin 	if (c[2].value > c[2].max)
337f499134dSBaptiste Daroussin 		c[2].value = c[2].max;
338c76f0793SBaptiste Daroussin 
339263660c0SAlfonso Siciliano 	get_buttons(conf, &bs, BUTTON_OK_LABEL, BUTTON_CANCEL_LABEL);
340c76f0793SBaptiste Daroussin 
341f499134dSBaptiste Daroussin 	if (set_widget_size(conf, rows, cols, &h, &w) != 0)
342263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
343263660c0SAlfonso Siciliano 	if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text,
344263660c0SAlfonso Siciliano 	    bs) != 0)
345263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
346263660c0SAlfonso Siciliano 	if (datetime_checksize(h, w, MINWDATE, bs) != 0)
347263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
348f499134dSBaptiste Daroussin 	if (set_widget_position(conf, &y, &x, h, w) != 0)
349263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
350f499134dSBaptiste Daroussin 
351263660c0SAlfonso Siciliano 	if (new_dialog(conf, &shadow, &widget, y, x, h, w, &textpad, text, &bs,
352263660c0SAlfonso Siciliano 	    true) != 0)
353263660c0SAlfonso Siciliano 		return (BSDDIALOG_ERROR);
354f499134dSBaptiste Daroussin 
355263660c0SAlfonso Siciliano 	pnoutrefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
356263660c0SAlfonso Siciliano 	doupdate();
357f499134dSBaptiste Daroussin 
358f499134dSBaptiste Daroussin 	c[0].win = new_boxed_window(conf, y+h-6, x + w/2 - 11, 3, 6, LOWERED);
359f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 - 5, '/');
360f499134dSBaptiste Daroussin 	c[1].win = new_boxed_window(conf, y+h-6, x + w/2 - 4, 3, 11, LOWERED);
361f499134dSBaptiste Daroussin 	mvwaddch(widget, h - 5, w/2 + 7, '/');
362f499134dSBaptiste Daroussin 	c[2].win = new_boxed_window(conf, y+h-6, x + w/2 + 8, 3, 4, LOWERED);
363f499134dSBaptiste Daroussin 
364f499134dSBaptiste Daroussin 	wrefresh(widget);
365f499134dSBaptiste Daroussin 
366*bce40c02SAlfonso S. Siciliano 	loop = focusbuttons = true;
367c76f0793SBaptiste Daroussin 	while (loop) {
368f499134dSBaptiste Daroussin 		mvwprintw(c[0].win, 1, 1, "%4d", c[0].value);
369f499134dSBaptiste Daroussin 		mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name);
370f499134dSBaptiste Daroussin 		mvwprintw(c[2].win, 1, 1, "%2d", c[2].value);
371c76f0793SBaptiste Daroussin 		for (i = 0; i < 3; i++) {
372c76f0793SBaptiste Daroussin 			wrefresh(c[i].win);
373c76f0793SBaptiste Daroussin 		}
374*bce40c02SAlfonso S. Siciliano 		if (focusbuttons == false) {
375c76f0793SBaptiste Daroussin 			wmove(c[sel].win, 1, c[sel].x);
376c76f0793SBaptiste Daroussin 			wrefresh(c[sel].win);
377*bce40c02SAlfonso S. Siciliano 		}
378c76f0793SBaptiste Daroussin 
379c76f0793SBaptiste Daroussin 		input = getch();
380c76f0793SBaptiste Daroussin 		switch(input) {
381f499134dSBaptiste Daroussin 		case KEY_ENTER:
382f499134dSBaptiste Daroussin 		case 10: /* Enter */
383*bce40c02SAlfonso S. Siciliano 			if (focusbuttons == false)
384*bce40c02SAlfonso S. Siciliano 				break;
385f499134dSBaptiste Daroussin 			output = bs.value[bs.curr];
386c76f0793SBaptiste Daroussin 			loop = false;
387c76f0793SBaptiste Daroussin 			break;
388f499134dSBaptiste Daroussin 		case 27: /* Esc */
389263660c0SAlfonso Siciliano 			if (conf->key.enable_esc) {
390c76f0793SBaptiste Daroussin 				output = BSDDIALOG_ESC;
391c76f0793SBaptiste Daroussin 				loop = false;
392263660c0SAlfonso Siciliano 			}
393c76f0793SBaptiste Daroussin 			break;
394*bce40c02SAlfonso S. Siciliano 		case KEY_RIGHT:
395f499134dSBaptiste Daroussin 		case '\t': /* TAB */
396*bce40c02SAlfonso S. Siciliano 			if (focusbuttons) {
397*bce40c02SAlfonso S. Siciliano 				bs.curr++;
398*bce40c02SAlfonso S. Siciliano 				focusbuttons = bs.curr < (int)bs.nbuttons ?
399*bce40c02SAlfonso S. Siciliano 				    true : false;
400*bce40c02SAlfonso S. Siciliano 				if (focusbuttons == false) {
401*bce40c02SAlfonso S. Siciliano 					curs_set(1);
402*bce40c02SAlfonso S. Siciliano 					sel = 0;
403*bce40c02SAlfonso S. Siciliano 				}
404*bce40c02SAlfonso S. Siciliano 			} else {
405*bce40c02SAlfonso S. Siciliano 				sel++;
406*bce40c02SAlfonso S. Siciliano 				focusbuttons = sel > 2 ? true : false;
407*bce40c02SAlfonso S. Siciliano 				if (focusbuttons) {
408*bce40c02SAlfonso S. Siciliano 					curs_set(0);
409*bce40c02SAlfonso S. Siciliano 					bs.curr = 0;
410*bce40c02SAlfonso S. Siciliano 				}
411*bce40c02SAlfonso S. Siciliano 			}
412263660c0SAlfonso Siciliano 			draw_buttons(widget, bs, true);
413263660c0SAlfonso Siciliano 			wrefresh(widget);
414c76f0793SBaptiste Daroussin 			break;
415c76f0793SBaptiste Daroussin 		case KEY_LEFT:
416*bce40c02SAlfonso S. Siciliano 			if (focusbuttons) {
417*bce40c02SAlfonso S. Siciliano 				bs.curr--;
418*bce40c02SAlfonso S. Siciliano 				focusbuttons = bs.curr < 0 ? false : true;
419*bce40c02SAlfonso S. Siciliano 				if (focusbuttons == false) {
420*bce40c02SAlfonso S. Siciliano 					curs_set(1);
421*bce40c02SAlfonso S. Siciliano 					sel = 2;
422*bce40c02SAlfonso S. Siciliano 				}
423*bce40c02SAlfonso S. Siciliano 			} else {
424*bce40c02SAlfonso S. Siciliano 				sel--;
425*bce40c02SAlfonso S. Siciliano 				focusbuttons = sel < 0 ? true : false;
426*bce40c02SAlfonso S. Siciliano 				if (focusbuttons) {
427*bce40c02SAlfonso S. Siciliano 					curs_set(0);
428*bce40c02SAlfonso S. Siciliano 					bs.curr = (int)bs.nbuttons - 1;
429*bce40c02SAlfonso S. Siciliano 				}
430*bce40c02SAlfonso S. Siciliano 			}
431*bce40c02SAlfonso S. Siciliano 			draw_buttons(widget, bs, true);
432*bce40c02SAlfonso S. Siciliano 			wrefresh(widget);
433c76f0793SBaptiste Daroussin 			break;
434c76f0793SBaptiste Daroussin 		case KEY_UP:
435*bce40c02SAlfonso S. Siciliano 			if (focusbuttons)
436*bce40c02SAlfonso S. Siciliano 				break;
437263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value > 1 ?
438263660c0SAlfonso Siciliano 			    c[sel].value - 1 : c[sel].max ;
439f499134dSBaptiste Daroussin 			/* if mount change */
440f499134dSBaptiste Daroussin 			c[2].max = m[c[1].value -1].days;
441f499134dSBaptiste Daroussin 			/* if year change */
442f499134dSBaptiste Daroussin 			if (c[1].value == 2 && ISLEAF(c[0].value))
443f499134dSBaptiste Daroussin 				c[2].max = 29;
444f499134dSBaptiste Daroussin 			/* set new day */
445f499134dSBaptiste Daroussin 			if (c[2].value > c[2].max)
446f499134dSBaptiste Daroussin 				c[2].value = c[2].max;
447c76f0793SBaptiste Daroussin 			break;
448c76f0793SBaptiste Daroussin 		case KEY_DOWN:
449*bce40c02SAlfonso S. Siciliano 			if (focusbuttons)
450*bce40c02SAlfonso S. Siciliano 				break;
451263660c0SAlfonso Siciliano 			c[sel].value = c[sel].value < c[sel].max ?
452263660c0SAlfonso Siciliano 			    c[sel].value + 1 : 1;
453f499134dSBaptiste Daroussin 			/* if mount change */
454f499134dSBaptiste Daroussin 			c[2].max = m[c[1].value -1].days;
455f499134dSBaptiste Daroussin 			/* if year change */
456f499134dSBaptiste Daroussin 			if (c[1].value == 2 && ISLEAF(c[0].value))
457f499134dSBaptiste Daroussin 				c[2].max = 29;
458f499134dSBaptiste Daroussin 			/* set new day */
459f499134dSBaptiste Daroussin 			if (c[2].value > c[2].max)
460f499134dSBaptiste Daroussin 				c[2].value = c[2].max;
461c76f0793SBaptiste Daroussin 			break;
462f499134dSBaptiste Daroussin 		case KEY_F(1):
463*bce40c02SAlfonso S. Siciliano 			if (conf->key.f1_file == NULL &&
464*bce40c02SAlfonso S. Siciliano 			    conf->key.f1_message == NULL)
465f499134dSBaptiste Daroussin 				break;
466f499134dSBaptiste Daroussin 			curs_set(0);
467f499134dSBaptiste Daroussin 			if (f1help(conf) != 0)
468263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
469*bce40c02SAlfonso S. Siciliano 			curs_set(1);
470263660c0SAlfonso Siciliano 			/* No break, screen size can change */
471f499134dSBaptiste Daroussin 		case KEY_RESIZE:
472263660c0SAlfonso Siciliano 			/* Important for decreasing screen */
473f499134dSBaptiste Daroussin 			hide_widget(y, x, h, w, conf->shadow);
474f499134dSBaptiste Daroussin 			refresh();
475f499134dSBaptiste Daroussin 
476f499134dSBaptiste Daroussin 			if (set_widget_size(conf, rows, cols, &h, &w) != 0)
477263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
478263660c0SAlfonso Siciliano 			if (datetime_autosize(conf, rows, cols, &h, &w,
479263660c0SAlfonso Siciliano 			    MINWDATE, text, bs) != 0)
480263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
481263660c0SAlfonso Siciliano 			if (datetime_checksize(h, w, MINWDATE, bs) != 0)
482263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
483f499134dSBaptiste Daroussin 			if (set_widget_position(conf, &y, &x, h, w) != 0)
484263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
485f499134dSBaptiste Daroussin 
486263660c0SAlfonso Siciliano 			if (update_dialog(conf, shadow, widget, y, x, h, w,
487263660c0SAlfonso Siciliano 			    textpad, text, &bs, true) != 0)
488263660c0SAlfonso Siciliano 				return (BSDDIALOG_ERROR);
489263660c0SAlfonso Siciliano 			doupdate();
490f499134dSBaptiste Daroussin 
491f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 - 5, '/');
492f499134dSBaptiste Daroussin 			mvwaddch(widget, h - 5, w/2 + 7, '/');
493f499134dSBaptiste Daroussin 			wrefresh(widget);
494f499134dSBaptiste Daroussin 
495f499134dSBaptiste Daroussin 			prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
496f499134dSBaptiste Daroussin 
497f499134dSBaptiste Daroussin 			wclear(c[0].win);
498f499134dSBaptiste Daroussin 			mvwin(c[0].win, y + h - 6, x + w/2 - 11);
499f499134dSBaptiste Daroussin 			draw_borders(conf, c[0].win, 3, 6, LOWERED);
500f499134dSBaptiste Daroussin 			wrefresh(c[0].win);
501f499134dSBaptiste Daroussin 
502f499134dSBaptiste Daroussin 			wclear(c[1].win);
503f499134dSBaptiste Daroussin 			mvwin(c[1].win, y + h - 6, x + w/2 - 4);
504f499134dSBaptiste Daroussin 			draw_borders(conf, c[1].win, 3, 11, LOWERED);
505f499134dSBaptiste Daroussin 			wrefresh(c[1].win);
506f499134dSBaptiste Daroussin 
507f499134dSBaptiste Daroussin 			wclear(c[2].win);
508f499134dSBaptiste Daroussin 			mvwin(c[2].win, y + h - 6, x + w/2 + 8);
509f499134dSBaptiste Daroussin 			draw_borders(conf, c[2].win, 3, 4, LOWERED);
510f499134dSBaptiste Daroussin 			wrefresh(c[2].win);
511f499134dSBaptiste Daroussin 
512f499134dSBaptiste Daroussin 			/* Important to avoid grey lines expanding screen */
513f499134dSBaptiste Daroussin 			refresh();
514f499134dSBaptiste Daroussin 			break;
515f499134dSBaptiste Daroussin 		default:
516263660c0SAlfonso Siciliano 			if (shortcut_buttons(input, &bs)) {
517263660c0SAlfonso Siciliano 				output = bs.value[bs.curr];
518f499134dSBaptiste Daroussin 				loop = false;
519f499134dSBaptiste Daroussin 			}
520c76f0793SBaptiste Daroussin 		}
521c76f0793SBaptiste Daroussin 	}
522c76f0793SBaptiste Daroussin 
523*bce40c02SAlfonso S. Siciliano 	if (output == BSDDIALOG_OK) {
524*bce40c02SAlfonso S. Siciliano 		*yy = c[0].value;
525*bce40c02SAlfonso S. Siciliano 		*mm = c[1].value;
526*bce40c02SAlfonso S. Siciliano 		*dd = c[2].value;
527*bce40c02SAlfonso S. Siciliano 	}
528*bce40c02SAlfonso S. Siciliano 
529c76f0793SBaptiste Daroussin 	curs_set(0);
530c76f0793SBaptiste Daroussin 
531c76f0793SBaptiste Daroussin 	for (i = 0; i < 3; i++)
532c76f0793SBaptiste Daroussin 		delwin(c[i].win);
533263660c0SAlfonso Siciliano 	end_dialog(conf, shadow, widget, textpad);
534c76f0793SBaptiste Daroussin 
535263660c0SAlfonso Siciliano 	return (output);
536c76f0793SBaptiste Daroussin }
537