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