162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * util.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 662306a36Sopenharmony_ci * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <stdarg.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "dialog.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* Needed in signal handler in mconf.c */ 1462306a36Sopenharmony_ciint saved_x, saved_y; 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct dialog_info dlg; 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic void set_mono_theme(void) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci dlg.screen.atr = A_NORMAL; 2162306a36Sopenharmony_ci dlg.shadow.atr = A_NORMAL; 2262306a36Sopenharmony_ci dlg.dialog.atr = A_NORMAL; 2362306a36Sopenharmony_ci dlg.title.atr = A_BOLD; 2462306a36Sopenharmony_ci dlg.border.atr = A_NORMAL; 2562306a36Sopenharmony_ci dlg.button_active.atr = A_REVERSE; 2662306a36Sopenharmony_ci dlg.button_inactive.atr = A_DIM; 2762306a36Sopenharmony_ci dlg.button_key_active.atr = A_REVERSE; 2862306a36Sopenharmony_ci dlg.button_key_inactive.atr = A_BOLD; 2962306a36Sopenharmony_ci dlg.button_label_active.atr = A_REVERSE; 3062306a36Sopenharmony_ci dlg.button_label_inactive.atr = A_NORMAL; 3162306a36Sopenharmony_ci dlg.inputbox.atr = A_NORMAL; 3262306a36Sopenharmony_ci dlg.inputbox_border.atr = A_NORMAL; 3362306a36Sopenharmony_ci dlg.searchbox.atr = A_NORMAL; 3462306a36Sopenharmony_ci dlg.searchbox_title.atr = A_BOLD; 3562306a36Sopenharmony_ci dlg.searchbox_border.atr = A_NORMAL; 3662306a36Sopenharmony_ci dlg.position_indicator.atr = A_BOLD; 3762306a36Sopenharmony_ci dlg.menubox.atr = A_NORMAL; 3862306a36Sopenharmony_ci dlg.menubox_border.atr = A_NORMAL; 3962306a36Sopenharmony_ci dlg.item.atr = A_NORMAL; 4062306a36Sopenharmony_ci dlg.item_selected.atr = A_REVERSE; 4162306a36Sopenharmony_ci dlg.tag.atr = A_BOLD; 4262306a36Sopenharmony_ci dlg.tag_selected.atr = A_REVERSE; 4362306a36Sopenharmony_ci dlg.tag_key.atr = A_BOLD; 4462306a36Sopenharmony_ci dlg.tag_key_selected.atr = A_REVERSE; 4562306a36Sopenharmony_ci dlg.check.atr = A_BOLD; 4662306a36Sopenharmony_ci dlg.check_selected.atr = A_REVERSE; 4762306a36Sopenharmony_ci dlg.uarrow.atr = A_BOLD; 4862306a36Sopenharmony_ci dlg.darrow.atr = A_BOLD; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define DLG_COLOR(dialog, f, b, h) \ 5262306a36Sopenharmony_cido { \ 5362306a36Sopenharmony_ci dlg.dialog.fg = (f); \ 5462306a36Sopenharmony_ci dlg.dialog.bg = (b); \ 5562306a36Sopenharmony_ci dlg.dialog.hl = (h); \ 5662306a36Sopenharmony_ci} while (0) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void set_classic_theme(void) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); 6162306a36Sopenharmony_ci DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); 6262306a36Sopenharmony_ci DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); 6362306a36Sopenharmony_ci DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); 6462306a36Sopenharmony_ci DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); 6562306a36Sopenharmony_ci DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); 6662306a36Sopenharmony_ci DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); 6762306a36Sopenharmony_ci DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); 6862306a36Sopenharmony_ci DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); 6962306a36Sopenharmony_ci DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); 7062306a36Sopenharmony_ci DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); 7162306a36Sopenharmony_ci DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); 7262306a36Sopenharmony_ci DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); 7362306a36Sopenharmony_ci DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); 7462306a36Sopenharmony_ci DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); 7562306a36Sopenharmony_ci DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); 7662306a36Sopenharmony_ci DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); 7762306a36Sopenharmony_ci DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); 7862306a36Sopenharmony_ci DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); 7962306a36Sopenharmony_ci DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); 8062306a36Sopenharmony_ci DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); 8162306a36Sopenharmony_ci DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); 8262306a36Sopenharmony_ci DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); 8362306a36Sopenharmony_ci DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); 8462306a36Sopenharmony_ci DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); 8562306a36Sopenharmony_ci DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); 8662306a36Sopenharmony_ci DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); 8762306a36Sopenharmony_ci DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); 8862306a36Sopenharmony_ci DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic void set_blackbg_theme(void) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); 9462306a36Sopenharmony_ci DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); 9562306a36Sopenharmony_ci DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); 9662306a36Sopenharmony_ci DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); 9762306a36Sopenharmony_ci DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); 10062306a36Sopenharmony_ci DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); 10162306a36Sopenharmony_ci DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); 10262306a36Sopenharmony_ci DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); 10362306a36Sopenharmony_ci DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); 10462306a36Sopenharmony_ci DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); 10762306a36Sopenharmony_ci DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); 11062306a36Sopenharmony_ci DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); 11162306a36Sopenharmony_ci DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); 11662306a36Sopenharmony_ci DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); 11962306a36Sopenharmony_ci DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); 12262306a36Sopenharmony_ci DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); 12362306a36Sopenharmony_ci DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); 12462306a36Sopenharmony_ci DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); 12762306a36Sopenharmony_ci DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); 13062306a36Sopenharmony_ci DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void set_bluetitle_theme(void) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci set_classic_theme(); 13662306a36Sopenharmony_ci DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); 13762306a36Sopenharmony_ci DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); 13862306a36Sopenharmony_ci DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); 13962306a36Sopenharmony_ci DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); 14062306a36Sopenharmony_ci DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); 14162306a36Sopenharmony_ci DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); 14262306a36Sopenharmony_ci DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* 14762306a36Sopenharmony_ci * Select color theme 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_cistatic int set_theme(const char *theme) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci int use_color = 1; 15262306a36Sopenharmony_ci if (!theme) 15362306a36Sopenharmony_ci set_bluetitle_theme(); 15462306a36Sopenharmony_ci else if (strcmp(theme, "classic") == 0) 15562306a36Sopenharmony_ci set_classic_theme(); 15662306a36Sopenharmony_ci else if (strcmp(theme, "bluetitle") == 0) 15762306a36Sopenharmony_ci set_bluetitle_theme(); 15862306a36Sopenharmony_ci else if (strcmp(theme, "blackbg") == 0) 15962306a36Sopenharmony_ci set_blackbg_theme(); 16062306a36Sopenharmony_ci else if (strcmp(theme, "mono") == 0) 16162306a36Sopenharmony_ci use_color = 0; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return use_color; 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic void init_one_color(struct dialog_color *color) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci static int pair = 0; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci pair++; 17162306a36Sopenharmony_ci init_pair(pair, color->fg, color->bg); 17262306a36Sopenharmony_ci if (color->hl) 17362306a36Sopenharmony_ci color->atr = A_BOLD | COLOR_PAIR(pair); 17462306a36Sopenharmony_ci else 17562306a36Sopenharmony_ci color->atr = COLOR_PAIR(pair); 17662306a36Sopenharmony_ci} 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cistatic void init_dialog_colors(void) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci init_one_color(&dlg.screen); 18162306a36Sopenharmony_ci init_one_color(&dlg.shadow); 18262306a36Sopenharmony_ci init_one_color(&dlg.dialog); 18362306a36Sopenharmony_ci init_one_color(&dlg.title); 18462306a36Sopenharmony_ci init_one_color(&dlg.border); 18562306a36Sopenharmony_ci init_one_color(&dlg.button_active); 18662306a36Sopenharmony_ci init_one_color(&dlg.button_inactive); 18762306a36Sopenharmony_ci init_one_color(&dlg.button_key_active); 18862306a36Sopenharmony_ci init_one_color(&dlg.button_key_inactive); 18962306a36Sopenharmony_ci init_one_color(&dlg.button_label_active); 19062306a36Sopenharmony_ci init_one_color(&dlg.button_label_inactive); 19162306a36Sopenharmony_ci init_one_color(&dlg.inputbox); 19262306a36Sopenharmony_ci init_one_color(&dlg.inputbox_border); 19362306a36Sopenharmony_ci init_one_color(&dlg.searchbox); 19462306a36Sopenharmony_ci init_one_color(&dlg.searchbox_title); 19562306a36Sopenharmony_ci init_one_color(&dlg.searchbox_border); 19662306a36Sopenharmony_ci init_one_color(&dlg.position_indicator); 19762306a36Sopenharmony_ci init_one_color(&dlg.menubox); 19862306a36Sopenharmony_ci init_one_color(&dlg.menubox_border); 19962306a36Sopenharmony_ci init_one_color(&dlg.item); 20062306a36Sopenharmony_ci init_one_color(&dlg.item_selected); 20162306a36Sopenharmony_ci init_one_color(&dlg.tag); 20262306a36Sopenharmony_ci init_one_color(&dlg.tag_selected); 20362306a36Sopenharmony_ci init_one_color(&dlg.tag_key); 20462306a36Sopenharmony_ci init_one_color(&dlg.tag_key_selected); 20562306a36Sopenharmony_ci init_one_color(&dlg.check); 20662306a36Sopenharmony_ci init_one_color(&dlg.check_selected); 20762306a36Sopenharmony_ci init_one_color(&dlg.uarrow); 20862306a36Sopenharmony_ci init_one_color(&dlg.darrow); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/* 21262306a36Sopenharmony_ci * Setup for color display 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_cistatic void color_setup(const char *theme) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci int use_color; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci use_color = set_theme(theme); 21962306a36Sopenharmony_ci if (use_color && has_colors()) { 22062306a36Sopenharmony_ci start_color(); 22162306a36Sopenharmony_ci init_dialog_colors(); 22262306a36Sopenharmony_ci } else 22362306a36Sopenharmony_ci set_mono_theme(); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* 22762306a36Sopenharmony_ci * Set window to attribute 'attr' 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_civoid attr_clear(WINDOW * win, int height, int width, chtype attr) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci int i, j; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci wattrset(win, attr); 23462306a36Sopenharmony_ci for (i = 0; i < height; i++) { 23562306a36Sopenharmony_ci wmove(win, i, 0); 23662306a36Sopenharmony_ci for (j = 0; j < width; j++) 23762306a36Sopenharmony_ci waddch(win, ' '); 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci touchwin(win); 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_civoid dialog_clear(void) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci int lines, columns; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci lines = getmaxy(stdscr); 24762306a36Sopenharmony_ci columns = getmaxx(stdscr); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci attr_clear(stdscr, lines, columns, dlg.screen.atr); 25062306a36Sopenharmony_ci /* Display background title if it exists ... - SLH */ 25162306a36Sopenharmony_ci if (dlg.backtitle != NULL) { 25262306a36Sopenharmony_ci int i, len = 0, skip = 0; 25362306a36Sopenharmony_ci struct subtitle_list *pos; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci wattrset(stdscr, dlg.screen.atr); 25662306a36Sopenharmony_ci mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { 25962306a36Sopenharmony_ci /* 3 is for the arrow and spaces */ 26062306a36Sopenharmony_ci len += strlen(pos->text) + 3; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci wmove(stdscr, 1, 1); 26462306a36Sopenharmony_ci if (len > columns - 2) { 26562306a36Sopenharmony_ci const char *ellipsis = "[...] "; 26662306a36Sopenharmony_ci waddstr(stdscr, ellipsis); 26762306a36Sopenharmony_ci skip = len - (columns - 2 - strlen(ellipsis)); 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { 27162306a36Sopenharmony_ci if (skip == 0) 27262306a36Sopenharmony_ci waddch(stdscr, ACS_RARROW); 27362306a36Sopenharmony_ci else 27462306a36Sopenharmony_ci skip--; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (skip == 0) 27762306a36Sopenharmony_ci waddch(stdscr, ' '); 27862306a36Sopenharmony_ci else 27962306a36Sopenharmony_ci skip--; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (skip < strlen(pos->text)) { 28262306a36Sopenharmony_ci waddstr(stdscr, pos->text + skip); 28362306a36Sopenharmony_ci skip = 0; 28462306a36Sopenharmony_ci } else 28562306a36Sopenharmony_ci skip -= strlen(pos->text); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (skip == 0) 28862306a36Sopenharmony_ci waddch(stdscr, ' '); 28962306a36Sopenharmony_ci else 29062306a36Sopenharmony_ci skip--; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci for (i = len + 1; i < columns - 1; i++) 29462306a36Sopenharmony_ci waddch(stdscr, ACS_HLINE); 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci wnoutrefresh(stdscr); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci/* 30062306a36Sopenharmony_ci * Do some initialization for dialog 30162306a36Sopenharmony_ci */ 30262306a36Sopenharmony_ciint init_dialog(const char *backtitle) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci int height, width; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci initscr(); /* Init curses */ 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* Get current cursor position for signal handler in mconf.c */ 30962306a36Sopenharmony_ci getyx(stdscr, saved_y, saved_x); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci getmaxyx(stdscr, height, width); 31262306a36Sopenharmony_ci if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { 31362306a36Sopenharmony_ci endwin(); 31462306a36Sopenharmony_ci return -ERRDISPLAYTOOSMALL; 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci dlg.backtitle = backtitle; 31862306a36Sopenharmony_ci color_setup(getenv("MENUCONFIG_COLOR")); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci keypad(stdscr, TRUE); 32162306a36Sopenharmony_ci cbreak(); 32262306a36Sopenharmony_ci noecho(); 32362306a36Sopenharmony_ci dialog_clear(); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_civoid set_dialog_backtitle(const char *backtitle) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci dlg.backtitle = backtitle; 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_civoid set_dialog_subtitles(struct subtitle_list *subtitles) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci dlg.subtitles = subtitles; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci/* 33962306a36Sopenharmony_ci * End using dialog functions. 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_civoid end_dialog(int x, int y) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci /* move cursor back to original position */ 34462306a36Sopenharmony_ci move(y, x); 34562306a36Sopenharmony_ci refresh(); 34662306a36Sopenharmony_ci endwin(); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/* Print the title of the dialog. Center the title and truncate 35062306a36Sopenharmony_ci * tile if wider than dialog (- 2 chars). 35162306a36Sopenharmony_ci **/ 35262306a36Sopenharmony_civoid print_title(WINDOW *dialog, const char *title, int width) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci if (title) { 35562306a36Sopenharmony_ci int tlen = MIN(width - 2, strlen(title)); 35662306a36Sopenharmony_ci wattrset(dialog, dlg.title.atr); 35762306a36Sopenharmony_ci mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); 35862306a36Sopenharmony_ci mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); 35962306a36Sopenharmony_ci waddch(dialog, ' '); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* 36462306a36Sopenharmony_ci * Print a string of text in a window, automatically wrap around to the 36562306a36Sopenharmony_ci * next line if the string is too long to fit on one line. Newline 36662306a36Sopenharmony_ci * characters '\n' are properly processed. We start on a new line 36762306a36Sopenharmony_ci * if there is no room for at least 4 nonblanks following a double-space. 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_civoid print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci int newl, cur_x, cur_y; 37262306a36Sopenharmony_ci int prompt_len, room, wlen; 37362306a36Sopenharmony_ci char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci strcpy(tempstr, prompt); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci prompt_len = strlen(tempstr); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (prompt_len <= width - x * 2) { /* If prompt is short */ 38062306a36Sopenharmony_ci wmove(win, y, (width - prompt_len) / 2); 38162306a36Sopenharmony_ci waddstr(win, tempstr); 38262306a36Sopenharmony_ci } else { 38362306a36Sopenharmony_ci cur_x = x; 38462306a36Sopenharmony_ci cur_y = y; 38562306a36Sopenharmony_ci newl = 1; 38662306a36Sopenharmony_ci word = tempstr; 38762306a36Sopenharmony_ci while (word && *word) { 38862306a36Sopenharmony_ci sp = strpbrk(word, "\n "); 38962306a36Sopenharmony_ci if (sp && *sp == '\n') 39062306a36Sopenharmony_ci newline_separator = sp; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (sp) 39362306a36Sopenharmony_ci *sp++ = 0; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* Wrap to next line if either the word does not fit, 39662306a36Sopenharmony_ci or it is the first word of a new sentence, and it is 39762306a36Sopenharmony_ci short, and the next word does not fit. */ 39862306a36Sopenharmony_ci room = width - cur_x; 39962306a36Sopenharmony_ci wlen = strlen(word); 40062306a36Sopenharmony_ci if (wlen > room || 40162306a36Sopenharmony_ci (newl && wlen < 4 && sp 40262306a36Sopenharmony_ci && wlen + 1 + strlen(sp) > room 40362306a36Sopenharmony_ci && (!(sp2 = strpbrk(sp, "\n ")) 40462306a36Sopenharmony_ci || wlen + 1 + (sp2 - sp) > room))) { 40562306a36Sopenharmony_ci cur_y++; 40662306a36Sopenharmony_ci cur_x = x; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci wmove(win, cur_y, cur_x); 40962306a36Sopenharmony_ci waddstr(win, word); 41062306a36Sopenharmony_ci getyx(win, cur_y, cur_x); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* Move to the next line if the word separator was a newline */ 41362306a36Sopenharmony_ci if (newline_separator) { 41462306a36Sopenharmony_ci cur_y++; 41562306a36Sopenharmony_ci cur_x = x; 41662306a36Sopenharmony_ci newline_separator = 0; 41762306a36Sopenharmony_ci } else 41862306a36Sopenharmony_ci cur_x++; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci if (sp && *sp == ' ') { 42162306a36Sopenharmony_ci cur_x++; /* double space */ 42262306a36Sopenharmony_ci while (*++sp == ' ') ; 42362306a36Sopenharmony_ci newl = 1; 42462306a36Sopenharmony_ci } else 42562306a36Sopenharmony_ci newl = 0; 42662306a36Sopenharmony_ci word = sp; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci } 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci/* 43262306a36Sopenharmony_ci * Print a button 43362306a36Sopenharmony_ci */ 43462306a36Sopenharmony_civoid print_button(WINDOW * win, const char *label, int y, int x, int selected) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci int i, temp; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci wmove(win, y, x); 43962306a36Sopenharmony_ci wattrset(win, selected ? dlg.button_active.atr 44062306a36Sopenharmony_ci : dlg.button_inactive.atr); 44162306a36Sopenharmony_ci waddstr(win, "<"); 44262306a36Sopenharmony_ci temp = strspn(label, " "); 44362306a36Sopenharmony_ci label += temp; 44462306a36Sopenharmony_ci wattrset(win, selected ? dlg.button_label_active.atr 44562306a36Sopenharmony_ci : dlg.button_label_inactive.atr); 44662306a36Sopenharmony_ci for (i = 0; i < temp; i++) 44762306a36Sopenharmony_ci waddch(win, ' '); 44862306a36Sopenharmony_ci wattrset(win, selected ? dlg.button_key_active.atr 44962306a36Sopenharmony_ci : dlg.button_key_inactive.atr); 45062306a36Sopenharmony_ci waddch(win, label[0]); 45162306a36Sopenharmony_ci wattrset(win, selected ? dlg.button_label_active.atr 45262306a36Sopenharmony_ci : dlg.button_label_inactive.atr); 45362306a36Sopenharmony_ci waddstr(win, (char *)label + 1); 45462306a36Sopenharmony_ci wattrset(win, selected ? dlg.button_active.atr 45562306a36Sopenharmony_ci : dlg.button_inactive.atr); 45662306a36Sopenharmony_ci waddstr(win, ">"); 45762306a36Sopenharmony_ci wmove(win, y, x + temp + 1); 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/* 46162306a36Sopenharmony_ci * Draw a rectangular box with line drawing characters 46262306a36Sopenharmony_ci */ 46362306a36Sopenharmony_civoid 46462306a36Sopenharmony_cidraw_box(WINDOW * win, int y, int x, int height, int width, 46562306a36Sopenharmony_ci chtype box, chtype border) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci int i, j; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci wattrset(win, 0); 47062306a36Sopenharmony_ci for (i = 0; i < height; i++) { 47162306a36Sopenharmony_ci wmove(win, y + i, x); 47262306a36Sopenharmony_ci for (j = 0; j < width; j++) 47362306a36Sopenharmony_ci if (!i && !j) 47462306a36Sopenharmony_ci waddch(win, border | ACS_ULCORNER); 47562306a36Sopenharmony_ci else if (i == height - 1 && !j) 47662306a36Sopenharmony_ci waddch(win, border | ACS_LLCORNER); 47762306a36Sopenharmony_ci else if (!i && j == width - 1) 47862306a36Sopenharmony_ci waddch(win, box | ACS_URCORNER); 47962306a36Sopenharmony_ci else if (i == height - 1 && j == width - 1) 48062306a36Sopenharmony_ci waddch(win, box | ACS_LRCORNER); 48162306a36Sopenharmony_ci else if (!i) 48262306a36Sopenharmony_ci waddch(win, border | ACS_HLINE); 48362306a36Sopenharmony_ci else if (i == height - 1) 48462306a36Sopenharmony_ci waddch(win, box | ACS_HLINE); 48562306a36Sopenharmony_ci else if (!j) 48662306a36Sopenharmony_ci waddch(win, border | ACS_VLINE); 48762306a36Sopenharmony_ci else if (j == width - 1) 48862306a36Sopenharmony_ci waddch(win, box | ACS_VLINE); 48962306a36Sopenharmony_ci else 49062306a36Sopenharmony_ci waddch(win, box | ' '); 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/* 49562306a36Sopenharmony_ci * Draw shadows along the right and bottom edge to give a more 3D look 49662306a36Sopenharmony_ci * to the boxes 49762306a36Sopenharmony_ci */ 49862306a36Sopenharmony_civoid draw_shadow(WINDOW * win, int y, int x, int height, int width) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci int i; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci if (has_colors()) { /* Whether terminal supports color? */ 50362306a36Sopenharmony_ci wattrset(win, dlg.shadow.atr); 50462306a36Sopenharmony_ci wmove(win, y + height, x + 2); 50562306a36Sopenharmony_ci for (i = 0; i < width; i++) 50662306a36Sopenharmony_ci waddch(win, winch(win) & A_CHARTEXT); 50762306a36Sopenharmony_ci for (i = y + 1; i < y + height + 1; i++) { 50862306a36Sopenharmony_ci wmove(win, i, x + width); 50962306a36Sopenharmony_ci waddch(win, winch(win) & A_CHARTEXT); 51062306a36Sopenharmony_ci waddch(win, winch(win) & A_CHARTEXT); 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci wnoutrefresh(win); 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci} 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci/* 51762306a36Sopenharmony_ci * Return the position of the first alphabetic character in a string. 51862306a36Sopenharmony_ci */ 51962306a36Sopenharmony_ciint first_alpha(const char *string, const char *exempt) 52062306a36Sopenharmony_ci{ 52162306a36Sopenharmony_ci int i, in_paren = 0, c; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci for (i = 0; i < strlen(string); i++) { 52462306a36Sopenharmony_ci c = tolower(string[i]); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (strchr("<[(", c)) 52762306a36Sopenharmony_ci ++in_paren; 52862306a36Sopenharmony_ci if (strchr(">])", c) && in_paren > 0) 52962306a36Sopenharmony_ci --in_paren; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) 53262306a36Sopenharmony_ci return i; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci return 0; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci/* 53962306a36Sopenharmony_ci * ncurses uses ESC to detect escaped char sequences. This resutl in 54062306a36Sopenharmony_ci * a small timeout before ESC is actually delivered to the application. 54162306a36Sopenharmony_ci * lxdialog suggest <ESC> <ESC> which is correctly translated to two 54262306a36Sopenharmony_ci * times esc. But then we need to ignore the second esc to avoid stepping 54362306a36Sopenharmony_ci * out one menu too much. Filter away all escaped key sequences since 54462306a36Sopenharmony_ci * keypad(FALSE) turn off ncurses support for escape sequences - and that's 54562306a36Sopenharmony_ci * needed to make notimeout() do as expected. 54662306a36Sopenharmony_ci */ 54762306a36Sopenharmony_ciint on_key_esc(WINDOW *win) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci int key; 55062306a36Sopenharmony_ci int key2; 55162306a36Sopenharmony_ci int key3; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci nodelay(win, TRUE); 55462306a36Sopenharmony_ci keypad(win, FALSE); 55562306a36Sopenharmony_ci key = wgetch(win); 55662306a36Sopenharmony_ci key2 = wgetch(win); 55762306a36Sopenharmony_ci do { 55862306a36Sopenharmony_ci key3 = wgetch(win); 55962306a36Sopenharmony_ci } while (key3 != ERR); 56062306a36Sopenharmony_ci nodelay(win, FALSE); 56162306a36Sopenharmony_ci keypad(win, TRUE); 56262306a36Sopenharmony_ci if (key == KEY_ESC && key2 == ERR) 56362306a36Sopenharmony_ci return KEY_ESC; 56462306a36Sopenharmony_ci else if (key != ERR && key != KEY_ESC && key2 == ERR) 56562306a36Sopenharmony_ci ungetch(key); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci return -1; 56862306a36Sopenharmony_ci} 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci/* redraw screen in new size */ 57162306a36Sopenharmony_ciint on_key_resize(void) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci dialog_clear(); 57462306a36Sopenharmony_ci return KEY_RESIZE; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistruct dialog_list *item_cur; 57862306a36Sopenharmony_cistruct dialog_list item_nil; 57962306a36Sopenharmony_cistruct dialog_list *item_head; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_civoid item_reset(void) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct dialog_list *p, *next; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci for (p = item_head; p; p = next) { 58662306a36Sopenharmony_ci next = p->next; 58762306a36Sopenharmony_ci free(p); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci item_head = NULL; 59062306a36Sopenharmony_ci item_cur = &item_nil; 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_civoid item_make(const char *fmt, ...) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci va_list ap; 59662306a36Sopenharmony_ci struct dialog_list *p = malloc(sizeof(*p)); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (item_head) 59962306a36Sopenharmony_ci item_cur->next = p; 60062306a36Sopenharmony_ci else 60162306a36Sopenharmony_ci item_head = p; 60262306a36Sopenharmony_ci item_cur = p; 60362306a36Sopenharmony_ci memset(p, 0, sizeof(*p)); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci va_start(ap, fmt); 60662306a36Sopenharmony_ci vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); 60762306a36Sopenharmony_ci va_end(ap); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_civoid item_add_str(const char *fmt, ...) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci va_list ap; 61362306a36Sopenharmony_ci size_t avail; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci va_start(ap, fmt); 61862306a36Sopenharmony_ci vsnprintf(item_cur->node.str + strlen(item_cur->node.str), 61962306a36Sopenharmony_ci avail, fmt, ap); 62062306a36Sopenharmony_ci item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; 62162306a36Sopenharmony_ci va_end(ap); 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_civoid item_set_tag(char tag) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci item_cur->node.tag = tag; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_civoid item_set_data(void *ptr) 62962306a36Sopenharmony_ci{ 63062306a36Sopenharmony_ci item_cur->node.data = ptr; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_civoid item_set_selected(int val) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci item_cur->node.selected = val; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ciint item_activate_selected(void) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci item_foreach() 64162306a36Sopenharmony_ci if (item_is_selected()) 64262306a36Sopenharmony_ci return 1; 64362306a36Sopenharmony_ci return 0; 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_civoid *item_data(void) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci return item_cur->node.data; 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cichar item_tag(void) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci return item_cur->node.tag; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ciint item_count(void) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci int n = 0; 65962306a36Sopenharmony_ci struct dialog_list *p; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci for (p = item_head; p; p = p->next) 66262306a36Sopenharmony_ci n++; 66362306a36Sopenharmony_ci return n; 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_civoid item_set(int n) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci int i = 0; 66962306a36Sopenharmony_ci item_foreach() 67062306a36Sopenharmony_ci if (i++ == n) 67162306a36Sopenharmony_ci return; 67262306a36Sopenharmony_ci} 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ciint item_n(void) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci int n = 0; 67762306a36Sopenharmony_ci struct dialog_list *p; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci for (p = item_head; p; p = p->next) { 68062306a36Sopenharmony_ci if (p == item_cur) 68162306a36Sopenharmony_ci return n; 68262306a36Sopenharmony_ci n++; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci return 0; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciconst char *item_str(void) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci return item_cur->node.str; 69062306a36Sopenharmony_ci} 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ciint item_is_selected(void) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci return (item_cur->node.selected != 0); 69562306a36Sopenharmony_ci} 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ciint item_is_tag(char tag) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci return (item_cur->node.tag == tag); 70062306a36Sopenharmony_ci} 701