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.
 
 
 

389 lines
10 KiB

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