1*c76f0793SBaptiste Daroussin /*- 2*c76f0793SBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause 3*c76f0793SBaptiste Daroussin * 4*c76f0793SBaptiste Daroussin * Copyright (c) 2021 Alfonso Sabato Siciliano 5*c76f0793SBaptiste Daroussin * 6*c76f0793SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 7*c76f0793SBaptiste Daroussin * modification, are permitted provided that the following conditions 8*c76f0793SBaptiste Daroussin * are met: 9*c76f0793SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 10*c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 11*c76f0793SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 12*c76f0793SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 13*c76f0793SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 14*c76f0793SBaptiste Daroussin * 15*c76f0793SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*c76f0793SBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*c76f0793SBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*c76f0793SBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*c76f0793SBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*c76f0793SBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*c76f0793SBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*c76f0793SBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*c76f0793SBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*c76f0793SBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*c76f0793SBaptiste Daroussin * SUCH DAMAGE. 26*c76f0793SBaptiste Daroussin */ 27*c76f0793SBaptiste Daroussin 28*c76f0793SBaptiste Daroussin #ifdef PORTNCURSES 29*c76f0793SBaptiste Daroussin #include <ncurses/curses.h> 30*c76f0793SBaptiste Daroussin #else 31*c76f0793SBaptiste Daroussin #include <curses.h> 32*c76f0793SBaptiste Daroussin #endif 33*c76f0793SBaptiste Daroussin 34*c76f0793SBaptiste Daroussin #include "bsddialog.h" 35*c76f0793SBaptiste Daroussin #include "lib_util.h" 36*c76f0793SBaptiste Daroussin 37*c76f0793SBaptiste Daroussin /* "Time": timebox - calendar */ 38*c76f0793SBaptiste Daroussin 39*c76f0793SBaptiste Daroussin int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols, 40*c76f0793SBaptiste Daroussin unsigned int *hh, unsigned int *mm, unsigned int *ss) 41*c76f0793SBaptiste Daroussin { 42*c76f0793SBaptiste Daroussin WINDOW *widget, *shadow; 43*c76f0793SBaptiste Daroussin int i, input, output, y, x, sel; 44*c76f0793SBaptiste Daroussin struct buttons bs; 45*c76f0793SBaptiste Daroussin bool loop, buttupdate; 46*c76f0793SBaptiste Daroussin 47*c76f0793SBaptiste Daroussin if (hh == NULL || mm == NULL || ss == NULL) 48*c76f0793SBaptiste Daroussin RETURN_ERROR("hh or mm or ss == NULL"); 49*c76f0793SBaptiste Daroussin 50*c76f0793SBaptiste Daroussin struct myclockstruct { 51*c76f0793SBaptiste Daroussin unsigned int max; 52*c76f0793SBaptiste Daroussin unsigned int curr; 53*c76f0793SBaptiste Daroussin WINDOW *win; 54*c76f0793SBaptiste Daroussin } c[3] = { {23, *hh, NULL}, {59, *mm, NULL}, {59, *ss, NULL} }; 55*c76f0793SBaptiste Daroussin 56*c76f0793SBaptiste Daroussin if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow, 57*c76f0793SBaptiste Daroussin true) <0) 58*c76f0793SBaptiste Daroussin return -1; 59*c76f0793SBaptiste Daroussin 60*c76f0793SBaptiste Daroussin c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 7, 3, 4, LOWERED); 61*c76f0793SBaptiste Daroussin mvwaddch(widget, rows - 5, cols/2 - 3, ':'); 62*c76f0793SBaptiste Daroussin c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 2, 3, 4, LOWERED); 63*c76f0793SBaptiste Daroussin mvwaddch(widget, rows - 5, cols/2 + 2, ':'); 64*c76f0793SBaptiste Daroussin c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 3, 3, 4, LOWERED); 65*c76f0793SBaptiste Daroussin 66*c76f0793SBaptiste Daroussin get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), 67*c76f0793SBaptiste Daroussin BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); 68*c76f0793SBaptiste Daroussin 69*c76f0793SBaptiste Daroussin sel=0; 70*c76f0793SBaptiste Daroussin curs_set(2); 71*c76f0793SBaptiste Daroussin loop = buttupdate = true; 72*c76f0793SBaptiste Daroussin while(loop) { 73*c76f0793SBaptiste Daroussin if (buttupdate) { 74*c76f0793SBaptiste Daroussin draw_buttons(widget, rows-2, cols, bs, true); 75*c76f0793SBaptiste Daroussin wrefresh(widget); 76*c76f0793SBaptiste Daroussin buttupdate = false; 77*c76f0793SBaptiste Daroussin } 78*c76f0793SBaptiste Daroussin 79*c76f0793SBaptiste Daroussin for (i=0; i<3; i++) { 80*c76f0793SBaptiste Daroussin mvwprintw(c[i].win, 1, 1, "%2d", c[i].curr); 81*c76f0793SBaptiste Daroussin wrefresh(c[i].win); 82*c76f0793SBaptiste Daroussin } 83*c76f0793SBaptiste Daroussin wmove(c[sel].win, 1, 2); 84*c76f0793SBaptiste Daroussin wrefresh(c[sel].win); 85*c76f0793SBaptiste Daroussin 86*c76f0793SBaptiste Daroussin input = getch(); 87*c76f0793SBaptiste Daroussin switch(input) { 88*c76f0793SBaptiste Daroussin case 10: /* Enter */ 89*c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; 90*c76f0793SBaptiste Daroussin if (output == BSDDIALOG_YESOK) { 91*c76f0793SBaptiste Daroussin *hh = c[0].curr - 1900; 92*c76f0793SBaptiste Daroussin *mm = c[1].curr; 93*c76f0793SBaptiste Daroussin *ss = c[2].curr; 94*c76f0793SBaptiste Daroussin } 95*c76f0793SBaptiste Daroussin loop = false; 96*c76f0793SBaptiste Daroussin break; 97*c76f0793SBaptiste Daroussin case 27: /* Esc */ 98*c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 99*c76f0793SBaptiste Daroussin loop = false; 100*c76f0793SBaptiste Daroussin break; 101*c76f0793SBaptiste Daroussin case '\t': /* TAB */ 102*c76f0793SBaptiste Daroussin sel = (sel + 1) % 3; 103*c76f0793SBaptiste Daroussin break; 104*c76f0793SBaptiste Daroussin case KEY_LEFT: 105*c76f0793SBaptiste Daroussin if (bs.curr > 0) { 106*c76f0793SBaptiste Daroussin bs.curr--; 107*c76f0793SBaptiste Daroussin buttupdate = true; 108*c76f0793SBaptiste Daroussin } 109*c76f0793SBaptiste Daroussin break; 110*c76f0793SBaptiste Daroussin case KEY_RIGHT: 111*c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 112*c76f0793SBaptiste Daroussin bs.curr++; 113*c76f0793SBaptiste Daroussin buttupdate = true; 114*c76f0793SBaptiste Daroussin } 115*c76f0793SBaptiste Daroussin break; 116*c76f0793SBaptiste Daroussin case KEY_UP: 117*c76f0793SBaptiste Daroussin c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 0; 118*c76f0793SBaptiste Daroussin break; 119*c76f0793SBaptiste Daroussin case KEY_DOWN: 120*c76f0793SBaptiste Daroussin c[sel].curr = c[sel].curr > 0 ? c[sel].curr - 1 : c[sel].max; 121*c76f0793SBaptiste Daroussin break; 122*c76f0793SBaptiste Daroussin } 123*c76f0793SBaptiste Daroussin } 124*c76f0793SBaptiste Daroussin 125*c76f0793SBaptiste Daroussin curs_set(0); 126*c76f0793SBaptiste Daroussin 127*c76f0793SBaptiste Daroussin for (i=0; i<3; i++) 128*c76f0793SBaptiste Daroussin delwin(c[i].win); 129*c76f0793SBaptiste Daroussin end_widget(conf, widget, rows, cols, shadow); 130*c76f0793SBaptiste Daroussin 131*c76f0793SBaptiste Daroussin return output; 132*c76f0793SBaptiste Daroussin } 133*c76f0793SBaptiste Daroussin 134*c76f0793SBaptiste Daroussin int bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int cols, 135*c76f0793SBaptiste Daroussin unsigned int *yy, unsigned int *mm, unsigned int *dd) 136*c76f0793SBaptiste Daroussin { 137*c76f0793SBaptiste Daroussin WINDOW *widget, *shadow; 138*c76f0793SBaptiste Daroussin int i, input, output, y, x, sel; 139*c76f0793SBaptiste Daroussin struct buttons bs; 140*c76f0793SBaptiste Daroussin bool loop, buttupdate; 141*c76f0793SBaptiste Daroussin 142*c76f0793SBaptiste Daroussin if (yy == NULL || mm == NULL || dd == NULL) 143*c76f0793SBaptiste Daroussin RETURN_ERROR("yy or mm or dd == NULL"); 144*c76f0793SBaptiste Daroussin 145*c76f0793SBaptiste Daroussin struct calendar { 146*c76f0793SBaptiste Daroussin unsigned int max; 147*c76f0793SBaptiste Daroussin unsigned int curr; 148*c76f0793SBaptiste Daroussin WINDOW *win; 149*c76f0793SBaptiste Daroussin unsigned int x; 150*c76f0793SBaptiste Daroussin } c[3] = {{9999, *yy, NULL, 4 }, {12, *mm, NULL, 9 }, {31, *dd, NULL, 2 }}; 151*c76f0793SBaptiste Daroussin struct month { 152*c76f0793SBaptiste Daroussin char *name; 153*c76f0793SBaptiste Daroussin unsigned int days; 154*c76f0793SBaptiste Daroussin } m[12] = { 155*c76f0793SBaptiste Daroussin { "January", 30 }, { "February", 30 }, { "March", 30 }, 156*c76f0793SBaptiste Daroussin { "April", 30 }, { "May", 30 }, { "June", 30 }, 157*c76f0793SBaptiste Daroussin { "July", 30 }, { "August", 30 }, { "September", 30 }, 158*c76f0793SBaptiste Daroussin { "October", 30 }, { "November", 30 }, { "December", 30 } 159*c76f0793SBaptiste Daroussin }; 160*c76f0793SBaptiste Daroussin 161*c76f0793SBaptiste Daroussin if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow, 162*c76f0793SBaptiste Daroussin true) <0) 163*c76f0793SBaptiste Daroussin return -1; 164*c76f0793SBaptiste Daroussin 165*c76f0793SBaptiste Daroussin c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 12, 3, 6, LOWERED); 166*c76f0793SBaptiste Daroussin mvwaddch(widget, rows - 5, cols/2 - 6, '/'); 167*c76f0793SBaptiste Daroussin c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 5, 3, 11, LOWERED); 168*c76f0793SBaptiste Daroussin mvwaddch(widget, rows - 5, cols/2 + 6, '/'); 169*c76f0793SBaptiste Daroussin c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 7, 3, 4, LOWERED); 170*c76f0793SBaptiste Daroussin 171*c76f0793SBaptiste Daroussin wrefresh(widget); 172*c76f0793SBaptiste Daroussin 173*c76f0793SBaptiste Daroussin get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label), 174*c76f0793SBaptiste Daroussin BUTTONLABEL(cancel_label), BUTTONLABEL(help_label)); 175*c76f0793SBaptiste Daroussin 176*c76f0793SBaptiste Daroussin sel=2; 177*c76f0793SBaptiste Daroussin curs_set(2); 178*c76f0793SBaptiste Daroussin loop = buttupdate = true; 179*c76f0793SBaptiste Daroussin while(loop) { 180*c76f0793SBaptiste Daroussin if (buttupdate) { 181*c76f0793SBaptiste Daroussin draw_buttons(widget, rows-2, cols, bs, true); 182*c76f0793SBaptiste Daroussin wrefresh(widget); 183*c76f0793SBaptiste Daroussin buttupdate = false; 184*c76f0793SBaptiste Daroussin } 185*c76f0793SBaptiste Daroussin 186*c76f0793SBaptiste Daroussin mvwprintw(c[0].win, 1, 1, "%4d", c[0].curr); 187*c76f0793SBaptiste Daroussin mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].curr-1].name); 188*c76f0793SBaptiste Daroussin mvwprintw(c[2].win, 1, 1, "%2d", c[2].curr); 189*c76f0793SBaptiste Daroussin for (i=0; i<3; i++) { 190*c76f0793SBaptiste Daroussin wrefresh(c[i].win); 191*c76f0793SBaptiste Daroussin } 192*c76f0793SBaptiste Daroussin wmove(c[sel].win, 1, c[sel].x); 193*c76f0793SBaptiste Daroussin wrefresh(c[sel].win); 194*c76f0793SBaptiste Daroussin 195*c76f0793SBaptiste Daroussin input = getch(); 196*c76f0793SBaptiste Daroussin switch(input) { 197*c76f0793SBaptiste Daroussin case 10: // Enter 198*c76f0793SBaptiste Daroussin output = bs.value[bs.curr]; // values -> outputs 199*c76f0793SBaptiste Daroussin if (output == BSDDIALOG_YESOK) { 200*c76f0793SBaptiste Daroussin *yy = c[0].curr - 1900; 201*c76f0793SBaptiste Daroussin *mm = c[1].curr; 202*c76f0793SBaptiste Daroussin *dd = c[2].curr; 203*c76f0793SBaptiste Daroussin } 204*c76f0793SBaptiste Daroussin loop = false; 205*c76f0793SBaptiste Daroussin break; 206*c76f0793SBaptiste Daroussin case 27: // Esc 207*c76f0793SBaptiste Daroussin output = BSDDIALOG_ESC; 208*c76f0793SBaptiste Daroussin loop = false; 209*c76f0793SBaptiste Daroussin break; 210*c76f0793SBaptiste Daroussin case '\t': // TAB 211*c76f0793SBaptiste Daroussin sel = (sel + 1) % 3; 212*c76f0793SBaptiste Daroussin break; 213*c76f0793SBaptiste Daroussin case KEY_LEFT: 214*c76f0793SBaptiste Daroussin if (bs.curr > 0) { 215*c76f0793SBaptiste Daroussin bs.curr--; 216*c76f0793SBaptiste Daroussin buttupdate = true; 217*c76f0793SBaptiste Daroussin } 218*c76f0793SBaptiste Daroussin break; 219*c76f0793SBaptiste Daroussin case KEY_RIGHT: 220*c76f0793SBaptiste Daroussin if (bs.curr < (int) bs.nbuttons - 1) { 221*c76f0793SBaptiste Daroussin bs.curr++; 222*c76f0793SBaptiste Daroussin buttupdate = true; 223*c76f0793SBaptiste Daroussin } 224*c76f0793SBaptiste Daroussin break; 225*c76f0793SBaptiste Daroussin case KEY_UP: 226*c76f0793SBaptiste Daroussin c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 1; 227*c76f0793SBaptiste Daroussin break; 228*c76f0793SBaptiste Daroussin case KEY_DOWN: 229*c76f0793SBaptiste Daroussin c[sel].curr = c[sel].curr > 1 ? c[sel].curr - 1 : c[sel].max; 230*c76f0793SBaptiste Daroussin break; 231*c76f0793SBaptiste Daroussin } 232*c76f0793SBaptiste Daroussin } 233*c76f0793SBaptiste Daroussin 234*c76f0793SBaptiste Daroussin curs_set(0); 235*c76f0793SBaptiste Daroussin 236*c76f0793SBaptiste Daroussin for (i=0; i<3; i++) 237*c76f0793SBaptiste Daroussin delwin(c[i].win); 238*c76f0793SBaptiste Daroussin end_widget(conf, widget, rows, cols, shadow); 239*c76f0793SBaptiste Daroussin 240*c76f0793SBaptiste Daroussin return output; 241*c76f0793SBaptiste Daroussin } 242