1/* 2 * util.c 3 * 4 * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) 5 * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but 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. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include "dialog.h" 23 24/* use colors by default? */ 25bool use_colors = 1; 26 27const char *backtitle = NULL; 28 29/* 30 * Attribute values, default is for mono display 31 */ 32chtype attributes[] = { 33 A_NORMAL, /* screen_attr */ 34 A_NORMAL, /* shadow_attr */ 35 A_NORMAL, /* dialog_attr */ 36 A_BOLD, /* title_attr */ 37 A_NORMAL, /* border_attr */ 38 A_REVERSE, /* button_active_attr */ 39 A_DIM, /* button_inactive_attr */ 40 A_REVERSE, /* button_key_active_attr */ 41 A_BOLD, /* button_key_inactive_attr */ 42 A_REVERSE, /* button_label_active_attr */ 43 A_NORMAL, /* button_label_inactive_attr */ 44 A_NORMAL, /* inputbox_attr */ 45 A_NORMAL, /* inputbox_border_attr */ 46 A_NORMAL, /* searchbox_attr */ 47 A_BOLD, /* searchbox_title_attr */ 48 A_NORMAL, /* searchbox_border_attr */ 49 A_BOLD, /* position_indicator_attr */ 50 A_NORMAL, /* menubox_attr */ 51 A_NORMAL, /* menubox_border_attr */ 52 A_NORMAL, /* item_attr */ 53 A_REVERSE, /* item_selected_attr */ 54 A_BOLD, /* tag_attr */ 55 A_REVERSE, /* tag_selected_attr */ 56 A_BOLD, /* tag_key_attr */ 57 A_REVERSE, /* tag_key_selected_attr */ 58 A_BOLD, /* check_attr */ 59 A_REVERSE, /* check_selected_attr */ 60 A_BOLD, /* uarrow_attr */ 61 A_BOLD /* darrow_attr */ 62}; 63 64#include "colors.h" 65 66/* 67 * Table of color values 68 */ 69int color_table[][3] = { 70 {SCREEN_FG, SCREEN_BG, SCREEN_HL}, 71 {SHADOW_FG, SHADOW_BG, SHADOW_HL}, 72 {DIALOG_FG, DIALOG_BG, DIALOG_HL}, 73 {TITLE_FG, TITLE_BG, TITLE_HL}, 74 {BORDER_FG, BORDER_BG, BORDER_HL}, 75 {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, 76 {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, 77 {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, 78 {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, 79 BUTTON_KEY_INACTIVE_HL}, 80 {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, 81 BUTTON_LABEL_ACTIVE_HL}, 82 {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, 83 BUTTON_LABEL_INACTIVE_HL}, 84 {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, 85 {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, 86 {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, 87 {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, 88 {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, 89 {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, 90 {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, 91 {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, 92 {ITEM_FG, ITEM_BG, ITEM_HL}, 93 {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, 94 {TAG_FG, TAG_BG, TAG_HL}, 95 {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, 96 {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, 97 {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, 98 {CHECK_FG, CHECK_BG, CHECK_HL}, 99 {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, 100 {UARROW_FG, UARROW_BG, UARROW_HL}, 101 {DARROW_FG, DARROW_BG, DARROW_HL}, 102}; /* color_table */ 103 104/* 105 * Set window to attribute 'attr' 106 */ 107void attr_clear(WINDOW * win, int height, int width, chtype attr) 108{ 109 int i, j; 110 111 wattrset(win, attr); 112 for (i = 0; i < height; i++) { 113 wmove(win, i, 0); 114 for (j = 0; j < width; j++) 115 waddch(win, ' '); 116 } 117 touchwin(win); 118} 119 120void dialog_clear(void) 121{ 122 attr_clear(stdscr, LINES, COLS, screen_attr); 123 /* Display background title if it exists ... - SLH */ 124 if (backtitle != NULL) { 125 int i; 126 127 wattrset(stdscr, screen_attr); 128 mvwaddstr(stdscr, 0, 1, (char *)backtitle); 129 wmove(stdscr, 1, 1); 130 for (i = 1; i < COLS - 1; i++) 131 waddch(stdscr, ACS_HLINE); 132 } 133 wnoutrefresh(stdscr); 134} 135 136/* 137 * Do some initialization for dialog 138 */ 139void init_dialog(void) 140{ 141 initscr(); /* Init curses */ 142 keypad(stdscr, TRUE); 143 cbreak(); 144 noecho(); 145 146 if (use_colors) /* Set up colors */ 147 color_setup(); 148 149 dialog_clear(); 150} 151 152/* 153 * Setup for color display 154 */ 155void color_setup(void) 156{ 157 int i; 158 159 if (has_colors()) { /* Terminal supports color? */ 160 start_color(); 161 162 /* Initialize color pairs */ 163 for (i = 0; i < ATTRIBUTE_COUNT; i++) 164 init_pair(i + 1, color_table[i][0], color_table[i][1]); 165 166 /* Setup color attributes */ 167 for (i = 0; i < ATTRIBUTE_COUNT; i++) 168 attributes[i] = C_ATTR(color_table[i][2], i + 1); 169 } 170} 171 172/* 173 * End using dialog functions. 174 */ 175void end_dialog(void) 176{ 177 endwin(); 178} 179 180/* Print the title of the dialog. Center the title and truncate 181 * tile if wider than dialog (- 2 chars). 182 **/ 183void print_title(WINDOW *dialog, const char *title, int width) 184{ 185 if (title) { 186 int tlen = MIN(width - 2, strlen(title)); 187 wattrset(dialog, title_attr); 188 mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); 189 mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); 190 waddch(dialog, ' '); 191 } 192} 193 194/* 195 * Print a string of text in a window, automatically wrap around to the 196 * next line if the string is too long to fit on one line. Newline 197 * characters '\n' are replaced by spaces. We start on a new line 198 * if there is no room for at least 4 nonblanks following a double-space. 199 */ 200void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) 201{ 202 int newl, cur_x, cur_y; 203 int i, prompt_len, room, wlen; 204 char tempstr[MAX_LEN + 1], *word, *sp, *sp2; 205 206 strcpy(tempstr, prompt); 207 208 prompt_len = strlen(tempstr); 209 210 /* 211 * Remove newlines 212 */ 213 for (i = 0; i < prompt_len; i++) { 214 if (tempstr[i] == '\n') 215 tempstr[i] = ' '; 216 } 217 218 if (prompt_len <= width - x * 2) { /* If prompt is short */ 219 wmove(win, y, (width - prompt_len) / 2); 220 waddstr(win, tempstr); 221 } else { 222 cur_x = x; 223 cur_y = y; 224 newl = 1; 225 word = tempstr; 226 while (word && *word) { 227 sp = strchr(word, ' '); 228 if (sp) 229 *sp++ = 0; 230 231 /* Wrap to next line if either the word does not fit, 232 or it is the first word of a new sentence, and it is 233 short, and the next word does not fit. */ 234 room = width - cur_x; 235 wlen = strlen(word); 236 if (wlen > room || 237 (newl && wlen < 4 && sp 238 && wlen + 1 + strlen(sp) > room 239 && (!(sp2 = strchr(sp, ' ')) 240 || wlen + 1 + (sp2 - sp) > room))) { 241 cur_y++; 242 cur_x = x; 243 } 244 wmove(win, cur_y, cur_x); 245 waddstr(win, word); 246 getyx(win, cur_y, cur_x); 247 cur_x++; 248 if (sp && *sp == ' ') { 249 cur_x++; /* double space */ 250 while (*++sp == ' ') ; 251 newl = 1; 252 } else 253 newl = 0; 254 word = sp; 255 } 256 } 257} 258 259/* 260 * Print a button 261 */ 262void print_button(WINDOW * win, const char *label, int y, int x, int selected) 263{ 264 int i, temp; 265 266 wmove(win, y, x); 267 wattrset(win, selected ? button_active_attr : button_inactive_attr); 268 waddstr(win, "<"); 269 temp = strspn(label, " "); 270 label += temp; 271 wattrset(win, selected ? button_label_active_attr 272 : button_label_inactive_attr); 273 for (i = 0; i < temp; i++) 274 waddch(win, ' '); 275 wattrset(win, selected ? button_key_active_attr 276 : button_key_inactive_attr); 277 waddch(win, label[0]); 278 wattrset(win, selected ? button_label_active_attr 279 : button_label_inactive_attr); 280 waddstr(win, (char *)label + 1); 281 wattrset(win, selected ? button_active_attr : button_inactive_attr); 282 waddstr(win, ">"); 283 wmove(win, y, x + temp + 1); 284} 285 286/* 287 * Draw a rectangular box with line drawing characters 288 */ 289void 290draw_box(WINDOW * win, int y, int x, int height, int width, 291 chtype box, chtype border) 292{ 293 int i, j; 294 295 wattrset(win, 0); 296 for (i = 0; i < height; i++) { 297 wmove(win, y + i, x); 298 for (j = 0; j < width; j++) 299 if (!i && !j) 300 waddch(win, border | ACS_ULCORNER); 301 else if (i == height - 1 && !j) 302 waddch(win, border | ACS_LLCORNER); 303 else if (!i && j == width - 1) 304 waddch(win, box | ACS_URCORNER); 305 else if (i == height - 1 && j == width - 1) 306 waddch(win, box | ACS_LRCORNER); 307 else if (!i) 308 waddch(win, border | ACS_HLINE); 309 else if (i == height - 1) 310 waddch(win, box | ACS_HLINE); 311 else if (!j) 312 waddch(win, border | ACS_VLINE); 313 else if (j == width - 1) 314 waddch(win, box | ACS_VLINE); 315 else 316 waddch(win, box | ' '); 317 } 318} 319 320/* 321 * Draw shadows along the right and bottom edge to give a more 3D look 322 * to the boxes 323 */ 324void draw_shadow(WINDOW * win, int y, int x, int height, int width) 325{ 326 int i; 327 328 if (has_colors()) { /* Whether terminal supports color? */ 329 wattrset(win, shadow_attr); 330 wmove(win, y + height, x + 2); 331 for (i = 0; i < width; i++) 332 waddch(win, winch(win) & A_CHARTEXT); 333 for (i = y + 1; i < y + height + 1; i++) { 334 wmove(win, i, x + width); 335 waddch(win, winch(win) & A_CHARTEXT); 336 waddch(win, winch(win) & A_CHARTEXT); 337 } 338 wnoutrefresh(win); 339 } 340} 341 342/* 343 * Return the position of the first alphabetic character in a string. 344 */ 345int first_alpha(const char *string, const char *exempt) 346{ 347 int i, in_paren = 0, c; 348 349 for (i = 0; i < strlen(string); i++) { 350 c = tolower(string[i]); 351 352 if (strchr("<[(", c)) 353 ++in_paren; 354 if (strchr(">])", c) && in_paren > 0) 355 --in_paren; 356 357 if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) 358 return i; 359 } 360 361 return 0; 362} 363