1c76f0793SBaptiste Daroussin /*- 2c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3c76f0793SBaptiste Daroussin * 4c76f0793SBaptiste Daroussin * Copyright (c) 2021 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 30c76f0793SBaptiste Daroussin #ifdef PORTNCURSES 31*8c4f4028SBaptiste Daroussin #include <ncurses/ncurses.h> 32c76f0793SBaptiste Daroussin #else 33*8c4f4028SBaptiste Daroussin #include <ncurses.h> 34c76f0793SBaptiste Daroussin #endif 35c76f0793SBaptiste Daroussin 36f499134dSBaptiste Daroussin #include <ctype.h> 37f499134dSBaptiste Daroussin #include <string.h> 38f499134dSBaptiste Daroussin 39c76f0793SBaptiste Daroussin #include "bsddialog.h" 40c76f0793SBaptiste Daroussin #include "lib_util.h" 41f499134dSBaptiste Daroussin #include "bsddialog_theme.h" 42c76f0793SBaptiste Daroussin 43f499134dSBaptiste Daroussin #define MINWDATE 25 /* 23 wins + 2 VBORDERS */ 44f499134dSBaptiste Daroussin #define MINWTIME 16 /*14 wins + 2 VBORDERS */ 45f499134dSBaptiste Daroussin #define MINHEIGHT 8 /* 2 for text */ 46c76f0793SBaptiste Daroussin 47f499134dSBaptiste Daroussin /* "Time": timebox - datebox */ 48f499134dSBaptiste Daroussin 49f499134dSBaptiste Daroussin extern struct bsddialog_theme t; 50f499134dSBaptiste Daroussin 51f499134dSBaptiste Daroussin static int 52f499134dSBaptiste Daroussin datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, 53f499134dSBaptiste Daroussin int *w, int minw, char *text, struct buttons bs) 54f499134dSBaptiste Daroussin { 55f499134dSBaptiste Daroussin int maxword, maxline, nlines, line; 56f499134dSBaptiste Daroussin 57f499134dSBaptiste Daroussin if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0) 58f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 59f499134dSBaptiste Daroussin 60f499134dSBaptiste Daroussin if (cols == BSDDIALOG_AUTOSIZE) { 61f499134dSBaptiste Daroussin *w = VBORDERS; 62f499134dSBaptiste Daroussin /* buttons size */ 63f499134dSBaptiste Daroussin *w += bs.nbuttons * bs.sizebutton; 64f499134dSBaptiste Daroussin *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; 65f499134dSBaptiste Daroussin /* text size */ 66f499134dSBaptiste Daroussin line = maxline + VBORDERS + t.text.hmargin * 2; 67f499134dSBaptiste Daroussin line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2)); 68f499134dSBaptiste Daroussin *w = MAX(*w, line); 69f499134dSBaptiste Daroussin /* date windows */ 70f499134dSBaptiste Daroussin *w = MAX(*w, minw); 71*8c4f4028SBaptiste Daroussin /* conf.auto_minwidth */ 72*8c4f4028SBaptiste Daroussin *w = MAX(*w, (int)conf->auto_minwidth); 73f499134dSBaptiste Daroussin /* avoid terminal overflow */ 74f499134dSBaptiste Daroussin *w = MIN(*w, widget_max_width(conf) -1); 75f499134dSBaptiste Daroussin } 76f499134dSBaptiste Daroussin 77f499134dSBaptiste Daroussin if (rows == BSDDIALOG_AUTOSIZE) { 78f499134dSBaptiste Daroussin *h = MINHEIGHT; 79f499134dSBaptiste Daroussin if (maxword > 0) 80*8c4f4028SBaptiste Daroussin *h += MAX(nlines, (int)(*w / GET_ASPECT_RATIO(conf))); 81*8c4f4028SBaptiste Daroussin /* conf.auto_minheight */ 82*8c4f4028SBaptiste Daroussin *h = MAX(*h, (int)conf->auto_minheight); 83f499134dSBaptiste Daroussin /* avoid terminal overflow */ 84f499134dSBaptiste Daroussin *h = MIN(*h, widget_max_height(conf) -1); 85f499134dSBaptiste Daroussin } 86f499134dSBaptiste Daroussin 87f499134dSBaptiste Daroussin return 0; 88f499134dSBaptiste Daroussin } 89f499134dSBaptiste Daroussin 90f499134dSBaptiste Daroussin static int 91f499134dSBaptiste Daroussin datetime_checksize(int rows, int cols, char *text, int minw, struct buttons bs) 92f499134dSBaptiste Daroussin { 93f499134dSBaptiste Daroussin int mincols; 94f499134dSBaptiste Daroussin 95f499134dSBaptiste Daroussin mincols = VBORDERS; 96f499134dSBaptiste Daroussin mincols += bs.nbuttons * bs.sizebutton; 97f499134dSBaptiste Daroussin mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0; 98f499134dSBaptiste Daroussin mincols = MAX(minw, mincols); 99f499134dSBaptiste Daroussin 100f499134dSBaptiste Daroussin if (cols < mincols) 101f499134dSBaptiste Daroussin RETURN_ERROR("Few cols for this timebox/datebox"); 102f499134dSBaptiste Daroussin 103f499134dSBaptiste Daroussin if (rows < MINHEIGHT + (strlen(text) > 0 ? 1 : 0)) 104f499134dSBaptiste Daroussin RETURN_ERROR("Few rows for this timebox/datebox"); 105f499134dSBaptiste Daroussin 106f499134dSBaptiste Daroussin return 0; 107f499134dSBaptiste Daroussin } 108f499134dSBaptiste Daroussin 109f499134dSBaptiste Daroussin int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int cols, 110c76f0793SBaptiste Daroussin unsigned int *hh, unsigned int *mm, unsigned int *ss) 111c76f0793SBaptiste Daroussin { 112f499134dSBaptiste Daroussin WINDOW *widget, *textpad, *shadow; 113f499134dSBaptiste Daroussin int i, input, output, y, x, h, w, sel, htextpad; 114c76f0793SBaptiste Daroussin struct buttons bs; 115f499134dSBaptiste Daroussin bool loop; 116c76f0793SBaptiste Daroussin struct myclockstruct { 117c76f0793SBaptiste Daroussin unsigned int max; 118f499134dSBaptiste Daroussin unsigned int value; 119c76f0793SBaptiste Daroussin WINDOW *win; 120f499134dSBaptiste Daroussin }; 121c76f0793SBaptiste Daroussin 122f499134dSBaptiste Daroussin if (hh == NULL || mm == NULL || ss == NULL) 123f499134dSBaptiste Daroussin RETURN_ERROR("hh / mm / ss cannot be NULL"); 124c76f0793SBaptiste Daroussin 125f499134dSBaptiste Daroussin struct myclockstruct c[3] = { 126f499134dSBaptiste Daroussin {23, *hh, NULL}, 127f499134dSBaptiste Daroussin {59, *mm, NULL}, 128f499134dSBaptiste Daroussin {59, *ss, NULL} 129f499134dSBaptiste Daroussin }; 130f499134dSBaptiste Daroussin 131f499134dSBaptiste Daroussin for (i = 0 ; i < 3; i++) { 132f499134dSBaptiste Daroussin if (c[i].value > c[i].max) 133f499134dSBaptiste Daroussin c[i].value = c[i].max; 134f499134dSBaptiste Daroussin } 135c76f0793SBaptiste Daroussin 136c76f0793SBaptiste Daroussin get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), 137c76f0793SBaptiste Daroussin BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); 138c76f0793SBaptiste Daroussin 139f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 140f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 141f499134dSBaptiste Daroussin if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0) 142f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 143f499134dSBaptiste Daroussin if (datetime_checksize(h, w, text, MINWTIME, bs) != 0) 144f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 145f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 146f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 147f499134dSBaptiste Daroussin 148f499134dSBaptiste Daroussin if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, 149f499134dSBaptiste Daroussin &textpad, &htextpad, text, true) != 0) 150f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 151f499134dSBaptiste Daroussin 152f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 153f499134dSBaptiste Daroussin 154f499134dSBaptiste Daroussin wrefresh(widget); 155f499134dSBaptiste Daroussin 156f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); 157f499134dSBaptiste Daroussin 158f499134dSBaptiste Daroussin c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 7, 3, 4, LOWERED); 159f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 - 3, ':'); 160f499134dSBaptiste Daroussin c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 2, 3, 4, LOWERED); 161f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 + 2, ':'); 162f499134dSBaptiste Daroussin c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 3, 3, 4, LOWERED); 163f499134dSBaptiste Daroussin 164f499134dSBaptiste Daroussin wrefresh(widget); 165f499134dSBaptiste Daroussin 166c76f0793SBaptiste Daroussin sel = 0; 167c76f0793SBaptiste Daroussin curs_set(2); 168f499134dSBaptiste Daroussin loop = true; 169c76f0793SBaptiste Daroussin while(loop) { 170c76f0793SBaptiste Daroussin for (i=0; i<3; i++) { 171f499134dSBaptiste Daroussin mvwprintw(c[i].win, 1, 1, "%2d", c[i].value); 172c76f0793SBaptiste Daroussin wrefresh(c[i].win); 173c76f0793SBaptiste Daroussin } 174c76f0793SBaptiste Daroussin wmove(c[sel].win, 1, 2); 175c76f0793SBaptiste Daroussin wrefresh(c[sel].win); 176c76f0793SBaptiste Daroussin 177c76f0793SBaptiste Daroussin input = getch(); 178c76f0793SBaptiste Daroussin switch(input) { 179f499134dSBaptiste Daroussin case KEY_ENTER: 180c76f0793SBaptiste Daroussin case 10: /* Enter */ 181c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; 182*8c4f4028SBaptiste Daroussin if (output == BSDDIALOG_OK) { 183f499134dSBaptiste Daroussin *hh = c[0].value; 184f499134dSBaptiste Daroussin *mm = c[1].value; 185f499134dSBaptiste Daroussin *ss = c[2].value; 186c76f0793SBaptiste Daroussin } 187c76f0793SBaptiste Daroussin loop = false; 188c76f0793SBaptiste Daroussin break; 189c76f0793SBaptiste Daroussin case 27: /* Esc */ 190c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 191c76f0793SBaptiste Daroussin loop = false; 192c76f0793SBaptiste Daroussin break; 193c76f0793SBaptiste Daroussin case '\t': /* TAB */ 194c76f0793SBaptiste Daroussin sel = (sel + 1) % 3; 195c76f0793SBaptiste Daroussin break; 196c76f0793SBaptiste Daroussin case KEY_LEFT: 197c76f0793SBaptiste Daroussin if (bs.curr > 0) { 198c76f0793SBaptiste Daroussin bs.curr--; 199f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 200f499134dSBaptiste Daroussin wrefresh(widget); 201c76f0793SBaptiste Daroussin } 202c76f0793SBaptiste Daroussin break; 203c76f0793SBaptiste Daroussin case KEY_RIGHT: 204c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 205c76f0793SBaptiste Daroussin bs.curr++; 206f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 207f499134dSBaptiste Daroussin wrefresh(widget); 208c76f0793SBaptiste Daroussin } 209c76f0793SBaptiste Daroussin break; 210c76f0793SBaptiste Daroussin case KEY_UP: 211f499134dSBaptiste Daroussin c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 0; 212c76f0793SBaptiste Daroussin break; 213c76f0793SBaptiste Daroussin case KEY_DOWN: 214f499134dSBaptiste Daroussin c[sel].value = c[sel].value > 0 ? c[sel].value - 1 : c[sel].max; 215c76f0793SBaptiste Daroussin break; 216f499134dSBaptiste Daroussin case KEY_F(1): 217*8c4f4028SBaptiste Daroussin if (conf->f1_file == NULL && conf->f1_message == NULL) 218f499134dSBaptiste Daroussin break; 219f499134dSBaptiste Daroussin curs_set(0); 220f499134dSBaptiste Daroussin if (f1help(conf) != 0) 221f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 222f499134dSBaptiste Daroussin curs_set(2); 223f499134dSBaptiste Daroussin /* No break! the terminal size can change */ 224f499134dSBaptiste Daroussin case KEY_RESIZE: 225f499134dSBaptiste Daroussin hide_widget(y, x, h, w,conf->shadow); 226f499134dSBaptiste Daroussin 227f499134dSBaptiste Daroussin /* 228f499134dSBaptiste Daroussin * Unnecessary, but, when the columns decrease the 229f499134dSBaptiste Daroussin * following "refresh" seem not work 230f499134dSBaptiste Daroussin */ 231f499134dSBaptiste Daroussin refresh(); 232f499134dSBaptiste Daroussin 233f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 234f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 235f499134dSBaptiste Daroussin if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0) 236f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 237f499134dSBaptiste Daroussin if (datetime_checksize(h, w, text, MINWTIME, bs) != 0) 238f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 239f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 240f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 241f499134dSBaptiste Daroussin 242f499134dSBaptiste Daroussin wclear(shadow); 243f499134dSBaptiste Daroussin mvwin(shadow, y + t.shadow.h, x + t.shadow.w); 244f499134dSBaptiste Daroussin wresize(shadow, h, w); 245f499134dSBaptiste Daroussin 246f499134dSBaptiste Daroussin wclear(widget); 247f499134dSBaptiste Daroussin mvwin(widget, y, x); 248f499134dSBaptiste Daroussin wresize(widget, h, w); 249f499134dSBaptiste Daroussin 250f499134dSBaptiste Daroussin htextpad = 1; 251f499134dSBaptiste Daroussin wclear(textpad); 252f499134dSBaptiste Daroussin wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); 253f499134dSBaptiste Daroussin 254f499134dSBaptiste Daroussin if(update_widget_withtextpad(conf, shadow, widget, h, w, 255f499134dSBaptiste Daroussin RAISED, textpad, &htextpad, text, true) != 0) 256f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 257f499134dSBaptiste Daroussin 258f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 - 3, ':'); 259f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 + 2, ':'); 260f499134dSBaptiste Daroussin 261f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 262f499134dSBaptiste Daroussin 263f499134dSBaptiste Daroussin wrefresh(widget); 264f499134dSBaptiste Daroussin 265f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); 266f499134dSBaptiste Daroussin 267f499134dSBaptiste Daroussin wclear(c[0].win); 268f499134dSBaptiste Daroussin mvwin(c[0].win, y + h - 6, x + w/2 - 7); 269f499134dSBaptiste Daroussin draw_borders(conf, c[0].win, 3, 4, LOWERED); 270f499134dSBaptiste Daroussin wrefresh(c[0].win); 271f499134dSBaptiste Daroussin 272f499134dSBaptiste Daroussin wclear(c[1].win); 273f499134dSBaptiste Daroussin mvwin(c[1].win, y + h - 6, x + w/2 - 2); 274f499134dSBaptiste Daroussin draw_borders(conf, c[1].win, 3, 4, LOWERED); 275f499134dSBaptiste Daroussin wrefresh(c[1].win); 276f499134dSBaptiste Daroussin 277f499134dSBaptiste Daroussin wclear(c[2].win); 278f499134dSBaptiste Daroussin mvwin(c[2].win, y + h - 6, x + w/2 + 3); 279f499134dSBaptiste Daroussin draw_borders(conf, c[2].win, 3, 4, LOWERED); 280f499134dSBaptiste Daroussin wrefresh(c[2].win); 281f499134dSBaptiste Daroussin 282f499134dSBaptiste Daroussin /* Important to avoid grey lines expanding screen */ 283f499134dSBaptiste Daroussin refresh(); 284f499134dSBaptiste Daroussin break; 285f499134dSBaptiste Daroussin default: 286f499134dSBaptiste Daroussin for (i = 0; i < (int) bs.nbuttons; i++) 287f499134dSBaptiste Daroussin if (tolower(input) == tolower((bs.label[i])[0])) { 288f499134dSBaptiste Daroussin output = bs.value[i]; 289f499134dSBaptiste Daroussin loop = false; 290f499134dSBaptiste Daroussin } 291c76f0793SBaptiste Daroussin } 292c76f0793SBaptiste Daroussin } 293c76f0793SBaptiste Daroussin 294c76f0793SBaptiste Daroussin curs_set(0); 295c76f0793SBaptiste Daroussin 296c76f0793SBaptiste Daroussin for (i=0; i<3; i++) 297c76f0793SBaptiste Daroussin delwin(c[i].win); 298f499134dSBaptiste Daroussin end_widget_withtextpad(conf, widget, h, w, textpad, shadow); 299c76f0793SBaptiste Daroussin 300c76f0793SBaptiste Daroussin return output; 301c76f0793SBaptiste Daroussin } 302c76f0793SBaptiste Daroussin 303f499134dSBaptiste Daroussin int 304f499134dSBaptiste Daroussin bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols, 305c76f0793SBaptiste Daroussin unsigned int *yy, unsigned int *mm, unsigned int *dd) 306c76f0793SBaptiste Daroussin { 307f499134dSBaptiste Daroussin WINDOW *widget, *textpad, *shadow; 308f499134dSBaptiste Daroussin int i, input, output, y, x, h, w, sel, htextpad; 309c76f0793SBaptiste Daroussin struct buttons bs; 310f499134dSBaptiste Daroussin bool loop; 311c76f0793SBaptiste Daroussin struct calendar { 312f499134dSBaptiste Daroussin int max; 313f499134dSBaptiste Daroussin int value; 314c76f0793SBaptiste Daroussin WINDOW *win; 315c76f0793SBaptiste Daroussin unsigned int x; 316f499134dSBaptiste Daroussin }; 317c76f0793SBaptiste Daroussin struct month { 318c76f0793SBaptiste Daroussin char *name; 319c76f0793SBaptiste Daroussin unsigned int days; 320c76f0793SBaptiste Daroussin }; 321c76f0793SBaptiste Daroussin 322f499134dSBaptiste Daroussin if (yy == NULL || mm == NULL || dd == NULL) 323f499134dSBaptiste Daroussin RETURN_ERROR("yy / mm / dd cannot be NULL"); 324c76f0793SBaptiste Daroussin 325f499134dSBaptiste Daroussin struct calendar c[3] = { 326f499134dSBaptiste Daroussin {9999, *yy, NULL, 4 }, 327f499134dSBaptiste Daroussin {12, *mm, NULL, 9 }, 328f499134dSBaptiste Daroussin {31, *dd, NULL, 2 } 329f499134dSBaptiste Daroussin }; 330c76f0793SBaptiste Daroussin 331f499134dSBaptiste Daroussin struct month m[12] = { 332f499134dSBaptiste Daroussin { "January", 31 }, { "February", 28 }, { "March", 31 }, 333f499134dSBaptiste Daroussin { "April", 30 }, { "May", 31 }, { "June", 30 }, 334f499134dSBaptiste Daroussin { "July", 31 }, { "August", 31 }, { "September", 30 }, 335f499134dSBaptiste Daroussin { "October", 31 }, { "November", 30 }, { "December", 31 } 336f499134dSBaptiste Daroussin }; 337f499134dSBaptiste Daroussin 338f499134dSBaptiste Daroussin #define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) 339f499134dSBaptiste Daroussin 340f499134dSBaptiste Daroussin for (i = 0 ; i < 3; i++) { 341f499134dSBaptiste Daroussin if (c[i].value > c[i].max) 342f499134dSBaptiste Daroussin c[i].value = c[i].max; 343f499134dSBaptiste Daroussin if (c[i].value < 1) 344f499134dSBaptiste Daroussin c[i].value = 1; 345f499134dSBaptiste Daroussin } 346f499134dSBaptiste Daroussin c[2].max = m[c[1].value -1].days; 347f499134dSBaptiste Daroussin if (c[1].value == 2 && ISLEAF(c[0].value)) 348f499134dSBaptiste Daroussin c[2].max = 29; 349f499134dSBaptiste Daroussin if (c[2].value > c[2].max) 350f499134dSBaptiste Daroussin c[2].value = c[2].max; 351c76f0793SBaptiste Daroussin 352c76f0793SBaptiste Daroussin get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), 353c76f0793SBaptiste Daroussin BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); 354c76f0793SBaptiste Daroussin 355f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 356f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 357f499134dSBaptiste Daroussin if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0) 358f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 359f499134dSBaptiste Daroussin if (datetime_checksize(h, w, text, MINWDATE, bs) != 0) 360f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 361f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 362f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 363f499134dSBaptiste Daroussin 364f499134dSBaptiste Daroussin if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED, 365f499134dSBaptiste Daroussin &textpad, &htextpad, text, true) != 0) 366f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 367f499134dSBaptiste Daroussin 368f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 369f499134dSBaptiste Daroussin 370f499134dSBaptiste Daroussin wrefresh(widget); 371f499134dSBaptiste Daroussin 372f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); 373f499134dSBaptiste Daroussin 374f499134dSBaptiste Daroussin c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 11, 3, 6, LOWERED); 375f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 - 5, '/'); 376f499134dSBaptiste Daroussin c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 4, 3, 11, LOWERED); 377f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 + 7, '/'); 378f499134dSBaptiste Daroussin c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 8, 3, 4, LOWERED); 379f499134dSBaptiste Daroussin 380f499134dSBaptiste Daroussin wrefresh(widget); 381f499134dSBaptiste Daroussin 382c76f0793SBaptiste Daroussin sel = 2; 383c76f0793SBaptiste Daroussin curs_set(2); 384f499134dSBaptiste Daroussin loop = true; 385c76f0793SBaptiste Daroussin while(loop) { 386f499134dSBaptiste Daroussin mvwprintw(c[0].win, 1, 1, "%4d", c[0].value); 387f499134dSBaptiste Daroussin mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name); 388f499134dSBaptiste Daroussin mvwprintw(c[2].win, 1, 1, "%2d", c[2].value); 389c76f0793SBaptiste Daroussin for (i=0; i<3; i++) { 390c76f0793SBaptiste Daroussin wrefresh(c[i].win); 391c76f0793SBaptiste Daroussin } 392c76f0793SBaptiste Daroussin wmove(c[sel].win, 1, c[sel].x); 393c76f0793SBaptiste Daroussin wrefresh(c[sel].win); 394c76f0793SBaptiste Daroussin 395c76f0793SBaptiste Daroussin input = getch(); 396c76f0793SBaptiste Daroussin switch(input) { 397f499134dSBaptiste Daroussin case KEY_ENTER: 398f499134dSBaptiste Daroussin case 10: /* Enter */ 399f499134dSBaptiste Daroussin output = bs.value[bs.curr]; 400*8c4f4028SBaptiste Daroussin if (output == BSDDIALOG_OK) { 401f499134dSBaptiste Daroussin *yy = c[0].value; 402f499134dSBaptiste Daroussin *mm = c[1].value; 403f499134dSBaptiste Daroussin *dd = c[2].value; 404c76f0793SBaptiste Daroussin } 405c76f0793SBaptiste Daroussin loop = false; 406c76f0793SBaptiste Daroussin break; 407f499134dSBaptiste Daroussin case 27: /* Esc */ 408c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 409c76f0793SBaptiste Daroussin loop = false; 410c76f0793SBaptiste Daroussin break; 411f499134dSBaptiste Daroussin case '\t': /* TAB */ 412c76f0793SBaptiste Daroussin sel = (sel + 1) % 3; 413c76f0793SBaptiste Daroussin break; 414c76f0793SBaptiste Daroussin case KEY_LEFT: 415c76f0793SBaptiste Daroussin if (bs.curr > 0) { 416c76f0793SBaptiste Daroussin bs.curr--; 417f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 418f499134dSBaptiste Daroussin wrefresh(widget); 419c76f0793SBaptiste Daroussin } 420c76f0793SBaptiste Daroussin break; 421c76f0793SBaptiste Daroussin case KEY_RIGHT: 422c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 423c76f0793SBaptiste Daroussin bs.curr++; 424f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 425f499134dSBaptiste Daroussin wrefresh(widget); 426c76f0793SBaptiste Daroussin } 427c76f0793SBaptiste Daroussin break; 428c76f0793SBaptiste Daroussin case KEY_UP: 429f499134dSBaptiste Daroussin c[sel].value = c[sel].value > 1 ? c[sel].value - 1 : c[sel].max ; 430f499134dSBaptiste Daroussin /* if mount change */ 431f499134dSBaptiste Daroussin c[2].max = m[c[1].value -1].days; 432f499134dSBaptiste Daroussin /* if year change */ 433f499134dSBaptiste Daroussin if (c[1].value == 2 && ISLEAF(c[0].value)) 434f499134dSBaptiste Daroussin c[2].max = 29; 435f499134dSBaptiste Daroussin /* set new day */ 436f499134dSBaptiste Daroussin if (c[2].value > c[2].max) 437f499134dSBaptiste Daroussin c[2].value = c[2].max; 438c76f0793SBaptiste Daroussin break; 439c76f0793SBaptiste Daroussin case KEY_DOWN: 440f499134dSBaptiste Daroussin c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 1; 441f499134dSBaptiste Daroussin /* if mount change */ 442f499134dSBaptiste Daroussin c[2].max = m[c[1].value -1].days; 443f499134dSBaptiste Daroussin /* if year change */ 444f499134dSBaptiste Daroussin if (c[1].value == 2 && ISLEAF(c[0].value)) 445f499134dSBaptiste Daroussin c[2].max = 29; 446f499134dSBaptiste Daroussin /* set new day */ 447f499134dSBaptiste Daroussin if (c[2].value > c[2].max) 448f499134dSBaptiste Daroussin c[2].value = c[2].max; 449c76f0793SBaptiste Daroussin break; 450f499134dSBaptiste Daroussin case KEY_F(1): 451*8c4f4028SBaptiste Daroussin if (conf->f1_file == NULL && conf->f1_message == NULL) 452f499134dSBaptiste Daroussin break; 453f499134dSBaptiste Daroussin curs_set(0); 454f499134dSBaptiste Daroussin if (f1help(conf) != 0) 455f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 456f499134dSBaptiste Daroussin curs_set(2); 457f499134dSBaptiste Daroussin /* No break! the terminal size can change */ 458f499134dSBaptiste Daroussin case KEY_RESIZE: 459f499134dSBaptiste Daroussin hide_widget(y, x, h, w,conf->shadow); 460f499134dSBaptiste Daroussin 461f499134dSBaptiste Daroussin /* 462f499134dSBaptiste Daroussin * Unnecessary, but, when the columns decrease the 463f499134dSBaptiste Daroussin * following "refresh" seem not work 464f499134dSBaptiste Daroussin */ 465f499134dSBaptiste Daroussin refresh(); 466f499134dSBaptiste Daroussin 467f499134dSBaptiste Daroussin if (set_widget_size(conf, rows, cols, &h, &w) != 0) 468f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 469f499134dSBaptiste Daroussin if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0) 470f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 471f499134dSBaptiste Daroussin if (datetime_checksize(h, w, text, MINWDATE, bs) != 0) 472f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 473f499134dSBaptiste Daroussin if (set_widget_position(conf, &y, &x, h, w) != 0) 474f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 475f499134dSBaptiste Daroussin 476f499134dSBaptiste Daroussin wclear(shadow); 477f499134dSBaptiste Daroussin mvwin(shadow, y + t.shadow.h, x + t.shadow.w); 478f499134dSBaptiste Daroussin wresize(shadow, h, w); 479f499134dSBaptiste Daroussin 480f499134dSBaptiste Daroussin wclear(widget); 481f499134dSBaptiste Daroussin mvwin(widget, y, x); 482f499134dSBaptiste Daroussin wresize(widget, h, w); 483f499134dSBaptiste Daroussin 484f499134dSBaptiste Daroussin htextpad = 1; 485f499134dSBaptiste Daroussin wclear(textpad); 486f499134dSBaptiste Daroussin wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2); 487f499134dSBaptiste Daroussin 488f499134dSBaptiste Daroussin if(update_widget_withtextpad(conf, shadow, widget, h, w, 489f499134dSBaptiste Daroussin RAISED, textpad, &htextpad, text, true) != 0) 490f499134dSBaptiste Daroussin return BSDDIALOG_ERROR; 491f499134dSBaptiste Daroussin 492f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 - 5, '/'); 493f499134dSBaptiste Daroussin mvwaddch(widget, h - 5, w/2 + 7, '/'); 494f499134dSBaptiste Daroussin 495f499134dSBaptiste Daroussin draw_buttons(widget, h-2, w, bs, true); 496f499134dSBaptiste Daroussin 497f499134dSBaptiste Daroussin wrefresh(widget); 498f499134dSBaptiste Daroussin 499f499134dSBaptiste Daroussin prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2); 500f499134dSBaptiste Daroussin 501f499134dSBaptiste Daroussin wclear(c[0].win); 502f499134dSBaptiste Daroussin mvwin(c[0].win, y + h - 6, x + w/2 - 11); 503f499134dSBaptiste Daroussin draw_borders(conf, c[0].win, 3, 6, LOWERED); 504f499134dSBaptiste Daroussin wrefresh(c[0].win); 505f499134dSBaptiste Daroussin 506f499134dSBaptiste Daroussin wclear(c[1].win); 507f499134dSBaptiste Daroussin mvwin(c[1].win, y + h - 6, x + w/2 - 4); 508f499134dSBaptiste Daroussin draw_borders(conf, c[1].win, 3, 11, LOWERED); 509f499134dSBaptiste Daroussin wrefresh(c[1].win); 510f499134dSBaptiste Daroussin 511f499134dSBaptiste Daroussin wclear(c[2].win); 512f499134dSBaptiste Daroussin mvwin(c[2].win, y + h - 6, x + w/2 + 8); 513f499134dSBaptiste Daroussin draw_borders(conf, c[2].win, 3, 4, LOWERED); 514f499134dSBaptiste Daroussin wrefresh(c[2].win); 515f499134dSBaptiste Daroussin 516f499134dSBaptiste Daroussin /* Important to avoid grey lines expanding screen */ 517f499134dSBaptiste Daroussin refresh(); 518f499134dSBaptiste Daroussin break; 519f499134dSBaptiste Daroussin default: 520f499134dSBaptiste Daroussin for (i = 0; i < (int) bs.nbuttons; i++) 521f499134dSBaptiste Daroussin if (tolower(input) == tolower((bs.label[i])[0])) { 522f499134dSBaptiste Daroussin output = bs.value[i]; 523f499134dSBaptiste Daroussin loop = false; 524f499134dSBaptiste Daroussin } 525c76f0793SBaptiste Daroussin } 526c76f0793SBaptiste Daroussin } 527c76f0793SBaptiste Daroussin 528c76f0793SBaptiste Daroussin curs_set(0); 529c76f0793SBaptiste Daroussin 530c76f0793SBaptiste Daroussin for (i=0; i<3; i++) 531c76f0793SBaptiste Daroussin delwin(c[i].win); 532f499134dSBaptiste Daroussin end_widget_withtextpad(conf, widget, h, w, textpad, shadow); 533c76f0793SBaptiste Daroussin 534c76f0793SBaptiste Daroussin return output; 535c76f0793SBaptiste Daroussin } 536