busybox/scripts/kconfig/lxdialog/util.c
<<
>>
Prefs
   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