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