1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * inputbox.c -- implements the input box 4 * 5 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 6 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 7 */ 8 9 #include "dialog.h" 10 11 char dialog_input_result[MAX_LEN + 1]; 12 13 /* 14 * Print the termination buttons 15 */ 16 static void print_buttons(WINDOW * dialog, int height, int width, int selected) 17 { 18 int x = width / 2 - 11; 19 int y = height - 2; 20 21 print_button(dialog, " Ok ", y, x, selected == 0); 22 print_button(dialog, " Help ", y, x + 14, selected == 1); 23 24 wmove(dialog, y, x + 1 + 14 * selected); 25 wrefresh(dialog); 26 } 27 28 /* 29 * Display a dialog box for inputing a string 30 */ 31 int dialog_inputbox(const char *title, const char *prompt, int height, int width, 32 const char *init) 33 { 34 int i, x, y, box_y, box_x, box_width; 35 int input_x = 0, key = 0, button = -1; 36 int show_x, len, pos; 37 char *instr = dialog_input_result; 38 WINDOW *dialog; 39 40 if (!init) 41 instr[0] = '\0'; 42 else { 43 strncpy(instr, init, sizeof(dialog_input_result) - 1); 44 instr[sizeof(dialog_input_result) - 1] = '\0'; 45 } 46 47 do_resize: 48 if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGHT_MIN)) 49 return -ERRDISPLAYTOOSMALL; 50 if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) 51 return -ERRDISPLAYTOOSMALL; 52 53 /* center dialog box on screen */ 54 x = (getmaxx(stdscr) - width) / 2; 55 y = (getmaxy(stdscr) - height) / 2; 56 57 draw_shadow(stdscr, y, x, height, width); 58 59 dialog = newwin(height, width, y, x); 60 keypad(dialog, TRUE); 61 62 draw_box(dialog, 0, 0, height, width, 63 dlg.dialog.atr, dlg.border.atr); 64 wattrset(dialog, dlg.border.atr); 65 mvwaddch(dialog, height - 3, 0, ACS_LTEE); 66 for (i = 0; i < width - 2; i++) 67 waddch(dialog, ACS_HLINE); 68 wattrset(dialog, dlg.dialog.atr); 69 waddch(dialog, ACS_RTEE); 70 71 print_title(dialog, title, width); 72 73 wattrset(dialog, dlg.dialog.atr); 74 print_autowrap(dialog, prompt, width - 2, 1, 3); 75 76 /* Draw the input field box */ 77 box_width = width - 6; 78 getyx(dialog, y, x); 79 box_y = y + 2; 80 box_x = (width - box_width) / 2; 81 draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, 82 dlg.dialog.atr, dlg.border.atr); 83 84 print_buttons(dialog, height, width, 0); 85 86 /* Set up the initial value */ 87 wmove(dialog, box_y, box_x); 88 wattrset(dialog, dlg.inputbox.atr); 89 90 len = strlen(instr); 91 pos = len; 92 93 if (len >= box_width) { 94 show_x = len - box_width + 1; 95 input_x = box_width - 1; 96 for (i = 0; i < box_width - 1; i++) 97 waddch(dialog, instr[show_x + i]); 98 } else { 99 show_x = 0; 100 input_x = len; 101 waddstr(dialog, instr); 102 } 103 104 wmove(dialog, box_y, box_x + input_x); 105 106 wrefresh(dialog); 107 108 while (key != KEY_ESC) { 109 key = wgetch(dialog); 110 111 if (button == -1) { /* Input box selected */ 112 switch (key) { 113 case TAB: 114 case KEY_UP: 115 case KEY_DOWN: 116 break; 117 case KEY_BACKSPACE: 118 case 8: /* ^H */ 119 case 127: /* ^? */ 120 if (pos) { 121 wattrset(dialog, dlg.inputbox.atr); 122 if (input_x == 0) { 123 show_x--; 124 } else 125 input_x--; 126 127 if (pos < len) { 128 for (i = pos - 1; i < len; i++) { 129 instr[i] = instr[i+1]; 130 } 131 } 132 133 pos--; 134 len--; 135 instr[len] = '\0'; 136 wmove(dialog, box_y, box_x); 137 for (i = 0; i < box_width; i++) { 138 if (!instr[show_x + i]) { 139 waddch(dialog, ' '); 140 break; 141 } 142 waddch(dialog, instr[show_x + i]); 143 } 144 wmove(dialog, box_y, input_x + box_x); 145 wrefresh(dialog); 146 } 147 continue; 148 case KEY_LEFT: 149 if (pos > 0) { 150 if (input_x > 0) { 151 wmove(dialog, box_y, --input_x + box_x); 152 } else if (input_x == 0) { 153 show_x--; 154 wmove(dialog, box_y, box_x); 155 for (i = 0; i < box_width; i++) { 156 if (!instr[show_x + i]) { 157 waddch(dialog, ' '); 158 break; 159 } 160 waddch(dialog, instr[show_x + i]); 161 } 162 wmove(dialog, box_y, box_x); 163 } 164 pos--; 165 } 166 continue; 167 case KEY_RIGHT: 168 if (pos < len) { 169 if (input_x < box_width - 1) { 170 wmove(dialog, box_y, ++input_x + box_x); 171 } else if (input_x == box_width - 1) { 172 show_x++; 173 wmove(dialog, box_y, box_x); 174 for (i = 0; i < box_width; i++) { 175 if (!instr[show_x + i]) { 176 waddch(dialog, ' '); 177 break; 178 } 179 waddch(dialog, instr[show_x + i]); 180 } 181 wmove(dialog, box_y, input_x + box_x); 182 } 183 pos++; 184 } 185 continue; 186 default: 187 if (key < 0x100 && isprint(key)) { 188 if (len < MAX_LEN) { 189 wattrset(dialog, dlg.inputbox.atr); 190 if (pos < len) { 191 for (i = len; i > pos; i--) 192 instr[i] = instr[i-1]; 193 instr[pos] = key; 194 } else { 195 instr[len] = key; 196 } 197 pos++; 198 len++; 199 instr[len] = '\0'; 200 201 if (input_x == box_width - 1) { 202 show_x++; 203 } else { 204 input_x++; 205 } 206 207 wmove(dialog, box_y, box_x); 208 for (i = 0; i < box_width; i++) { 209 if (!instr[show_x + i]) { 210 waddch(dialog, ' '); 211 break; 212 } 213 waddch(dialog, instr[show_x + i]); 214 } 215 wmove(dialog, box_y, input_x + box_x); 216 wrefresh(dialog); 217 } else 218 flash(); /* Alarm user about overflow */ 219 continue; 220 } 221 } 222 } 223 switch (key) { 224 case 'O': 225 case 'o': 226 delwin(dialog); 227 return 0; 228 case 'H': 229 case 'h': 230 delwin(dialog); 231 return 1; 232 case KEY_UP: 233 case KEY_LEFT: 234 switch (button) { 235 case -1: 236 button = 1; /* Indicates "Help" button is selected */ 237 print_buttons(dialog, height, width, 1); 238 break; 239 case 0: 240 button = -1; /* Indicates input box is selected */ 241 print_buttons(dialog, height, width, 0); 242 wmove(dialog, box_y, box_x + input_x); 243 wrefresh(dialog); 244 break; 245 case 1: 246 button = 0; /* Indicates "OK" button is selected */ 247 print_buttons(dialog, height, width, 0); 248 break; 249 } 250 break; 251 case TAB: 252 case KEY_DOWN: 253 case KEY_RIGHT: 254 switch (button) { 255 case -1: 256 button = 0; /* Indicates "OK" button is selected */ 257 print_buttons(dialog, height, width, 0); 258 break; 259 case 0: 260 button = 1; /* Indicates "Help" button is selected */ 261 print_buttons(dialog, height, width, 1); 262 break; 263 case 1: 264 button = -1; /* Indicates input box is selected */ 265 print_buttons(dialog, height, width, 0); 266 wmove(dialog, box_y, box_x + input_x); 267 wrefresh(dialog); 268 break; 269 } 270 break; 271 case ' ': 272 case '\n': 273 delwin(dialog); 274 return (button == -1 ? 0 : button); 275 case 'X': 276 case 'x': 277 key = KEY_ESC; 278 break; 279 case KEY_ESC: 280 key = on_key_esc(dialog); 281 break; 282 case KEY_RESIZE: 283 delwin(dialog); 284 on_key_resize(); 285 goto do_resize; 286 } 287 } 288 289 delwin(dialog); 290 return KEY_ESC; /* ESC pressed */ 291 } 292