1*0a9064fbSMasahiro Yamada /* 2*0a9064fbSMasahiro Yamada * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com? 3*0a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0. 4*0a9064fbSMasahiro Yamada * 5*0a9064fbSMasahiro Yamada * Derived from menuconfig. 6*0a9064fbSMasahiro Yamada * 7*0a9064fbSMasahiro Yamada */ 8*0a9064fbSMasahiro Yamada #include "nconf.h" 9*0a9064fbSMasahiro Yamada 10*0a9064fbSMasahiro Yamada /* a list of all the different widgets we use */ 11*0a9064fbSMasahiro Yamada attributes_t attributes[ATTR_MAX+1] = {0}; 12*0a9064fbSMasahiro Yamada 13*0a9064fbSMasahiro Yamada /* available colors: 14*0a9064fbSMasahiro Yamada COLOR_BLACK 0 15*0a9064fbSMasahiro Yamada COLOR_RED 1 16*0a9064fbSMasahiro Yamada COLOR_GREEN 2 17*0a9064fbSMasahiro Yamada COLOR_YELLOW 3 18*0a9064fbSMasahiro Yamada COLOR_BLUE 4 19*0a9064fbSMasahiro Yamada COLOR_MAGENTA 5 20*0a9064fbSMasahiro Yamada COLOR_CYAN 6 21*0a9064fbSMasahiro Yamada COLOR_WHITE 7 22*0a9064fbSMasahiro Yamada */ 23*0a9064fbSMasahiro Yamada static void set_normal_colors(void) 24*0a9064fbSMasahiro Yamada { 25*0a9064fbSMasahiro Yamada init_pair(NORMAL, -1, -1); 26*0a9064fbSMasahiro Yamada init_pair(MAIN_HEADING, COLOR_MAGENTA, -1); 27*0a9064fbSMasahiro Yamada 28*0a9064fbSMasahiro Yamada /* FORE is for the selected item */ 29*0a9064fbSMasahiro Yamada init_pair(MAIN_MENU_FORE, -1, -1); 30*0a9064fbSMasahiro Yamada /* BACK for all the rest */ 31*0a9064fbSMasahiro Yamada init_pair(MAIN_MENU_BACK, -1, -1); 32*0a9064fbSMasahiro Yamada init_pair(MAIN_MENU_GREY, -1, -1); 33*0a9064fbSMasahiro Yamada init_pair(MAIN_MENU_HEADING, COLOR_GREEN, -1); 34*0a9064fbSMasahiro Yamada init_pair(MAIN_MENU_BOX, COLOR_YELLOW, -1); 35*0a9064fbSMasahiro Yamada 36*0a9064fbSMasahiro Yamada init_pair(SCROLLWIN_TEXT, -1, -1); 37*0a9064fbSMasahiro Yamada init_pair(SCROLLWIN_HEADING, COLOR_GREEN, -1); 38*0a9064fbSMasahiro Yamada init_pair(SCROLLWIN_BOX, COLOR_YELLOW, -1); 39*0a9064fbSMasahiro Yamada 40*0a9064fbSMasahiro Yamada init_pair(DIALOG_TEXT, -1, -1); 41*0a9064fbSMasahiro Yamada init_pair(DIALOG_BOX, COLOR_YELLOW, -1); 42*0a9064fbSMasahiro Yamada init_pair(DIALOG_MENU_BACK, COLOR_YELLOW, -1); 43*0a9064fbSMasahiro Yamada init_pair(DIALOG_MENU_FORE, COLOR_RED, -1); 44*0a9064fbSMasahiro Yamada 45*0a9064fbSMasahiro Yamada init_pair(INPUT_BOX, COLOR_YELLOW, -1); 46*0a9064fbSMasahiro Yamada init_pair(INPUT_HEADING, COLOR_GREEN, -1); 47*0a9064fbSMasahiro Yamada init_pair(INPUT_TEXT, -1, -1); 48*0a9064fbSMasahiro Yamada init_pair(INPUT_FIELD, -1, -1); 49*0a9064fbSMasahiro Yamada 50*0a9064fbSMasahiro Yamada init_pair(FUNCTION_HIGHLIGHT, -1, -1); 51*0a9064fbSMasahiro Yamada init_pair(FUNCTION_TEXT, COLOR_YELLOW, -1); 52*0a9064fbSMasahiro Yamada } 53*0a9064fbSMasahiro Yamada 54*0a9064fbSMasahiro Yamada /* available attributes: 55*0a9064fbSMasahiro Yamada A_NORMAL Normal display (no highlight) 56*0a9064fbSMasahiro Yamada A_STANDOUT Best highlighting mode of the terminal. 57*0a9064fbSMasahiro Yamada A_UNDERLINE Underlining 58*0a9064fbSMasahiro Yamada A_REVERSE Reverse video 59*0a9064fbSMasahiro Yamada A_BLINK Blinking 60*0a9064fbSMasahiro Yamada A_DIM Half bright 61*0a9064fbSMasahiro Yamada A_BOLD Extra bright or bold 62*0a9064fbSMasahiro Yamada A_PROTECT Protected mode 63*0a9064fbSMasahiro Yamada A_INVIS Invisible or blank mode 64*0a9064fbSMasahiro Yamada A_ALTCHARSET Alternate character set 65*0a9064fbSMasahiro Yamada A_CHARTEXT Bit-mask to extract a character 66*0a9064fbSMasahiro Yamada COLOR_PAIR(n) Color-pair number n 67*0a9064fbSMasahiro Yamada */ 68*0a9064fbSMasahiro Yamada static void normal_color_theme(void) 69*0a9064fbSMasahiro Yamada { 70*0a9064fbSMasahiro Yamada /* automatically add color... */ 71*0a9064fbSMasahiro Yamada #define mkattr(name, attr) do { \ 72*0a9064fbSMasahiro Yamada attributes[name] = attr | COLOR_PAIR(name); } while (0) 73*0a9064fbSMasahiro Yamada mkattr(NORMAL, NORMAL); 74*0a9064fbSMasahiro Yamada mkattr(MAIN_HEADING, A_BOLD | A_UNDERLINE); 75*0a9064fbSMasahiro Yamada 76*0a9064fbSMasahiro Yamada mkattr(MAIN_MENU_FORE, A_REVERSE); 77*0a9064fbSMasahiro Yamada mkattr(MAIN_MENU_BACK, A_NORMAL); 78*0a9064fbSMasahiro Yamada mkattr(MAIN_MENU_GREY, A_NORMAL); 79*0a9064fbSMasahiro Yamada mkattr(MAIN_MENU_HEADING, A_BOLD); 80*0a9064fbSMasahiro Yamada mkattr(MAIN_MENU_BOX, A_NORMAL); 81*0a9064fbSMasahiro Yamada 82*0a9064fbSMasahiro Yamada mkattr(SCROLLWIN_TEXT, A_NORMAL); 83*0a9064fbSMasahiro Yamada mkattr(SCROLLWIN_HEADING, A_BOLD); 84*0a9064fbSMasahiro Yamada mkattr(SCROLLWIN_BOX, A_BOLD); 85*0a9064fbSMasahiro Yamada 86*0a9064fbSMasahiro Yamada mkattr(DIALOG_TEXT, A_BOLD); 87*0a9064fbSMasahiro Yamada mkattr(DIALOG_BOX, A_BOLD); 88*0a9064fbSMasahiro Yamada mkattr(DIALOG_MENU_FORE, A_STANDOUT); 89*0a9064fbSMasahiro Yamada mkattr(DIALOG_MENU_BACK, A_NORMAL); 90*0a9064fbSMasahiro Yamada 91*0a9064fbSMasahiro Yamada mkattr(INPUT_BOX, A_NORMAL); 92*0a9064fbSMasahiro Yamada mkattr(INPUT_HEADING, A_BOLD); 93*0a9064fbSMasahiro Yamada mkattr(INPUT_TEXT, A_NORMAL); 94*0a9064fbSMasahiro Yamada mkattr(INPUT_FIELD, A_UNDERLINE); 95*0a9064fbSMasahiro Yamada 96*0a9064fbSMasahiro Yamada mkattr(FUNCTION_HIGHLIGHT, A_BOLD); 97*0a9064fbSMasahiro Yamada mkattr(FUNCTION_TEXT, A_REVERSE); 98*0a9064fbSMasahiro Yamada } 99*0a9064fbSMasahiro Yamada 100*0a9064fbSMasahiro Yamada static void no_colors_theme(void) 101*0a9064fbSMasahiro Yamada { 102*0a9064fbSMasahiro Yamada /* automatically add highlight, no color */ 103*0a9064fbSMasahiro Yamada #define mkattrn(name, attr) { attributes[name] = attr; } 104*0a9064fbSMasahiro Yamada 105*0a9064fbSMasahiro Yamada mkattrn(NORMAL, NORMAL); 106*0a9064fbSMasahiro Yamada mkattrn(MAIN_HEADING, A_BOLD | A_UNDERLINE); 107*0a9064fbSMasahiro Yamada 108*0a9064fbSMasahiro Yamada mkattrn(MAIN_MENU_FORE, A_STANDOUT); 109*0a9064fbSMasahiro Yamada mkattrn(MAIN_MENU_BACK, A_NORMAL); 110*0a9064fbSMasahiro Yamada mkattrn(MAIN_MENU_GREY, A_NORMAL); 111*0a9064fbSMasahiro Yamada mkattrn(MAIN_MENU_HEADING, A_BOLD); 112*0a9064fbSMasahiro Yamada mkattrn(MAIN_MENU_BOX, A_NORMAL); 113*0a9064fbSMasahiro Yamada 114*0a9064fbSMasahiro Yamada mkattrn(SCROLLWIN_TEXT, A_NORMAL); 115*0a9064fbSMasahiro Yamada mkattrn(SCROLLWIN_HEADING, A_BOLD); 116*0a9064fbSMasahiro Yamada mkattrn(SCROLLWIN_BOX, A_BOLD); 117*0a9064fbSMasahiro Yamada 118*0a9064fbSMasahiro Yamada mkattrn(DIALOG_TEXT, A_NORMAL); 119*0a9064fbSMasahiro Yamada mkattrn(DIALOG_BOX, A_BOLD); 120*0a9064fbSMasahiro Yamada mkattrn(DIALOG_MENU_FORE, A_STANDOUT); 121*0a9064fbSMasahiro Yamada mkattrn(DIALOG_MENU_BACK, A_NORMAL); 122*0a9064fbSMasahiro Yamada 123*0a9064fbSMasahiro Yamada mkattrn(INPUT_BOX, A_BOLD); 124*0a9064fbSMasahiro Yamada mkattrn(INPUT_HEADING, A_BOLD); 125*0a9064fbSMasahiro Yamada mkattrn(INPUT_TEXT, A_NORMAL); 126*0a9064fbSMasahiro Yamada mkattrn(INPUT_FIELD, A_UNDERLINE); 127*0a9064fbSMasahiro Yamada 128*0a9064fbSMasahiro Yamada mkattrn(FUNCTION_HIGHLIGHT, A_BOLD); 129*0a9064fbSMasahiro Yamada mkattrn(FUNCTION_TEXT, A_REVERSE); 130*0a9064fbSMasahiro Yamada } 131*0a9064fbSMasahiro Yamada 132*0a9064fbSMasahiro Yamada void set_colors() 133*0a9064fbSMasahiro Yamada { 134*0a9064fbSMasahiro Yamada start_color(); 135*0a9064fbSMasahiro Yamada use_default_colors(); 136*0a9064fbSMasahiro Yamada set_normal_colors(); 137*0a9064fbSMasahiro Yamada if (has_colors()) { 138*0a9064fbSMasahiro Yamada normal_color_theme(); 139*0a9064fbSMasahiro Yamada } else { 140*0a9064fbSMasahiro Yamada /* give defaults */ 141*0a9064fbSMasahiro Yamada no_colors_theme(); 142*0a9064fbSMasahiro Yamada } 143*0a9064fbSMasahiro Yamada } 144*0a9064fbSMasahiro Yamada 145*0a9064fbSMasahiro Yamada 146*0a9064fbSMasahiro Yamada /* this changes the windows attributes !!! */ 147*0a9064fbSMasahiro Yamada void print_in_middle(WINDOW *win, 148*0a9064fbSMasahiro Yamada int starty, 149*0a9064fbSMasahiro Yamada int startx, 150*0a9064fbSMasahiro Yamada int width, 151*0a9064fbSMasahiro Yamada const char *string, 152*0a9064fbSMasahiro Yamada chtype color) 153*0a9064fbSMasahiro Yamada { int length, x, y; 154*0a9064fbSMasahiro Yamada float temp; 155*0a9064fbSMasahiro Yamada 156*0a9064fbSMasahiro Yamada 157*0a9064fbSMasahiro Yamada if (win == NULL) 158*0a9064fbSMasahiro Yamada win = stdscr; 159*0a9064fbSMasahiro Yamada getyx(win, y, x); 160*0a9064fbSMasahiro Yamada if (startx != 0) 161*0a9064fbSMasahiro Yamada x = startx; 162*0a9064fbSMasahiro Yamada if (starty != 0) 163*0a9064fbSMasahiro Yamada y = starty; 164*0a9064fbSMasahiro Yamada if (width == 0) 165*0a9064fbSMasahiro Yamada width = 80; 166*0a9064fbSMasahiro Yamada 167*0a9064fbSMasahiro Yamada length = strlen(string); 168*0a9064fbSMasahiro Yamada temp = (width - length) / 2; 169*0a9064fbSMasahiro Yamada x = startx + (int)temp; 170*0a9064fbSMasahiro Yamada (void) wattrset(win, color); 171*0a9064fbSMasahiro Yamada mvwprintw(win, y, x, "%s", string); 172*0a9064fbSMasahiro Yamada refresh(); 173*0a9064fbSMasahiro Yamada } 174*0a9064fbSMasahiro Yamada 175*0a9064fbSMasahiro Yamada int get_line_no(const char *text) 176*0a9064fbSMasahiro Yamada { 177*0a9064fbSMasahiro Yamada int i; 178*0a9064fbSMasahiro Yamada int total = 1; 179*0a9064fbSMasahiro Yamada 180*0a9064fbSMasahiro Yamada if (!text) 181*0a9064fbSMasahiro Yamada return 0; 182*0a9064fbSMasahiro Yamada 183*0a9064fbSMasahiro Yamada for (i = 0; text[i] != '\0'; i++) 184*0a9064fbSMasahiro Yamada if (text[i] == '\n') 185*0a9064fbSMasahiro Yamada total++; 186*0a9064fbSMasahiro Yamada return total; 187*0a9064fbSMasahiro Yamada } 188*0a9064fbSMasahiro Yamada 189*0a9064fbSMasahiro Yamada const char *get_line(const char *text, int line_no) 190*0a9064fbSMasahiro Yamada { 191*0a9064fbSMasahiro Yamada int i; 192*0a9064fbSMasahiro Yamada int lines = 0; 193*0a9064fbSMasahiro Yamada 194*0a9064fbSMasahiro Yamada if (!text) 195*0a9064fbSMasahiro Yamada return 0; 196*0a9064fbSMasahiro Yamada 197*0a9064fbSMasahiro Yamada for (i = 0; text[i] != '\0' && lines < line_no; i++) 198*0a9064fbSMasahiro Yamada if (text[i] == '\n') 199*0a9064fbSMasahiro Yamada lines++; 200*0a9064fbSMasahiro Yamada return text+i; 201*0a9064fbSMasahiro Yamada } 202*0a9064fbSMasahiro Yamada 203*0a9064fbSMasahiro Yamada int get_line_length(const char *line) 204*0a9064fbSMasahiro Yamada { 205*0a9064fbSMasahiro Yamada int res = 0; 206*0a9064fbSMasahiro Yamada while (*line != '\0' && *line != '\n') { 207*0a9064fbSMasahiro Yamada line++; 208*0a9064fbSMasahiro Yamada res++; 209*0a9064fbSMasahiro Yamada } 210*0a9064fbSMasahiro Yamada return res; 211*0a9064fbSMasahiro Yamada } 212*0a9064fbSMasahiro Yamada 213*0a9064fbSMasahiro Yamada /* print all lines to the window. */ 214*0a9064fbSMasahiro Yamada void fill_window(WINDOW *win, const char *text) 215*0a9064fbSMasahiro Yamada { 216*0a9064fbSMasahiro Yamada int x, y; 217*0a9064fbSMasahiro Yamada int total_lines = get_line_no(text); 218*0a9064fbSMasahiro Yamada int i; 219*0a9064fbSMasahiro Yamada 220*0a9064fbSMasahiro Yamada getmaxyx(win, y, x); 221*0a9064fbSMasahiro Yamada /* do not go over end of line */ 222*0a9064fbSMasahiro Yamada total_lines = min(total_lines, y); 223*0a9064fbSMasahiro Yamada for (i = 0; i < total_lines; i++) { 224*0a9064fbSMasahiro Yamada char tmp[x+10]; 225*0a9064fbSMasahiro Yamada const char *line = get_line(text, i); 226*0a9064fbSMasahiro Yamada int len = get_line_length(line); 227*0a9064fbSMasahiro Yamada strncpy(tmp, line, min(len, x)); 228*0a9064fbSMasahiro Yamada tmp[len] = '\0'; 229*0a9064fbSMasahiro Yamada mvwprintw(win, i, 0, "%s", tmp); 230*0a9064fbSMasahiro Yamada } 231*0a9064fbSMasahiro Yamada } 232*0a9064fbSMasahiro Yamada 233*0a9064fbSMasahiro Yamada /* get the message, and buttons. 234*0a9064fbSMasahiro Yamada * each button must be a char* 235*0a9064fbSMasahiro Yamada * return the selected button 236*0a9064fbSMasahiro Yamada * 237*0a9064fbSMasahiro Yamada * this dialog is used for 2 different things: 238*0a9064fbSMasahiro Yamada * 1) show a text box, no buttons. 239*0a9064fbSMasahiro Yamada * 2) show a dialog, with horizontal buttons 240*0a9064fbSMasahiro Yamada */ 241*0a9064fbSMasahiro Yamada int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...) 242*0a9064fbSMasahiro Yamada { 243*0a9064fbSMasahiro Yamada va_list ap; 244*0a9064fbSMasahiro Yamada char *btn; 245*0a9064fbSMasahiro Yamada int btns_width = 0; 246*0a9064fbSMasahiro Yamada int msg_lines = 0; 247*0a9064fbSMasahiro Yamada int msg_width = 0; 248*0a9064fbSMasahiro Yamada int total_width; 249*0a9064fbSMasahiro Yamada int win_rows = 0; 250*0a9064fbSMasahiro Yamada WINDOW *win; 251*0a9064fbSMasahiro Yamada WINDOW *msg_win; 252*0a9064fbSMasahiro Yamada WINDOW *menu_win; 253*0a9064fbSMasahiro Yamada MENU *menu; 254*0a9064fbSMasahiro Yamada ITEM *btns[btn_num+1]; 255*0a9064fbSMasahiro Yamada int i, x, y; 256*0a9064fbSMasahiro Yamada int res = -1; 257*0a9064fbSMasahiro Yamada 258*0a9064fbSMasahiro Yamada 259*0a9064fbSMasahiro Yamada va_start(ap, btn_num); 260*0a9064fbSMasahiro Yamada for (i = 0; i < btn_num; i++) { 261*0a9064fbSMasahiro Yamada btn = va_arg(ap, char *); 262*0a9064fbSMasahiro Yamada btns[i] = new_item(btn, ""); 263*0a9064fbSMasahiro Yamada btns_width += strlen(btn)+1; 264*0a9064fbSMasahiro Yamada } 265*0a9064fbSMasahiro Yamada va_end(ap); 266*0a9064fbSMasahiro Yamada btns[btn_num] = NULL; 267*0a9064fbSMasahiro Yamada 268*0a9064fbSMasahiro Yamada /* find the widest line of msg: */ 269*0a9064fbSMasahiro Yamada msg_lines = get_line_no(msg); 270*0a9064fbSMasahiro Yamada for (i = 0; i < msg_lines; i++) { 271*0a9064fbSMasahiro Yamada const char *line = get_line(msg, i); 272*0a9064fbSMasahiro Yamada int len = get_line_length(line); 273*0a9064fbSMasahiro Yamada if (msg_width < len) 274*0a9064fbSMasahiro Yamada msg_width = len; 275*0a9064fbSMasahiro Yamada } 276*0a9064fbSMasahiro Yamada 277*0a9064fbSMasahiro Yamada total_width = max(msg_width, btns_width); 278*0a9064fbSMasahiro Yamada /* place dialog in middle of screen */ 279*0a9064fbSMasahiro Yamada y = (getmaxy(stdscr)-(msg_lines+4))/2; 280*0a9064fbSMasahiro Yamada x = (getmaxx(stdscr)-(total_width+4))/2; 281*0a9064fbSMasahiro Yamada 282*0a9064fbSMasahiro Yamada 283*0a9064fbSMasahiro Yamada /* create the windows */ 284*0a9064fbSMasahiro Yamada if (btn_num > 0) 285*0a9064fbSMasahiro Yamada win_rows = msg_lines+4; 286*0a9064fbSMasahiro Yamada else 287*0a9064fbSMasahiro Yamada win_rows = msg_lines+2; 288*0a9064fbSMasahiro Yamada 289*0a9064fbSMasahiro Yamada win = newwin(win_rows, total_width+4, y, x); 290*0a9064fbSMasahiro Yamada keypad(win, TRUE); 291*0a9064fbSMasahiro Yamada menu_win = derwin(win, 1, btns_width, win_rows-2, 292*0a9064fbSMasahiro Yamada 1+(total_width+2-btns_width)/2); 293*0a9064fbSMasahiro Yamada menu = new_menu(btns); 294*0a9064fbSMasahiro Yamada msg_win = derwin(win, win_rows-2, msg_width, 1, 295*0a9064fbSMasahiro Yamada 1+(total_width+2-msg_width)/2); 296*0a9064fbSMasahiro Yamada 297*0a9064fbSMasahiro Yamada set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); 298*0a9064fbSMasahiro Yamada set_menu_back(menu, attributes[DIALOG_MENU_BACK]); 299*0a9064fbSMasahiro Yamada 300*0a9064fbSMasahiro Yamada (void) wattrset(win, attributes[DIALOG_BOX]); 301*0a9064fbSMasahiro Yamada box(win, 0, 0); 302*0a9064fbSMasahiro Yamada 303*0a9064fbSMasahiro Yamada /* print message */ 304*0a9064fbSMasahiro Yamada (void) wattrset(msg_win, attributes[DIALOG_TEXT]); 305*0a9064fbSMasahiro Yamada fill_window(msg_win, msg); 306*0a9064fbSMasahiro Yamada 307*0a9064fbSMasahiro Yamada set_menu_win(menu, win); 308*0a9064fbSMasahiro Yamada set_menu_sub(menu, menu_win); 309*0a9064fbSMasahiro Yamada set_menu_format(menu, 1, btn_num); 310*0a9064fbSMasahiro Yamada menu_opts_off(menu, O_SHOWDESC); 311*0a9064fbSMasahiro Yamada menu_opts_off(menu, O_SHOWMATCH); 312*0a9064fbSMasahiro Yamada menu_opts_on(menu, O_ONEVALUE); 313*0a9064fbSMasahiro Yamada menu_opts_on(menu, O_NONCYCLIC); 314*0a9064fbSMasahiro Yamada set_menu_mark(menu, ""); 315*0a9064fbSMasahiro Yamada post_menu(menu); 316*0a9064fbSMasahiro Yamada 317*0a9064fbSMasahiro Yamada 318*0a9064fbSMasahiro Yamada touchwin(win); 319*0a9064fbSMasahiro Yamada refresh_all_windows(main_window); 320*0a9064fbSMasahiro Yamada while ((res = wgetch(win))) { 321*0a9064fbSMasahiro Yamada switch (res) { 322*0a9064fbSMasahiro Yamada case KEY_LEFT: 323*0a9064fbSMasahiro Yamada menu_driver(menu, REQ_LEFT_ITEM); 324*0a9064fbSMasahiro Yamada break; 325*0a9064fbSMasahiro Yamada case KEY_RIGHT: 326*0a9064fbSMasahiro Yamada menu_driver(menu, REQ_RIGHT_ITEM); 327*0a9064fbSMasahiro Yamada break; 328*0a9064fbSMasahiro Yamada case 10: /* ENTER */ 329*0a9064fbSMasahiro Yamada case 27: /* ESCAPE */ 330*0a9064fbSMasahiro Yamada case ' ': 331*0a9064fbSMasahiro Yamada case KEY_F(F_BACK): 332*0a9064fbSMasahiro Yamada case KEY_F(F_EXIT): 333*0a9064fbSMasahiro Yamada break; 334*0a9064fbSMasahiro Yamada } 335*0a9064fbSMasahiro Yamada touchwin(win); 336*0a9064fbSMasahiro Yamada refresh_all_windows(main_window); 337*0a9064fbSMasahiro Yamada 338*0a9064fbSMasahiro Yamada if (res == 10 || res == ' ') { 339*0a9064fbSMasahiro Yamada res = item_index(current_item(menu)); 340*0a9064fbSMasahiro Yamada break; 341*0a9064fbSMasahiro Yamada } else if (res == 27 || res == KEY_F(F_BACK) || 342*0a9064fbSMasahiro Yamada res == KEY_F(F_EXIT)) { 343*0a9064fbSMasahiro Yamada res = KEY_EXIT; 344*0a9064fbSMasahiro Yamada break; 345*0a9064fbSMasahiro Yamada } 346*0a9064fbSMasahiro Yamada } 347*0a9064fbSMasahiro Yamada 348*0a9064fbSMasahiro Yamada unpost_menu(menu); 349*0a9064fbSMasahiro Yamada free_menu(menu); 350*0a9064fbSMasahiro Yamada for (i = 0; i < btn_num; i++) 351*0a9064fbSMasahiro Yamada free_item(btns[i]); 352*0a9064fbSMasahiro Yamada 353*0a9064fbSMasahiro Yamada delwin(win); 354*0a9064fbSMasahiro Yamada return res; 355*0a9064fbSMasahiro Yamada } 356*0a9064fbSMasahiro Yamada 357*0a9064fbSMasahiro Yamada int dialog_inputbox(WINDOW *main_window, 358*0a9064fbSMasahiro Yamada const char *title, const char *prompt, 359*0a9064fbSMasahiro Yamada const char *init, char **resultp, int *result_len) 360*0a9064fbSMasahiro Yamada { 361*0a9064fbSMasahiro Yamada int prompt_lines = 0; 362*0a9064fbSMasahiro Yamada int prompt_width = 0; 363*0a9064fbSMasahiro Yamada WINDOW *win; 364*0a9064fbSMasahiro Yamada WINDOW *prompt_win; 365*0a9064fbSMasahiro Yamada WINDOW *form_win; 366*0a9064fbSMasahiro Yamada PANEL *panel; 367*0a9064fbSMasahiro Yamada int i, x, y; 368*0a9064fbSMasahiro Yamada int res = -1; 369*0a9064fbSMasahiro Yamada int cursor_position = strlen(init); 370*0a9064fbSMasahiro Yamada int cursor_form_win; 371*0a9064fbSMasahiro Yamada char *result = *resultp; 372*0a9064fbSMasahiro Yamada 373*0a9064fbSMasahiro Yamada if (strlen(init)+1 > *result_len) { 374*0a9064fbSMasahiro Yamada *result_len = strlen(init)+1; 375*0a9064fbSMasahiro Yamada *resultp = result = realloc(result, *result_len); 376*0a9064fbSMasahiro Yamada } 377*0a9064fbSMasahiro Yamada 378*0a9064fbSMasahiro Yamada /* find the widest line of msg: */ 379*0a9064fbSMasahiro Yamada prompt_lines = get_line_no(prompt); 380*0a9064fbSMasahiro Yamada for (i = 0; i < prompt_lines; i++) { 381*0a9064fbSMasahiro Yamada const char *line = get_line(prompt, i); 382*0a9064fbSMasahiro Yamada int len = get_line_length(line); 383*0a9064fbSMasahiro Yamada prompt_width = max(prompt_width, len); 384*0a9064fbSMasahiro Yamada } 385*0a9064fbSMasahiro Yamada 386*0a9064fbSMasahiro Yamada if (title) 387*0a9064fbSMasahiro Yamada prompt_width = max(prompt_width, strlen(title)); 388*0a9064fbSMasahiro Yamada 389*0a9064fbSMasahiro Yamada /* place dialog in middle of screen */ 390*0a9064fbSMasahiro Yamada y = (getmaxy(stdscr)-(prompt_lines+4))/2; 391*0a9064fbSMasahiro Yamada x = (getmaxx(stdscr)-(prompt_width+4))/2; 392*0a9064fbSMasahiro Yamada 393*0a9064fbSMasahiro Yamada strncpy(result, init, *result_len); 394*0a9064fbSMasahiro Yamada 395*0a9064fbSMasahiro Yamada /* create the windows */ 396*0a9064fbSMasahiro Yamada win = newwin(prompt_lines+6, prompt_width+7, y, x); 397*0a9064fbSMasahiro Yamada prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); 398*0a9064fbSMasahiro Yamada form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); 399*0a9064fbSMasahiro Yamada keypad(form_win, TRUE); 400*0a9064fbSMasahiro Yamada 401*0a9064fbSMasahiro Yamada (void) wattrset(form_win, attributes[INPUT_FIELD]); 402*0a9064fbSMasahiro Yamada 403*0a9064fbSMasahiro Yamada (void) wattrset(win, attributes[INPUT_BOX]); 404*0a9064fbSMasahiro Yamada box(win, 0, 0); 405*0a9064fbSMasahiro Yamada (void) wattrset(win, attributes[INPUT_HEADING]); 406*0a9064fbSMasahiro Yamada if (title) 407*0a9064fbSMasahiro Yamada mvwprintw(win, 0, 3, "%s", title); 408*0a9064fbSMasahiro Yamada 409*0a9064fbSMasahiro Yamada /* print message */ 410*0a9064fbSMasahiro Yamada (void) wattrset(prompt_win, attributes[INPUT_TEXT]); 411*0a9064fbSMasahiro Yamada fill_window(prompt_win, prompt); 412*0a9064fbSMasahiro Yamada 413*0a9064fbSMasahiro Yamada mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); 414*0a9064fbSMasahiro Yamada cursor_form_win = min(cursor_position, prompt_width-1); 415*0a9064fbSMasahiro Yamada mvwprintw(form_win, 0, 0, "%s", 416*0a9064fbSMasahiro Yamada result + cursor_position-cursor_form_win); 417*0a9064fbSMasahiro Yamada 418*0a9064fbSMasahiro Yamada /* create panels */ 419*0a9064fbSMasahiro Yamada panel = new_panel(win); 420*0a9064fbSMasahiro Yamada 421*0a9064fbSMasahiro Yamada /* show the cursor */ 422*0a9064fbSMasahiro Yamada curs_set(1); 423*0a9064fbSMasahiro Yamada 424*0a9064fbSMasahiro Yamada touchwin(win); 425*0a9064fbSMasahiro Yamada refresh_all_windows(main_window); 426*0a9064fbSMasahiro Yamada while ((res = wgetch(form_win))) { 427*0a9064fbSMasahiro Yamada int len = strlen(result); 428*0a9064fbSMasahiro Yamada switch (res) { 429*0a9064fbSMasahiro Yamada case 10: /* ENTER */ 430*0a9064fbSMasahiro Yamada case 27: /* ESCAPE */ 431*0a9064fbSMasahiro Yamada case KEY_F(F_HELP): 432*0a9064fbSMasahiro Yamada case KEY_F(F_EXIT): 433*0a9064fbSMasahiro Yamada case KEY_F(F_BACK): 434*0a9064fbSMasahiro Yamada break; 435*0a9064fbSMasahiro Yamada case 127: 436*0a9064fbSMasahiro Yamada case KEY_BACKSPACE: 437*0a9064fbSMasahiro Yamada if (cursor_position > 0) { 438*0a9064fbSMasahiro Yamada memmove(&result[cursor_position-1], 439*0a9064fbSMasahiro Yamada &result[cursor_position], 440*0a9064fbSMasahiro Yamada len-cursor_position+1); 441*0a9064fbSMasahiro Yamada cursor_position--; 442*0a9064fbSMasahiro Yamada cursor_form_win--; 443*0a9064fbSMasahiro Yamada len--; 444*0a9064fbSMasahiro Yamada } 445*0a9064fbSMasahiro Yamada break; 446*0a9064fbSMasahiro Yamada case KEY_DC: 447*0a9064fbSMasahiro Yamada if (cursor_position >= 0 && cursor_position < len) { 448*0a9064fbSMasahiro Yamada memmove(&result[cursor_position], 449*0a9064fbSMasahiro Yamada &result[cursor_position+1], 450*0a9064fbSMasahiro Yamada len-cursor_position+1); 451*0a9064fbSMasahiro Yamada len--; 452*0a9064fbSMasahiro Yamada } 453*0a9064fbSMasahiro Yamada break; 454*0a9064fbSMasahiro Yamada case KEY_UP: 455*0a9064fbSMasahiro Yamada case KEY_RIGHT: 456*0a9064fbSMasahiro Yamada if (cursor_position < len) { 457*0a9064fbSMasahiro Yamada cursor_position++; 458*0a9064fbSMasahiro Yamada cursor_form_win++; 459*0a9064fbSMasahiro Yamada } 460*0a9064fbSMasahiro Yamada break; 461*0a9064fbSMasahiro Yamada case KEY_DOWN: 462*0a9064fbSMasahiro Yamada case KEY_LEFT: 463*0a9064fbSMasahiro Yamada if (cursor_position > 0) { 464*0a9064fbSMasahiro Yamada cursor_position--; 465*0a9064fbSMasahiro Yamada cursor_form_win--; 466*0a9064fbSMasahiro Yamada } 467*0a9064fbSMasahiro Yamada break; 468*0a9064fbSMasahiro Yamada case KEY_HOME: 469*0a9064fbSMasahiro Yamada cursor_position = 0; 470*0a9064fbSMasahiro Yamada cursor_form_win = 0; 471*0a9064fbSMasahiro Yamada break; 472*0a9064fbSMasahiro Yamada case KEY_END: 473*0a9064fbSMasahiro Yamada cursor_position = len; 474*0a9064fbSMasahiro Yamada cursor_form_win = min(cursor_position, prompt_width-1); 475*0a9064fbSMasahiro Yamada break; 476*0a9064fbSMasahiro Yamada default: 477*0a9064fbSMasahiro Yamada if ((isgraph(res) || isspace(res))) { 478*0a9064fbSMasahiro Yamada /* one for new char, one for '\0' */ 479*0a9064fbSMasahiro Yamada if (len+2 > *result_len) { 480*0a9064fbSMasahiro Yamada *result_len = len+2; 481*0a9064fbSMasahiro Yamada *resultp = result = realloc(result, 482*0a9064fbSMasahiro Yamada *result_len); 483*0a9064fbSMasahiro Yamada } 484*0a9064fbSMasahiro Yamada /* insert the char at the proper position */ 485*0a9064fbSMasahiro Yamada memmove(&result[cursor_position+1], 486*0a9064fbSMasahiro Yamada &result[cursor_position], 487*0a9064fbSMasahiro Yamada len-cursor_position+1); 488*0a9064fbSMasahiro Yamada result[cursor_position] = res; 489*0a9064fbSMasahiro Yamada cursor_position++; 490*0a9064fbSMasahiro Yamada cursor_form_win++; 491*0a9064fbSMasahiro Yamada len++; 492*0a9064fbSMasahiro Yamada } else { 493*0a9064fbSMasahiro Yamada mvprintw(0, 0, "unknown key: %d\n", res); 494*0a9064fbSMasahiro Yamada } 495*0a9064fbSMasahiro Yamada break; 496*0a9064fbSMasahiro Yamada } 497*0a9064fbSMasahiro Yamada if (cursor_form_win < 0) 498*0a9064fbSMasahiro Yamada cursor_form_win = 0; 499*0a9064fbSMasahiro Yamada else if (cursor_form_win > prompt_width-1) 500*0a9064fbSMasahiro Yamada cursor_form_win = prompt_width-1; 501*0a9064fbSMasahiro Yamada 502*0a9064fbSMasahiro Yamada wmove(form_win, 0, 0); 503*0a9064fbSMasahiro Yamada wclrtoeol(form_win); 504*0a9064fbSMasahiro Yamada mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); 505*0a9064fbSMasahiro Yamada mvwprintw(form_win, 0, 0, "%s", 506*0a9064fbSMasahiro Yamada result + cursor_position-cursor_form_win); 507*0a9064fbSMasahiro Yamada wmove(form_win, 0, cursor_form_win); 508*0a9064fbSMasahiro Yamada touchwin(win); 509*0a9064fbSMasahiro Yamada refresh_all_windows(main_window); 510*0a9064fbSMasahiro Yamada 511*0a9064fbSMasahiro Yamada if (res == 10) { 512*0a9064fbSMasahiro Yamada res = 0; 513*0a9064fbSMasahiro Yamada break; 514*0a9064fbSMasahiro Yamada } else if (res == 27 || res == KEY_F(F_BACK) || 515*0a9064fbSMasahiro Yamada res == KEY_F(F_EXIT)) { 516*0a9064fbSMasahiro Yamada res = KEY_EXIT; 517*0a9064fbSMasahiro Yamada break; 518*0a9064fbSMasahiro Yamada } else if (res == KEY_F(F_HELP)) { 519*0a9064fbSMasahiro Yamada res = 1; 520*0a9064fbSMasahiro Yamada break; 521*0a9064fbSMasahiro Yamada } 522*0a9064fbSMasahiro Yamada } 523*0a9064fbSMasahiro Yamada 524*0a9064fbSMasahiro Yamada /* hide the cursor */ 525*0a9064fbSMasahiro Yamada curs_set(0); 526*0a9064fbSMasahiro Yamada del_panel(panel); 527*0a9064fbSMasahiro Yamada delwin(prompt_win); 528*0a9064fbSMasahiro Yamada delwin(form_win); 529*0a9064fbSMasahiro Yamada delwin(win); 530*0a9064fbSMasahiro Yamada return res; 531*0a9064fbSMasahiro Yamada } 532*0a9064fbSMasahiro Yamada 533*0a9064fbSMasahiro Yamada /* refresh all windows in the correct order */ 534*0a9064fbSMasahiro Yamada void refresh_all_windows(WINDOW *main_window) 535*0a9064fbSMasahiro Yamada { 536*0a9064fbSMasahiro Yamada update_panels(); 537*0a9064fbSMasahiro Yamada touchwin(main_window); 538*0a9064fbSMasahiro Yamada refresh(); 539*0a9064fbSMasahiro Yamada } 540*0a9064fbSMasahiro Yamada 541*0a9064fbSMasahiro Yamada /* layman's scrollable window... */ 542*0a9064fbSMasahiro Yamada void show_scroll_win(WINDOW *main_window, 543*0a9064fbSMasahiro Yamada const char *title, 544*0a9064fbSMasahiro Yamada const char *text) 545*0a9064fbSMasahiro Yamada { 546*0a9064fbSMasahiro Yamada int res; 547*0a9064fbSMasahiro Yamada int total_lines = get_line_no(text); 548*0a9064fbSMasahiro Yamada int x, y, lines, columns; 549*0a9064fbSMasahiro Yamada int start_x = 0, start_y = 0; 550*0a9064fbSMasahiro Yamada int text_lines = 0, text_cols = 0; 551*0a9064fbSMasahiro Yamada int total_cols = 0; 552*0a9064fbSMasahiro Yamada int win_cols = 0; 553*0a9064fbSMasahiro Yamada int win_lines = 0; 554*0a9064fbSMasahiro Yamada int i = 0; 555*0a9064fbSMasahiro Yamada WINDOW *win; 556*0a9064fbSMasahiro Yamada WINDOW *pad; 557*0a9064fbSMasahiro Yamada PANEL *panel; 558*0a9064fbSMasahiro Yamada 559*0a9064fbSMasahiro Yamada getmaxyx(stdscr, lines, columns); 560*0a9064fbSMasahiro Yamada 561*0a9064fbSMasahiro Yamada /* find the widest line of msg: */ 562*0a9064fbSMasahiro Yamada total_lines = get_line_no(text); 563*0a9064fbSMasahiro Yamada for (i = 0; i < total_lines; i++) { 564*0a9064fbSMasahiro Yamada const char *line = get_line(text, i); 565*0a9064fbSMasahiro Yamada int len = get_line_length(line); 566*0a9064fbSMasahiro Yamada total_cols = max(total_cols, len+2); 567*0a9064fbSMasahiro Yamada } 568*0a9064fbSMasahiro Yamada 569*0a9064fbSMasahiro Yamada /* create the pad */ 570*0a9064fbSMasahiro Yamada pad = newpad(total_lines+10, total_cols+10); 571*0a9064fbSMasahiro Yamada (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); 572*0a9064fbSMasahiro Yamada fill_window(pad, text); 573*0a9064fbSMasahiro Yamada 574*0a9064fbSMasahiro Yamada win_lines = min(total_lines+4, lines-2); 575*0a9064fbSMasahiro Yamada win_cols = min(total_cols+2, columns-2); 576*0a9064fbSMasahiro Yamada text_lines = max(win_lines-4, 0); 577*0a9064fbSMasahiro Yamada text_cols = max(win_cols-2, 0); 578*0a9064fbSMasahiro Yamada 579*0a9064fbSMasahiro Yamada /* place window in middle of screen */ 580*0a9064fbSMasahiro Yamada y = (lines-win_lines)/2; 581*0a9064fbSMasahiro Yamada x = (columns-win_cols)/2; 582*0a9064fbSMasahiro Yamada 583*0a9064fbSMasahiro Yamada win = newwin(win_lines, win_cols, y, x); 584*0a9064fbSMasahiro Yamada keypad(win, TRUE); 585*0a9064fbSMasahiro Yamada /* show the help in the help window, and show the help panel */ 586*0a9064fbSMasahiro Yamada (void) wattrset(win, attributes[SCROLLWIN_BOX]); 587*0a9064fbSMasahiro Yamada box(win, 0, 0); 588*0a9064fbSMasahiro Yamada (void) wattrset(win, attributes[SCROLLWIN_HEADING]); 589*0a9064fbSMasahiro Yamada mvwprintw(win, 0, 3, " %s ", title); 590*0a9064fbSMasahiro Yamada panel = new_panel(win); 591*0a9064fbSMasahiro Yamada 592*0a9064fbSMasahiro Yamada /* handle scrolling */ 593*0a9064fbSMasahiro Yamada do { 594*0a9064fbSMasahiro Yamada 595*0a9064fbSMasahiro Yamada copywin(pad, win, start_y, start_x, 2, 2, text_lines, 596*0a9064fbSMasahiro Yamada text_cols, 0); 597*0a9064fbSMasahiro Yamada print_in_middle(win, 598*0a9064fbSMasahiro Yamada text_lines+2, 599*0a9064fbSMasahiro Yamada 0, 600*0a9064fbSMasahiro Yamada text_cols, 601*0a9064fbSMasahiro Yamada "<OK>", 602*0a9064fbSMasahiro Yamada attributes[DIALOG_MENU_FORE]); 603*0a9064fbSMasahiro Yamada wrefresh(win); 604*0a9064fbSMasahiro Yamada 605*0a9064fbSMasahiro Yamada res = wgetch(win); 606*0a9064fbSMasahiro Yamada switch (res) { 607*0a9064fbSMasahiro Yamada case KEY_NPAGE: 608*0a9064fbSMasahiro Yamada case ' ': 609*0a9064fbSMasahiro Yamada case 'd': 610*0a9064fbSMasahiro Yamada start_y += text_lines-2; 611*0a9064fbSMasahiro Yamada break; 612*0a9064fbSMasahiro Yamada case KEY_PPAGE: 613*0a9064fbSMasahiro Yamada case 'u': 614*0a9064fbSMasahiro Yamada start_y -= text_lines+2; 615*0a9064fbSMasahiro Yamada break; 616*0a9064fbSMasahiro Yamada case KEY_HOME: 617*0a9064fbSMasahiro Yamada start_y = 0; 618*0a9064fbSMasahiro Yamada break; 619*0a9064fbSMasahiro Yamada case KEY_END: 620*0a9064fbSMasahiro Yamada start_y = total_lines-text_lines; 621*0a9064fbSMasahiro Yamada break; 622*0a9064fbSMasahiro Yamada case KEY_DOWN: 623*0a9064fbSMasahiro Yamada case 'j': 624*0a9064fbSMasahiro Yamada start_y++; 625*0a9064fbSMasahiro Yamada break; 626*0a9064fbSMasahiro Yamada case KEY_UP: 627*0a9064fbSMasahiro Yamada case 'k': 628*0a9064fbSMasahiro Yamada start_y--; 629*0a9064fbSMasahiro Yamada break; 630*0a9064fbSMasahiro Yamada case KEY_LEFT: 631*0a9064fbSMasahiro Yamada case 'h': 632*0a9064fbSMasahiro Yamada start_x--; 633*0a9064fbSMasahiro Yamada break; 634*0a9064fbSMasahiro Yamada case KEY_RIGHT: 635*0a9064fbSMasahiro Yamada case 'l': 636*0a9064fbSMasahiro Yamada start_x++; 637*0a9064fbSMasahiro Yamada break; 638*0a9064fbSMasahiro Yamada } 639*0a9064fbSMasahiro Yamada if (res == 10 || res == 27 || res == 'q' || 640*0a9064fbSMasahiro Yamada res == KEY_F(F_HELP) || res == KEY_F(F_BACK) || 641*0a9064fbSMasahiro Yamada res == KEY_F(F_EXIT)) 642*0a9064fbSMasahiro Yamada break; 643*0a9064fbSMasahiro Yamada if (start_y < 0) 644*0a9064fbSMasahiro Yamada start_y = 0; 645*0a9064fbSMasahiro Yamada if (start_y >= total_lines-text_lines) 646*0a9064fbSMasahiro Yamada start_y = total_lines-text_lines; 647*0a9064fbSMasahiro Yamada if (start_x < 0) 648*0a9064fbSMasahiro Yamada start_x = 0; 649*0a9064fbSMasahiro Yamada if (start_x >= total_cols-text_cols) 650*0a9064fbSMasahiro Yamada start_x = total_cols-text_cols; 651*0a9064fbSMasahiro Yamada } while (res); 652*0a9064fbSMasahiro Yamada 653*0a9064fbSMasahiro Yamada del_panel(panel); 654*0a9064fbSMasahiro Yamada delwin(win); 655*0a9064fbSMasahiro Yamada refresh_all_windows(main_window); 656*0a9064fbSMasahiro Yamada } 657