xref: /freebsd/contrib/bsddialog/lib/datebox.c (revision 61ba55bcf70f2340f9c943c9571113b3fd8eda69)
1*61ba55bcSBaptiste Daroussin /*-
2*61ba55bcSBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
3*61ba55bcSBaptiste Daroussin  *
4*61ba55bcSBaptiste Daroussin  * Copyright (c) 2022-2023 Alfonso Sabato Siciliano
5*61ba55bcSBaptiste Daroussin  *
6*61ba55bcSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7*61ba55bcSBaptiste Daroussin  * modification, are permitted provided that the following conditions
8*61ba55bcSBaptiste Daroussin  * are met:
9*61ba55bcSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10*61ba55bcSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
11*61ba55bcSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12*61ba55bcSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13*61ba55bcSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14*61ba55bcSBaptiste Daroussin  *
15*61ba55bcSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*61ba55bcSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*61ba55bcSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*61ba55bcSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*61ba55bcSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*61ba55bcSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*61ba55bcSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*61ba55bcSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*61ba55bcSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*61ba55bcSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*61ba55bcSBaptiste Daroussin  * SUCH DAMAGE.
26*61ba55bcSBaptiste Daroussin  */
27*61ba55bcSBaptiste Daroussin 
28*61ba55bcSBaptiste Daroussin #include <curses.h>
29*61ba55bcSBaptiste Daroussin #include <stdlib.h>
30*61ba55bcSBaptiste Daroussin #include <string.h>
31*61ba55bcSBaptiste Daroussin 
32*61ba55bcSBaptiste Daroussin #include "bsddialog.h"
33*61ba55bcSBaptiste Daroussin #include "bsddialog_theme.h"
34*61ba55bcSBaptiste Daroussin #include "lib_util.h"
35*61ba55bcSBaptiste Daroussin 
36*61ba55bcSBaptiste Daroussin /* Calendar */
37*61ba55bcSBaptiste Daroussin #define MIN_YEAR_CAL   0
38*61ba55bcSBaptiste Daroussin #define MAX_YEAR_CAL   999999999
39*61ba55bcSBaptiste Daroussin #define MINHCAL        13
40*61ba55bcSBaptiste Daroussin #define MINWCAL        36 /* 34 calendar, 1 + 1 margins */
41*61ba55bcSBaptiste Daroussin /* Datebox */
42*61ba55bcSBaptiste Daroussin #define MIN_YEAR_DATE  0
43*61ba55bcSBaptiste Daroussin #define MAX_YEAR_DATE  9999
44*61ba55bcSBaptiste Daroussin #define MINWDATE       23 /* 3 windows and their borders */
45*61ba55bcSBaptiste Daroussin 
46*61ba55bcSBaptiste Daroussin #define ISLEAP(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
47*61ba55bcSBaptiste Daroussin 
48*61ba55bcSBaptiste Daroussin static int minyear;
49*61ba55bcSBaptiste Daroussin static int maxyear;
50*61ba55bcSBaptiste Daroussin 
51*61ba55bcSBaptiste Daroussin static const char *m[12] = {
52*61ba55bcSBaptiste Daroussin 	"January",
53*61ba55bcSBaptiste Daroussin 	"February",
54*61ba55bcSBaptiste Daroussin 	"March",
55*61ba55bcSBaptiste Daroussin 	"April",
56*61ba55bcSBaptiste Daroussin 	"May",
57*61ba55bcSBaptiste Daroussin 	"June",
58*61ba55bcSBaptiste Daroussin 	"July",
59*61ba55bcSBaptiste Daroussin 	"August",
60*61ba55bcSBaptiste Daroussin 	"September",
61*61ba55bcSBaptiste Daroussin 	"October",
62*61ba55bcSBaptiste Daroussin 	"November",
63*61ba55bcSBaptiste Daroussin 	"December"
64*61ba55bcSBaptiste Daroussin };
65*61ba55bcSBaptiste Daroussin 
66*61ba55bcSBaptiste Daroussin enum operation {
67*61ba55bcSBaptiste Daroussin 	UP_DAY,
68*61ba55bcSBaptiste Daroussin 	DOWN_DAY,
69*61ba55bcSBaptiste Daroussin 	LEFT_DAY,
70*61ba55bcSBaptiste Daroussin 	RIGHT_DAY,
71*61ba55bcSBaptiste Daroussin 	UP_MONTH,
72*61ba55bcSBaptiste Daroussin 	DOWN_MONTH,
73*61ba55bcSBaptiste Daroussin 	UP_YEAR,
74*61ba55bcSBaptiste Daroussin 	DOWN_YEAR
75*61ba55bcSBaptiste Daroussin };
76*61ba55bcSBaptiste Daroussin 
77*61ba55bcSBaptiste Daroussin /* private datebox item */
78*61ba55bcSBaptiste Daroussin struct dateitem {
79*61ba55bcSBaptiste Daroussin 	enum operation up;
80*61ba55bcSBaptiste Daroussin 	enum operation down;
81*61ba55bcSBaptiste Daroussin 	WINDOW *win;
82*61ba55bcSBaptiste Daroussin 	int width;
83*61ba55bcSBaptiste Daroussin 	const char *fmt;
84*61ba55bcSBaptiste Daroussin 	int *value;
85*61ba55bcSBaptiste Daroussin };
86*61ba55bcSBaptiste Daroussin 
87*61ba55bcSBaptiste Daroussin static int month_days(int yy, int mm)
88*61ba55bcSBaptiste Daroussin {
89*61ba55bcSBaptiste Daroussin 	int days;
90*61ba55bcSBaptiste Daroussin 
91*61ba55bcSBaptiste Daroussin 	if (mm == 2)
92*61ba55bcSBaptiste Daroussin 		days = ISLEAP(yy) ? 29 : 28;
93*61ba55bcSBaptiste Daroussin 	else if (mm == 4 || mm == 6 || mm == 9 || mm == 11)
94*61ba55bcSBaptiste Daroussin 		days = 30;
95*61ba55bcSBaptiste Daroussin 	else
96*61ba55bcSBaptiste Daroussin 		days = 31;
97*61ba55bcSBaptiste Daroussin 
98*61ba55bcSBaptiste Daroussin 	return (days);
99*61ba55bcSBaptiste Daroussin }
100*61ba55bcSBaptiste Daroussin 
101*61ba55bcSBaptiste Daroussin static int week_day(int yy, int mm, int dd)
102*61ba55bcSBaptiste Daroussin {
103*61ba55bcSBaptiste Daroussin 	int wd;
104*61ba55bcSBaptiste Daroussin 
105*61ba55bcSBaptiste Daroussin 	dd += mm < 3 ? yy-- : yy - 2;
106*61ba55bcSBaptiste Daroussin 	wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400;
107*61ba55bcSBaptiste Daroussin 	wd %= 7;
108*61ba55bcSBaptiste Daroussin 
109*61ba55bcSBaptiste Daroussin 	return (wd);
110*61ba55bcSBaptiste Daroussin }
111*61ba55bcSBaptiste Daroussin 
112*61ba55bcSBaptiste Daroussin static void
113*61ba55bcSBaptiste Daroussin init_date(unsigned int *year, unsigned int *month, unsigned int *day, int *yy,
114*61ba55bcSBaptiste Daroussin     int *mm, int *dd)
115*61ba55bcSBaptiste Daroussin {
116*61ba55bcSBaptiste Daroussin 	*yy = MIN(*year, (unsigned int)maxyear);
117*61ba55bcSBaptiste Daroussin 	if (*yy < minyear)
118*61ba55bcSBaptiste Daroussin 		*yy = minyear;
119*61ba55bcSBaptiste Daroussin 	*mm = MIN(*month, 12);
120*61ba55bcSBaptiste Daroussin 	if (*mm == 0)
121*61ba55bcSBaptiste Daroussin 		*mm = 1;
122*61ba55bcSBaptiste Daroussin 	*dd = (*day == 0) ? 1 : *day;
123*61ba55bcSBaptiste Daroussin 	if(*dd > month_days(*yy, *mm))
124*61ba55bcSBaptiste Daroussin 		*dd = month_days(*yy, *mm);
125*61ba55bcSBaptiste Daroussin }
126*61ba55bcSBaptiste Daroussin 
127*61ba55bcSBaptiste Daroussin static void datectl(enum operation op, int *yy, int *mm, int *dd)
128*61ba55bcSBaptiste Daroussin {
129*61ba55bcSBaptiste Daroussin 	int ndays;
130*61ba55bcSBaptiste Daroussin 
131*61ba55bcSBaptiste Daroussin 	ndays = month_days(*yy, *mm);
132*61ba55bcSBaptiste Daroussin 
133*61ba55bcSBaptiste Daroussin 	switch (op) {
134*61ba55bcSBaptiste Daroussin 	case UP_DAY:
135*61ba55bcSBaptiste Daroussin 		if (*dd > 7)
136*61ba55bcSBaptiste Daroussin 			*dd -= 7;
137*61ba55bcSBaptiste Daroussin 		else {
138*61ba55bcSBaptiste Daroussin 			if (*mm == 1) {
139*61ba55bcSBaptiste Daroussin 				*yy -= 1;
140*61ba55bcSBaptiste Daroussin 				*mm = 12;
141*61ba55bcSBaptiste Daroussin 			} else
142*61ba55bcSBaptiste Daroussin 				*mm -= 1;
143*61ba55bcSBaptiste Daroussin 			ndays = month_days(*yy, *mm);
144*61ba55bcSBaptiste Daroussin 			*dd = ndays - abs(7 - *dd);
145*61ba55bcSBaptiste Daroussin 		}
146*61ba55bcSBaptiste Daroussin 		break;
147*61ba55bcSBaptiste Daroussin 	case DOWN_DAY:
148*61ba55bcSBaptiste Daroussin 		if (*dd + 7 < ndays)
149*61ba55bcSBaptiste Daroussin 			*dd += 7;
150*61ba55bcSBaptiste Daroussin 		else {
151*61ba55bcSBaptiste Daroussin 			if (*mm == 12) {
152*61ba55bcSBaptiste Daroussin 				*yy += 1;
153*61ba55bcSBaptiste Daroussin 				*mm = 1;
154*61ba55bcSBaptiste Daroussin 			} else
155*61ba55bcSBaptiste Daroussin 				*mm += 1;
156*61ba55bcSBaptiste Daroussin 			*dd = *dd + 7 - ndays;
157*61ba55bcSBaptiste Daroussin 		}
158*61ba55bcSBaptiste Daroussin 		break;
159*61ba55bcSBaptiste Daroussin 	case LEFT_DAY:
160*61ba55bcSBaptiste Daroussin 		if (*dd > 1)
161*61ba55bcSBaptiste Daroussin 			*dd -= 1;
162*61ba55bcSBaptiste Daroussin 		else {
163*61ba55bcSBaptiste Daroussin 			if (*mm == 1) {
164*61ba55bcSBaptiste Daroussin 				*yy -= 1;
165*61ba55bcSBaptiste Daroussin 				*mm = 12;
166*61ba55bcSBaptiste Daroussin 			} else
167*61ba55bcSBaptiste Daroussin 				*mm -= 1;
168*61ba55bcSBaptiste Daroussin 			*dd = month_days(*yy, *mm);
169*61ba55bcSBaptiste Daroussin 		}
170*61ba55bcSBaptiste Daroussin 		break;
171*61ba55bcSBaptiste Daroussin 	case RIGHT_DAY:
172*61ba55bcSBaptiste Daroussin 		if (*dd < ndays)
173*61ba55bcSBaptiste Daroussin 			*dd += 1;
174*61ba55bcSBaptiste Daroussin 		else {
175*61ba55bcSBaptiste Daroussin 			if (*mm == 12) {
176*61ba55bcSBaptiste Daroussin 				*yy += 1;
177*61ba55bcSBaptiste Daroussin 				*mm = 1;
178*61ba55bcSBaptiste Daroussin 			} else
179*61ba55bcSBaptiste Daroussin 				*mm += 1;
180*61ba55bcSBaptiste Daroussin 			*dd = 1;
181*61ba55bcSBaptiste Daroussin 		}
182*61ba55bcSBaptiste Daroussin 		break;
183*61ba55bcSBaptiste Daroussin 	case UP_MONTH:
184*61ba55bcSBaptiste Daroussin 		if (*mm == 1) {
185*61ba55bcSBaptiste Daroussin 			*mm = 12;
186*61ba55bcSBaptiste Daroussin 			*yy -= 1;
187*61ba55bcSBaptiste Daroussin 		} else
188*61ba55bcSBaptiste Daroussin 			*mm -= 1;
189*61ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
190*61ba55bcSBaptiste Daroussin 		if (*dd > ndays)
191*61ba55bcSBaptiste Daroussin 			*dd = ndays;
192*61ba55bcSBaptiste Daroussin 		break;
193*61ba55bcSBaptiste Daroussin 	case DOWN_MONTH:
194*61ba55bcSBaptiste Daroussin 		if (*mm == 12) {
195*61ba55bcSBaptiste Daroussin 			*mm = 1;
196*61ba55bcSBaptiste Daroussin 			*yy += 1;
197*61ba55bcSBaptiste Daroussin 		} else
198*61ba55bcSBaptiste Daroussin 			*mm += 1;
199*61ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
200*61ba55bcSBaptiste Daroussin 		if (*dd > ndays)
201*61ba55bcSBaptiste Daroussin 			*dd = ndays;
202*61ba55bcSBaptiste Daroussin 		break;
203*61ba55bcSBaptiste Daroussin 	case UP_YEAR:
204*61ba55bcSBaptiste Daroussin 		*yy -= 1;
205*61ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
206*61ba55bcSBaptiste Daroussin 		if (*dd > ndays)
207*61ba55bcSBaptiste Daroussin 			*dd = ndays;
208*61ba55bcSBaptiste Daroussin 		break;
209*61ba55bcSBaptiste Daroussin 	case DOWN_YEAR:
210*61ba55bcSBaptiste Daroussin 		*yy += 1;
211*61ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
212*61ba55bcSBaptiste Daroussin 		if (*dd > ndays)
213*61ba55bcSBaptiste Daroussin 			*dd = ndays;
214*61ba55bcSBaptiste Daroussin 		break;
215*61ba55bcSBaptiste Daroussin 	}
216*61ba55bcSBaptiste Daroussin 
217*61ba55bcSBaptiste Daroussin 	if (*yy < minyear) {
218*61ba55bcSBaptiste Daroussin 		*yy = minyear;
219*61ba55bcSBaptiste Daroussin 		*mm = 1;
220*61ba55bcSBaptiste Daroussin 		*dd = 1;
221*61ba55bcSBaptiste Daroussin 	}
222*61ba55bcSBaptiste Daroussin 	if (*yy > maxyear) {
223*61ba55bcSBaptiste Daroussin 		*yy = maxyear;
224*61ba55bcSBaptiste Daroussin 		*mm = 12;
225*61ba55bcSBaptiste Daroussin 		*dd = 31;
226*61ba55bcSBaptiste Daroussin 	}
227*61ba55bcSBaptiste Daroussin }
228*61ba55bcSBaptiste Daroussin 
229*61ba55bcSBaptiste Daroussin static void
230*61ba55bcSBaptiste Daroussin drawsquare(struct bsddialog_conf *conf, WINDOW *win, enum elevation elev,
231*61ba55bcSBaptiste Daroussin     const char *fmt, int value, bool focus)
232*61ba55bcSBaptiste Daroussin {
233*61ba55bcSBaptiste Daroussin 	int h, l, w;
234*61ba55bcSBaptiste Daroussin 
235*61ba55bcSBaptiste Daroussin 	getmaxyx(win, h, w);
236*61ba55bcSBaptiste Daroussin 	draw_borders(conf, win, elev);
237*61ba55bcSBaptiste Daroussin 	if (focus) {
238*61ba55bcSBaptiste Daroussin 		l = 2 + w%2;
239*61ba55bcSBaptiste Daroussin 		wattron(win, t.dialog.arrowcolor);
240*61ba55bcSBaptiste Daroussin 		mvwhline(win, 0, w/2 - l/2,
241*61ba55bcSBaptiste Daroussin 		    conf->ascii_lines ? '^' : ACS_UARROW, l);
242*61ba55bcSBaptiste Daroussin 		mvwhline(win, h-1, w/2 - l/2,
243*61ba55bcSBaptiste Daroussin 		    conf->ascii_lines ? 'v' : ACS_DARROW, l);
244*61ba55bcSBaptiste Daroussin 		wattroff(win, t.dialog.arrowcolor);
245*61ba55bcSBaptiste Daroussin 	}
246*61ba55bcSBaptiste Daroussin 
247*61ba55bcSBaptiste Daroussin 	if (focus)
248*61ba55bcSBaptiste Daroussin 		wattron(win, t.menu.f_namecolor);
249*61ba55bcSBaptiste Daroussin 	if (strchr(fmt, 's') != NULL)
250*61ba55bcSBaptiste Daroussin 		mvwprintw(win, 1, 1, fmt, m[value - 1]);
251*61ba55bcSBaptiste Daroussin 	else
252*61ba55bcSBaptiste Daroussin 		mvwprintw(win, 1, 1, fmt, value);
253*61ba55bcSBaptiste Daroussin 	if (focus)
254*61ba55bcSBaptiste Daroussin 		wattroff(win, t.menu.f_namecolor);
255*61ba55bcSBaptiste Daroussin 
256*61ba55bcSBaptiste Daroussin 	wnoutrefresh(win);
257*61ba55bcSBaptiste Daroussin }
258*61ba55bcSBaptiste Daroussin 
259*61ba55bcSBaptiste Daroussin static void
260*61ba55bcSBaptiste Daroussin print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
261*61ba55bcSBaptiste Daroussin     bool active)
262*61ba55bcSBaptiste Daroussin {
263*61ba55bcSBaptiste Daroussin 	int ndays, i, y, x, wd, h, w;
264*61ba55bcSBaptiste Daroussin 
265*61ba55bcSBaptiste Daroussin 	getmaxyx(win, h, w);
266*61ba55bcSBaptiste Daroussin 	wclear(win);
267*61ba55bcSBaptiste Daroussin 	draw_borders(conf, win, RAISED);
268*61ba55bcSBaptiste Daroussin 	if (active) {
269*61ba55bcSBaptiste Daroussin 		wattron(win, t.dialog.arrowcolor);
270*61ba55bcSBaptiste Daroussin 		mvwhline(win, 0, 15, conf->ascii_lines ? '^' : ACS_UARROW, 4);
271*61ba55bcSBaptiste Daroussin 		mvwhline(win, h-1, 15, conf->ascii_lines ? 'v' : ACS_DARROW, 4);
272*61ba55bcSBaptiste Daroussin 		mvwvline(win, 3, 0, conf->ascii_lines ? '<' : ACS_LARROW, 3);
273*61ba55bcSBaptiste Daroussin 		mvwvline(win, 3, w-1, conf->ascii_lines ? '>' : ACS_RARROW, 3);
274*61ba55bcSBaptiste Daroussin 		wattroff(win, t.dialog.arrowcolor);
275*61ba55bcSBaptiste Daroussin 	}
276*61ba55bcSBaptiste Daroussin 
277*61ba55bcSBaptiste Daroussin 	mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat");
278*61ba55bcSBaptiste Daroussin 	ndays = month_days(yy, mm);
279*61ba55bcSBaptiste Daroussin 	y = 2;
280*61ba55bcSBaptiste Daroussin 	wd = week_day(yy, mm, 1);
281*61ba55bcSBaptiste Daroussin 	for (i = 1; i <= ndays; i++) {
282*61ba55bcSBaptiste Daroussin 		x = 5 + (4 * wd); /* x has to be 6 with week number */
283*61ba55bcSBaptiste Daroussin 		wmove(win, y, x);
284*61ba55bcSBaptiste Daroussin 		mvwprintw(win, y, x, "%2d", i);
285*61ba55bcSBaptiste Daroussin 		if (i == dd) {
286*61ba55bcSBaptiste Daroussin 			wattron(win, t.menu.f_namecolor);
287*61ba55bcSBaptiste Daroussin 			mvwprintw(win, y, x, "%2d", i);
288*61ba55bcSBaptiste Daroussin 			wattroff(win, t.menu.f_namecolor);
289*61ba55bcSBaptiste Daroussin 		}
290*61ba55bcSBaptiste Daroussin 		wd++;
291*61ba55bcSBaptiste Daroussin 		if (wd > 6) {
292*61ba55bcSBaptiste Daroussin 			wd = 0;
293*61ba55bcSBaptiste Daroussin 			y++;
294*61ba55bcSBaptiste Daroussin 		}
295*61ba55bcSBaptiste Daroussin 	}
296*61ba55bcSBaptiste Daroussin 
297*61ba55bcSBaptiste Daroussin 	wnoutrefresh(win);
298*61ba55bcSBaptiste Daroussin }
299*61ba55bcSBaptiste Daroussin 
300*61ba55bcSBaptiste Daroussin static int
301*61ba55bcSBaptiste Daroussin calendar_redraw(struct dialog *d, WINDOW *yy_win, WINDOW *mm_win,
302*61ba55bcSBaptiste Daroussin     WINDOW *dd_win)
303*61ba55bcSBaptiste Daroussin {
304*61ba55bcSBaptiste Daroussin 	int ycal, xcal;
305*61ba55bcSBaptiste Daroussin 
306*61ba55bcSBaptiste Daroussin 	if (d->built) {
307*61ba55bcSBaptiste Daroussin 		hide_dialog(d);
308*61ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
309*61ba55bcSBaptiste Daroussin 	}
310*61ba55bcSBaptiste Daroussin 	if (dialog_size_position(d, MINHCAL, MINWCAL, NULL) != 0)
311*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
312*61ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
313*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
314*61ba55bcSBaptiste Daroussin 	if (d->built)
315*61ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
316*61ba55bcSBaptiste Daroussin 	TEXTPAD(d, MINHCAL + HBUTTONS);
317*61ba55bcSBaptiste Daroussin 
318*61ba55bcSBaptiste Daroussin 	ycal = d->y + d->h - 15;
319*61ba55bcSBaptiste Daroussin 	xcal = d->x + d->w/2 - 17;
320*61ba55bcSBaptiste Daroussin 	mvwaddstr(d->widget, d->h - 16, d->w/2 - 17, "Month");
321*61ba55bcSBaptiste Daroussin 	update_box(d->conf, mm_win, ycal, xcal, 3, 17, RAISED);
322*61ba55bcSBaptiste Daroussin 	mvwaddstr(d->widget, d->h - 16, d->w/2, "Year");
323*61ba55bcSBaptiste Daroussin 	update_box(d->conf, yy_win, ycal, xcal + 17, 3, 17, RAISED);
324*61ba55bcSBaptiste Daroussin 	update_box(d->conf, dd_win, ycal + 3, xcal, 9, 34, RAISED);
325*61ba55bcSBaptiste Daroussin 	wnoutrefresh(d->widget);
326*61ba55bcSBaptiste Daroussin 
327*61ba55bcSBaptiste Daroussin 	return (0);
328*61ba55bcSBaptiste Daroussin }
329*61ba55bcSBaptiste Daroussin 
330*61ba55bcSBaptiste Daroussin int
331*61ba55bcSBaptiste Daroussin bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
332*61ba55bcSBaptiste Daroussin     int cols, unsigned int *year, unsigned int *month, unsigned int *day)
333*61ba55bcSBaptiste Daroussin {
334*61ba55bcSBaptiste Daroussin 	bool loop, focusbuttons;
335*61ba55bcSBaptiste Daroussin 	int retval, sel, yy, mm, dd;
336*61ba55bcSBaptiste Daroussin 	wint_t input;
337*61ba55bcSBaptiste Daroussin 	WINDOW *yy_win, *mm_win, *dd_win;
338*61ba55bcSBaptiste Daroussin 	struct dialog d;
339*61ba55bcSBaptiste Daroussin 
340*61ba55bcSBaptiste Daroussin 	CHECK_PTR(year);
341*61ba55bcSBaptiste Daroussin 	CHECK_PTR(month);
342*61ba55bcSBaptiste Daroussin 	CHECK_PTR(day);
343*61ba55bcSBaptiste Daroussin 	minyear = MIN_YEAR_CAL;
344*61ba55bcSBaptiste Daroussin 	maxyear = MAX_YEAR_CAL;
345*61ba55bcSBaptiste Daroussin 	init_date(year, month, day, &yy, &mm, &dd);
346*61ba55bcSBaptiste Daroussin 
347*61ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
348*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
349*61ba55bcSBaptiste Daroussin 	set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
350*61ba55bcSBaptiste Daroussin 	if ((yy_win = newwin(1, 1, 1, 1)) == NULL)
351*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for yy");
352*61ba55bcSBaptiste Daroussin 	wbkgd(yy_win, t.dialog.color);
353*61ba55bcSBaptiste Daroussin 	if ((mm_win = newwin(1, 1, 1, 1)) == NULL)
354*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for mm");
355*61ba55bcSBaptiste Daroussin 	wbkgd(mm_win, t.dialog.color);
356*61ba55bcSBaptiste Daroussin 	if ((dd_win = newwin(1, 1, 1, 1)) == NULL)
357*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for dd");
358*61ba55bcSBaptiste Daroussin 	wbkgd(dd_win, t.dialog.color);
359*61ba55bcSBaptiste Daroussin 	if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
360*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
361*61ba55bcSBaptiste Daroussin 
362*61ba55bcSBaptiste Daroussin 	sel = -1;
363*61ba55bcSBaptiste Daroussin 	loop = focusbuttons = true;
364*61ba55bcSBaptiste Daroussin 	while (loop) {
365*61ba55bcSBaptiste Daroussin 		drawsquare(conf, mm_win, RAISED, "%15s", mm, sel == 0);
366*61ba55bcSBaptiste Daroussin 		drawsquare(conf, yy_win, RAISED, "%15d", yy, sel == 1);
367*61ba55bcSBaptiste Daroussin 		print_calendar(conf, dd_win, yy, mm, dd, sel == 2);
368*61ba55bcSBaptiste Daroussin 		doupdate();
369*61ba55bcSBaptiste Daroussin 
370*61ba55bcSBaptiste Daroussin 		if (get_wch(&input) == ERR)
371*61ba55bcSBaptiste Daroussin 			continue;
372*61ba55bcSBaptiste Daroussin 		switch(input) {
373*61ba55bcSBaptiste Daroussin 		case KEY_ENTER:
374*61ba55bcSBaptiste Daroussin 		case 10: /* Enter */
375*61ba55bcSBaptiste Daroussin 			if (focusbuttons || conf->button.always_active) {
376*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
377*61ba55bcSBaptiste Daroussin 				loop = false;
378*61ba55bcSBaptiste Daroussin 			}
379*61ba55bcSBaptiste Daroussin 			break;
380*61ba55bcSBaptiste Daroussin 		case 27: /* Esc */
381*61ba55bcSBaptiste Daroussin 			if (conf->key.enable_esc) {
382*61ba55bcSBaptiste Daroussin 				retval = BSDDIALOG_ESC;
383*61ba55bcSBaptiste Daroussin 				loop = false;
384*61ba55bcSBaptiste Daroussin 			}
385*61ba55bcSBaptiste Daroussin 			break;
386*61ba55bcSBaptiste Daroussin 		case '\t': /* TAB */
387*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
388*61ba55bcSBaptiste Daroussin 				d.bs.curr++;
389*61ba55bcSBaptiste Daroussin 				if (d.bs.curr >= (int)d.bs.nbuttons) {
390*61ba55bcSBaptiste Daroussin 					focusbuttons = false;
391*61ba55bcSBaptiste Daroussin 					sel = 0;
392*61ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
393*61ba55bcSBaptiste Daroussin 					    0 : -1;
394*61ba55bcSBaptiste Daroussin 				}
395*61ba55bcSBaptiste Daroussin 			} else {
396*61ba55bcSBaptiste Daroussin 				sel++;
397*61ba55bcSBaptiste Daroussin 				if (sel > 2) {
398*61ba55bcSBaptiste Daroussin 					focusbuttons = true;
399*61ba55bcSBaptiste Daroussin 					sel = -1;
400*61ba55bcSBaptiste Daroussin 					d.bs.curr = 0;
401*61ba55bcSBaptiste Daroussin 				}
402*61ba55bcSBaptiste Daroussin 			}
403*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
404*61ba55bcSBaptiste Daroussin 			break;
405*61ba55bcSBaptiste Daroussin 		case KEY_RIGHT:
406*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
407*61ba55bcSBaptiste Daroussin 				d.bs.curr++;
408*61ba55bcSBaptiste Daroussin 				if (d.bs.curr >= (int)d.bs.nbuttons) {
409*61ba55bcSBaptiste Daroussin 					focusbuttons = false;
410*61ba55bcSBaptiste Daroussin 					sel = 0;
411*61ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
412*61ba55bcSBaptiste Daroussin 					    0 : -1;
413*61ba55bcSBaptiste Daroussin 				}
414*61ba55bcSBaptiste Daroussin 			} else if (sel == 2) {
415*61ba55bcSBaptiste Daroussin 				datectl(RIGHT_DAY, &yy, &mm, &dd);
416*61ba55bcSBaptiste Daroussin 			} else { /* Month or Year*/
417*61ba55bcSBaptiste Daroussin 				sel++;
418*61ba55bcSBaptiste Daroussin 			}
419*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
420*61ba55bcSBaptiste Daroussin 			break;
421*61ba55bcSBaptiste Daroussin 		case KEY_LEFT:
422*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
423*61ba55bcSBaptiste Daroussin 				d.bs.curr--;
424*61ba55bcSBaptiste Daroussin 				if (d.bs.curr < 0) {
425*61ba55bcSBaptiste Daroussin 					focusbuttons = false;
426*61ba55bcSBaptiste Daroussin 					sel = 2;
427*61ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
428*61ba55bcSBaptiste Daroussin 					    0 : -1;
429*61ba55bcSBaptiste Daroussin 				}
430*61ba55bcSBaptiste Daroussin 			} else if (sel == 2) {
431*61ba55bcSBaptiste Daroussin 				datectl(LEFT_DAY, &yy, &mm, &dd);
432*61ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
433*61ba55bcSBaptiste Daroussin 				sel = 0;
434*61ba55bcSBaptiste Daroussin 			} else { /* sel = 0, Month */
435*61ba55bcSBaptiste Daroussin 				focusbuttons = true;
436*61ba55bcSBaptiste Daroussin 				sel = -1;
437*61ba55bcSBaptiste Daroussin 				d.bs.curr = 0;
438*61ba55bcSBaptiste Daroussin 			}
439*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
440*61ba55bcSBaptiste Daroussin 			break;
441*61ba55bcSBaptiste Daroussin 		case KEY_UP:
442*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
443*61ba55bcSBaptiste Daroussin 				sel = 2;
444*61ba55bcSBaptiste Daroussin 				focusbuttons = false;
445*61ba55bcSBaptiste Daroussin 				d.bs.curr = conf->button.always_active ? 0 : -1;
446*61ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
447*61ba55bcSBaptiste Daroussin 			} else if (sel == 0) {
448*61ba55bcSBaptiste Daroussin 				datectl(UP_MONTH, &yy, &mm, &dd);
449*61ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
450*61ba55bcSBaptiste Daroussin 				datectl(UP_YEAR, &yy, &mm, &dd);
451*61ba55bcSBaptiste Daroussin 			} else { /* sel = 2 */
452*61ba55bcSBaptiste Daroussin 				datectl(UP_DAY, &yy, &mm, &dd);
453*61ba55bcSBaptiste Daroussin 			}
454*61ba55bcSBaptiste Daroussin 			break;
455*61ba55bcSBaptiste Daroussin 		case KEY_DOWN:
456*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
457*61ba55bcSBaptiste Daroussin 				break;
458*61ba55bcSBaptiste Daroussin 			} else if (sel == 0) {
459*61ba55bcSBaptiste Daroussin 				datectl(DOWN_MONTH, &yy, &mm, &dd);
460*61ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
461*61ba55bcSBaptiste Daroussin 				datectl(DOWN_YEAR, &yy, &mm, &dd);
462*61ba55bcSBaptiste Daroussin 			} else { /* sel = 2 */
463*61ba55bcSBaptiste Daroussin 				datectl(DOWN_DAY, &yy, &mm, &dd);
464*61ba55bcSBaptiste Daroussin 			}
465*61ba55bcSBaptiste Daroussin 			break;
466*61ba55bcSBaptiste Daroussin 		case KEY_HOME:
467*61ba55bcSBaptiste Daroussin 			datectl(UP_MONTH, &yy, &mm, &dd);
468*61ba55bcSBaptiste Daroussin 			break;
469*61ba55bcSBaptiste Daroussin 		case KEY_END:
470*61ba55bcSBaptiste Daroussin 			datectl(DOWN_MONTH, &yy, &mm, &dd);
471*61ba55bcSBaptiste Daroussin 			break;
472*61ba55bcSBaptiste Daroussin 		case KEY_PPAGE:
473*61ba55bcSBaptiste Daroussin 			datectl(UP_YEAR, &yy, &mm, &dd);
474*61ba55bcSBaptiste Daroussin 			break;
475*61ba55bcSBaptiste Daroussin 		case KEY_NPAGE:
476*61ba55bcSBaptiste Daroussin 			datectl(DOWN_YEAR, &yy, &mm, &dd);
477*61ba55bcSBaptiste Daroussin 			break;
478*61ba55bcSBaptiste Daroussin 		case KEY_F(1):
479*61ba55bcSBaptiste Daroussin 			if (conf->key.f1_file == NULL &&
480*61ba55bcSBaptiste Daroussin 			    conf->key.f1_message == NULL)
481*61ba55bcSBaptiste Daroussin 				break;
482*61ba55bcSBaptiste Daroussin 			if (f1help_dialog(conf) != 0)
483*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
484*61ba55bcSBaptiste Daroussin 			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
485*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
486*61ba55bcSBaptiste Daroussin 			break;
487*61ba55bcSBaptiste Daroussin 		case KEY_RESIZE:
488*61ba55bcSBaptiste Daroussin 			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
489*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
490*61ba55bcSBaptiste Daroussin 			break;
491*61ba55bcSBaptiste Daroussin 		default:
492*61ba55bcSBaptiste Daroussin 			if (shortcut_buttons(input, &d.bs)) {
493*61ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
494*61ba55bcSBaptiste Daroussin 				doupdate();
495*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
496*61ba55bcSBaptiste Daroussin 				loop = false;
497*61ba55bcSBaptiste Daroussin 			}
498*61ba55bcSBaptiste Daroussin 		}
499*61ba55bcSBaptiste Daroussin 	}
500*61ba55bcSBaptiste Daroussin 
501*61ba55bcSBaptiste Daroussin 	*year  = yy;
502*61ba55bcSBaptiste Daroussin 	*month = mm;
503*61ba55bcSBaptiste Daroussin 	*day   = dd;
504*61ba55bcSBaptiste Daroussin 
505*61ba55bcSBaptiste Daroussin 	delwin(yy_win);
506*61ba55bcSBaptiste Daroussin 	delwin(mm_win);
507*61ba55bcSBaptiste Daroussin 	delwin(dd_win);
508*61ba55bcSBaptiste Daroussin 	end_dialog(&d);
509*61ba55bcSBaptiste Daroussin 
510*61ba55bcSBaptiste Daroussin 	return (retval);
511*61ba55bcSBaptiste Daroussin }
512*61ba55bcSBaptiste Daroussin 
513*61ba55bcSBaptiste Daroussin static int datebox_redraw(struct dialog *d, struct dateitem *di)
514*61ba55bcSBaptiste Daroussin {
515*61ba55bcSBaptiste Daroussin 	int y, x;
516*61ba55bcSBaptiste Daroussin 
517*61ba55bcSBaptiste Daroussin 	if (d->built) {
518*61ba55bcSBaptiste Daroussin 		hide_dialog(d);
519*61ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
520*61ba55bcSBaptiste Daroussin 	}
521*61ba55bcSBaptiste Daroussin 	if (dialog_size_position(d, 3 /*windows*/, MINWDATE, NULL) != 0)
522*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
523*61ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
524*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
525*61ba55bcSBaptiste Daroussin 	if (d->built)
526*61ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
527*61ba55bcSBaptiste Daroussin 	TEXTPAD(d, 3 /*windows*/ + HBUTTONS);
528*61ba55bcSBaptiste Daroussin 
529*61ba55bcSBaptiste Daroussin 	y = d->y + d->h - 6;
530*61ba55bcSBaptiste Daroussin 	x = (d->x + d->w / 2) - 11;
531*61ba55bcSBaptiste Daroussin 	update_box(d->conf, di[0].win, y, x, 3, di[0].width, LOWERED);
532*61ba55bcSBaptiste Daroussin 	mvwaddch(d->widget, d->h - 5, x - d->x + di[0].width, '/');
533*61ba55bcSBaptiste Daroussin 	x += di[0].width + 1;
534*61ba55bcSBaptiste Daroussin 	update_box(d->conf, di[1].win, y, x , 3, di[1].width, LOWERED);
535*61ba55bcSBaptiste Daroussin 	mvwaddch(d->widget, d->h - 5, x - d->x + di[1].width, '/');
536*61ba55bcSBaptiste Daroussin 	x += di[1].width + 1;
537*61ba55bcSBaptiste Daroussin 	update_box(d->conf, di[2].win, y, x, 3, di[2].width, LOWERED);
538*61ba55bcSBaptiste Daroussin 	wnoutrefresh(d->widget);
539*61ba55bcSBaptiste Daroussin 
540*61ba55bcSBaptiste Daroussin 	return (0);
541*61ba55bcSBaptiste Daroussin }
542*61ba55bcSBaptiste Daroussin 
543*61ba55bcSBaptiste Daroussin static int
544*61ba55bcSBaptiste Daroussin build_dateitem(const char *format, int *yy, int *mm, int *dd,
545*61ba55bcSBaptiste Daroussin     struct dateitem *dt)
546*61ba55bcSBaptiste Daroussin {
547*61ba55bcSBaptiste Daroussin 	int i;
548*61ba55bcSBaptiste Daroussin 	wchar_t *wformat;
549*61ba55bcSBaptiste Daroussin 	struct dateitem init[3] = {
550*61ba55bcSBaptiste Daroussin 		{UP_YEAR,  DOWN_YEAR,  NULL, 6,  "%4d",  yy},
551*61ba55bcSBaptiste Daroussin 		{UP_MONTH, DOWN_MONTH, NULL, 11, "%9s",  mm},
552*61ba55bcSBaptiste Daroussin 		{LEFT_DAY, RIGHT_DAY,  NULL, 4,  "%02d", dd},
553*61ba55bcSBaptiste Daroussin 	};
554*61ba55bcSBaptiste Daroussin 
555*61ba55bcSBaptiste Daroussin 	for (i = 0; i < 3; i++) {
556*61ba55bcSBaptiste Daroussin 		if ((init[i].win = newwin(1, 1, 1, 1)) == NULL)
557*61ba55bcSBaptiste Daroussin 			RETURN_FMTERROR("Cannot build WINDOW dateitem[%d]", i);
558*61ba55bcSBaptiste Daroussin 		wbkgd(init[i].win, t.dialog.color);
559*61ba55bcSBaptiste Daroussin 	}
560*61ba55bcSBaptiste Daroussin 
561*61ba55bcSBaptiste Daroussin 	if ((wformat = alloc_mbstows(CHECK_STR(format))) == NULL)
562*61ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot allocate conf.date.format in wchar_t*");
563*61ba55bcSBaptiste Daroussin 	if (format == NULL || wcscmp(wformat, L"d/m/y") == 0) {
564*61ba55bcSBaptiste Daroussin 		dt[0] = init[2];
565*61ba55bcSBaptiste Daroussin 		dt[1] = init[1];
566*61ba55bcSBaptiste Daroussin 		dt[2] = init[0];
567*61ba55bcSBaptiste Daroussin 	} else if (wcscmp(wformat, L"m/d/y") == 0) {
568*61ba55bcSBaptiste Daroussin 		dt[0] = init[1];
569*61ba55bcSBaptiste Daroussin 		dt[1] = init[2];
570*61ba55bcSBaptiste Daroussin 		dt[2] = init[0];
571*61ba55bcSBaptiste Daroussin 	} else if (wcscmp(wformat, L"y/m/d") == 0) {
572*61ba55bcSBaptiste Daroussin 		dt[0] = init[0];
573*61ba55bcSBaptiste Daroussin 		dt[1] = init[1];
574*61ba55bcSBaptiste Daroussin 		dt[2] = init[2];
575*61ba55bcSBaptiste Daroussin 	} else
576*61ba55bcSBaptiste Daroussin 		RETURN_FMTERROR("Invalid conf.date.format=\"%s\"", format);
577*61ba55bcSBaptiste Daroussin 	free(wformat);
578*61ba55bcSBaptiste Daroussin 
579*61ba55bcSBaptiste Daroussin 	return (0);
580*61ba55bcSBaptiste Daroussin }
581*61ba55bcSBaptiste Daroussin 
582*61ba55bcSBaptiste Daroussin int
583*61ba55bcSBaptiste Daroussin bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
584*61ba55bcSBaptiste Daroussin     int cols, unsigned int *year, unsigned int *month, unsigned int *day)
585*61ba55bcSBaptiste Daroussin {
586*61ba55bcSBaptiste Daroussin 	bool loop, focusbuttons;
587*61ba55bcSBaptiste Daroussin 	int retval, i, sel, yy, mm, dd;
588*61ba55bcSBaptiste Daroussin 	wint_t input;
589*61ba55bcSBaptiste Daroussin 	struct dateitem  di[3];
590*61ba55bcSBaptiste Daroussin 	struct dialog d;
591*61ba55bcSBaptiste Daroussin 
592*61ba55bcSBaptiste Daroussin 	CHECK_PTR(year);
593*61ba55bcSBaptiste Daroussin 	CHECK_PTR(month);
594*61ba55bcSBaptiste Daroussin 	CHECK_PTR(day);
595*61ba55bcSBaptiste Daroussin 	minyear = MIN_YEAR_DATE;
596*61ba55bcSBaptiste Daroussin 	maxyear = MAX_YEAR_DATE;
597*61ba55bcSBaptiste Daroussin 	init_date(year, month, day, &yy, &mm, &dd);
598*61ba55bcSBaptiste Daroussin 
599*61ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
600*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
601*61ba55bcSBaptiste Daroussin 	set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
602*61ba55bcSBaptiste Daroussin 	if (build_dateitem(conf->date.format, &yy, &mm, &dd, di) != 0)
603*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
604*61ba55bcSBaptiste Daroussin 	if (datebox_redraw(&d, di) != 0)
605*61ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
606*61ba55bcSBaptiste Daroussin 
607*61ba55bcSBaptiste Daroussin 	sel = -1;
608*61ba55bcSBaptiste Daroussin 	loop = focusbuttons = true;
609*61ba55bcSBaptiste Daroussin 	while (loop) {
610*61ba55bcSBaptiste Daroussin 		for (i = 0; i < 3; i++)
611*61ba55bcSBaptiste Daroussin 			drawsquare(conf, di[i].win, LOWERED, di[i].fmt,
612*61ba55bcSBaptiste Daroussin 			    *di[i].value, sel == i);
613*61ba55bcSBaptiste Daroussin 		doupdate();
614*61ba55bcSBaptiste Daroussin 
615*61ba55bcSBaptiste Daroussin 		if (get_wch(&input) == ERR)
616*61ba55bcSBaptiste Daroussin 			continue;
617*61ba55bcSBaptiste Daroussin 		switch(input) {
618*61ba55bcSBaptiste Daroussin 		case KEY_ENTER:
619*61ba55bcSBaptiste Daroussin 		case 10: /* Enter */
620*61ba55bcSBaptiste Daroussin 			if (focusbuttons || conf->button.always_active) {
621*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
622*61ba55bcSBaptiste Daroussin 				loop = false;
623*61ba55bcSBaptiste Daroussin 			}
624*61ba55bcSBaptiste Daroussin 			break;
625*61ba55bcSBaptiste Daroussin 		case 27: /* Esc */
626*61ba55bcSBaptiste Daroussin 			if (conf->key.enable_esc) {
627*61ba55bcSBaptiste Daroussin 				retval = BSDDIALOG_ESC;
628*61ba55bcSBaptiste Daroussin 				loop = false;
629*61ba55bcSBaptiste Daroussin 			}
630*61ba55bcSBaptiste Daroussin 			break;
631*61ba55bcSBaptiste Daroussin 		case KEY_RIGHT:
632*61ba55bcSBaptiste Daroussin 		case '\t': /* TAB */
633*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
634*61ba55bcSBaptiste Daroussin 				d.bs.curr++;
635*61ba55bcSBaptiste Daroussin 				focusbuttons = d.bs.curr < (int)d.bs.nbuttons ?
636*61ba55bcSBaptiste Daroussin 				    true : false;
637*61ba55bcSBaptiste Daroussin 				if (focusbuttons == false) {
638*61ba55bcSBaptiste Daroussin 					sel = 0;
639*61ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
640*61ba55bcSBaptiste Daroussin 					    0 : -1;
641*61ba55bcSBaptiste Daroussin 				}
642*61ba55bcSBaptiste Daroussin 			} else {
643*61ba55bcSBaptiste Daroussin 				sel++;
644*61ba55bcSBaptiste Daroussin 				focusbuttons = sel > 2 ? true : false;
645*61ba55bcSBaptiste Daroussin 				if (focusbuttons) {
646*61ba55bcSBaptiste Daroussin 					d.bs.curr = 0;
647*61ba55bcSBaptiste Daroussin 				}
648*61ba55bcSBaptiste Daroussin 			}
649*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
650*61ba55bcSBaptiste Daroussin 			break;
651*61ba55bcSBaptiste Daroussin 		case KEY_LEFT:
652*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
653*61ba55bcSBaptiste Daroussin 				d.bs.curr--;
654*61ba55bcSBaptiste Daroussin 				focusbuttons = d.bs.curr < 0 ? false : true;
655*61ba55bcSBaptiste Daroussin 				if (focusbuttons == false) {
656*61ba55bcSBaptiste Daroussin 					sel = 2;
657*61ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
658*61ba55bcSBaptiste Daroussin 					    0 : -1;
659*61ba55bcSBaptiste Daroussin 				}
660*61ba55bcSBaptiste Daroussin 			} else {
661*61ba55bcSBaptiste Daroussin 				sel--;
662*61ba55bcSBaptiste Daroussin 				focusbuttons = sel < 0 ? true : false;
663*61ba55bcSBaptiste Daroussin 				if (focusbuttons)
664*61ba55bcSBaptiste Daroussin 					d.bs.curr = (int)d.bs.nbuttons - 1;
665*61ba55bcSBaptiste Daroussin 			}
666*61ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
667*61ba55bcSBaptiste Daroussin 			break;
668*61ba55bcSBaptiste Daroussin 		case KEY_UP:
669*61ba55bcSBaptiste Daroussin 			if (focusbuttons) {
670*61ba55bcSBaptiste Daroussin 				sel = 0;
671*61ba55bcSBaptiste Daroussin 				focusbuttons = false;
672*61ba55bcSBaptiste Daroussin 				d.bs.curr = conf->button.always_active ? 0 : -1;
673*61ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
674*61ba55bcSBaptiste Daroussin 			} else {
675*61ba55bcSBaptiste Daroussin 				datectl(di[sel].up, &yy, &mm, &dd);
676*61ba55bcSBaptiste Daroussin 			}
677*61ba55bcSBaptiste Daroussin 			break;
678*61ba55bcSBaptiste Daroussin 		case KEY_DOWN:
679*61ba55bcSBaptiste Daroussin 			if (focusbuttons)
680*61ba55bcSBaptiste Daroussin 				break;
681*61ba55bcSBaptiste Daroussin 			datectl(di[sel].down, &yy, &mm, &dd);
682*61ba55bcSBaptiste Daroussin 			break;
683*61ba55bcSBaptiste Daroussin 		case KEY_F(1):
684*61ba55bcSBaptiste Daroussin 			if (conf->key.f1_file == NULL &&
685*61ba55bcSBaptiste Daroussin 			    conf->key.f1_message == NULL)
686*61ba55bcSBaptiste Daroussin 				break;
687*61ba55bcSBaptiste Daroussin 			if (f1help_dialog(conf) != 0)
688*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
689*61ba55bcSBaptiste Daroussin 			if (datebox_redraw(&d, di) != 0)
690*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
691*61ba55bcSBaptiste Daroussin 			break;
692*61ba55bcSBaptiste Daroussin 		case KEY_RESIZE:
693*61ba55bcSBaptiste Daroussin 			if (datebox_redraw(&d, di) != 0)
694*61ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
695*61ba55bcSBaptiste Daroussin 			break;
696*61ba55bcSBaptiste Daroussin 		default:
697*61ba55bcSBaptiste Daroussin 			if (shortcut_buttons(input, &d.bs)) {
698*61ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
699*61ba55bcSBaptiste Daroussin 				doupdate();
700*61ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
701*61ba55bcSBaptiste Daroussin 				loop = false;
702*61ba55bcSBaptiste Daroussin 			}
703*61ba55bcSBaptiste Daroussin 		}
704*61ba55bcSBaptiste Daroussin 	}
705*61ba55bcSBaptiste Daroussin 
706*61ba55bcSBaptiste Daroussin 	*year  = yy;
707*61ba55bcSBaptiste Daroussin 	*month = mm;
708*61ba55bcSBaptiste Daroussin 	*day   = dd;
709*61ba55bcSBaptiste Daroussin 
710*61ba55bcSBaptiste Daroussin 	for (i = 0; i < 3 ; i++)
711*61ba55bcSBaptiste Daroussin 		delwin(di[i].win);
712*61ba55bcSBaptiste Daroussin 	end_dialog(&d);
713*61ba55bcSBaptiste Daroussin 
714*61ba55bcSBaptiste Daroussin 	return (retval);
715*61ba55bcSBaptiste Daroussin }