2 * input.c from Access Point SNMP Utils for Linux
3 * program input & screen related functions
5 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
6 * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License Version 2 from
10 * June 1991 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 extern WINDOW *main_sub, *win_for_help;
32 #define GEN_IV_MSG _("Invalid value. Press any key to continue.")
33 #define OOR_IV_MSG _("Value must be in range %u - %u. Press any key to continue.")
39 get_mac(char *mac, int row, int col)
41 char message[MAC_LEN+1], mess[MAC_LEN/MAC_BYTES+1];
45 while (strlen(message) != 12)
46 get_value(message, row, col, MAC_LEN+1, HEX_STRING, 0, 0, NULL);
48 for (i = 0; i < MAC_BYTES; i++) {
49 mess[0] = message[2 * i];
50 mess[1] = message[2 * i + 1];
52 mac[i] = strtol(mess, NULL, 16);
59 get_ip(struct in_addr *ip, int row, int col, char *helpmsg)
61 char message[IP_LEN+1], *cp;
65 get_value(message, row, col, IP_LEN+1, ANY_STRING, 0, 0, NULL);
66 for (cp = message, dotc = 0; *cp && (cp = index(cp, '.')); cp++, dotc++);
67 if (dotc < 3 || !(inet_aton(message, ip))) {
69 print_helperr(GEN_IV_MSG);
78 get_mask(struct in_addr *ip, int row, int col, char *helpmsg)
80 int i, bit, hmask, trans_count;
84 get_ip(ip, row, col, helpmsg);
85 hmask = ntohl(ip->s_addr);
86 bit = hmask & 0x00000001;
87 for (i = 1; i < 32; i++)
88 if (((hmask >> i) & 0x00000001) != bit) {
93 if (trans_count > 1) {
94 print_helperr(GEN_IV_MSG);
102 * This is the main input function for all cases when user needs to enter
103 * a visible string. It also performs syntax correctness checks
104 * as well as bounds checks if required.
106 * value ....... this should keep the value, entered by the user,
107 * in ascii string notation
109 * col ......... the begin coordinates, relative to the current window,
110 * at which the string entered by the user will appear
111 * len ......... maximum length of the entered string, including the
112 * tailing '\0' character. Negative value along with
113 * vt=ANY_STRING means that zero-length string is allowed.
114 * vt .......... desired input value type (types INT_STRING, HEX_STRING,
116 * minv, maxv .. min/max bounds in case of integer value input. Each can be
117 * of value 0-0xFFFFFFFF. If both are 0, it means no value bounds
118 * checking will be performed. Used only with vt=INT_STRING.
119 * helpmsg ..... pointer to string that will be printed after OOR_IV_MSG
120 * message if the entered integer value is out of range.
121 * If NULL, then no 'invalid value' and subsequent status line
122 * message will be printed, and whole input process will be
123 * repeated. Used only with vt=INT_STRING.
126 get_value(char *value, int row, int col, int len,
127 char vt, unsigned int minv, unsigned int maxv, char *helpmsg)
131 char iv_msg[128], zerolen_perm = 0;
132 enum { INSERT, OVERWRITE } mode;
135 if (vt == ANY_STRING && len < 0) {
140 gv_win = derwin(main_sub, 1, len - 1, row, col);
141 wbkgdset(gv_win, A_REVERSE);
149 i = 0; /* means 'character count' here */
155 if (c >= '0' && c <= '9') acs = 1;
158 if ((c >= '0' && c <= '9') ||
159 (c >= 'a' && c <= 'f') ||
160 (c >= 'A' && c <= 'F')) acs = 1;
165 /* rather do not ask, how this works... */
169 /* lefthandside DELETE */
172 * do not step cursor back only if window is filled AND
173 * cursor is totally on RHS
175 if ((i < len - 1) || (x < len - 2))
177 mvwdelch(gv_win, 0, x);
183 /* righthandside DELETE */
187 mvwdelch(gv_win, 0, x);
194 wmove(gv_win, 0, --x);
200 wmove(gv_win, 0, ++x);
209 wmove(gv_win, 0, (i == len - 1 ? i - 1 : i));
213 mode = (mode == INSERT ? OVERWRITE : INSERT);
214 curs_set(mode == INSERT ? 1 : 2);
218 if (i > 0 || zerolen_perm)
223 if (acs && (c < 0x100)) {
224 if (mode == INSERT) {
228 wmove(gv_win, 0, ++x);
233 // wechochar(gv_win, c);
237 wmove(gv_win, 0, ++x);
247 winnstr(gv_win, value, i);
251 if (vt == INT_STRING) {
252 i = strtoul(value, (char **)NULL, 10);
253 sprintf(value, "%i", i); /* eat leading zeros */
256 if ((unsigned)i < minv || (unsigned)i > maxv || errno == ERANGE) {
258 snprintf(iv_msg, sizeof(iv_msg) -1, OOR_IV_MSG, minv, maxv);
259 print_helperr(iv_msg);
263 goto get_value_again;
268 wbkgdset(gv_win, A_BOLD);
270 waddstr(gv_win, value);
272 // mvwprintw(main_sub, 18, 1, "length: %i", i);
273 // wrefresh(main_sub);
278 * Note: indeed we should use get_value() for this action, but for the moment,
279 * we'll settle with this one.
283 get_pass(char *value, int row, int col, int len)
287 wattrset(main_sub, COLOR_PAIR(12));
288 wmove(main_sub, row, col);
289 for (i = 0; i < len - 1; i++)
290 waddch(main_sub, ' ');
294 value[j] = mvwgetch(main_sub, row, col + j);
295 if (value[j] == 0x0A) /* NEWLINE */
297 if (value[j] == 0x1B) /* ESCAPE */
299 if (value[j] != 0x7F) { /* BACKSPACE */
301 mvwaddch(main_sub, row, col + j++, '*');
304 mvwaddch(main_sub, row, col + --j, ' ');
310 wattrset(main_sub, A_BOLD);
311 wmove(main_sub, row, col);
312 for (i = 0; i < len - 1; i++)
313 waddch(main_sub, ' ');
314 wmove(main_sub, row, col);
315 for (i = 0; i < j; i++)
316 waddch(main_sub, '*');
317 wattrset(main_sub, A_NORMAL);
322 yes_no(int brow, int bcol)
324 char *names[2] = { YES, NO };
326 return menu_choose(brow, bcol, names, 2) + 1;
330 on_off(int brow, int bcol)
332 char *names[2] = { ON, OFF };
334 return menu_choose(brow, bcol, names, 2) + 1;
337 int menu_choose(int brow, int bcol, char **names, unsigned int num)
339 unsigned short int c;
340 ITEM **menu_item = calloc(num, sizeof(ITEM)), **ip = menu_item;
342 unsigned int ncol = 2, i, nrow;
343 WINDOW *choose_menu, *sub_choose_menu;
344 extern WINDOW *main_sub;
346 for (i = 0; i < num; i++) {
347 *ip++ = new_item(names[i], "");
348 if (ncol < strlen(names[i]) + 3)
349 ncol = strlen(names[i]) + 3;
355 if (brow + 2 + nrow <= (unsigned int) LINES - 2)
356 choose_menu = newwin(nrow, ncol, brow + 2, bcol + MCOLS);
358 choose_menu = newwin(nrow, ncol, brow - nrow + 3, bcol + MCOLS);
359 sub_choose_menu = derwin(choose_menu, nrow - 2, ncol - 2, 1, 1);
360 attrset(COLOR_PAIR(11));
362 mvwaddch(choose_menu, 0, 0, ACS_ULCORNER);
363 mvwaddch(choose_menu, 0, ncol - 1, ACS_URCORNER);
364 mvwaddch(choose_menu, nrow - 1, 0, ACS_LLCORNER);
365 mvwaddch(choose_menu, nrow - 1, ncol - 1, ACS_LRCORNER);
366 for (i = 1; i < ncol - 1; i++) {
367 mvwaddch(choose_menu, 0, i, ACS_HLINE);
368 mvwaddch(choose_menu, nrow - 1, i, ACS_HLINE);
370 for (i = 1; i < nrow - 1; i++) {
371 mvwaddch(choose_menu, i, 0, ACS_VLINE);
372 mvwaddch(choose_menu, i, ncol - 1, ACS_VLINE);
374 wrefresh(choose_menu);
377 menu1 = new_menu(menu_item);
378 set_menu_win(menu1, choose_menu);
379 set_menu_sub(menu1, sub_choose_menu);
381 set_menu_opts(menu1, O_ONEVALUE);
385 wrefresh(sub_choose_menu);
392 menu_driver(menu1, REQ_NEXT_ITEM);
393 wrefresh(sub_choose_menu);
398 menu_driver(menu1, REQ_LAST_ITEM);
399 wrefresh(sub_choose_menu);
404 menu_driver(menu1, REQ_FIRST_ITEM);
405 wrefresh(sub_choose_menu);
410 menu_driver(menu1, REQ_PREV_ITEM);
411 wrefresh(sub_choose_menu);
414 i = item_index(current_item(menu1));
417 for (c = 0; c < nrow - 2; c++)
418 free_item(menu_item[c]);
419 delwin(sub_choose_menu);
430 * Reads key by either no-delay getch() (WAIT_FOREVER mode) or using
431 * getch() with tval tenths of second timeout (WAIT_TIMEOUT mode).
432 * Returns 0 for timeout, or pressed key code.
434 int wait_key(int tval)
437 extern int wait_mode;
439 if (wait_mode == WAIT_TIMEOUT)
444 if (wait_mode == WAIT_TIMEOUT) {
460 print_help (_("Y - Yes; Any other key - No (it's safer to answer No)"));
463 if (c == 'y' || c == 'Y')