|
|
1.1 ! root 1: /* ! 2: * util.c ! 3: * ! 4: * ORIGINAL AUTHOR: Savio Lam ([email protected]) ! 5: * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap ([email protected]) ! 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 <stdarg.h> ! 23: ! 24: #include "dialog.h" ! 25: ! 26: struct dialog_info dlg; ! 27: ! 28: static void set_mono_theme(void) ! 29: { ! 30: dlg.screen.atr = A_NORMAL; ! 31: dlg.shadow.atr = A_NORMAL; ! 32: dlg.dialog.atr = A_NORMAL; ! 33: dlg.title.atr = A_BOLD; ! 34: dlg.border.atr = A_NORMAL; ! 35: dlg.button_active.atr = A_REVERSE; ! 36: dlg.button_inactive.atr = A_DIM; ! 37: dlg.button_key_active.atr = A_REVERSE; ! 38: dlg.button_key_inactive.atr = A_BOLD; ! 39: dlg.button_label_active.atr = A_REVERSE; ! 40: dlg.button_label_inactive.atr = A_NORMAL; ! 41: dlg.inputbox.atr = A_NORMAL; ! 42: dlg.inputbox_border.atr = A_NORMAL; ! 43: dlg.searchbox.atr = A_NORMAL; ! 44: dlg.searchbox_title.atr = A_BOLD; ! 45: dlg.searchbox_border.atr = A_NORMAL; ! 46: dlg.position_indicator.atr = A_BOLD; ! 47: dlg.menubox.atr = A_NORMAL; ! 48: dlg.menubox_border.atr = A_NORMAL; ! 49: dlg.item.atr = A_NORMAL; ! 50: dlg.item_selected.atr = A_REVERSE; ! 51: dlg.tag.atr = A_BOLD; ! 52: dlg.tag_selected.atr = A_REVERSE; ! 53: dlg.tag_key.atr = A_BOLD; ! 54: dlg.tag_key_selected.atr = A_REVERSE; ! 55: dlg.check.atr = A_BOLD; ! 56: dlg.check_selected.atr = A_REVERSE; ! 57: dlg.uarrow.atr = A_BOLD; ! 58: dlg.darrow.atr = A_BOLD; ! 59: } ! 60: ! 61: #define DLG_COLOR(dialog, f, b, h) \ ! 62: do { \ ! 63: dlg.dialog.fg = (f); \ ! 64: dlg.dialog.bg = (b); \ ! 65: dlg.dialog.hl = (h); \ ! 66: } while (0) ! 67: ! 68: static void set_classic_theme(void) ! 69: { ! 70: DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); ! 71: DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); ! 72: DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); ! 73: DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); ! 74: DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); ! 75: DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); ! 76: DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); ! 77: DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); ! 78: DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); ! 79: DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); ! 80: DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); ! 81: DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); ! 82: DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); ! 83: DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); ! 84: DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); ! 85: DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); ! 86: DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); ! 87: DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); ! 88: DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); ! 89: DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); ! 90: DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); ! 91: DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); ! 92: DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); ! 93: DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); ! 94: DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); ! 95: DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); ! 96: DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); ! 97: DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); ! 98: DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); ! 99: } ! 100: ! 101: static void set_blackbg_theme(void) ! 102: { ! 103: DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); ! 104: DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); ! 105: DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); ! 106: DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); ! 107: DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); ! 108: ! 109: DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); ! 110: DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); ! 111: DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); ! 112: DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); ! 113: DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); ! 114: DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); ! 115: ! 116: DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); ! 117: DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); ! 118: ! 119: DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); ! 120: DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); ! 121: DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); ! 122: ! 123: DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); ! 124: ! 125: DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); ! 126: DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); ! 127: ! 128: DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); ! 129: DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); ! 130: ! 131: DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); ! 132: DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); ! 133: DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); ! 134: DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); ! 135: ! 136: DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); ! 137: DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); ! 138: ! 139: DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); ! 140: DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); ! 141: } ! 142: ! 143: static void set_bluetitle_theme(void) ! 144: { ! 145: set_classic_theme(); ! 146: DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); ! 147: DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); ! 148: DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); ! 149: DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); ! 150: DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); ! 151: DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); ! 152: DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); ! 153: ! 154: } ! 155: ! 156: /* ! 157: * Select color theme ! 158: */ ! 159: static int set_theme(const char *theme) ! 160: { ! 161: int use_color = 1; ! 162: if (!theme) ! 163: set_bluetitle_theme(); ! 164: else if (strcmp(theme, "classic") == 0) ! 165: set_classic_theme(); ! 166: else if (strcmp(theme, "bluetitle") == 0) ! 167: set_bluetitle_theme(); ! 168: else if (strcmp(theme, "blackbg") == 0) ! 169: set_blackbg_theme(); ! 170: else if (strcmp(theme, "mono") == 0) ! 171: use_color = 0; ! 172: ! 173: return use_color; ! 174: } ! 175: ! 176: static void init_one_color(struct dialog_color *color) ! 177: { ! 178: static int pair = 0; ! 179: ! 180: pair++; ! 181: init_pair(pair, color->fg, color->bg); ! 182: if (color->hl) ! 183: color->atr = A_BOLD | COLOR_PAIR(pair); ! 184: else ! 185: color->atr = COLOR_PAIR(pair); ! 186: } ! 187: ! 188: static void init_dialog_colors(void) ! 189: { ! 190: init_one_color(&dlg.screen); ! 191: init_one_color(&dlg.shadow); ! 192: init_one_color(&dlg.dialog); ! 193: init_one_color(&dlg.title); ! 194: init_one_color(&dlg.border); ! 195: init_one_color(&dlg.button_active); ! 196: init_one_color(&dlg.button_inactive); ! 197: init_one_color(&dlg.button_key_active); ! 198: init_one_color(&dlg.button_key_inactive); ! 199: init_one_color(&dlg.button_label_active); ! 200: init_one_color(&dlg.button_label_inactive); ! 201: init_one_color(&dlg.inputbox); ! 202: init_one_color(&dlg.inputbox_border); ! 203: init_one_color(&dlg.searchbox); ! 204: init_one_color(&dlg.searchbox_title); ! 205: init_one_color(&dlg.searchbox_border); ! 206: init_one_color(&dlg.position_indicator); ! 207: init_one_color(&dlg.menubox); ! 208: init_one_color(&dlg.menubox_border); ! 209: init_one_color(&dlg.item); ! 210: init_one_color(&dlg.item_selected); ! 211: init_one_color(&dlg.tag); ! 212: init_one_color(&dlg.tag_selected); ! 213: init_one_color(&dlg.tag_key); ! 214: init_one_color(&dlg.tag_key_selected); ! 215: init_one_color(&dlg.check); ! 216: init_one_color(&dlg.check_selected); ! 217: init_one_color(&dlg.uarrow); ! 218: init_one_color(&dlg.darrow); ! 219: } ! 220: ! 221: /* ! 222: * Setup for color display ! 223: */ ! 224: static void color_setup(const char *theme) ! 225: { ! 226: int use_color; ! 227: ! 228: use_color = set_theme(theme); ! 229: if (use_color && has_colors()) { ! 230: start_color(); ! 231: init_dialog_colors(); ! 232: } else ! 233: set_mono_theme(); ! 234: } ! 235: ! 236: /* ! 237: * Set window to attribute 'attr' ! 238: */ ! 239: void attr_clear(WINDOW * win, int height, int width, chtype attr) ! 240: { ! 241: int i, j; ! 242: ! 243: wattrset(win, attr); ! 244: for (i = 0; i < height; i++) { ! 245: wmove(win, i, 0); ! 246: for (j = 0; j < width; j++) ! 247: waddch(win, ' '); ! 248: } ! 249: touchwin(win); ! 250: } ! 251: ! 252: void dialog_clear(void) ! 253: { ! 254: attr_clear(stdscr, LINES, COLS, dlg.screen.atr); ! 255: /* Display background title if it exists ... - SLH */ ! 256: if (dlg.backtitle != NULL) { ! 257: int i; ! 258: ! 259: wattrset(stdscr, dlg.screen.atr); ! 260: mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); ! 261: wmove(stdscr, 1, 1); ! 262: for (i = 1; i < COLS - 1; i++) ! 263: waddch(stdscr, ACS_HLINE); ! 264: } ! 265: wnoutrefresh(stdscr); ! 266: } ! 267: ! 268: /* ! 269: * Do some initialization for dialog ! 270: */ ! 271: int init_dialog(const char *backtitle) ! 272: { ! 273: int height, width; ! 274: ! 275: initscr(); /* Init curses */ ! 276: getmaxyx(stdscr, height, width); ! 277: if (height < 19 || width < 80) { ! 278: endwin(); ! 279: return -ERRDISPLAYTOOSMALL; ! 280: } ! 281: ! 282: dlg.backtitle = backtitle; ! 283: color_setup(getenv("MENUCONFIG_COLOR")); ! 284: ! 285: keypad(stdscr, TRUE); ! 286: cbreak(); ! 287: noecho(); ! 288: dialog_clear(); ! 289: ! 290: return 0; ! 291: } ! 292: ! 293: void set_dialog_backtitle(const char *backtitle) ! 294: { ! 295: dlg.backtitle = backtitle; ! 296: } ! 297: ! 298: /* ! 299: * End using dialog functions. ! 300: */ ! 301: void end_dialog(int x, int y) ! 302: { ! 303: /* move cursor back to original position */ ! 304: move(y, x); ! 305: refresh(); ! 306: endwin(); ! 307: } ! 308: ! 309: /* Print the title of the dialog. Center the title and truncate ! 310: * tile if wider than dialog (- 2 chars). ! 311: **/ ! 312: void print_title(WINDOW *dialog, const char *title, int width) ! 313: { ! 314: if (title) { ! 315: int tlen = MIN(width - 2, strlen(title)); ! 316: wattrset(dialog, dlg.title.atr); ! 317: mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); ! 318: mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); ! 319: waddch(dialog, ' '); ! 320: } ! 321: } ! 322: ! 323: /* ! 324: * Print a string of text in a window, automatically wrap around to the ! 325: * next line if the string is too long to fit on one line. Newline ! 326: * characters '\n' are replaced by spaces. We start on a new line ! 327: * if there is no room for at least 4 nonblanks following a double-space. ! 328: */ ! 329: void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) ! 330: { ! 331: int newl, cur_x, cur_y; ! 332: int i, prompt_len, room, wlen; ! 333: char tempstr[MAX_LEN + 1], *word, *sp, *sp2; ! 334: ! 335: strcpy(tempstr, prompt); ! 336: ! 337: prompt_len = strlen(tempstr); ! 338: ! 339: /* ! 340: * Remove newlines ! 341: */ ! 342: for (i = 0; i < prompt_len; i++) { ! 343: if (tempstr[i] == '\n') ! 344: tempstr[i] = ' '; ! 345: } ! 346: ! 347: if (prompt_len <= width - x * 2) { /* If prompt is short */ ! 348: wmove(win, y, (width - prompt_len) / 2); ! 349: waddstr(win, tempstr); ! 350: } else { ! 351: cur_x = x; ! 352: cur_y = y; ! 353: newl = 1; ! 354: word = tempstr; ! 355: while (word && *word) { ! 356: sp = strchr(word, ' '); ! 357: if (sp) ! 358: *sp++ = 0; ! 359: ! 360: /* Wrap to next line if either the word does not fit, ! 361: or it is the first word of a new sentence, and it is ! 362: short, and the next word does not fit. */ ! 363: room = width - cur_x; ! 364: wlen = strlen(word); ! 365: if (wlen > room || ! 366: (newl && wlen < 4 && sp ! 367: && wlen + 1 + strlen(sp) > room ! 368: && (!(sp2 = strchr(sp, ' ')) ! 369: || wlen + 1 + (sp2 - sp) > room))) { ! 370: cur_y++; ! 371: cur_x = x; ! 372: } ! 373: wmove(win, cur_y, cur_x); ! 374: waddstr(win, word); ! 375: getyx(win, cur_y, cur_x); ! 376: cur_x++; ! 377: if (sp && *sp == ' ') { ! 378: cur_x++; /* double space */ ! 379: while (*++sp == ' ') ; ! 380: newl = 1; ! 381: } else ! 382: newl = 0; ! 383: word = sp; ! 384: } ! 385: } ! 386: } ! 387: ! 388: /* ! 389: * Print a button ! 390: */ ! 391: void print_button(WINDOW * win, const char *label, int y, int x, int selected) ! 392: { ! 393: int i, temp; ! 394: ! 395: wmove(win, y, x); ! 396: wattrset(win, selected ? dlg.button_active.atr ! 397: : dlg.button_inactive.atr); ! 398: waddstr(win, "<"); ! 399: temp = strspn(label, " "); ! 400: label += temp; ! 401: wattrset(win, selected ? dlg.button_label_active.atr ! 402: : dlg.button_label_inactive.atr); ! 403: for (i = 0; i < temp; i++) ! 404: waddch(win, ' '); ! 405: wattrset(win, selected ? dlg.button_key_active.atr ! 406: : dlg.button_key_inactive.atr); ! 407: waddch(win, label[0]); ! 408: wattrset(win, selected ? dlg.button_label_active.atr ! 409: : dlg.button_label_inactive.atr); ! 410: waddstr(win, (char *)label + 1); ! 411: wattrset(win, selected ? dlg.button_active.atr ! 412: : dlg.button_inactive.atr); ! 413: waddstr(win, ">"); ! 414: wmove(win, y, x + temp + 1); ! 415: } ! 416: ! 417: /* ! 418: * Draw a rectangular box with line drawing characters ! 419: */ ! 420: void ! 421: draw_box(WINDOW * win, int y, int x, int height, int width, ! 422: chtype box, chtype border) ! 423: { ! 424: int i, j; ! 425: ! 426: wattrset(win, 0); ! 427: for (i = 0; i < height; i++) { ! 428: wmove(win, y + i, x); ! 429: for (j = 0; j < width; j++) ! 430: if (!i && !j) ! 431: waddch(win, border | ACS_ULCORNER); ! 432: else if (i == height - 1 && !j) ! 433: waddch(win, border | ACS_LLCORNER); ! 434: else if (!i && j == width - 1) ! 435: waddch(win, box | ACS_URCORNER); ! 436: else if (i == height - 1 && j == width - 1) ! 437: waddch(win, box | ACS_LRCORNER); ! 438: else if (!i) ! 439: waddch(win, border | ACS_HLINE); ! 440: else if (i == height - 1) ! 441: waddch(win, box | ACS_HLINE); ! 442: else if (!j) ! 443: waddch(win, border | ACS_VLINE); ! 444: else if (j == width - 1) ! 445: waddch(win, box | ACS_VLINE); ! 446: else ! 447: waddch(win, box | ' '); ! 448: } ! 449: } ! 450: ! 451: /* ! 452: * Draw shadows along the right and bottom edge to give a more 3D look ! 453: * to the boxes ! 454: */ ! 455: void draw_shadow(WINDOW * win, int y, int x, int height, int width) ! 456: { ! 457: int i; ! 458: ! 459: if (has_colors()) { /* Whether terminal supports color? */ ! 460: wattrset(win, dlg.shadow.atr); ! 461: wmove(win, y + height, x + 2); ! 462: for (i = 0; i < width; i++) ! 463: waddch(win, winch(win) & A_CHARTEXT); ! 464: for (i = y + 1; i < y + height + 1; i++) { ! 465: wmove(win, i, x + width); ! 466: waddch(win, winch(win) & A_CHARTEXT); ! 467: waddch(win, winch(win) & A_CHARTEXT); ! 468: } ! 469: wnoutrefresh(win); ! 470: } ! 471: } ! 472: ! 473: /* ! 474: * Return the position of the first alphabetic character in a string. ! 475: */ ! 476: int first_alpha(const char *string, const char *exempt) ! 477: { ! 478: int i, in_paren = 0, c; ! 479: ! 480: for (i = 0; i < strlen(string); i++) { ! 481: c = tolower(string[i]); ! 482: ! 483: if (strchr("<[(", c)) ! 484: ++in_paren; ! 485: if (strchr(">])", c) && in_paren > 0) ! 486: --in_paren; ! 487: ! 488: if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) ! 489: return i; ! 490: } ! 491: ! 492: return 0; ! 493: } ! 494: ! 495: /* ! 496: * ncurses uses ESC to detect escaped char sequences. This resutl in ! 497: * a small timeout before ESC is actually delivered to the application. ! 498: * lxdialog suggest <ESC> <ESC> which is correctly translated to two ! 499: * times esc. But then we need to ignore the second esc to avoid stepping ! 500: * out one menu too much. Filter away all escaped key sequences since ! 501: * keypad(FALSE) turn off ncurses support for escape sequences - and thats ! 502: * needed to make notimeout() do as expected. ! 503: */ ! 504: int on_key_esc(WINDOW *win) ! 505: { ! 506: int key; ! 507: int key2; ! 508: int key3; ! 509: ! 510: nodelay(win, TRUE); ! 511: keypad(win, FALSE); ! 512: key = wgetch(win); ! 513: key2 = wgetch(win); ! 514: do { ! 515: key3 = wgetch(win); ! 516: } while (key3 != ERR); ! 517: nodelay(win, FALSE); ! 518: keypad(win, TRUE); ! 519: if (key == KEY_ESC && key2 == ERR) ! 520: return KEY_ESC; ! 521: else if (key != ERR && key != KEY_ESC && key2 == ERR) ! 522: ungetch(key); ! 523: ! 524: return -1; ! 525: } ! 526: ! 527: /* redraw screen in new size */ ! 528: int on_key_resize(void) ! 529: { ! 530: dialog_clear(); ! 531: return KEY_RESIZE; ! 532: } ! 533: ! 534: struct dialog_list *item_cur; ! 535: struct dialog_list item_nil; ! 536: struct dialog_list *item_head; ! 537: ! 538: void item_reset(void) ! 539: { ! 540: struct dialog_list *p, *next; ! 541: ! 542: for (p = item_head; p; p = next) { ! 543: next = p->next; ! 544: free(p); ! 545: } ! 546: item_head = NULL; ! 547: item_cur = &item_nil; ! 548: } ! 549: ! 550: void item_make(const char *fmt, ...) ! 551: { ! 552: va_list ap; ! 553: struct dialog_list *p = malloc(sizeof(*p)); ! 554: ! 555: if (item_head) ! 556: item_cur->next = p; ! 557: else ! 558: item_head = p; ! 559: item_cur = p; ! 560: memset(p, 0, sizeof(*p)); ! 561: ! 562: va_start(ap, fmt); ! 563: vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); ! 564: va_end(ap); ! 565: } ! 566: ! 567: void item_add_str(const char *fmt, ...) ! 568: { ! 569: va_list ap; ! 570: size_t avail; ! 571: ! 572: avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); ! 573: ! 574: va_start(ap, fmt); ! 575: vsnprintf(item_cur->node.str + strlen(item_cur->node.str), ! 576: avail, fmt, ap); ! 577: item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; ! 578: va_end(ap); ! 579: } ! 580: ! 581: void item_set_tag(char tag) ! 582: { ! 583: item_cur->node.tag = tag; ! 584: } ! 585: void item_set_data(void *ptr) ! 586: { ! 587: item_cur->node.data = ptr; ! 588: } ! 589: ! 590: void item_set_selected(int val) ! 591: { ! 592: item_cur->node.selected = val; ! 593: } ! 594: ! 595: int item_activate_selected(void) ! 596: { ! 597: item_foreach() ! 598: if (item_is_selected()) ! 599: return 1; ! 600: return 0; ! 601: } ! 602: ! 603: void *item_data(void) ! 604: { ! 605: return item_cur->node.data; ! 606: } ! 607: ! 608: char item_tag(void) ! 609: { ! 610: return item_cur->node.tag; ! 611: } ! 612: ! 613: int item_count(void) ! 614: { ! 615: int n = 0; ! 616: struct dialog_list *p; ! 617: ! 618: for (p = item_head; p; p = p->next) ! 619: n++; ! 620: return n; ! 621: } ! 622: ! 623: void item_set(int n) ! 624: { ! 625: int i = 0; ! 626: item_foreach() ! 627: if (i++ == n) ! 628: return; ! 629: } ! 630: ! 631: int item_n(void) ! 632: { ! 633: int n = 0; ! 634: struct dialog_list *p; ! 635: ! 636: for (p = item_head; p; p = p->next) { ! 637: if (p == item_cur) ! 638: return n; ! 639: n++; ! 640: } ! 641: return 0; ! 642: } ! 643: ! 644: const char *item_str(void) ! 645: { ! 646: return item_cur->node.str; ! 647: } ! 648: ! 649: int item_is_selected(void) ! 650: { ! 651: return (item_cur->node.selected != 0); ! 652: } ! 653: ! 654: int item_is_tag(char tag) ! 655: { ! 656: return (item_cur->node.tag == tag); ! 657: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.