| /* | 
 |  *  util.c | 
 |  * | 
 |  *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) | 
 |  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) | 
 |  * | 
 |  *  This program is free software; you can redistribute it and/or | 
 |  *  modify it under the terms of the GNU General Public License | 
 |  *  as published by the Free Software Foundation; either version 2 | 
 |  *  of the License, or (at your option) any later version. | 
 |  * | 
 |  *  This program is distributed in the hope that it will be useful, | 
 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  *  GNU General Public License for more details. | 
 |  * | 
 |  *  You should have received a copy of the GNU General Public License | 
 |  *  along with this program; if not, write to the Free Software | 
 |  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 
 |  */ | 
 |  | 
 | #include "dialog.h" | 
 |  | 
 |  | 
 | /* use colors by default? */ | 
 | bool use_colors = 1; | 
 |  | 
 | const char *backtitle = NULL; | 
 |  | 
 | const char *dialog_result; | 
 |  | 
 | /*  | 
 |  * Attribute values, default is for mono display | 
 |  */ | 
 | chtype attributes[] = | 
 | { | 
 |     A_NORMAL,			/* screen_attr */ | 
 |     A_NORMAL,			/* shadow_attr */ | 
 |     A_NORMAL,			/* dialog_attr */ | 
 |     A_BOLD,			/* title_attr */ | 
 |     A_NORMAL,			/* border_attr */ | 
 |     A_REVERSE,			/* button_active_attr */ | 
 |     A_DIM,			/* button_inactive_attr */ | 
 |     A_REVERSE,			/* button_key_active_attr */ | 
 |     A_BOLD,			/* button_key_inactive_attr */ | 
 |     A_REVERSE,			/* button_label_active_attr */ | 
 |     A_NORMAL,			/* button_label_inactive_attr */ | 
 |     A_NORMAL,			/* inputbox_attr */ | 
 |     A_NORMAL,			/* inputbox_border_attr */ | 
 |     A_NORMAL,			/* searchbox_attr */ | 
 |     A_BOLD,			/* searchbox_title_attr */ | 
 |     A_NORMAL,			/* searchbox_border_attr */ | 
 |     A_BOLD,			/* position_indicator_attr */ | 
 |     A_NORMAL,			/* menubox_attr */ | 
 |     A_NORMAL,			/* menubox_border_attr */ | 
 |     A_NORMAL,			/* item_attr */ | 
 |     A_REVERSE,			/* item_selected_attr */ | 
 |     A_BOLD,			/* tag_attr */ | 
 |     A_REVERSE,			/* tag_selected_attr */ | 
 |     A_BOLD,			/* tag_key_attr */ | 
 |     A_REVERSE,			/* tag_key_selected_attr */ | 
 |     A_BOLD,			/* check_attr */ | 
 |     A_REVERSE,			/* check_selected_attr */ | 
 |     A_BOLD,			/* uarrow_attr */ | 
 |     A_BOLD			/* darrow_attr */ | 
 | }; | 
 |  | 
 |  | 
 | #include "colors.h" | 
 |  | 
 | /* | 
 |  * Table of color values | 
 |  */ | 
 | int color_table[][3] = | 
 | { | 
 |     {SCREEN_FG, SCREEN_BG, SCREEN_HL}, | 
 |     {SHADOW_FG, SHADOW_BG, SHADOW_HL}, | 
 |     {DIALOG_FG, DIALOG_BG, DIALOG_HL}, | 
 |     {TITLE_FG, TITLE_BG, TITLE_HL}, | 
 |     {BORDER_FG, BORDER_BG, BORDER_HL}, | 
 |     {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, | 
 |     {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, | 
 |     {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, | 
 |     {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, | 
 |     {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, | 
 |     {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, | 
 |      BUTTON_LABEL_INACTIVE_HL}, | 
 |     {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, | 
 |     {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, | 
 |     {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, | 
 |     {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, | 
 |     {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, | 
 |     {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, | 
 |     {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, | 
 |     {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, | 
 |     {ITEM_FG, ITEM_BG, ITEM_HL}, | 
 |     {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, | 
 |     {TAG_FG, TAG_BG, TAG_HL}, | 
 |     {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, | 
 |     {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, | 
 |     {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, | 
 |     {CHECK_FG, CHECK_BG, CHECK_HL}, | 
 |     {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, | 
 |     {UARROW_FG, UARROW_BG, UARROW_HL}, | 
 |     {DARROW_FG, DARROW_BG, DARROW_HL}, | 
 | };				/* color_table */ | 
 |  | 
 | /* | 
 |  * Set window to attribute 'attr' | 
 |  */ | 
 | void | 
 | attr_clear (WINDOW * win, int height, int width, chtype attr) | 
 | { | 
 |     int i, j; | 
 |  | 
 |     wattrset (win, attr); | 
 |     for (i = 0; i < height; i++) { | 
 | 	wmove (win, i, 0); | 
 | 	for (j = 0; j < width; j++) | 
 | 	    waddch (win, ' '); | 
 |     } | 
 |     touchwin (win); | 
 | } | 
 |  | 
 | void dialog_clear (void) | 
 | { | 
 |     attr_clear (stdscr, LINES, COLS, screen_attr); | 
 |     /* Display background title if it exists ... - SLH */ | 
 |     if (backtitle != NULL) { | 
 |         int i; | 
 |  | 
 |         wattrset (stdscr, screen_attr); | 
 |         mvwaddstr (stdscr, 0, 1, (char *)backtitle); | 
 |         wmove (stdscr, 1, 1); | 
 |         for (i = 1; i < COLS - 1; i++) | 
 |             waddch (stdscr, ACS_HLINE); | 
 |     } | 
 |     wnoutrefresh (stdscr); | 
 | } | 
 |  | 
 | /* | 
 |  * Do some initialization for dialog | 
 |  */ | 
 | void | 
 | init_dialog (void) | 
 | { | 
 |     initscr ();			/* Init curses */ | 
 |     keypad (stdscr, TRUE); | 
 |     cbreak (); | 
 |     noecho (); | 
 |  | 
 |  | 
 |     if (use_colors)	/* Set up colors */ | 
 | 	color_setup (); | 
 |  | 
 |  | 
 |     dialog_clear (); | 
 | } | 
 |  | 
 | /* | 
 |  * Setup for color display | 
 |  */ | 
 | void | 
 | color_setup (void) | 
 | { | 
 |     int i; | 
 |  | 
 |     if (has_colors ()) {	/* Terminal supports color? */ | 
 | 	start_color (); | 
 |  | 
 | 	/* Initialize color pairs */ | 
 | 	for (i = 0; i < ATTRIBUTE_COUNT; i++) | 
 | 	    init_pair (i + 1, color_table[i][0], color_table[i][1]); | 
 |  | 
 | 	/* Setup color attributes */ | 
 | 	for (i = 0; i < ATTRIBUTE_COUNT; i++) | 
 | 	    attributes[i] = C_ATTR (color_table[i][2], i + 1); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * End using dialog functions. | 
 |  */ | 
 | void | 
 | end_dialog (void) | 
 | { | 
 |     endwin (); | 
 | } | 
 |  | 
 |  | 
 | /* | 
 |  * Print a string of text in a window, automatically wrap around to the | 
 |  * next line if the string is too long to fit on one line. Newline | 
 |  * characters '\n' are replaced by spaces.  We start on a new line | 
 |  * if there is no room for at least 4 nonblanks following a double-space. | 
 |  */ | 
 | void | 
 | print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) | 
 | { | 
 |     int newl, cur_x, cur_y; | 
 |     int i, prompt_len, room, wlen; | 
 |     char tempstr[MAX_LEN + 1], *word, *sp, *sp2; | 
 |  | 
 |     strcpy (tempstr, prompt); | 
 |  | 
 |     prompt_len = strlen(tempstr); | 
 | 	 | 
 |     /* | 
 |      * Remove newlines | 
 |      */ | 
 |     for(i=0; i<prompt_len; i++) { | 
 | 	if(tempstr[i] == '\n') tempstr[i] = ' '; | 
 |     } | 
 |  | 
 |     if (prompt_len <= width - x * 2) {	/* If prompt is short */ | 
 | 	wmove (win, y, (width - prompt_len) / 2); | 
 | 	waddstr (win, tempstr); | 
 |     } else { | 
 | 	cur_x = x; | 
 | 	cur_y = y; | 
 | 	newl = 1; | 
 | 	word = tempstr; | 
 | 	while (word && *word) { | 
 | 	    sp = index(word, ' '); | 
 | 	    if (sp) | 
 | 	        *sp++ = 0; | 
 |  | 
 | 	    /* Wrap to next line if either the word does not fit, | 
 | 	       or it is the first word of a new sentence, and it is | 
 | 	       short, and the next word does not fit. */ | 
 | 	    room = width - cur_x; | 
 | 	    wlen = strlen(word); | 
 | 	    if (wlen > room || | 
 | 	       (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room | 
 | 		     && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { | 
 | 		cur_y++; | 
 | 		cur_x = x; | 
 | 	    } | 
 | 	    wmove (win, cur_y, cur_x); | 
 | 	    waddstr (win, word); | 
 | 	    getyx (win, cur_y, cur_x); | 
 | 	    cur_x++; | 
 | 	    if (sp && *sp == ' ') { | 
 | 	        cur_x++;	/* double space */ | 
 | 		while (*++sp == ' '); | 
 | 		newl = 1; | 
 | 	    } else | 
 | 	        newl = 0; | 
 | 	    word = sp; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * Print a button | 
 |  */ | 
 | void | 
 | print_button (WINDOW * win, const char *label, int y, int x, int selected) | 
 | { | 
 |     int i, temp; | 
 |  | 
 |     wmove (win, y, x); | 
 |     wattrset (win, selected ? button_active_attr : button_inactive_attr); | 
 |     waddstr (win, "<"); | 
 |     temp = strspn (label, " "); | 
 |     label += temp; | 
 |     wattrset (win, selected ? button_label_active_attr | 
 | 	      : button_label_inactive_attr); | 
 |     for (i = 0; i < temp; i++) | 
 | 	waddch (win, ' '); | 
 |     wattrset (win, selected ? button_key_active_attr | 
 | 	      : button_key_inactive_attr); | 
 |     waddch (win, label[0]); | 
 |     wattrset (win, selected ? button_label_active_attr | 
 | 	      : button_label_inactive_attr); | 
 |     waddstr (win, (char *)label + 1); | 
 |     wattrset (win, selected ? button_active_attr : button_inactive_attr); | 
 |     waddstr (win, ">"); | 
 |     wmove (win, y, x + temp + 1); | 
 | } | 
 |  | 
 | /* | 
 |  * Draw a rectangular box with line drawing characters | 
 |  */ | 
 | void | 
 | draw_box (WINDOW * win, int y, int x, int height, int width, | 
 | 	  chtype box, chtype border) | 
 | { | 
 |     int i, j; | 
 |  | 
 |     wattrset (win, 0); | 
 |     for (i = 0; i < height; i++) { | 
 | 	wmove (win, y + i, x); | 
 | 	for (j = 0; j < width; j++) | 
 | 	    if (!i && !j) | 
 | 		waddch (win, border | ACS_ULCORNER); | 
 | 	    else if (i == height - 1 && !j) | 
 | 		waddch (win, border | ACS_LLCORNER); | 
 | 	    else if (!i && j == width - 1) | 
 | 		waddch (win, box | ACS_URCORNER); | 
 | 	    else if (i == height - 1 && j == width - 1) | 
 | 		waddch (win, box | ACS_LRCORNER); | 
 | 	    else if (!i) | 
 | 		waddch (win, border | ACS_HLINE); | 
 | 	    else if (i == height - 1) | 
 | 		waddch (win, box | ACS_HLINE); | 
 | 	    else if (!j) | 
 | 		waddch (win, border | ACS_VLINE); | 
 | 	    else if (j == width - 1) | 
 | 		waddch (win, box | ACS_VLINE); | 
 | 	    else | 
 | 		waddch (win, box | ' '); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  * Draw shadows along the right and bottom edge to give a more 3D look | 
 |  * to the boxes | 
 |  */ | 
 | void | 
 | draw_shadow (WINDOW * win, int y, int x, int height, int width) | 
 | { | 
 |     int i; | 
 |  | 
 |     if (has_colors ()) {	/* Whether terminal supports color? */ | 
 | 	wattrset (win, shadow_attr); | 
 | 	wmove (win, y + height, x + 2); | 
 | 	for (i = 0; i < width; i++) | 
 | 	    waddch (win, winch (win) & A_CHARTEXT); | 
 | 	for (i = y + 1; i < y + height + 1; i++) { | 
 | 	    wmove (win, i, x + width); | 
 | 	    waddch (win, winch (win) & A_CHARTEXT); | 
 | 	    waddch (win, winch (win) & A_CHARTEXT); | 
 | 	} | 
 | 	wnoutrefresh (win); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  *  Return the position of the first alphabetic character in a string. | 
 |  */ | 
 | int | 
 | first_alpha(const char *string, const char *exempt) | 
 | { | 
 | 	int i, in_paren=0, c; | 
 |  | 
 | 	for (i = 0; i < strlen(string); i++) { | 
 | 		c = tolower(string[i]); | 
 |  | 
 | 		if (strchr("<[(", c)) ++in_paren; | 
 | 		if (strchr(">])", c) && in_paren > 0) --in_paren; | 
 |  | 
 | 		if ((! in_paren) && isalpha(c) &&  | 
 | 		     strchr(exempt, c) == 0) | 
 | 			return i; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } |