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