util.c 9.3 KB

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