util.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. #include "dialog.h"
  22. /* use colors by default? */
  23. bool use_colors = 1;
  24. const char *backtitle = NULL;
  25. const char *dialog_result;
  26. /*
  27. * Attribute values, default is for mono display
  28. */
  29. chtype attributes[] = {
  30. A_NORMAL, /* screen_attr */
  31. A_NORMAL, /* shadow_attr */
  32. A_NORMAL, /* dialog_attr */
  33. A_BOLD, /* title_attr */
  34. A_NORMAL, /* border_attr */
  35. A_REVERSE, /* button_active_attr */
  36. A_DIM, /* button_inactive_attr */
  37. A_REVERSE, /* button_key_active_attr */
  38. A_BOLD, /* button_key_inactive_attr */
  39. A_REVERSE, /* button_label_active_attr */
  40. A_NORMAL, /* button_label_inactive_attr */
  41. A_NORMAL, /* inputbox_attr */
  42. A_NORMAL, /* inputbox_border_attr */
  43. A_NORMAL, /* searchbox_attr */
  44. A_BOLD, /* searchbox_title_attr */
  45. A_NORMAL, /* searchbox_border_attr */
  46. A_BOLD, /* position_indicator_attr */
  47. A_NORMAL, /* menubox_attr */
  48. A_NORMAL, /* menubox_border_attr */
  49. A_NORMAL, /* item_attr */
  50. A_REVERSE, /* item_selected_attr */
  51. A_BOLD, /* tag_attr */
  52. A_REVERSE, /* tag_selected_attr */
  53. A_BOLD, /* tag_key_attr */
  54. A_REVERSE, /* tag_key_selected_attr */
  55. A_BOLD, /* check_attr */
  56. A_REVERSE, /* check_selected_attr */
  57. A_BOLD, /* uarrow_attr */
  58. A_BOLD /* darrow_attr */
  59. };
  60. #include "colors.h"
  61. /*
  62. * Table of color values
  63. */
  64. int color_table[][3] = {
  65. {SCREEN_FG, SCREEN_BG, SCREEN_HL},
  66. {SHADOW_FG, SHADOW_BG, SHADOW_HL},
  67. {DIALOG_FG, DIALOG_BG, DIALOG_HL},
  68. {TITLE_FG, TITLE_BG, TITLE_HL},
  69. {BORDER_FG, BORDER_BG, BORDER_HL},
  70. {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL},
  71. {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL},
  72. {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL},
  73. {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG,
  74. BUTTON_KEY_INACTIVE_HL},
  75. {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG,
  76. BUTTON_LABEL_ACTIVE_HL},
  77. {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG,
  78. BUTTON_LABEL_INACTIVE_HL},
  79. {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL},
  80. {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL},
  81. {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL},
  82. {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL},
  83. {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL},
  84. {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL},
  85. {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL},
  86. {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL},
  87. {ITEM_FG, ITEM_BG, ITEM_HL},
  88. {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL},
  89. {TAG_FG, TAG_BG, TAG_HL},
  90. {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL},
  91. {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL},
  92. {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL},
  93. {CHECK_FG, CHECK_BG, CHECK_HL},
  94. {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL},
  95. {UARROW_FG, UARROW_BG, UARROW_HL},
  96. {DARROW_FG, DARROW_BG, DARROW_HL},
  97. }; /* color_table */
  98. /*
  99. * Set window to attribute 'attr'
  100. */
  101. void attr_clear(WINDOW * win, int height, int width, chtype attr)
  102. {
  103. int i, j;
  104. wattrset(win, attr);
  105. for (i = 0; i < height; i++) {
  106. wmove(win, i, 0);
  107. for (j = 0; j < width; j++)
  108. waddch(win, ' ');
  109. }
  110. touchwin(win);
  111. }
  112. void dialog_clear(void)
  113. {
  114. attr_clear(stdscr, LINES, COLS, screen_attr);
  115. /* Display background title if it exists ... - SLH */
  116. if (backtitle != NULL) {
  117. int i;
  118. wattrset(stdscr, screen_attr);
  119. mvwaddstr(stdscr, 0, 1, (char *)backtitle);
  120. wmove(stdscr, 1, 1);
  121. for (i = 1; i < COLS - 1; i++)
  122. waddch(stdscr, ACS_HLINE);
  123. }
  124. wnoutrefresh(stdscr);
  125. }
  126. /*
  127. * Do some initialization for dialog
  128. */
  129. void init_dialog(void)
  130. {
  131. initscr(); /* Init curses */
  132. keypad(stdscr, TRUE);
  133. cbreak();
  134. noecho();
  135. if (use_colors) /* Set up colors */
  136. color_setup();
  137. dialog_clear();
  138. }
  139. /*
  140. * Setup for color display
  141. */
  142. void color_setup(void)
  143. {
  144. int i;
  145. if (has_colors()) { /* Terminal supports color? */
  146. start_color();
  147. /* Initialize color pairs */
  148. for (i = 0; i < ATTRIBUTE_COUNT; i++)
  149. init_pair(i + 1, color_table[i][0], color_table[i][1]);
  150. /* Setup color attributes */
  151. for (i = 0; i < ATTRIBUTE_COUNT; i++)
  152. attributes[i] = C_ATTR(color_table[i][2], i + 1);
  153. }
  154. }
  155. /*
  156. * End using dialog functions.
  157. */
  158. void end_dialog(void)
  159. {
  160. endwin();
  161. }
  162. /*
  163. * Print a string of text in a window, automatically wrap around to the
  164. * next line if the string is too long to fit on one line. Newline
  165. * characters '\n' are replaced by spaces. We start on a new line
  166. * if there is no room for at least 4 nonblanks following a double-space.
  167. */
  168. void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
  169. {
  170. int newl, cur_x, cur_y;
  171. int i, prompt_len, room, wlen;
  172. char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
  173. strcpy(tempstr, prompt);
  174. prompt_len = strlen(tempstr);
  175. /*
  176. * Remove newlines
  177. */
  178. for (i = 0; i < prompt_len; i++) {
  179. if (tempstr[i] == '\n')
  180. tempstr[i] = ' ';
  181. }
  182. if (prompt_len <= width - x * 2) { /* If prompt is short */
  183. wmove(win, y, (width - prompt_len) / 2);
  184. waddstr(win, tempstr);
  185. } else {
  186. cur_x = x;
  187. cur_y = y;
  188. newl = 1;
  189. word = tempstr;
  190. while (word && *word) {
  191. sp = index(word, ' ');
  192. if (sp)
  193. *sp++ = 0;
  194. /* Wrap to next line if either the word does not fit,
  195. or it is the first word of a new sentence, and it is
  196. short, and the next word does not fit. */
  197. room = width - cur_x;
  198. wlen = strlen(word);
  199. if (wlen > room ||
  200. (newl && wlen < 4 && sp
  201. && wlen + 1 + strlen(sp) > room
  202. && (!(sp2 = index(sp, ' '))
  203. || wlen + 1 + (sp2 - sp) > room))) {
  204. cur_y++;
  205. cur_x = x;
  206. }
  207. wmove(win, cur_y, cur_x);
  208. waddstr(win, word);
  209. getyx(win, cur_y, cur_x);
  210. cur_x++;
  211. if (sp && *sp == ' ') {
  212. cur_x++; /* double space */
  213. while (*++sp == ' ') ;
  214. newl = 1;
  215. } else
  216. newl = 0;
  217. word = sp;
  218. }
  219. }
  220. }
  221. /*
  222. * Print a button
  223. */
  224. void print_button(WINDOW * win, const char *label, int y, int x, int selected)
  225. {
  226. int i, temp;
  227. wmove(win, y, x);
  228. wattrset(win, selected ? button_active_attr : button_inactive_attr);
  229. waddstr(win, "<");
  230. temp = strspn(label, " ");
  231. label += temp;
  232. wattrset(win, selected ? button_label_active_attr
  233. : button_label_inactive_attr);
  234. for (i = 0; i < temp; i++)
  235. waddch(win, ' ');
  236. wattrset(win, selected ? button_key_active_attr
  237. : button_key_inactive_attr);
  238. waddch(win, label[0]);
  239. wattrset(win, selected ? button_label_active_attr
  240. : button_label_inactive_attr);
  241. waddstr(win, (char *)label + 1);
  242. wattrset(win, selected ? button_active_attr : button_inactive_attr);
  243. waddstr(win, ">");
  244. wmove(win, y, x + temp + 1);
  245. }
  246. /*
  247. * Draw a rectangular box with line drawing characters
  248. */
  249. void
  250. draw_box(WINDOW * win, int y, int x, int height, int width,
  251. chtype box, chtype border)
  252. {
  253. int i, j;
  254. wattrset(win, 0);
  255. for (i = 0; i < height; i++) {
  256. wmove(win, y + i, x);
  257. for (j = 0; j < width; j++)
  258. if (!i && !j)
  259. waddch(win, border | ACS_ULCORNER);
  260. else if (i == height - 1 && !j)
  261. waddch(win, border | ACS_LLCORNER);
  262. else if (!i && j == width - 1)
  263. waddch(win, box | ACS_URCORNER);
  264. else if (i == height - 1 && j == width - 1)
  265. waddch(win, box | ACS_LRCORNER);
  266. else if (!i)
  267. waddch(win, border | ACS_HLINE);
  268. else if (i == height - 1)
  269. waddch(win, box | ACS_HLINE);
  270. else if (!j)
  271. waddch(win, border | ACS_VLINE);
  272. else if (j == width - 1)
  273. waddch(win, box | ACS_VLINE);
  274. else
  275. waddch(win, box | ' ');
  276. }
  277. }
  278. /*
  279. * Draw shadows along the right and bottom edge to give a more 3D look
  280. * to the boxes
  281. */
  282. void draw_shadow(WINDOW * win, int y, int x, int height, int width)
  283. {
  284. int i;
  285. if (has_colors()) { /* Whether terminal supports color? */
  286. wattrset(win, shadow_attr);
  287. wmove(win, y + height, x + 2);
  288. for (i = 0; i < width; i++)
  289. waddch(win, winch(win) & A_CHARTEXT);
  290. for (i = y + 1; i < y + height + 1; i++) {
  291. wmove(win, i, x + width);
  292. waddch(win, winch(win) & A_CHARTEXT);
  293. waddch(win, winch(win) & A_CHARTEXT);
  294. }
  295. wnoutrefresh(win);
  296. }
  297. }
  298. /*
  299. * Return the position of the first alphabetic character in a string.
  300. */
  301. int first_alpha(const char *string, const char *exempt)
  302. {
  303. int i, in_paren = 0, c;
  304. for (i = 0; i < strlen(string); i++) {
  305. c = tolower(string[i]);
  306. if (strchr("<[(", c))
  307. ++in_paren;
  308. if (strchr(">])", c) && in_paren > 0)
  309. --in_paren;
  310. if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
  311. return i;
  312. }
  313. return 0;
  314. }