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.

slangui.c 9.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* $Id: slangui.c,v 1.2 1999/11/21 22:30:55 tausq Exp $ */
  2. /* slangui.c - SLang user interface routines */
  3. /* TODO: the redraw code is a bit broken, also this module is usually way too many
  4. * global vars */
  5. #include "slangui.h"
  6. #include <slang.h>
  7. #include <libintl.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include "data.h"
  11. #include "strutl.h"
  12. #include "macros.h"
  13. #include "help.h"
  14. /* Slang object number mapping */
  15. #define DEFAULTOBJ 0
  16. #define CHOOSEROBJ 1
  17. #define DESCOBJ 2
  18. #define STATUSOBJ 3
  19. #define DIALOGOBJ 4
  20. #define POINTEROBJ 5
  21. #define BUTTONOBJ 6
  22. #define ROWS SLtt_Screen_Rows
  23. #define COLUMNS SLtt_Screen_Cols
  24. /* Module private variables */
  25. static int _chooser_coloffset = 5;
  26. static int _chooser_rowoffset = 3;
  27. static int _chooser_height = 0;
  28. static int _chooser_width = 0;
  29. static int _chooser_topindex = 0;
  30. static int _resized = 0;
  31. static struct packages_t *_packages = NULL;
  32. static struct packages_t *_taskpackages = NULL;
  33. static struct package_t **_taskpackagesary = NULL;
  34. static void write_centered_str(int row, int coloffset, int width, char *txt)
  35. {
  36. int col;
  37. int len = strlen(txt);
  38. if (txt == NULL) return;
  39. SLsmg_fill_region(row, coloffset, 1, width, ' ');
  40. if (coloffset + len >= width) col = 0;
  41. else col = (width - len) / 2;
  42. SLsmg_gotorc(row, coloffset + col);
  43. SLsmg_write_nstring(txt, width);
  44. }
  45. void ui_init(int argc, char * const argv[], struct packages_t *taskpkgs, struct packages_t *pkgs)
  46. {
  47. _taskpackages = taskpkgs;
  48. _taskpackagesary = packages_enumerate(taskpkgs);
  49. _packages = pkgs;
  50. SLang_set_abort_signal(NULL);
  51. /* assign attributes to objects */
  52. SLtt_set_color(DEFAULTOBJ, NULL, "white", "black");
  53. SLtt_set_color(CHOOSEROBJ, NULL, "black", "cyan");
  54. SLtt_set_color(POINTEROBJ, NULL, "brightblue", "cyan");
  55. SLtt_set_color(DESCOBJ, NULL, "black", "cyan");
  56. SLtt_set_color(STATUSOBJ, NULL, "yellow", "blue");
  57. SLtt_set_color(DIALOGOBJ, NULL, "black", "white");
  58. SLtt_set_color(BUTTONOBJ, NULL, "white", "red");
  59. ui_resize();
  60. }
  61. int ui_shutdown(void)
  62. {
  63. SLsmg_reset_smg();
  64. SLang_reset_tty();
  65. return 0;
  66. }
  67. void ui_resize(void)
  68. {
  69. /* SIGWINCH handler */
  70. if (-1 == SLang_init_tty(-1, 0, 1)) DIE(_("Unable to initialize the terminal"));
  71. SLtt_get_terminfo();
  72. if (-1 == SLsmg_init_smg()) DIE(_("Unable to initialize screen output"));
  73. if (-1 == SLkp_init()) DIE(_("Unable to initialize keyboard interface"));
  74. if (SLtt_Screen_Rows < 20 || SLtt_Screen_Cols < 70) {
  75. DIE(_("Sorry, tasksel needs a terminal with at least 70 columns and 20 rows"));
  76. }
  77. _chooser_height = ROWS - 2 * _chooser_rowoffset;
  78. _chooser_width = COLUMNS - 2 * _chooser_coloffset;
  79. ui_drawscreen(0);
  80. _resized = 1;
  81. }
  82. int ui_eventloop(void)
  83. {
  84. int done = 0;
  85. int ret = 0;
  86. int pos = 0;
  87. int c, i;
  88. _chooser_topindex = 0;
  89. ui_redrawcursor(0);
  90. while (!done) {
  91. c = SLkp_getkey();
  92. switch (c) {
  93. case SL_KEY_UP:
  94. case SL_KEY_LEFT:
  95. if (pos > 0) pos--; else pos = _taskpackages->count - 1;
  96. ui_redrawcursor(pos);
  97. break;
  98. case SL_KEY_DOWN:
  99. case SL_KEY_RIGHT:
  100. if (pos < _taskpackages->count - 1) pos++; else pos = 0;
  101. ui_redrawcursor(pos);
  102. break;
  103. case SL_KEY_PPAGE:
  104. pos -= _chooser_height;
  105. if (pos < 0) pos = 0;
  106. ui_redrawcursor(pos);
  107. break;
  108. case SL_KEY_NPAGE:
  109. pos += _chooser_height;
  110. if (pos >= _taskpackages->count - 1) pos = _taskpackages->count - 1;
  111. ui_redrawcursor(pos);
  112. break;
  113. case SL_KEY_ENTER: case '\r': case '\n':
  114. case ' ': ui_toggleselection(pos); break;
  115. case 'A': case 'a':
  116. for (i = 0; i < _taskpackages->count; i++) _taskpackagesary[i]->selected = 1;
  117. ui_drawscreen(pos);
  118. break;
  119. case 'N': case 'n':
  120. for (i = 0; i < _taskpackages->count; i++) _taskpackagesary[i]->selected = 0;
  121. ui_drawscreen(pos);
  122. break;
  123. case 'H': case 'h': case SL_KEY_F(1): ui_showhelp(); break;
  124. case 'I': case 'i': ui_showpackageinfo(pos); break;
  125. case 'Q': case 'q': done = 1; break;
  126. }
  127. }
  128. return ret;
  129. }
  130. int ui_drawbox(int obj, int r, int c, unsigned int dr, unsigned int dc)
  131. {
  132. SLsmg_set_color(obj);
  133. SLsmg_draw_box(r, c, dr, dc);
  134. return 0;
  135. }
  136. int ui_drawscreen(int index)
  137. {
  138. int i;
  139. char buf[160];
  140. SLsmg_cls();
  141. /* Show version and status lines */
  142. SLsmg_set_color(STATUSOBJ);
  143. snprintf(buf, 160, "%s v%s - %s",
  144. _(" Debian Installation Task Selector"), VERSION,
  145. _("(c) 1999 SPI and others "));
  146. write_centered_str(0, 0, COLUMNS, buf);
  147. write_centered_str(ROWS-1, 0, COLUMNS,
  148. _(" h - Help SPACE - Toggle selection i - Task info q - Exit"));
  149. /* Draw the chooser screen */
  150. SLsmg_set_color(DEFAULTOBJ);
  151. write_centered_str(1, 0, COLUMNS,
  152. _("Select the task package(s) appropriate for your system:"));
  153. ui_drawbox(CHOOSEROBJ, _chooser_rowoffset - 1, _chooser_coloffset - 1, _chooser_height + 2, _chooser_width + 2);
  154. for (i = 0; i < _taskpackages->count && i < _chooser_height; i++)
  155. ui_drawchooseritem(i);
  156. ui_redrawcursor(index);
  157. SLsmg_refresh();
  158. _resized = 0;
  159. return 0;
  160. }
  161. void ui_button(int row, int col, char *txt)
  162. {
  163. SLsmg_set_color(BUTTONOBJ);
  164. SLsmg_gotorc(row, col);
  165. SLsmg_write_char(' ');
  166. SLsmg_write_string(txt);
  167. SLsmg_write_char(' ');
  168. }
  169. void ui_dialog(int row, int col, int height, int width, char *title, char *msg)
  170. {
  171. char *reflowbuf;
  172. int ri, c, pos;
  173. char *line, *txt;
  174. reflowbuf = reflowtext(width - 4, msg);
  175. SLsmg_set_color(DIALOGOBJ);
  176. ui_drawbox(DIALOGOBJ, row, col, height, width);
  177. SLsmg_fill_region(row+1, col+1, height-2, width-2, ' ');
  178. if (title) {
  179. pos = col + (width - strlen(title))/2;
  180. SLsmg_gotorc(row, pos);
  181. SLsmg_write_char(' ');
  182. SLsmg_write_string(title);
  183. SLsmg_write_char(' ');
  184. }
  185. if (reflowbuf != NULL) {
  186. txt = reflowbuf;
  187. ri = 0;
  188. while ((line = strsep(&txt, "\n")) && (ri < height - 3)) {
  189. SLsmg_gotorc(row + 1 + ri, col + 1);
  190. SLsmg_write_nstring(line, width - 4);
  191. ri++;
  192. }
  193. }
  194. ui_button(row+height-2, col+(width-4)/2, " OK ");
  195. SLsmg_refresh();
  196. do {
  197. c = SLkp_getkey();
  198. } while (!(c == '\n' || c == '\r' || c == SL_KEY_ENTER || isspace(c)) && (_resized == 0));
  199. }
  200. void ui_drawchooseritem(int index)
  201. {
  202. char buf[1024];
  203. ASSERT(_taskpackages != NULL);
  204. if (index >= _taskpackages->count) DIE("Index out of bounds: %d >= %d", index, _taskpackages->count);
  205. if (index < _chooser_topindex) return;
  206. SLsmg_set_color(CHOOSEROBJ);
  207. SLsmg_gotorc(_chooser_rowoffset + index - _chooser_topindex, _chooser_coloffset);
  208. snprintf(buf, 1024, " (%c) %s: %s",
  209. (_taskpackagesary[index]->selected == 0 ? ' ' : '*'),
  210. _taskpackagesary[index]->name, _taskpackagesary[index]->shortdesc);
  211. SLsmg_write_nstring(buf, _chooser_width);
  212. }
  213. void ui_toggleselection(int index)
  214. {
  215. ASSERT(_taskpackages != NULL);
  216. if (index >= _taskpackages->count) DIE("Index out of bounds: %d >= %d", index, _taskpackages->count);
  217. if (_taskpackagesary[index]->selected == 0)
  218. _taskpackagesary[index]->selected = 1;
  219. else
  220. _taskpackagesary[index]->selected = 0;
  221. SLsmg_set_color(CHOOSEROBJ);
  222. SLsmg_gotorc(_chooser_rowoffset + index - _chooser_topindex, _chooser_coloffset + 3);
  223. if (_taskpackagesary[index]->selected == 0)
  224. SLsmg_write_string("( )");
  225. else
  226. SLsmg_write_string("(*)");
  227. SLsmg_refresh();
  228. }
  229. void ui_showhelp(void)
  230. {
  231. ui_dialog(3, 3, ROWS-6, COLUMNS-6, "Help", HELPTXT);
  232. ui_drawscreen(0);
  233. }
  234. void ui_redrawchooser(int index)
  235. {
  236. int i;
  237. for (i = _chooser_topindex; i < _chooser_topindex + _chooser_height; i++)
  238. if (i < _taskpackages->count) ui_drawchooseritem(i);
  239. }
  240. void ui_redrawcursor(int index)
  241. {
  242. /* Check to see if we have to scroll the selection */
  243. if (index + 1 - _chooser_height > _chooser_topindex) {
  244. _chooser_topindex = index + 1 - _chooser_height;
  245. ui_redrawchooser(index);
  246. } else if (index < _chooser_topindex) {
  247. _chooser_topindex = 0;
  248. ui_redrawchooser(index);
  249. }
  250. SLsmg_set_color(POINTEROBJ);
  251. SLsmg_fill_region(_chooser_rowoffset, _chooser_coloffset, _chooser_height, 3, ' ');
  252. SLsmg_gotorc(_chooser_rowoffset + index - _chooser_topindex, _chooser_coloffset);
  253. SLsmg_write_string("->");
  254. SLsmg_refresh();
  255. }
  256. void ui_showpackageinfo(int index)
  257. {
  258. struct package_t *pkg, *deppkg;
  259. int i;
  260. int width;
  261. char buf[4096];
  262. char shortbuf[256];
  263. int bufleft;
  264. ASSERT(_taskpackages != NULL);
  265. if (index >= _taskpackages->count) DIE("Index out of bounds: %d >= %d", index, _taskpackages->count);
  266. pkg = _taskpackagesary[index];
  267. /* pack buf with package info */
  268. snprintf(buf, sizeof(buf), "Name: %s\nDescription:\n%s\n\nDependent packages:\n", pkg->name, pkg->longdesc);
  269. bufleft = sizeof(buf) - strlen(buf) - 1;
  270. width = COLUMNS - 5;
  271. ASSERT(width < sizeof(shortbuf));
  272. for (i = 0; i < pkg->dependscount; i++) {
  273. deppkg = packages_find(_packages, pkg->depends[i]);
  274. snprintf(shortbuf, width, "%s - %s\n", pkg->depends[i],
  275. (deppkg && deppkg->shortdesc ? deppkg->shortdesc : "(no description available)"));
  276. strncat(buf, shortbuf, bufleft);
  277. bufleft = sizeof(buf) - strlen(buf) - 1;
  278. }
  279. ui_dialog(2, 2, ROWS-4, COLUMNS-4, pkg->name, buf);
  280. ui_drawscreen(index);
  281. }