You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
657 lines
17 KiB
657 lines
17 KiB
/* |
|
* 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 <stdarg.h> |
|
|
|
#include "dialog.h" |
|
|
|
struct dialog_info dlg; |
|
|
|
static void set_mono_theme(void) |
|
{ |
|
dlg.screen.atr = A_NORMAL; |
|
dlg.shadow.atr = A_NORMAL; |
|
dlg.dialog.atr = A_NORMAL; |
|
dlg.title.atr = A_BOLD; |
|
dlg.border.atr = A_NORMAL; |
|
dlg.button_active.atr = A_REVERSE; |
|
dlg.button_inactive.atr = A_DIM; |
|
dlg.button_key_active.atr = A_REVERSE; |
|
dlg.button_key_inactive.atr = A_BOLD; |
|
dlg.button_label_active.atr = A_REVERSE; |
|
dlg.button_label_inactive.atr = A_NORMAL; |
|
dlg.inputbox.atr = A_NORMAL; |
|
dlg.inputbox_border.atr = A_NORMAL; |
|
dlg.searchbox.atr = A_NORMAL; |
|
dlg.searchbox_title.atr = A_BOLD; |
|
dlg.searchbox_border.atr = A_NORMAL; |
|
dlg.position_indicator.atr = A_BOLD; |
|
dlg.menubox.atr = A_NORMAL; |
|
dlg.menubox_border.atr = A_NORMAL; |
|
dlg.item.atr = A_NORMAL; |
|
dlg.item_selected.atr = A_REVERSE; |
|
dlg.tag.atr = A_BOLD; |
|
dlg.tag_selected.atr = A_REVERSE; |
|
dlg.tag_key.atr = A_BOLD; |
|
dlg.tag_key_selected.atr = A_REVERSE; |
|
dlg.check.atr = A_BOLD; |
|
dlg.check_selected.atr = A_REVERSE; |
|
dlg.uarrow.atr = A_BOLD; |
|
dlg.darrow.atr = A_BOLD; |
|
} |
|
|
|
#define DLG_COLOR(dialog, f, b, h) \ |
|
do { \ |
|
dlg.dialog.fg = (f); \ |
|
dlg.dialog.bg = (b); \ |
|
dlg.dialog.hl = (h); \ |
|
} while (0) |
|
|
|
static void set_classic_theme(void) |
|
{ |
|
DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); |
|
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); |
|
DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); |
|
DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); |
|
DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); |
|
DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); |
|
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); |
|
DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); |
|
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); |
|
DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); |
|
DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); |
|
DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); |
|
DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); |
|
DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); |
|
DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); |
|
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); |
|
DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); |
|
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); |
|
DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); |
|
DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); |
|
DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); |
|
DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); |
|
} |
|
|
|
static void set_blackbg_theme(void) |
|
{ |
|
DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); |
|
DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); |
|
DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); |
|
DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); |
|
DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); |
|
|
|
DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); |
|
DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); |
|
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); |
|
DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); |
|
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); |
|
DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); |
|
|
|
DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); |
|
DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); |
|
|
|
DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); |
|
DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); |
|
DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); |
|
|
|
DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); |
|
|
|
DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); |
|
DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); |
|
|
|
DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); |
|
DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); |
|
|
|
DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); |
|
DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); |
|
DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); |
|
DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); |
|
|
|
DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); |
|
DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); |
|
|
|
DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); |
|
DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); |
|
} |
|
|
|
static void set_bluetitle_theme(void) |
|
{ |
|
set_classic_theme(); |
|
DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); |
|
DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); |
|
DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); |
|
DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); |
|
DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); |
|
DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); |
|
DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); |
|
|
|
} |
|
|
|
/* |
|
* Select color theme |
|
*/ |
|
static int set_theme(const char *theme) |
|
{ |
|
int use_color = 1; |
|
if (!theme) |
|
set_bluetitle_theme(); |
|
else if (strcmp(theme, "classic") == 0) |
|
set_classic_theme(); |
|
else if (strcmp(theme, "bluetitle") == 0) |
|
set_bluetitle_theme(); |
|
else if (strcmp(theme, "blackbg") == 0) |
|
set_blackbg_theme(); |
|
else if (strcmp(theme, "mono") == 0) |
|
use_color = 0; |
|
|
|
return use_color; |
|
} |
|
|
|
static void init_one_color(struct dialog_color *color) |
|
{ |
|
static int pair = 0; |
|
|
|
pair++; |
|
init_pair(pair, color->fg, color->bg); |
|
if (color->hl) |
|
color->atr = A_BOLD | COLOR_PAIR(pair); |
|
else |
|
color->atr = COLOR_PAIR(pair); |
|
} |
|
|
|
static void init_dialog_colors(void) |
|
{ |
|
init_one_color(&dlg.screen); |
|
init_one_color(&dlg.shadow); |
|
init_one_color(&dlg.dialog); |
|
init_one_color(&dlg.title); |
|
init_one_color(&dlg.border); |
|
init_one_color(&dlg.button_active); |
|
init_one_color(&dlg.button_inactive); |
|
init_one_color(&dlg.button_key_active); |
|
init_one_color(&dlg.button_key_inactive); |
|
init_one_color(&dlg.button_label_active); |
|
init_one_color(&dlg.button_label_inactive); |
|
init_one_color(&dlg.inputbox); |
|
init_one_color(&dlg.inputbox_border); |
|
init_one_color(&dlg.searchbox); |
|
init_one_color(&dlg.searchbox_title); |
|
init_one_color(&dlg.searchbox_border); |
|
init_one_color(&dlg.position_indicator); |
|
init_one_color(&dlg.menubox); |
|
init_one_color(&dlg.menubox_border); |
|
init_one_color(&dlg.item); |
|
init_one_color(&dlg.item_selected); |
|
init_one_color(&dlg.tag); |
|
init_one_color(&dlg.tag_selected); |
|
init_one_color(&dlg.tag_key); |
|
init_one_color(&dlg.tag_key_selected); |
|
init_one_color(&dlg.check); |
|
init_one_color(&dlg.check_selected); |
|
init_one_color(&dlg.uarrow); |
|
init_one_color(&dlg.darrow); |
|
} |
|
|
|
/* |
|
* Setup for color display |
|
*/ |
|
static void color_setup(const char *theme) |
|
{ |
|
int use_color; |
|
|
|
use_color = set_theme(theme); |
|
if (use_color && has_colors()) { |
|
start_color(); |
|
init_dialog_colors(); |
|
} else |
|
set_mono_theme(); |
|
} |
|
|
|
/* |
|
* 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, dlg.screen.atr); |
|
/* Display background title if it exists ... - SLH */ |
|
if (dlg.backtitle != NULL) { |
|
int i; |
|
|
|
wattrset(stdscr, dlg.screen.atr); |
|
mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); |
|
wmove(stdscr, 1, 1); |
|
for (i = 1; i < COLS - 1; i++) |
|
waddch(stdscr, ACS_HLINE); |
|
} |
|
wnoutrefresh(stdscr); |
|
} |
|
|
|
/* |
|
* Do some initialization for dialog |
|
*/ |
|
int init_dialog(const char *backtitle) |
|
{ |
|
int height, width; |
|
|
|
initscr(); /* Init curses */ |
|
getmaxyx(stdscr, height, width); |
|
if (height < 19 || width < 80) { |
|
endwin(); |
|
return -ERRDISPLAYTOOSMALL; |
|
} |
|
|
|
dlg.backtitle = backtitle; |
|
color_setup(getenv("MENUCONFIG_COLOR")); |
|
|
|
keypad(stdscr, TRUE); |
|
cbreak(); |
|
noecho(); |
|
dialog_clear(); |
|
|
|
return 0; |
|
} |
|
|
|
void set_dialog_backtitle(const char *backtitle) |
|
{ |
|
dlg.backtitle = backtitle; |
|
} |
|
|
|
/* |
|
* End using dialog functions. |
|
*/ |
|
void end_dialog(int x, int y) |
|
{ |
|
/* move cursor back to original position */ |
|
move(y, x); |
|
refresh(); |
|
endwin(); |
|
} |
|
|
|
/* Print the title of the dialog. Center the title and truncate |
|
* tile if wider than dialog (- 2 chars). |
|
**/ |
|
void print_title(WINDOW *dialog, const char *title, int width) |
|
{ |
|
if (title) { |
|
int tlen = MIN(width - 2, strlen(title)); |
|
wattrset(dialog, dlg.title.atr); |
|
mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); |
|
mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); |
|
waddch(dialog, ' '); |
|
} |
|
} |
|
|
|
/* |
|
* 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 = strchr(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 = strchr(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 ? dlg.button_active.atr |
|
: dlg.button_inactive.atr); |
|
waddstr(win, "<"); |
|
temp = strspn(label, " "); |
|
label += temp; |
|
wattrset(win, selected ? dlg.button_label_active.atr |
|
: dlg.button_label_inactive.atr); |
|
for (i = 0; i < temp; i++) |
|
waddch(win, ' '); |
|
wattrset(win, selected ? dlg.button_key_active.atr |
|
: dlg.button_key_inactive.atr); |
|
waddch(win, label[0]); |
|
wattrset(win, selected ? dlg.button_label_active.atr |
|
: dlg.button_label_inactive.atr); |
|
waddstr(win, (char *)label + 1); |
|
wattrset(win, selected ? dlg.button_active.atr |
|
: dlg.button_inactive.atr); |
|
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, dlg.shadow.atr); |
|
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; |
|
} |
|
|
|
/* |
|
* ncurses uses ESC to detect escaped char sequences. This resutl in |
|
* a small timeout before ESC is actually delivered to the application. |
|
* lxdialog suggest <ESC> <ESC> which is correctly translated to two |
|
* times esc. But then we need to ignore the second esc to avoid stepping |
|
* out one menu too much. Filter away all escaped key sequences since |
|
* keypad(FALSE) turn off ncurses support for escape sequences - and thats |
|
* needed to make notimeout() do as expected. |
|
*/ |
|
int on_key_esc(WINDOW *win) |
|
{ |
|
int key; |
|
int key2; |
|
int key3; |
|
|
|
nodelay(win, TRUE); |
|
keypad(win, FALSE); |
|
key = wgetch(win); |
|
key2 = wgetch(win); |
|
do { |
|
key3 = wgetch(win); |
|
} while (key3 != ERR); |
|
nodelay(win, FALSE); |
|
keypad(win, TRUE); |
|
if (key == KEY_ESC && key2 == ERR) |
|
return KEY_ESC; |
|
else if (key != ERR && key != KEY_ESC && key2 == ERR) |
|
ungetch(key); |
|
|
|
return -1; |
|
} |
|
|
|
/* redraw screen in new size */ |
|
int on_key_resize(void) |
|
{ |
|
dialog_clear(); |
|
return KEY_RESIZE; |
|
} |
|
|
|
struct dialog_list *item_cur; |
|
struct dialog_list item_nil; |
|
struct dialog_list *item_head; |
|
|
|
void item_reset(void) |
|
{ |
|
struct dialog_list *p, *next; |
|
|
|
for (p = item_head; p; p = next) { |
|
next = p->next; |
|
free(p); |
|
} |
|
item_head = NULL; |
|
item_cur = &item_nil; |
|
} |
|
|
|
void item_make(const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
struct dialog_list *p = malloc(sizeof(*p)); |
|
|
|
if (item_head) |
|
item_cur->next = p; |
|
else |
|
item_head = p; |
|
item_cur = p; |
|
memset(p, 0, sizeof(*p)); |
|
|
|
va_start(ap, fmt); |
|
vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); |
|
va_end(ap); |
|
} |
|
|
|
void item_add_str(const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
size_t avail; |
|
|
|
avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); |
|
|
|
va_start(ap, fmt); |
|
vsnprintf(item_cur->node.str + strlen(item_cur->node.str), |
|
avail, fmt, ap); |
|
item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; |
|
va_end(ap); |
|
} |
|
|
|
void item_set_tag(char tag) |
|
{ |
|
item_cur->node.tag = tag; |
|
} |
|
void item_set_data(void *ptr) |
|
{ |
|
item_cur->node.data = ptr; |
|
} |
|
|
|
void item_set_selected(int val) |
|
{ |
|
item_cur->node.selected = val; |
|
} |
|
|
|
int item_activate_selected(void) |
|
{ |
|
item_foreach() |
|
if (item_is_selected()) |
|
return 1; |
|
return 0; |
|
} |
|
|
|
void *item_data(void) |
|
{ |
|
return item_cur->node.data; |
|
} |
|
|
|
char item_tag(void) |
|
{ |
|
return item_cur->node.tag; |
|
} |
|
|
|
int item_count(void) |
|
{ |
|
int n = 0; |
|
struct dialog_list *p; |
|
|
|
for (p = item_head; p; p = p->next) |
|
n++; |
|
return n; |
|
} |
|
|
|
void item_set(int n) |
|
{ |
|
int i = 0; |
|
item_foreach() |
|
if (i++ == n) |
|
return; |
|
} |
|
|
|
int item_n(void) |
|
{ |
|
int n = 0; |
|
struct dialog_list *p; |
|
|
|
for (p = item_head; p; p = p->next) { |
|
if (p == item_cur) |
|
return n; |
|
n++; |
|
} |
|
return 0; |
|
} |
|
|
|
const char *item_str(void) |
|
{ |
|
return item_cur->node.str; |
|
} |
|
|
|
int item_is_selected(void) |
|
{ |
|
return (item_cur->node.selected != 0); |
|
} |
|
|
|
int item_is_tag(char tag) |
|
{ |
|
return (item_cur->node.tag == tag); |
|
}
|
|
|