1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/kconfig/lxdialog/util.c Tue Apr 10 14:55:15 2007 +0000
1.3 @@ -0,0 +1,642 @@
1.4 +/*
1.5 + * util.c
1.6 + *
1.7 + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
1.8 + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
1.9 + *
1.10 + * This program is free software; you can redistribute it and/or
1.11 + * modify it under the terms of the GNU General Public License
1.12 + * as published by the Free Software Foundation; either version 2
1.13 + * of the License, or (at your option) any later version.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful,
1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + * GNU General Public License for more details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License
1.21 + * along with this program; if not, write to the Free Software
1.22 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1.23 + */
1.24 +
1.25 +#include "dialog.h"
1.26 +
1.27 +struct dialog_info dlg;
1.28 +
1.29 +static void set_mono_theme(void)
1.30 +{
1.31 + dlg.screen.atr = A_NORMAL;
1.32 + dlg.shadow.atr = A_NORMAL;
1.33 + dlg.dialog.atr = A_NORMAL;
1.34 + dlg.title.atr = A_BOLD;
1.35 + dlg.border.atr = A_NORMAL;
1.36 + dlg.button_active.atr = A_REVERSE;
1.37 + dlg.button_inactive.atr = A_DIM;
1.38 + dlg.button_key_active.atr = A_REVERSE;
1.39 + dlg.button_key_inactive.atr = A_BOLD;
1.40 + dlg.button_label_active.atr = A_REVERSE;
1.41 + dlg.button_label_inactive.atr = A_NORMAL;
1.42 + dlg.inputbox.atr = A_NORMAL;
1.43 + dlg.inputbox_border.atr = A_NORMAL;
1.44 + dlg.searchbox.atr = A_NORMAL;
1.45 + dlg.searchbox_title.atr = A_BOLD;
1.46 + dlg.searchbox_border.atr = A_NORMAL;
1.47 + dlg.position_indicator.atr = A_BOLD;
1.48 + dlg.menubox.atr = A_NORMAL;
1.49 + dlg.menubox_border.atr = A_NORMAL;
1.50 + dlg.item.atr = A_NORMAL;
1.51 + dlg.item_selected.atr = A_REVERSE;
1.52 + dlg.tag.atr = A_BOLD;
1.53 + dlg.tag_selected.atr = A_REVERSE;
1.54 + dlg.tag_key.atr = A_BOLD;
1.55 + dlg.tag_key_selected.atr = A_REVERSE;
1.56 + dlg.check.atr = A_BOLD;
1.57 + dlg.check_selected.atr = A_REVERSE;
1.58 + dlg.uarrow.atr = A_BOLD;
1.59 + dlg.darrow.atr = A_BOLD;
1.60 +}
1.61 +
1.62 +#define DLG_COLOR(dialog, f, b, h) \
1.63 +do { \
1.64 + dlg.dialog.fg = (f); \
1.65 + dlg.dialog.bg = (b); \
1.66 + dlg.dialog.hl = (h); \
1.67 +} while (0)
1.68 +
1.69 +static void set_classic_theme(void)
1.70 +{
1.71 + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
1.72 + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
1.73 + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
1.74 + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
1.75 + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
1.76 + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
1.77 + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
1.78 + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
1.79 + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
1.80 + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
1.81 + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
1.82 + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
1.83 + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
1.84 + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
1.85 + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
1.86 + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
1.87 + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
1.88 + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
1.89 + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
1.90 + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
1.91 + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
1.92 + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
1.93 + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
1.94 + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
1.95 + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
1.96 + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
1.97 + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
1.98 + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
1.99 + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
1.100 +}
1.101 +
1.102 +static void set_blackbg_theme(void)
1.103 +{
1.104 + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
1.105 + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
1.106 + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
1.107 + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
1.108 + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
1.109 +
1.110 + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
1.111 + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
1.112 + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
1.113 + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
1.114 + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
1.115 + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
1.116 +
1.117 + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
1.118 + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
1.119 +
1.120 + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
1.121 + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
1.122 + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
1.123 +
1.124 + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
1.125 +
1.126 + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
1.127 + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
1.128 +
1.129 + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
1.130 + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
1.131 +
1.132 + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
1.133 + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
1.134 + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
1.135 + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
1.136 +
1.137 + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
1.138 + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
1.139 +
1.140 + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
1.141 + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
1.142 +}
1.143 +
1.144 +static void set_bluetitle_theme(void)
1.145 +{
1.146 + set_classic_theme();
1.147 + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
1.148 + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
1.149 + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
1.150 + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
1.151 + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
1.152 + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
1.153 + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
1.154 +
1.155 +}
1.156 +
1.157 +/*
1.158 + * Select color theme
1.159 + */
1.160 +static int set_theme(const char *theme)
1.161 +{
1.162 + int use_color = 1;
1.163 + if (!theme)
1.164 + set_bluetitle_theme();
1.165 + else if (strcmp(theme, "classic") == 0)
1.166 + set_classic_theme();
1.167 + else if (strcmp(theme, "bluetitle") == 0)
1.168 + set_bluetitle_theme();
1.169 + else if (strcmp(theme, "blackbg") == 0)
1.170 + set_blackbg_theme();
1.171 + else if (strcmp(theme, "mono") == 0)
1.172 + use_color = 0;
1.173 +
1.174 + return use_color;
1.175 +}
1.176 +
1.177 +static void init_one_color(struct dialog_color *color)
1.178 +{
1.179 + static int pair = 0;
1.180 +
1.181 + pair++;
1.182 + init_pair(pair, color->fg, color->bg);
1.183 + if (color->hl)
1.184 + color->atr = A_BOLD | COLOR_PAIR(pair);
1.185 + else
1.186 + color->atr = COLOR_PAIR(pair);
1.187 +}
1.188 +
1.189 +static void init_dialog_colors(void)
1.190 +{
1.191 + init_one_color(&dlg.screen);
1.192 + init_one_color(&dlg.shadow);
1.193 + init_one_color(&dlg.dialog);
1.194 + init_one_color(&dlg.title);
1.195 + init_one_color(&dlg.border);
1.196 + init_one_color(&dlg.button_active);
1.197 + init_one_color(&dlg.button_inactive);
1.198 + init_one_color(&dlg.button_key_active);
1.199 + init_one_color(&dlg.button_key_inactive);
1.200 + init_one_color(&dlg.button_label_active);
1.201 + init_one_color(&dlg.button_label_inactive);
1.202 + init_one_color(&dlg.inputbox);
1.203 + init_one_color(&dlg.inputbox_border);
1.204 + init_one_color(&dlg.searchbox);
1.205 + init_one_color(&dlg.searchbox_title);
1.206 + init_one_color(&dlg.searchbox_border);
1.207 + init_one_color(&dlg.position_indicator);
1.208 + init_one_color(&dlg.menubox);
1.209 + init_one_color(&dlg.menubox_border);
1.210 + init_one_color(&dlg.item);
1.211 + init_one_color(&dlg.item_selected);
1.212 + init_one_color(&dlg.tag);
1.213 + init_one_color(&dlg.tag_selected);
1.214 + init_one_color(&dlg.tag_key);
1.215 + init_one_color(&dlg.tag_key_selected);
1.216 + init_one_color(&dlg.check);
1.217 + init_one_color(&dlg.check_selected);
1.218 + init_one_color(&dlg.uarrow);
1.219 + init_one_color(&dlg.darrow);
1.220 +}
1.221 +
1.222 +/*
1.223 + * Setup for color display
1.224 + */
1.225 +static void color_setup(const char *theme)
1.226 +{
1.227 + if (set_theme(theme)) {
1.228 + if (has_colors()) { /* Terminal supports color? */
1.229 + start_color();
1.230 + init_dialog_colors();
1.231 + }
1.232 + }
1.233 + else
1.234 + {
1.235 + set_mono_theme();
1.236 + }
1.237 +}
1.238 +
1.239 +/*
1.240 + * Set window to attribute 'attr'
1.241 + */
1.242 +void attr_clear(WINDOW * win, int height, int width, chtype attr)
1.243 +{
1.244 + int i, j;
1.245 +
1.246 + wattrset(win, attr);
1.247 + for (i = 0; i < height; i++) {
1.248 + wmove(win, i, 0);
1.249 + for (j = 0; j < width; j++)
1.250 + waddch(win, ' ');
1.251 + }
1.252 + touchwin(win);
1.253 +}
1.254 +
1.255 +void dialog_clear(void)
1.256 +{
1.257 + attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
1.258 + /* Display background title if it exists ... - SLH */
1.259 + if (dlg.backtitle != NULL) {
1.260 + int i;
1.261 +
1.262 + wattrset(stdscr, dlg.screen.atr);
1.263 + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
1.264 + wmove(stdscr, 1, 1);
1.265 + for (i = 1; i < COLS - 1; i++)
1.266 + waddch(stdscr, ACS_HLINE);
1.267 + }
1.268 + wnoutrefresh(stdscr);
1.269 +}
1.270 +
1.271 +/*
1.272 + * Do some initialization for dialog
1.273 + */
1.274 +void init_dialog(const char *backtitle)
1.275 +{
1.276 + dlg.backtitle = backtitle;
1.277 + color_setup(getenv("MENUCONFIG_COLOR"));
1.278 +}
1.279 +
1.280 +void reset_dialog(void)
1.281 +{
1.282 + initscr(); /* Init curses */
1.283 + keypad(stdscr, TRUE);
1.284 + cbreak();
1.285 + noecho();
1.286 + dialog_clear();
1.287 +}
1.288 +
1.289 +/*
1.290 + * End using dialog functions.
1.291 + */
1.292 +void end_dialog(void)
1.293 +{
1.294 + endwin();
1.295 +}
1.296 +
1.297 +/* Print the title of the dialog. Center the title and truncate
1.298 + * tile if wider than dialog (- 2 chars).
1.299 + **/
1.300 +void print_title(WINDOW *dialog, const char *title, int width)
1.301 +{
1.302 + if (title) {
1.303 + int tlen = MIN(width - 2, strlen(title));
1.304 + wattrset(dialog, dlg.title.atr);
1.305 + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
1.306 + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
1.307 + waddch(dialog, ' ');
1.308 + }
1.309 +}
1.310 +
1.311 +/*
1.312 + * Print a string of text in a window, automatically wrap around to the
1.313 + * next line if the string is too long to fit on one line. Newline
1.314 + * characters '\n' are replaced by spaces. We start on a new line
1.315 + * if there is no room for at least 4 nonblanks following a double-space.
1.316 + */
1.317 +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
1.318 +{
1.319 + int newl, cur_x, cur_y;
1.320 + int i, prompt_len, room, wlen;
1.321 + char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
1.322 +
1.323 + strcpy(tempstr, prompt);
1.324 +
1.325 + prompt_len = strlen(tempstr);
1.326 +
1.327 + /*
1.328 + * Remove newlines
1.329 + */
1.330 + for (i = 0; i < prompt_len; i++) {
1.331 + if (tempstr[i] == '\n')
1.332 + tempstr[i] = ' ';
1.333 + }
1.334 +
1.335 + if (prompt_len <= width - x * 2) { /* If prompt is short */
1.336 + wmove(win, y, (width - prompt_len) / 2);
1.337 + waddstr(win, tempstr);
1.338 + } else {
1.339 + cur_x = x;
1.340 + cur_y = y;
1.341 + newl = 1;
1.342 + word = tempstr;
1.343 + while (word && *word) {
1.344 + sp = index(word, ' ');
1.345 + if (sp)
1.346 + *sp++ = 0;
1.347 +
1.348 + /* Wrap to next line if either the word does not fit,
1.349 + or it is the first word of a new sentence, and it is
1.350 + short, and the next word does not fit. */
1.351 + room = width - cur_x;
1.352 + wlen = strlen(word);
1.353 + if (wlen > room ||
1.354 + (newl && wlen < 4 && sp
1.355 + && wlen + 1 + strlen(sp) > room
1.356 + && (!(sp2 = index(sp, ' '))
1.357 + || wlen + 1 + (sp2 - sp) > room))) {
1.358 + cur_y++;
1.359 + cur_x = x;
1.360 + }
1.361 + wmove(win, cur_y, cur_x);
1.362 + waddstr(win, word);
1.363 + getyx(win, cur_y, cur_x);
1.364 + cur_x++;
1.365 + if (sp && *sp == ' ') {
1.366 + cur_x++; /* double space */
1.367 + while (*++sp == ' ') ;
1.368 + newl = 1;
1.369 + } else
1.370 + newl = 0;
1.371 + word = sp;
1.372 + }
1.373 + }
1.374 +}
1.375 +
1.376 +/*
1.377 + * Print a button
1.378 + */
1.379 +void print_button(WINDOW * win, const char *label, int y, int x, int selected)
1.380 +{
1.381 + int i, temp;
1.382 +
1.383 + wmove(win, y, x);
1.384 + wattrset(win, selected ? dlg.button_active.atr
1.385 + : dlg.button_inactive.atr);
1.386 + waddstr(win, "<");
1.387 + temp = strspn(label, " ");
1.388 + label += temp;
1.389 + wattrset(win, selected ? dlg.button_label_active.atr
1.390 + : dlg.button_label_inactive.atr);
1.391 + for (i = 0; i < temp; i++)
1.392 + waddch(win, ' ');
1.393 + wattrset(win, selected ? dlg.button_key_active.atr
1.394 + : dlg.button_key_inactive.atr);
1.395 + waddch(win, label[0]);
1.396 + wattrset(win, selected ? dlg.button_label_active.atr
1.397 + : dlg.button_label_inactive.atr);
1.398 + waddstr(win, (char *)label + 1);
1.399 + wattrset(win, selected ? dlg.button_active.atr
1.400 + : dlg.button_inactive.atr);
1.401 + waddstr(win, ">");
1.402 + wmove(win, y, x + temp + 1);
1.403 +}
1.404 +
1.405 +/*
1.406 + * Draw a rectangular box with line drawing characters
1.407 + */
1.408 +void
1.409 +draw_box(WINDOW * win, int y, int x, int height, int width,
1.410 + chtype box, chtype border)
1.411 +{
1.412 + int i, j;
1.413 +
1.414 + wattrset(win, 0);
1.415 + for (i = 0; i < height; i++) {
1.416 + wmove(win, y + i, x);
1.417 + for (j = 0; j < width; j++)
1.418 + if (!i && !j)
1.419 + waddch(win, border | ACS_ULCORNER);
1.420 + else if (i == height - 1 && !j)
1.421 + waddch(win, border | ACS_LLCORNER);
1.422 + else if (!i && j == width - 1)
1.423 + waddch(win, box | ACS_URCORNER);
1.424 + else if (i == height - 1 && j == width - 1)
1.425 + waddch(win, box | ACS_LRCORNER);
1.426 + else if (!i)
1.427 + waddch(win, border | ACS_HLINE);
1.428 + else if (i == height - 1)
1.429 + waddch(win, box | ACS_HLINE);
1.430 + else if (!j)
1.431 + waddch(win, border | ACS_VLINE);
1.432 + else if (j == width - 1)
1.433 + waddch(win, box | ACS_VLINE);
1.434 + else
1.435 + waddch(win, box | ' ');
1.436 + }
1.437 +}
1.438 +
1.439 +/*
1.440 + * Draw shadows along the right and bottom edge to give a more 3D look
1.441 + * to the boxes
1.442 + */
1.443 +void draw_shadow(WINDOW * win, int y, int x, int height, int width)
1.444 +{
1.445 + int i;
1.446 +
1.447 + if (has_colors()) { /* Whether terminal supports color? */
1.448 + wattrset(win, dlg.shadow.atr);
1.449 + wmove(win, y + height, x + 2);
1.450 + for (i = 0; i < width; i++)
1.451 + waddch(win, winch(win) & A_CHARTEXT);
1.452 + for (i = y + 1; i < y + height + 1; i++) {
1.453 + wmove(win, i, x + width);
1.454 + waddch(win, winch(win) & A_CHARTEXT);
1.455 + waddch(win, winch(win) & A_CHARTEXT);
1.456 + }
1.457 + wnoutrefresh(win);
1.458 + }
1.459 +}
1.460 +
1.461 +/*
1.462 + * Return the position of the first alphabetic character in a string.
1.463 + */
1.464 +int first_alpha(const char *string, const char *exempt)
1.465 +{
1.466 + int i, in_paren = 0, c;
1.467 +
1.468 + for (i = 0; i < strlen(string); i++) {
1.469 + c = tolower(string[i]);
1.470 +
1.471 + if (strchr("<[(", c))
1.472 + ++in_paren;
1.473 + if (strchr(">])", c) && in_paren > 0)
1.474 + --in_paren;
1.475 +
1.476 + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
1.477 + return i;
1.478 + }
1.479 +
1.480 + return 0;
1.481 +}
1.482 +
1.483 +/*
1.484 + * ncurses uses ESC to detect escaped char sequences. This resutl in
1.485 + * a small timeout before ESC is actually delivered to the application.
1.486 + * lxdialog suggest <ESC> <ESC> which is correctly translated to two
1.487 + * times esc. But then we need to ignore the second esc to avoid stepping
1.488 + * out one menu too much. Filter away all escaped key sequences since
1.489 + * keypad(FALSE) turn off ncurses support for escape sequences - and thats
1.490 + * needed to make notimeout() do as expected.
1.491 + */
1.492 +int on_key_esc(WINDOW *win)
1.493 +{
1.494 + int key;
1.495 + int key2;
1.496 + int key3;
1.497 +
1.498 + nodelay(win, TRUE);
1.499 + keypad(win, FALSE);
1.500 + key = wgetch(win);
1.501 + key2 = wgetch(win);
1.502 + do {
1.503 + key3 = wgetch(win);
1.504 + } while (key3 != ERR);
1.505 + nodelay(win, FALSE);
1.506 + keypad(win, TRUE);
1.507 + if (key == KEY_ESC && key2 == ERR)
1.508 + return KEY_ESC;
1.509 + else if (key != ERR && key != KEY_ESC && key2 == ERR)
1.510 + ungetch(key);
1.511 +
1.512 + return -1;
1.513 +}
1.514 +
1.515 +/* redraw screen in new size */
1.516 +int on_key_resize(void)
1.517 +{
1.518 + dialog_clear();
1.519 + return KEY_RESIZE;
1.520 +}
1.521 +
1.522 +struct dialog_list *item_cur;
1.523 +struct dialog_list item_nil;
1.524 +struct dialog_list *item_head;
1.525 +
1.526 +void item_reset(void)
1.527 +{
1.528 + struct dialog_list *p, *next;
1.529 +
1.530 + for (p = item_head; p; p = next) {
1.531 + next = p->next;
1.532 + free(p);
1.533 + }
1.534 + item_head = NULL;
1.535 + item_cur = &item_nil;
1.536 +}
1.537 +
1.538 +void item_make(const char *fmt, ...)
1.539 +{
1.540 + va_list ap;
1.541 + struct dialog_list *p = malloc(sizeof(*p));
1.542 +
1.543 + if (item_head)
1.544 + item_cur->next = p;
1.545 + else
1.546 + item_head = p;
1.547 + item_cur = p;
1.548 + memset(p, 0, sizeof(*p));
1.549 +
1.550 + va_start(ap, fmt);
1.551 + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
1.552 + va_end(ap);
1.553 +}
1.554 +
1.555 +void item_add_str(const char *fmt, ...)
1.556 +{
1.557 + va_list ap;
1.558 + size_t avail;
1.559 +
1.560 + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
1.561 +
1.562 + va_start(ap, fmt);
1.563 + vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
1.564 + avail, fmt, ap);
1.565 + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
1.566 + va_end(ap);
1.567 +}
1.568 +
1.569 +void item_set_tag(char tag)
1.570 +{
1.571 + item_cur->node.tag = tag;
1.572 +}
1.573 +void item_set_data(void *ptr)
1.574 +{
1.575 + item_cur->node.data = ptr;
1.576 +}
1.577 +
1.578 +void item_set_selected(int val)
1.579 +{
1.580 + item_cur->node.selected = val;
1.581 +}
1.582 +
1.583 +int item_activate_selected(void)
1.584 +{
1.585 + item_foreach()
1.586 + if (item_is_selected())
1.587 + return 1;
1.588 + return 0;
1.589 +}
1.590 +
1.591 +void *item_data(void)
1.592 +{
1.593 + return item_cur->node.data;
1.594 +}
1.595 +
1.596 +char item_tag(void)
1.597 +{
1.598 + return item_cur->node.tag;
1.599 +}
1.600 +
1.601 +int item_count(void)
1.602 +{
1.603 + int n = 0;
1.604 + struct dialog_list *p;
1.605 +
1.606 + for (p = item_head; p; p = p->next)
1.607 + n++;
1.608 + return n;
1.609 +}
1.610 +
1.611 +void item_set(int n)
1.612 +{
1.613 + int i = 0;
1.614 + item_foreach()
1.615 + if (i++ == n)
1.616 + return;
1.617 +}
1.618 +
1.619 +int item_n(void)
1.620 +{
1.621 + int n = 0;
1.622 + struct dialog_list *p;
1.623 +
1.624 + for (p = item_head; p; p = p->next) {
1.625 + if (p == item_cur)
1.626 + return n;
1.627 + n++;
1.628 + }
1.629 + return 0;
1.630 +}
1.631 +
1.632 +const char *item_str(void)
1.633 +{
1.634 + return item_cur->node.str;
1.635 +}
1.636 +
1.637 +int item_is_selected(void)
1.638 +{
1.639 + return (item_cur->node.selected != 0);
1.640 +}
1.641 +
1.642 +int item_is_tag(char tag)
1.643 +{
1.644 + return (item_cur->node.tag == tag);
1.645 +}