xref: /freebsd/contrib/bsddialog/lib/datebox.c (revision a6d8be451f62d425b71a4874f7d4e133b9fb393c)
161ba55bcSBaptiste Daroussin /*-
261ba55bcSBaptiste Daroussin  * SPDX-License-Identifier: BSD-2-Clause
361ba55bcSBaptiste Daroussin  *
4*a6d8be45SAlfonso S. Siciliano  * Copyright (c) 2022-2024 Alfonso Sabato Siciliano
561ba55bcSBaptiste Daroussin  *
661ba55bcSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
761ba55bcSBaptiste Daroussin  * modification, are permitted provided that the following conditions
861ba55bcSBaptiste Daroussin  * are met:
961ba55bcSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
1061ba55bcSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer.
1161ba55bcSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
1261ba55bcSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
1361ba55bcSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
1461ba55bcSBaptiste Daroussin  *
1561ba55bcSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1661ba55bcSBaptiste Daroussin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1761ba55bcSBaptiste Daroussin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1861ba55bcSBaptiste Daroussin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1961ba55bcSBaptiste Daroussin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2061ba55bcSBaptiste Daroussin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2161ba55bcSBaptiste Daroussin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2261ba55bcSBaptiste Daroussin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2361ba55bcSBaptiste Daroussin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2461ba55bcSBaptiste Daroussin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2561ba55bcSBaptiste Daroussin  * SUCH DAMAGE.
2661ba55bcSBaptiste Daroussin  */
2761ba55bcSBaptiste Daroussin 
2861ba55bcSBaptiste Daroussin #include <curses.h>
2961ba55bcSBaptiste Daroussin #include <stdlib.h>
3061ba55bcSBaptiste Daroussin #include <string.h>
3161ba55bcSBaptiste Daroussin 
3261ba55bcSBaptiste Daroussin #include "bsddialog.h"
3361ba55bcSBaptiste Daroussin #include "bsddialog_theme.h"
3461ba55bcSBaptiste Daroussin #include "lib_util.h"
3561ba55bcSBaptiste Daroussin 
3661ba55bcSBaptiste Daroussin /* Calendar */
3761ba55bcSBaptiste Daroussin #define MIN_YEAR_CAL   0
3861ba55bcSBaptiste Daroussin #define MAX_YEAR_CAL   999999999
3961ba55bcSBaptiste Daroussin #define MINHCAL        13
4061ba55bcSBaptiste Daroussin #define MINWCAL        36 /* 34 calendar, 1 + 1 margins */
4161ba55bcSBaptiste Daroussin /* Datebox */
4261ba55bcSBaptiste Daroussin #define MIN_YEAR_DATE  0
4361ba55bcSBaptiste Daroussin #define MAX_YEAR_DATE  9999
4461ba55bcSBaptiste Daroussin #define MINWDATE       23 /* 3 windows and their borders */
4561ba55bcSBaptiste Daroussin 
4661ba55bcSBaptiste Daroussin #define ISLEAP(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
4761ba55bcSBaptiste Daroussin 
4861ba55bcSBaptiste Daroussin static int minyear;
4961ba55bcSBaptiste Daroussin static int maxyear;
5061ba55bcSBaptiste Daroussin 
5161ba55bcSBaptiste Daroussin static const char *m[12] = {
5261ba55bcSBaptiste Daroussin 	"January",
5361ba55bcSBaptiste Daroussin 	"February",
5461ba55bcSBaptiste Daroussin 	"March",
5561ba55bcSBaptiste Daroussin 	"April",
5661ba55bcSBaptiste Daroussin 	"May",
5761ba55bcSBaptiste Daroussin 	"June",
5861ba55bcSBaptiste Daroussin 	"July",
5961ba55bcSBaptiste Daroussin 	"August",
6061ba55bcSBaptiste Daroussin 	"September",
6161ba55bcSBaptiste Daroussin 	"October",
6261ba55bcSBaptiste Daroussin 	"November",
6361ba55bcSBaptiste Daroussin 	"December"
6461ba55bcSBaptiste Daroussin };
6561ba55bcSBaptiste Daroussin 
6661ba55bcSBaptiste Daroussin enum operation {
6761ba55bcSBaptiste Daroussin 	UP_DAY,
6861ba55bcSBaptiste Daroussin 	DOWN_DAY,
6961ba55bcSBaptiste Daroussin 	LEFT_DAY,
7061ba55bcSBaptiste Daroussin 	RIGHT_DAY,
7161ba55bcSBaptiste Daroussin 	UP_MONTH,
7261ba55bcSBaptiste Daroussin 	DOWN_MONTH,
7361ba55bcSBaptiste Daroussin 	UP_YEAR,
7461ba55bcSBaptiste Daroussin 	DOWN_YEAR
7561ba55bcSBaptiste Daroussin };
7661ba55bcSBaptiste Daroussin 
7761ba55bcSBaptiste Daroussin /* private datebox item */
7861ba55bcSBaptiste Daroussin struct dateitem {
7961ba55bcSBaptiste Daroussin 	enum operation up;
8061ba55bcSBaptiste Daroussin 	enum operation down;
8161ba55bcSBaptiste Daroussin 	WINDOW *win;
8261ba55bcSBaptiste Daroussin 	int width;
8361ba55bcSBaptiste Daroussin 	const char *fmt;
8461ba55bcSBaptiste Daroussin 	int *value;
8561ba55bcSBaptiste Daroussin };
8661ba55bcSBaptiste Daroussin 
8761ba55bcSBaptiste Daroussin static int month_days(int yy, int mm)
8861ba55bcSBaptiste Daroussin {
8961ba55bcSBaptiste Daroussin 	int days;
9061ba55bcSBaptiste Daroussin 
9161ba55bcSBaptiste Daroussin 	if (mm == 2)
9261ba55bcSBaptiste Daroussin 		days = ISLEAP(yy) ? 29 : 28;
9361ba55bcSBaptiste Daroussin 	else if (mm == 4 || mm == 6 || mm == 9 || mm == 11)
9461ba55bcSBaptiste Daroussin 		days = 30;
9561ba55bcSBaptiste Daroussin 	else
9661ba55bcSBaptiste Daroussin 		days = 31;
9761ba55bcSBaptiste Daroussin 
9861ba55bcSBaptiste Daroussin 	return (days);
9961ba55bcSBaptiste Daroussin }
10061ba55bcSBaptiste Daroussin 
10161ba55bcSBaptiste Daroussin static int week_day(int yy, int mm, int dd)
10261ba55bcSBaptiste Daroussin {
10361ba55bcSBaptiste Daroussin 	int wd;
10461ba55bcSBaptiste Daroussin 
10561ba55bcSBaptiste Daroussin 	dd += mm < 3 ? yy-- : yy - 2;
10661ba55bcSBaptiste Daroussin 	wd = 23*mm/9 + dd + 4 + yy/4 - yy/100 + yy/400;
10761ba55bcSBaptiste Daroussin 	wd %= 7;
10861ba55bcSBaptiste Daroussin 
10961ba55bcSBaptiste Daroussin 	return (wd);
11061ba55bcSBaptiste Daroussin }
11161ba55bcSBaptiste Daroussin 
11261ba55bcSBaptiste Daroussin static void
11361ba55bcSBaptiste Daroussin init_date(unsigned int *year, unsigned int *month, unsigned int *day, int *yy,
11461ba55bcSBaptiste Daroussin     int *mm, int *dd)
11561ba55bcSBaptiste Daroussin {
11661ba55bcSBaptiste Daroussin 	*yy = MIN(*year, (unsigned int)maxyear);
11761ba55bcSBaptiste Daroussin 	if (*yy < minyear)
11861ba55bcSBaptiste Daroussin 		*yy = minyear;
11961ba55bcSBaptiste Daroussin 	*mm = MIN(*month, 12);
12061ba55bcSBaptiste Daroussin 	if (*mm == 0)
12161ba55bcSBaptiste Daroussin 		*mm = 1;
12261ba55bcSBaptiste Daroussin 	*dd = (*day == 0) ? 1 : *day;
12361ba55bcSBaptiste Daroussin 	if (*dd > month_days(*yy, *mm))
12461ba55bcSBaptiste Daroussin 		*dd = month_days(*yy, *mm);
12561ba55bcSBaptiste Daroussin }
12661ba55bcSBaptiste Daroussin 
12761ba55bcSBaptiste Daroussin static void datectl(enum operation op, int *yy, int *mm, int *dd)
12861ba55bcSBaptiste Daroussin {
12961ba55bcSBaptiste Daroussin 	int ndays;
13061ba55bcSBaptiste Daroussin 
13161ba55bcSBaptiste Daroussin 	ndays = month_days(*yy, *mm);
13261ba55bcSBaptiste Daroussin 
13361ba55bcSBaptiste Daroussin 	switch (op) {
13461ba55bcSBaptiste Daroussin 	case UP_DAY:
13561ba55bcSBaptiste Daroussin 		if (*dd > 7)
13661ba55bcSBaptiste Daroussin 			*dd -= 7;
13761ba55bcSBaptiste Daroussin 		else {
13861ba55bcSBaptiste Daroussin 			if (*mm == 1) {
13961ba55bcSBaptiste Daroussin 				*yy -= 1;
14061ba55bcSBaptiste Daroussin 				*mm = 12;
14161ba55bcSBaptiste Daroussin 			} else
14261ba55bcSBaptiste Daroussin 				*mm -= 1;
14361ba55bcSBaptiste Daroussin 			ndays = month_days(*yy, *mm);
14461ba55bcSBaptiste Daroussin 			*dd = ndays - abs(7 - *dd);
14561ba55bcSBaptiste Daroussin 		}
14661ba55bcSBaptiste Daroussin 		break;
14761ba55bcSBaptiste Daroussin 	case DOWN_DAY:
14861ba55bcSBaptiste Daroussin 		if (*dd + 7 < ndays)
14961ba55bcSBaptiste Daroussin 			*dd += 7;
15061ba55bcSBaptiste Daroussin 		else {
15161ba55bcSBaptiste Daroussin 			if (*mm == 12) {
15261ba55bcSBaptiste Daroussin 				*yy += 1;
15361ba55bcSBaptiste Daroussin 				*mm = 1;
15461ba55bcSBaptiste Daroussin 			} else
15561ba55bcSBaptiste Daroussin 				*mm += 1;
15661ba55bcSBaptiste Daroussin 			*dd = *dd + 7 - ndays;
15761ba55bcSBaptiste Daroussin 		}
15861ba55bcSBaptiste Daroussin 		break;
15961ba55bcSBaptiste Daroussin 	case LEFT_DAY:
16061ba55bcSBaptiste Daroussin 		if (*dd > 1)
16161ba55bcSBaptiste Daroussin 			*dd -= 1;
16261ba55bcSBaptiste Daroussin 		else {
16361ba55bcSBaptiste Daroussin 			if (*mm == 1) {
16461ba55bcSBaptiste Daroussin 				*yy -= 1;
16561ba55bcSBaptiste Daroussin 				*mm = 12;
16661ba55bcSBaptiste Daroussin 			} else
16761ba55bcSBaptiste Daroussin 				*mm -= 1;
16861ba55bcSBaptiste Daroussin 			*dd = month_days(*yy, *mm);
16961ba55bcSBaptiste Daroussin 		}
17061ba55bcSBaptiste Daroussin 		break;
17161ba55bcSBaptiste Daroussin 	case RIGHT_DAY:
17261ba55bcSBaptiste Daroussin 		if (*dd < ndays)
17361ba55bcSBaptiste Daroussin 			*dd += 1;
17461ba55bcSBaptiste Daroussin 		else {
17561ba55bcSBaptiste Daroussin 			if (*mm == 12) {
17661ba55bcSBaptiste Daroussin 				*yy += 1;
17761ba55bcSBaptiste Daroussin 				*mm = 1;
17861ba55bcSBaptiste Daroussin 			} else
17961ba55bcSBaptiste Daroussin 				*mm += 1;
18061ba55bcSBaptiste Daroussin 			*dd = 1;
18161ba55bcSBaptiste Daroussin 		}
18261ba55bcSBaptiste Daroussin 		break;
18361ba55bcSBaptiste Daroussin 	case UP_MONTH:
18461ba55bcSBaptiste Daroussin 		if (*mm == 1) {
18561ba55bcSBaptiste Daroussin 			*mm = 12;
18661ba55bcSBaptiste Daroussin 			*yy -= 1;
18761ba55bcSBaptiste Daroussin 		} else
18861ba55bcSBaptiste Daroussin 			*mm -= 1;
18961ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
19061ba55bcSBaptiste Daroussin 		if (*dd > ndays)
19161ba55bcSBaptiste Daroussin 			*dd = ndays;
19261ba55bcSBaptiste Daroussin 		break;
19361ba55bcSBaptiste Daroussin 	case DOWN_MONTH:
19461ba55bcSBaptiste Daroussin 		if (*mm == 12) {
19561ba55bcSBaptiste Daroussin 			*mm = 1;
19661ba55bcSBaptiste Daroussin 			*yy += 1;
19761ba55bcSBaptiste Daroussin 		} else
19861ba55bcSBaptiste Daroussin 			*mm += 1;
19961ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
20061ba55bcSBaptiste Daroussin 		if (*dd > ndays)
20161ba55bcSBaptiste Daroussin 			*dd = ndays;
20261ba55bcSBaptiste Daroussin 		break;
20361ba55bcSBaptiste Daroussin 	case UP_YEAR:
20461ba55bcSBaptiste Daroussin 		*yy -= 1;
20561ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
20661ba55bcSBaptiste Daroussin 		if (*dd > ndays)
20761ba55bcSBaptiste Daroussin 			*dd = ndays;
20861ba55bcSBaptiste Daroussin 		break;
20961ba55bcSBaptiste Daroussin 	case DOWN_YEAR:
21061ba55bcSBaptiste Daroussin 		*yy += 1;
21161ba55bcSBaptiste Daroussin 		ndays = month_days(*yy, *mm);
21261ba55bcSBaptiste Daroussin 		if (*dd > ndays)
21361ba55bcSBaptiste Daroussin 			*dd = ndays;
21461ba55bcSBaptiste Daroussin 		break;
21561ba55bcSBaptiste Daroussin 	}
21661ba55bcSBaptiste Daroussin 
21761ba55bcSBaptiste Daroussin 	if (*yy < minyear) {
21861ba55bcSBaptiste Daroussin 		*yy = minyear;
21961ba55bcSBaptiste Daroussin 		*mm = 1;
22061ba55bcSBaptiste Daroussin 		*dd = 1;
22161ba55bcSBaptiste Daroussin 	}
22261ba55bcSBaptiste Daroussin 	if (*yy > maxyear) {
22361ba55bcSBaptiste Daroussin 		*yy = maxyear;
22461ba55bcSBaptiste Daroussin 		*mm = 12;
22561ba55bcSBaptiste Daroussin 		*dd = 31;
22661ba55bcSBaptiste Daroussin 	}
22761ba55bcSBaptiste Daroussin }
22861ba55bcSBaptiste Daroussin 
22961ba55bcSBaptiste Daroussin static void
23061ba55bcSBaptiste Daroussin drawsquare(struct bsddialog_conf *conf, WINDOW *win, enum elevation elev,
23161ba55bcSBaptiste Daroussin     const char *fmt, int value, bool focus)
23261ba55bcSBaptiste Daroussin {
23361ba55bcSBaptiste Daroussin 	int h, l, w;
23461ba55bcSBaptiste Daroussin 
23561ba55bcSBaptiste Daroussin 	getmaxyx(win, h, w);
23661ba55bcSBaptiste Daroussin 	draw_borders(conf, win, elev);
23761ba55bcSBaptiste Daroussin 	if (focus) {
23861ba55bcSBaptiste Daroussin 		l = 2 + w%2;
23961ba55bcSBaptiste Daroussin 		wattron(win, t.dialog.arrowcolor);
240*a6d8be45SAlfonso S. Siciliano 		mvwhline(win, 0, w/2 - l/2, UARROW(conf), l);
241*a6d8be45SAlfonso S. Siciliano 		mvwhline(win, h-1, w/2 - l/2, DARROW(conf), l);
24261ba55bcSBaptiste Daroussin 		wattroff(win, t.dialog.arrowcolor);
24361ba55bcSBaptiste Daroussin 	}
24461ba55bcSBaptiste Daroussin 
24561ba55bcSBaptiste Daroussin 	if (focus)
24661ba55bcSBaptiste Daroussin 		wattron(win, t.menu.f_namecolor);
24761ba55bcSBaptiste Daroussin 	if (strchr(fmt, 's') != NULL)
24861ba55bcSBaptiste Daroussin 		mvwprintw(win, 1, 1, fmt, m[value - 1]);
24961ba55bcSBaptiste Daroussin 	else
25061ba55bcSBaptiste Daroussin 		mvwprintw(win, 1, 1, fmt, value);
25161ba55bcSBaptiste Daroussin 	if (focus)
25261ba55bcSBaptiste Daroussin 		wattroff(win, t.menu.f_namecolor);
25361ba55bcSBaptiste Daroussin 
25461ba55bcSBaptiste Daroussin 	wnoutrefresh(win);
25561ba55bcSBaptiste Daroussin }
25661ba55bcSBaptiste Daroussin 
25761ba55bcSBaptiste Daroussin static void
25861ba55bcSBaptiste Daroussin print_calendar(struct bsddialog_conf *conf, WINDOW *win, int yy, int mm, int dd,
25961ba55bcSBaptiste Daroussin     bool active)
26061ba55bcSBaptiste Daroussin {
26161ba55bcSBaptiste Daroussin 	int ndays, i, y, x, wd, h, w;
26261ba55bcSBaptiste Daroussin 
26361ba55bcSBaptiste Daroussin 	getmaxyx(win, h, w);
26461ba55bcSBaptiste Daroussin 	wclear(win);
26561ba55bcSBaptiste Daroussin 	draw_borders(conf, win, RAISED);
26661ba55bcSBaptiste Daroussin 	if (active) {
26761ba55bcSBaptiste Daroussin 		wattron(win, t.dialog.arrowcolor);
268*a6d8be45SAlfonso S. Siciliano 		mvwhline(win, 0, 15, UARROW(conf), 4);
269*a6d8be45SAlfonso S. Siciliano 		mvwhline(win, h-1, 15, DARROW(conf), 4);
270*a6d8be45SAlfonso S. Siciliano 		mvwvline(win, 3, 0, LARROW(conf), 3);
271*a6d8be45SAlfonso S. Siciliano 		mvwvline(win, 3, w-1, RARROW(conf), 3);
27261ba55bcSBaptiste Daroussin 		wattroff(win, t.dialog.arrowcolor);
27361ba55bcSBaptiste Daroussin 	}
27461ba55bcSBaptiste Daroussin 
27561ba55bcSBaptiste Daroussin 	mvwaddstr(win, 1, 5, "Sun Mon Tue Wed Thu Fri Sat");
27661ba55bcSBaptiste Daroussin 	ndays = month_days(yy, mm);
27761ba55bcSBaptiste Daroussin 	y = 2;
27861ba55bcSBaptiste Daroussin 	wd = week_day(yy, mm, 1);
27961ba55bcSBaptiste Daroussin 	for (i = 1; i <= ndays; i++) {
28061ba55bcSBaptiste Daroussin 		x = 5 + (4 * wd); /* x has to be 6 with week number */
28161ba55bcSBaptiste Daroussin 		wmove(win, y, x);
28261ba55bcSBaptiste Daroussin 		mvwprintw(win, y, x, "%2d", i);
28361ba55bcSBaptiste Daroussin 		if (i == dd) {
28461ba55bcSBaptiste Daroussin 			wattron(win, t.menu.f_namecolor);
28561ba55bcSBaptiste Daroussin 			mvwprintw(win, y, x, "%2d", i);
28661ba55bcSBaptiste Daroussin 			wattroff(win, t.menu.f_namecolor);
28761ba55bcSBaptiste Daroussin 		}
28861ba55bcSBaptiste Daroussin 		wd++;
28961ba55bcSBaptiste Daroussin 		if (wd > 6) {
29061ba55bcSBaptiste Daroussin 			wd = 0;
29161ba55bcSBaptiste Daroussin 			y++;
29261ba55bcSBaptiste Daroussin 		}
29361ba55bcSBaptiste Daroussin 	}
29461ba55bcSBaptiste Daroussin 
29561ba55bcSBaptiste Daroussin 	wnoutrefresh(win);
29661ba55bcSBaptiste Daroussin }
29761ba55bcSBaptiste Daroussin 
29861ba55bcSBaptiste Daroussin static int
29961ba55bcSBaptiste Daroussin calendar_redraw(struct dialog *d, WINDOW *yy_win, WINDOW *mm_win,
30061ba55bcSBaptiste Daroussin     WINDOW *dd_win)
30161ba55bcSBaptiste Daroussin {
30261ba55bcSBaptiste Daroussin 	int ycal, xcal;
30361ba55bcSBaptiste Daroussin 
30461ba55bcSBaptiste Daroussin 	if (d->built) {
30561ba55bcSBaptiste Daroussin 		hide_dialog(d);
30661ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
30761ba55bcSBaptiste Daroussin 	}
30861ba55bcSBaptiste Daroussin 	if (dialog_size_position(d, MINHCAL, MINWCAL, NULL) != 0)
30961ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
31061ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
31161ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
31261ba55bcSBaptiste Daroussin 	if (d->built)
31361ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
31461ba55bcSBaptiste Daroussin 	TEXTPAD(d, MINHCAL + HBUTTONS);
31561ba55bcSBaptiste Daroussin 
31661ba55bcSBaptiste Daroussin 	ycal = d->y + d->h - 15;
31761ba55bcSBaptiste Daroussin 	xcal = d->x + d->w/2 - 17;
31861ba55bcSBaptiste Daroussin 	mvwaddstr(d->widget, d->h - 16, d->w/2 - 17, "Month");
31961ba55bcSBaptiste Daroussin 	update_box(d->conf, mm_win, ycal, xcal, 3, 17, RAISED);
32061ba55bcSBaptiste Daroussin 	mvwaddstr(d->widget, d->h - 16, d->w/2, "Year");
32161ba55bcSBaptiste Daroussin 	update_box(d->conf, yy_win, ycal, xcal + 17, 3, 17, RAISED);
32261ba55bcSBaptiste Daroussin 	update_box(d->conf, dd_win, ycal + 3, xcal, 9, 34, RAISED);
32361ba55bcSBaptiste Daroussin 	wnoutrefresh(d->widget);
32461ba55bcSBaptiste Daroussin 
32561ba55bcSBaptiste Daroussin 	return (0);
32661ba55bcSBaptiste Daroussin }
32761ba55bcSBaptiste Daroussin 
32861ba55bcSBaptiste Daroussin int
32961ba55bcSBaptiste Daroussin bsddialog_calendar(struct bsddialog_conf *conf, const char *text, int rows,
33061ba55bcSBaptiste Daroussin     int cols, unsigned int *year, unsigned int *month, unsigned int *day)
33161ba55bcSBaptiste Daroussin {
33261ba55bcSBaptiste Daroussin 	bool loop, focusbuttons;
33361ba55bcSBaptiste Daroussin 	int retval, sel, yy, mm, dd;
33461ba55bcSBaptiste Daroussin 	wint_t input;
33561ba55bcSBaptiste Daroussin 	WINDOW *yy_win, *mm_win, *dd_win;
33661ba55bcSBaptiste Daroussin 	struct dialog d;
33761ba55bcSBaptiste Daroussin 
33861ba55bcSBaptiste Daroussin 	CHECK_PTR(year);
33961ba55bcSBaptiste Daroussin 	CHECK_PTR(month);
34061ba55bcSBaptiste Daroussin 	CHECK_PTR(day);
34161ba55bcSBaptiste Daroussin 	minyear = MIN_YEAR_CAL;
34261ba55bcSBaptiste Daroussin 	maxyear = MAX_YEAR_CAL;
34361ba55bcSBaptiste Daroussin 	init_date(year, month, day, &yy, &mm, &dd);
34461ba55bcSBaptiste Daroussin 
34561ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
34661ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
34761ba55bcSBaptiste Daroussin 	set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
34861ba55bcSBaptiste Daroussin 	if ((yy_win = newwin(1, 1, 1, 1)) == NULL)
34961ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for yy");
35061ba55bcSBaptiste Daroussin 	wbkgd(yy_win, t.dialog.color);
35161ba55bcSBaptiste Daroussin 	if ((mm_win = newwin(1, 1, 1, 1)) == NULL)
35261ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for mm");
35361ba55bcSBaptiste Daroussin 	wbkgd(mm_win, t.dialog.color);
35461ba55bcSBaptiste Daroussin 	if ((dd_win = newwin(1, 1, 1, 1)) == NULL)
35561ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot build WINDOW for dd");
35661ba55bcSBaptiste Daroussin 	wbkgd(dd_win, t.dialog.color);
35761ba55bcSBaptiste Daroussin 	if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
35861ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
35961ba55bcSBaptiste Daroussin 
36061ba55bcSBaptiste Daroussin 	sel = -1;
36161ba55bcSBaptiste Daroussin 	loop = focusbuttons = true;
36261ba55bcSBaptiste Daroussin 	while (loop) {
36361ba55bcSBaptiste Daroussin 		drawsquare(conf, mm_win, RAISED, "%15s", mm, sel == 0);
36461ba55bcSBaptiste Daroussin 		drawsquare(conf, yy_win, RAISED, "%15d", yy, sel == 1);
36561ba55bcSBaptiste Daroussin 		print_calendar(conf, dd_win, yy, mm, dd, sel == 2);
36661ba55bcSBaptiste Daroussin 		doupdate();
36761ba55bcSBaptiste Daroussin 
36861ba55bcSBaptiste Daroussin 		if (get_wch(&input) == ERR)
36961ba55bcSBaptiste Daroussin 			continue;
37061ba55bcSBaptiste Daroussin 		switch(input) {
37161ba55bcSBaptiste Daroussin 		case KEY_ENTER:
37261ba55bcSBaptiste Daroussin 		case 10: /* Enter */
37361ba55bcSBaptiste Daroussin 			if (focusbuttons || conf->button.always_active) {
37461ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
37561ba55bcSBaptiste Daroussin 				loop = false;
37661ba55bcSBaptiste Daroussin 			}
37761ba55bcSBaptiste Daroussin 			break;
37861ba55bcSBaptiste Daroussin 		case 27: /* Esc */
37961ba55bcSBaptiste Daroussin 			if (conf->key.enable_esc) {
38061ba55bcSBaptiste Daroussin 				retval = BSDDIALOG_ESC;
38161ba55bcSBaptiste Daroussin 				loop = false;
38261ba55bcSBaptiste Daroussin 			}
38361ba55bcSBaptiste Daroussin 			break;
38461ba55bcSBaptiste Daroussin 		case '\t': /* TAB */
38561ba55bcSBaptiste Daroussin 			if (focusbuttons) {
38661ba55bcSBaptiste Daroussin 				d.bs.curr++;
38761ba55bcSBaptiste Daroussin 				if (d.bs.curr >= (int)d.bs.nbuttons) {
38861ba55bcSBaptiste Daroussin 					focusbuttons = false;
38961ba55bcSBaptiste Daroussin 					sel = 0;
39061ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
39161ba55bcSBaptiste Daroussin 					    0 : -1;
39261ba55bcSBaptiste Daroussin 				}
39361ba55bcSBaptiste Daroussin 			} else {
39461ba55bcSBaptiste Daroussin 				sel++;
39561ba55bcSBaptiste Daroussin 				if (sel > 2) {
39661ba55bcSBaptiste Daroussin 					focusbuttons = true;
39761ba55bcSBaptiste Daroussin 					sel = -1;
39861ba55bcSBaptiste Daroussin 					d.bs.curr = 0;
39961ba55bcSBaptiste Daroussin 				}
40061ba55bcSBaptiste Daroussin 			}
40161ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
40261ba55bcSBaptiste Daroussin 			break;
403*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('n'):
40461ba55bcSBaptiste Daroussin 		case KEY_RIGHT:
40561ba55bcSBaptiste Daroussin 			if (focusbuttons) {
40661ba55bcSBaptiste Daroussin 				d.bs.curr++;
40761ba55bcSBaptiste Daroussin 				if (d.bs.curr >= (int)d.bs.nbuttons) {
40861ba55bcSBaptiste Daroussin 					focusbuttons = false;
40961ba55bcSBaptiste Daroussin 					sel = 0;
41061ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
41161ba55bcSBaptiste Daroussin 					    0 : -1;
41261ba55bcSBaptiste Daroussin 				}
41361ba55bcSBaptiste Daroussin 			} else if (sel == 2) {
41461ba55bcSBaptiste Daroussin 				datectl(RIGHT_DAY, &yy, &mm, &dd);
41561ba55bcSBaptiste Daroussin 			} else { /* Month or Year*/
41661ba55bcSBaptiste Daroussin 				sel++;
41761ba55bcSBaptiste Daroussin 			}
41861ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
41961ba55bcSBaptiste Daroussin 			break;
420*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('p'):
42161ba55bcSBaptiste Daroussin 		case KEY_LEFT:
42261ba55bcSBaptiste Daroussin 			if (focusbuttons) {
42361ba55bcSBaptiste Daroussin 				d.bs.curr--;
42461ba55bcSBaptiste Daroussin 				if (d.bs.curr < 0) {
42561ba55bcSBaptiste Daroussin 					focusbuttons = false;
42661ba55bcSBaptiste Daroussin 					sel = 2;
42761ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
42861ba55bcSBaptiste Daroussin 					    0 : -1;
42961ba55bcSBaptiste Daroussin 				}
43061ba55bcSBaptiste Daroussin 			} else if (sel == 2) {
43161ba55bcSBaptiste Daroussin 				datectl(LEFT_DAY, &yy, &mm, &dd);
43261ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
43361ba55bcSBaptiste Daroussin 				sel = 0;
43461ba55bcSBaptiste Daroussin 			} else { /* sel = 0, Month */
43561ba55bcSBaptiste Daroussin 				focusbuttons = true;
43661ba55bcSBaptiste Daroussin 				sel = -1;
43761ba55bcSBaptiste Daroussin 				d.bs.curr = 0;
43861ba55bcSBaptiste Daroussin 			}
43961ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
44061ba55bcSBaptiste Daroussin 			break;
44161ba55bcSBaptiste Daroussin 		case KEY_UP:
44261ba55bcSBaptiste Daroussin 			if (focusbuttons) {
44361ba55bcSBaptiste Daroussin 				sel = 2;
44461ba55bcSBaptiste Daroussin 				focusbuttons = false;
44561ba55bcSBaptiste Daroussin 				d.bs.curr = conf->button.always_active ? 0 : -1;
44661ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
44761ba55bcSBaptiste Daroussin 			} else if (sel == 0) {
44861ba55bcSBaptiste Daroussin 				datectl(UP_MONTH, &yy, &mm, &dd);
44961ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
45061ba55bcSBaptiste Daroussin 				datectl(UP_YEAR, &yy, &mm, &dd);
45161ba55bcSBaptiste Daroussin 			} else { /* sel = 2 */
45261ba55bcSBaptiste Daroussin 				datectl(UP_DAY, &yy, &mm, &dd);
45361ba55bcSBaptiste Daroussin 			}
45461ba55bcSBaptiste Daroussin 			break;
45561ba55bcSBaptiste Daroussin 		case KEY_DOWN:
45661ba55bcSBaptiste Daroussin 			if (focusbuttons) {
45761ba55bcSBaptiste Daroussin 				break;
45861ba55bcSBaptiste Daroussin 			} else if (sel == 0) {
45961ba55bcSBaptiste Daroussin 				datectl(DOWN_MONTH, &yy, &mm, &dd);
46061ba55bcSBaptiste Daroussin 			} else if (sel == 1) {
46161ba55bcSBaptiste Daroussin 				datectl(DOWN_YEAR, &yy, &mm, &dd);
46261ba55bcSBaptiste Daroussin 			} else { /* sel = 2 */
46361ba55bcSBaptiste Daroussin 				datectl(DOWN_DAY, &yy, &mm, &dd);
46461ba55bcSBaptiste Daroussin 			}
46561ba55bcSBaptiste Daroussin 			break;
466*a6d8be45SAlfonso S. Siciliano 		case '-':
467*a6d8be45SAlfonso S. Siciliano 			if (focusbuttons) {
468*a6d8be45SAlfonso S. Siciliano 				break;
469*a6d8be45SAlfonso S. Siciliano 			} else if (sel == 0) {
470*a6d8be45SAlfonso S. Siciliano 				datectl(UP_MONTH, &yy, &mm, &dd);
471*a6d8be45SAlfonso S. Siciliano 			} else if (sel == 1) {
472*a6d8be45SAlfonso S. Siciliano 				datectl(UP_YEAR, &yy, &mm, &dd);
473*a6d8be45SAlfonso S. Siciliano 			} else { /* sel = 2 */
474*a6d8be45SAlfonso S. Siciliano 				datectl(LEFT_DAY, &yy, &mm, &dd);
475*a6d8be45SAlfonso S. Siciliano 			}
476*a6d8be45SAlfonso S. Siciliano 			break;
477*a6d8be45SAlfonso S. Siciliano 		case '+':
478*a6d8be45SAlfonso S. Siciliano 			if (focusbuttons) {
479*a6d8be45SAlfonso S. Siciliano 				break;
480*a6d8be45SAlfonso S. Siciliano 			} else if (sel == 0) {
481*a6d8be45SAlfonso S. Siciliano 				datectl(DOWN_MONTH, &yy, &mm, &dd);
482*a6d8be45SAlfonso S. Siciliano 			} else if (sel == 1) {
483*a6d8be45SAlfonso S. Siciliano 				datectl(DOWN_YEAR, &yy, &mm, &dd);
484*a6d8be45SAlfonso S. Siciliano 			} else { /* sel = 2 */
485*a6d8be45SAlfonso S. Siciliano 				datectl(RIGHT_DAY, &yy, &mm, &dd);
486*a6d8be45SAlfonso S. Siciliano 			}
487*a6d8be45SAlfonso S. Siciliano 			break;
48861ba55bcSBaptiste Daroussin 		case KEY_HOME:
48961ba55bcSBaptiste Daroussin 			datectl(UP_MONTH, &yy, &mm, &dd);
49061ba55bcSBaptiste Daroussin 			break;
49161ba55bcSBaptiste Daroussin 		case KEY_END:
49261ba55bcSBaptiste Daroussin 			datectl(DOWN_MONTH, &yy, &mm, &dd);
49361ba55bcSBaptiste Daroussin 			break;
49461ba55bcSBaptiste Daroussin 		case KEY_PPAGE:
49561ba55bcSBaptiste Daroussin 			datectl(UP_YEAR, &yy, &mm, &dd);
49661ba55bcSBaptiste Daroussin 			break;
49761ba55bcSBaptiste Daroussin 		case KEY_NPAGE:
49861ba55bcSBaptiste Daroussin 			datectl(DOWN_YEAR, &yy, &mm, &dd);
49961ba55bcSBaptiste Daroussin 			break;
50061ba55bcSBaptiste Daroussin 		case KEY_F(1):
50161ba55bcSBaptiste Daroussin 			if (conf->key.f1_file == NULL &&
50261ba55bcSBaptiste Daroussin 			    conf->key.f1_message == NULL)
50361ba55bcSBaptiste Daroussin 				break;
50461ba55bcSBaptiste Daroussin 			if (f1help_dialog(conf) != 0)
50561ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
50661ba55bcSBaptiste Daroussin 			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
50761ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
50861ba55bcSBaptiste Daroussin 			break;
509*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('l'):
51061ba55bcSBaptiste Daroussin 		case KEY_RESIZE:
51161ba55bcSBaptiste Daroussin 			if (calendar_redraw(&d, yy_win, mm_win, dd_win) != 0)
51261ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
51361ba55bcSBaptiste Daroussin 			break;
51461ba55bcSBaptiste Daroussin 		default:
51561ba55bcSBaptiste Daroussin 			if (shortcut_buttons(input, &d.bs)) {
51661ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
51761ba55bcSBaptiste Daroussin 				doupdate();
51861ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
51961ba55bcSBaptiste Daroussin 				loop = false;
52061ba55bcSBaptiste Daroussin 			}
52161ba55bcSBaptiste Daroussin 		}
52261ba55bcSBaptiste Daroussin 	}
52361ba55bcSBaptiste Daroussin 
52461ba55bcSBaptiste Daroussin 	*year  = yy;
52561ba55bcSBaptiste Daroussin 	*month = mm;
52661ba55bcSBaptiste Daroussin 	*day   = dd;
52761ba55bcSBaptiste Daroussin 
52861ba55bcSBaptiste Daroussin 	delwin(yy_win);
52961ba55bcSBaptiste Daroussin 	delwin(mm_win);
53061ba55bcSBaptiste Daroussin 	delwin(dd_win);
53161ba55bcSBaptiste Daroussin 	end_dialog(&d);
53261ba55bcSBaptiste Daroussin 
53361ba55bcSBaptiste Daroussin 	return (retval);
53461ba55bcSBaptiste Daroussin }
53561ba55bcSBaptiste Daroussin 
53661ba55bcSBaptiste Daroussin static int datebox_redraw(struct dialog *d, struct dateitem *di)
53761ba55bcSBaptiste Daroussin {
53861ba55bcSBaptiste Daroussin 	int y, x;
53961ba55bcSBaptiste Daroussin 
54061ba55bcSBaptiste Daroussin 	if (d->built) {
54161ba55bcSBaptiste Daroussin 		hide_dialog(d);
54261ba55bcSBaptiste Daroussin 		refresh(); /* Important for decreasing screen */
54361ba55bcSBaptiste Daroussin 	}
54461ba55bcSBaptiste Daroussin 	if (dialog_size_position(d, 3 /*windows*/, MINWDATE, NULL) != 0)
54561ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
54661ba55bcSBaptiste Daroussin 	if (draw_dialog(d) != 0)
54761ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
54861ba55bcSBaptiste Daroussin 	if (d->built)
54961ba55bcSBaptiste Daroussin 		refresh(); /* Important to fix grey lines expanding screen */
55061ba55bcSBaptiste Daroussin 	TEXTPAD(d, 3 /*windows*/ + HBUTTONS);
55161ba55bcSBaptiste Daroussin 
55261ba55bcSBaptiste Daroussin 	y = d->y + d->h - 6;
55361ba55bcSBaptiste Daroussin 	x = (d->x + d->w / 2) - 11;
55461ba55bcSBaptiste Daroussin 	update_box(d->conf, di[0].win, y, x, 3, di[0].width, LOWERED);
55561ba55bcSBaptiste Daroussin 	mvwaddch(d->widget, d->h - 5, x - d->x + di[0].width, '/');
55661ba55bcSBaptiste Daroussin 	x += di[0].width + 1;
55761ba55bcSBaptiste Daroussin 	update_box(d->conf, di[1].win, y, x , 3, di[1].width, LOWERED);
55861ba55bcSBaptiste Daroussin 	mvwaddch(d->widget, d->h - 5, x - d->x + di[1].width, '/');
55961ba55bcSBaptiste Daroussin 	x += di[1].width + 1;
56061ba55bcSBaptiste Daroussin 	update_box(d->conf, di[2].win, y, x, 3, di[2].width, LOWERED);
56161ba55bcSBaptiste Daroussin 	wnoutrefresh(d->widget);
56261ba55bcSBaptiste Daroussin 
56361ba55bcSBaptiste Daroussin 	return (0);
56461ba55bcSBaptiste Daroussin }
56561ba55bcSBaptiste Daroussin 
56661ba55bcSBaptiste Daroussin static int
56761ba55bcSBaptiste Daroussin build_dateitem(const char *format, int *yy, int *mm, int *dd,
56861ba55bcSBaptiste Daroussin     struct dateitem *dt)
56961ba55bcSBaptiste Daroussin {
57061ba55bcSBaptiste Daroussin 	int i;
57161ba55bcSBaptiste Daroussin 	wchar_t *wformat;
57261ba55bcSBaptiste Daroussin 	struct dateitem init[3] = {
57361ba55bcSBaptiste Daroussin 		{UP_YEAR,  DOWN_YEAR,  NULL, 6,  "%4d",  yy},
57461ba55bcSBaptiste Daroussin 		{UP_MONTH, DOWN_MONTH, NULL, 11, "%9s",  mm},
57561ba55bcSBaptiste Daroussin 		{LEFT_DAY, RIGHT_DAY,  NULL, 4,  "%02d", dd},
57661ba55bcSBaptiste Daroussin 	};
57761ba55bcSBaptiste Daroussin 
57861ba55bcSBaptiste Daroussin 	for (i = 0; i < 3; i++) {
57961ba55bcSBaptiste Daroussin 		if ((init[i].win = newwin(1, 1, 1, 1)) == NULL)
58061ba55bcSBaptiste Daroussin 			RETURN_FMTERROR("Cannot build WINDOW dateitem[%d]", i);
58161ba55bcSBaptiste Daroussin 		wbkgd(init[i].win, t.dialog.color);
58261ba55bcSBaptiste Daroussin 	}
58361ba55bcSBaptiste Daroussin 
58461ba55bcSBaptiste Daroussin 	if ((wformat = alloc_mbstows(CHECK_STR(format))) == NULL)
58561ba55bcSBaptiste Daroussin 		RETURN_ERROR("Cannot allocate conf.date.format in wchar_t*");
58661ba55bcSBaptiste Daroussin 	if (format == NULL || wcscmp(wformat, L"d/m/y") == 0) {
58761ba55bcSBaptiste Daroussin 		dt[0] = init[2];
58861ba55bcSBaptiste Daroussin 		dt[1] = init[1];
58961ba55bcSBaptiste Daroussin 		dt[2] = init[0];
59061ba55bcSBaptiste Daroussin 	} else if (wcscmp(wformat, L"m/d/y") == 0) {
59161ba55bcSBaptiste Daroussin 		dt[0] = init[1];
59261ba55bcSBaptiste Daroussin 		dt[1] = init[2];
59361ba55bcSBaptiste Daroussin 		dt[2] = init[0];
59461ba55bcSBaptiste Daroussin 	} else if (wcscmp(wformat, L"y/m/d") == 0) {
59561ba55bcSBaptiste Daroussin 		dt[0] = init[0];
59661ba55bcSBaptiste Daroussin 		dt[1] = init[1];
59761ba55bcSBaptiste Daroussin 		dt[2] = init[2];
59861ba55bcSBaptiste Daroussin 	} else
59961ba55bcSBaptiste Daroussin 		RETURN_FMTERROR("Invalid conf.date.format=\"%s\"", format);
60061ba55bcSBaptiste Daroussin 	free(wformat);
60161ba55bcSBaptiste Daroussin 
60261ba55bcSBaptiste Daroussin 	return (0);
60361ba55bcSBaptiste Daroussin }
60461ba55bcSBaptiste Daroussin 
60561ba55bcSBaptiste Daroussin int
60661ba55bcSBaptiste Daroussin bsddialog_datebox(struct bsddialog_conf *conf, const char *text, int rows,
60761ba55bcSBaptiste Daroussin     int cols, unsigned int *year, unsigned int *month, unsigned int *day)
60861ba55bcSBaptiste Daroussin {
60961ba55bcSBaptiste Daroussin 	bool loop, focusbuttons;
61061ba55bcSBaptiste Daroussin 	int retval, i, sel, yy, mm, dd;
61161ba55bcSBaptiste Daroussin 	wint_t input;
61261ba55bcSBaptiste Daroussin 	struct dateitem  di[3];
61361ba55bcSBaptiste Daroussin 	struct dialog d;
61461ba55bcSBaptiste Daroussin 
61561ba55bcSBaptiste Daroussin 	CHECK_PTR(year);
61661ba55bcSBaptiste Daroussin 	CHECK_PTR(month);
61761ba55bcSBaptiste Daroussin 	CHECK_PTR(day);
61861ba55bcSBaptiste Daroussin 	minyear = MIN_YEAR_DATE;
61961ba55bcSBaptiste Daroussin 	maxyear = MAX_YEAR_DATE;
62061ba55bcSBaptiste Daroussin 	init_date(year, month, day, &yy, &mm, &dd);
62161ba55bcSBaptiste Daroussin 
62261ba55bcSBaptiste Daroussin 	if (prepare_dialog(conf, text, rows, cols, &d) != 0)
62361ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
62461ba55bcSBaptiste Daroussin 	set_buttons(&d, true, OK_LABEL, CANCEL_LABEL);
62561ba55bcSBaptiste Daroussin 	if (build_dateitem(conf->date.format, &yy, &mm, &dd, di) != 0)
62661ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
62761ba55bcSBaptiste Daroussin 	if (datebox_redraw(&d, di) != 0)
62861ba55bcSBaptiste Daroussin 		return (BSDDIALOG_ERROR);
62961ba55bcSBaptiste Daroussin 
63061ba55bcSBaptiste Daroussin 	sel = -1;
63161ba55bcSBaptiste Daroussin 	loop = focusbuttons = true;
63261ba55bcSBaptiste Daroussin 	while (loop) {
63361ba55bcSBaptiste Daroussin 		for (i = 0; i < 3; i++)
63461ba55bcSBaptiste Daroussin 			drawsquare(conf, di[i].win, LOWERED, di[i].fmt,
63561ba55bcSBaptiste Daroussin 			    *di[i].value, sel == i);
63661ba55bcSBaptiste Daroussin 		doupdate();
63761ba55bcSBaptiste Daroussin 
63861ba55bcSBaptiste Daroussin 		if (get_wch(&input) == ERR)
63961ba55bcSBaptiste Daroussin 			continue;
64061ba55bcSBaptiste Daroussin 		switch(input) {
64161ba55bcSBaptiste Daroussin 		case KEY_ENTER:
64261ba55bcSBaptiste Daroussin 		case 10: /* Enter */
64361ba55bcSBaptiste Daroussin 			if (focusbuttons || conf->button.always_active) {
64461ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
64561ba55bcSBaptiste Daroussin 				loop = false;
64661ba55bcSBaptiste Daroussin 			}
64761ba55bcSBaptiste Daroussin 			break;
64861ba55bcSBaptiste Daroussin 		case 27: /* Esc */
64961ba55bcSBaptiste Daroussin 			if (conf->key.enable_esc) {
65061ba55bcSBaptiste Daroussin 				retval = BSDDIALOG_ESC;
65161ba55bcSBaptiste Daroussin 				loop = false;
65261ba55bcSBaptiste Daroussin 			}
65361ba55bcSBaptiste Daroussin 			break;
65461ba55bcSBaptiste Daroussin 		case '\t': /* TAB */
655*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('n'):
656*a6d8be45SAlfonso S. Siciliano 		case KEY_RIGHT:
65761ba55bcSBaptiste Daroussin 			if (focusbuttons) {
65861ba55bcSBaptiste Daroussin 				d.bs.curr++;
65961ba55bcSBaptiste Daroussin 				focusbuttons = d.bs.curr < (int)d.bs.nbuttons ?
66061ba55bcSBaptiste Daroussin 				    true : false;
66161ba55bcSBaptiste Daroussin 				if (focusbuttons == false) {
66261ba55bcSBaptiste Daroussin 					sel = 0;
66361ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
66461ba55bcSBaptiste Daroussin 					    0 : -1;
66561ba55bcSBaptiste Daroussin 				}
66661ba55bcSBaptiste Daroussin 			} else {
66761ba55bcSBaptiste Daroussin 				sel++;
66861ba55bcSBaptiste Daroussin 				focusbuttons = sel > 2 ? true : false;
66961ba55bcSBaptiste Daroussin 				if (focusbuttons) {
67061ba55bcSBaptiste Daroussin 					d.bs.curr = 0;
67161ba55bcSBaptiste Daroussin 				}
67261ba55bcSBaptiste Daroussin 			}
67361ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
67461ba55bcSBaptiste Daroussin 			break;
675*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('p'):
67661ba55bcSBaptiste Daroussin 		case KEY_LEFT:
67761ba55bcSBaptiste Daroussin 			if (focusbuttons) {
67861ba55bcSBaptiste Daroussin 				d.bs.curr--;
67961ba55bcSBaptiste Daroussin 				focusbuttons = d.bs.curr < 0 ? false : true;
68061ba55bcSBaptiste Daroussin 				if (focusbuttons == false) {
68161ba55bcSBaptiste Daroussin 					sel = 2;
68261ba55bcSBaptiste Daroussin 					d.bs.curr = conf->button.always_active ?
68361ba55bcSBaptiste Daroussin 					    0 : -1;
68461ba55bcSBaptiste Daroussin 				}
68561ba55bcSBaptiste Daroussin 			} else {
68661ba55bcSBaptiste Daroussin 				sel--;
68761ba55bcSBaptiste Daroussin 				focusbuttons = sel < 0 ? true : false;
68861ba55bcSBaptiste Daroussin 				if (focusbuttons)
68961ba55bcSBaptiste Daroussin 					d.bs.curr = (int)d.bs.nbuttons - 1;
69061ba55bcSBaptiste Daroussin 			}
69161ba55bcSBaptiste Daroussin 			DRAW_BUTTONS(d);
69261ba55bcSBaptiste Daroussin 			break;
693*a6d8be45SAlfonso S. Siciliano 		case '-':
694*a6d8be45SAlfonso S. Siciliano 			if (focusbuttons == false)
695*a6d8be45SAlfonso S. Siciliano 				datectl(di[sel].up, &yy, &mm, &dd);
696*a6d8be45SAlfonso S. Siciliano 			break;
69761ba55bcSBaptiste Daroussin 		case KEY_UP:
69861ba55bcSBaptiste Daroussin 			if (focusbuttons) {
69961ba55bcSBaptiste Daroussin 				sel = 0;
70061ba55bcSBaptiste Daroussin 				focusbuttons = false;
70161ba55bcSBaptiste Daroussin 				d.bs.curr = conf->button.always_active ? 0 : -1;
70261ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
70361ba55bcSBaptiste Daroussin 			} else {
70461ba55bcSBaptiste Daroussin 				datectl(di[sel].up, &yy, &mm, &dd);
70561ba55bcSBaptiste Daroussin 			}
70661ba55bcSBaptiste Daroussin 			break;
707*a6d8be45SAlfonso S. Siciliano 		case '+':
70861ba55bcSBaptiste Daroussin 		case KEY_DOWN:
70961ba55bcSBaptiste Daroussin 			if (focusbuttons)
71061ba55bcSBaptiste Daroussin 				break;
71161ba55bcSBaptiste Daroussin 			datectl(di[sel].down, &yy, &mm, &dd);
71261ba55bcSBaptiste Daroussin 			break;
71361ba55bcSBaptiste Daroussin 		case KEY_F(1):
71461ba55bcSBaptiste Daroussin 			if (conf->key.f1_file == NULL &&
71561ba55bcSBaptiste Daroussin 			    conf->key.f1_message == NULL)
71661ba55bcSBaptiste Daroussin 				break;
71761ba55bcSBaptiste Daroussin 			if (f1help_dialog(conf) != 0)
71861ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
71961ba55bcSBaptiste Daroussin 			if (datebox_redraw(&d, di) != 0)
72061ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
72161ba55bcSBaptiste Daroussin 			break;
722*a6d8be45SAlfonso S. Siciliano 		case KEY_CTRL('l'):
72361ba55bcSBaptiste Daroussin 		case KEY_RESIZE:
72461ba55bcSBaptiste Daroussin 			if (datebox_redraw(&d, di) != 0)
72561ba55bcSBaptiste Daroussin 				return (BSDDIALOG_ERROR);
72661ba55bcSBaptiste Daroussin 			break;
72761ba55bcSBaptiste Daroussin 		default:
72861ba55bcSBaptiste Daroussin 			if (shortcut_buttons(input, &d.bs)) {
72961ba55bcSBaptiste Daroussin 				DRAW_BUTTONS(d);
73061ba55bcSBaptiste Daroussin 				doupdate();
73161ba55bcSBaptiste Daroussin 				retval = BUTTONVALUE(d.bs);
73261ba55bcSBaptiste Daroussin 				loop = false;
73361ba55bcSBaptiste Daroussin 			}
73461ba55bcSBaptiste Daroussin 		}
73561ba55bcSBaptiste Daroussin 	}
73661ba55bcSBaptiste Daroussin 
73761ba55bcSBaptiste Daroussin 	*year  = yy;
73861ba55bcSBaptiste Daroussin 	*month = mm;
73961ba55bcSBaptiste Daroussin 	*day   = dd;
74061ba55bcSBaptiste Daroussin 
74161ba55bcSBaptiste Daroussin 	for (i = 0; i < 3 ; i++)
74261ba55bcSBaptiste Daroussin 		delwin(di[i].win);
74361ba55bcSBaptiste Daroussin 	end_dialog(&d);
74461ba55bcSBaptiste Daroussin 
74561ba55bcSBaptiste Daroussin 	return (retval);
74661ba55bcSBaptiste Daroussin }