slk.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /* PDCurses */
  2. #include <curspriv.h>
  3. /*man-start**************************************************************
  4. slk
  5. ---
  6. ### Synopsis
  7. int slk_init(int fmt);
  8. int slk_set(int labnum, const char *label, int justify);
  9. int slk_refresh(void);
  10. int slk_noutrefresh(void);
  11. char *slk_label(int labnum);
  12. int slk_clear(void);
  13. int slk_restore(void);
  14. int slk_touch(void);
  15. int slk_attron(const chtype attrs);
  16. int slk_attr_on(const attr_t attrs, void *opts);
  17. int slk_attrset(const chtype attrs);
  18. int slk_attr_set(const attr_t attrs, short color_pair, void *opts);
  19. int slk_attroff(const chtype attrs);
  20. int slk_attr_off(const attr_t attrs, void *opts);
  21. int slk_color(short color_pair);
  22. int slk_wset(int labnum, const wchar_t *label, int justify);
  23. int PDC_mouse_in_slk(int y, int x);
  24. void PDC_slk_free(void);
  25. void PDC_slk_initialize(void);
  26. wchar_t *slk_wlabel(int labnum)
  27. ### Description
  28. These functions manipulate a window that contain Soft Label Keys
  29. (SLK). To use the SLK functions, a call to slk_init() must be made
  30. BEFORE initscr() or newterm(). slk_init() removes 1 or 2 lines from
  31. the useable screen, depending on the format selected.
  32. The line(s) removed from the screen are used as a separate window, in
  33. which SLKs are displayed.
  34. slk_init() requires a single parameter which describes the format of
  35. the SLKs as follows:
  36. 0 3-2-3 format
  37. 1 4-4 format
  38. 2 4-4-4 format (ncurses extension)
  39. 3 4-4-4 format with index line (ncurses extension)
  40. 2 lines used
  41. 55 5-5 format (pdcurses format)
  42. slk_refresh(), slk_noutrefresh() and slk_touch() are analogous to
  43. refresh(), noutrefresh() and touch().
  44. ### Return Value
  45. All functions return OK on success and ERR on error.
  46. ### Portability
  47. X/Open ncurses NetBSD
  48. slk_init Y Y Y
  49. slk_set Y Y Y
  50. slk_refresh Y Y Y
  51. slk_noutrefresh Y Y Y
  52. slk_label Y Y Y
  53. slk_clear Y Y Y
  54. slk_restore Y Y Y
  55. slk_touch Y Y Y
  56. slk_attron Y Y Y
  57. slk_attrset Y Y Y
  58. slk_attroff Y Y Y
  59. slk_attr_on Y Y Y
  60. slk_attr_set Y Y Y
  61. slk_attr_off Y Y Y
  62. slk_wset Y Y Y
  63. PDC_mouse_in_slk - - -
  64. PDC_slk_free - - -
  65. PDC_slk_initialize - - -
  66. slk_wlabel - - -
  67. **man-end****************************************************************/
  68. #include <stdlib.h>
  69. enum { LABEL_NORMAL = 8, LABEL_EXTENDED = 10, LABEL_NCURSES_EXTENDED = 12 };
  70. static int label_length = 0;
  71. static int labels = 0;
  72. static int label_fmt = 0;
  73. static int label_line = 0;
  74. static bool hidden = FALSE;
  75. static struct SLK {
  76. chtype label[32];
  77. int len;
  78. int format;
  79. int start_col;
  80. } *slk = (struct SLK *)NULL;
  81. /* slk_init() is the slk initialization routine.
  82. This must be called before initscr().
  83. label_fmt = 0, 1 or 55.
  84. 0 = 3-2-3 format
  85. 1 = 4 - 4 format
  86. 2 = 4-4-4 format (ncurses extension for PC 12 function keys)
  87. 3 = 4-4-4 format (ncurses extension for PC 12 function keys -
  88. with index line)
  89. 55 = 5 - 5 format (extended for PC, 10 function keys) */
  90. int slk_init(int fmt)
  91. {
  92. PDC_LOG(("slk_init() - called\n"));
  93. if (SP)
  94. return ERR;
  95. switch (fmt)
  96. {
  97. case 0: /* 3 - 2 - 3 */
  98. labels = LABEL_NORMAL;
  99. break;
  100. case 1: /* 4 - 4 */
  101. labels = LABEL_NORMAL;
  102. break;
  103. case 2: /* 4 4 4 */
  104. labels = LABEL_NCURSES_EXTENDED;
  105. break;
  106. case 3: /* 4 4 4 with index */
  107. labels = LABEL_NCURSES_EXTENDED;
  108. break;
  109. case 55: /* 5 - 5 */
  110. labels = LABEL_EXTENDED;
  111. break;
  112. default:
  113. return ERR;
  114. }
  115. label_fmt = fmt;
  116. slk = calloc(labels, sizeof(struct SLK));
  117. if (!slk)
  118. labels = 0;
  119. return slk ? OK : ERR;
  120. }
  121. /* draw a single button */
  122. static void _drawone(int num)
  123. {
  124. int i, col, slen;
  125. if (hidden)
  126. return;
  127. slen = slk[num].len;
  128. switch (slk[num].format)
  129. {
  130. case 0: /* LEFT */
  131. col = 0;
  132. break;
  133. case 1: /* CENTER */
  134. col = (label_length - slen) / 2;
  135. if (col + slen > label_length)
  136. --col;
  137. break;
  138. default: /* RIGHT */
  139. col = label_length - slen;
  140. }
  141. wmove(SP->slk_winptr, label_line, slk[num].start_col);
  142. for (i = 0; i < label_length; ++i)
  143. waddch(SP->slk_winptr, (i >= col && i < (col + slen)) ?
  144. slk[num].label[i - col] : ' ');
  145. }
  146. /* redraw each button */
  147. static void _redraw(void)
  148. {
  149. int i;
  150. for (i = 0; i < labels; ++i)
  151. _drawone(i);
  152. }
  153. /* slk_set() Used to set a slk label to a string.
  154. labnum = 1 - 8 (or 10) (number of the label)
  155. label = string (8 or 7 bytes total), or NULL
  156. justify = 0 : left, 1 : center, 2 : right */
  157. int slk_set(int labnum, const char *label, int justify)
  158. {
  159. #ifdef PDC_WIDE
  160. wchar_t wlabel[32];
  161. PDC_mbstowcs(wlabel, label, 31);
  162. return slk_wset(labnum, wlabel, justify);
  163. #else
  164. PDC_LOG(("slk_set() - called\n"));
  165. if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
  166. return ERR;
  167. labnum--;
  168. if (!label || !(*label))
  169. {
  170. /* Clear the label */
  171. *slk[labnum].label = 0;
  172. slk[labnum].format = 0;
  173. slk[labnum].len = 0;
  174. }
  175. else
  176. {
  177. int i, j = 0;
  178. /* Skip leading spaces */
  179. while (label[j] == ' ')
  180. j++;
  181. /* Copy it */
  182. for (i = 0; i < label_length; i++)
  183. {
  184. chtype ch = label[i + j];
  185. slk[labnum].label[i] = ch;
  186. if (!ch)
  187. break;
  188. }
  189. /* Drop trailing spaces */
  190. while ((i + j) && (label[i + j - 1] == ' '))
  191. i--;
  192. slk[labnum].label[i] = 0;
  193. slk[labnum].format = justify;
  194. slk[labnum].len = i;
  195. }
  196. _drawone(labnum);
  197. return OK;
  198. #endif
  199. }
  200. int slk_refresh(void)
  201. {
  202. PDC_LOG(("slk_refresh() - called\n"));
  203. return (slk_noutrefresh() == ERR) ? ERR : doupdate();
  204. }
  205. int slk_noutrefresh(void)
  206. {
  207. PDC_LOG(("slk_noutrefresh() - called\n"));
  208. if (!SP)
  209. return ERR;
  210. return wnoutrefresh(SP->slk_winptr);
  211. }
  212. char *slk_label(int labnum)
  213. {
  214. static char temp[33];
  215. #ifdef PDC_WIDE
  216. wchar_t *wtemp = slk_wlabel(labnum);
  217. PDC_wcstombs(temp, wtemp, 32);
  218. #else
  219. chtype *p;
  220. int i;
  221. PDC_LOG(("slk_label() - called\n"));
  222. if (labnum < 1 || labnum > labels)
  223. return (char *)0;
  224. for (i = 0, p = slk[labnum - 1].label; *p; i++)
  225. temp[i] = *p++;
  226. temp[i] = '\0';
  227. #endif
  228. return temp;
  229. }
  230. int slk_clear(void)
  231. {
  232. PDC_LOG(("slk_clear() - called\n"));
  233. if (!SP)
  234. return ERR;
  235. hidden = TRUE;
  236. werase(SP->slk_winptr);
  237. return wrefresh(SP->slk_winptr);
  238. }
  239. int slk_restore(void)
  240. {
  241. PDC_LOG(("slk_restore() - called\n"));
  242. if (!SP)
  243. return ERR;
  244. hidden = FALSE;
  245. _redraw();
  246. return wrefresh(SP->slk_winptr);
  247. }
  248. int slk_touch(void)
  249. {
  250. PDC_LOG(("slk_touch() - called\n"));
  251. if (!SP)
  252. return ERR;
  253. return touchwin(SP->slk_winptr);
  254. }
  255. int slk_attron(const chtype attrs)
  256. {
  257. int rc;
  258. PDC_LOG(("slk_attron() - called\n"));
  259. if (!SP)
  260. return ERR;
  261. rc = wattron(SP->slk_winptr, attrs);
  262. _redraw();
  263. return rc;
  264. }
  265. int slk_attr_on(const attr_t attrs, void *opts)
  266. {
  267. PDC_LOG(("slk_attr_on() - called\n"));
  268. return slk_attron(attrs);
  269. }
  270. int slk_attroff(const chtype attrs)
  271. {
  272. int rc;
  273. PDC_LOG(("slk_attroff() - called\n"));
  274. if (!SP)
  275. return ERR;
  276. rc = wattroff(SP->slk_winptr, attrs);
  277. _redraw();
  278. return rc;
  279. }
  280. int slk_attr_off(const attr_t attrs, void *opts)
  281. {
  282. PDC_LOG(("slk_attr_off() - called\n"));
  283. return slk_attroff(attrs);
  284. }
  285. int slk_attrset(const chtype attrs)
  286. {
  287. int rc;
  288. PDC_LOG(("slk_attrset() - called\n"));
  289. if (!SP)
  290. return ERR;
  291. rc = wattrset(SP->slk_winptr, attrs);
  292. _redraw();
  293. return rc;
  294. }
  295. int slk_color(short color_pair)
  296. {
  297. int rc;
  298. PDC_LOG(("slk_color() - called\n"));
  299. if (!SP)
  300. return ERR;
  301. rc = wcolor_set(SP->slk_winptr, color_pair, NULL);
  302. _redraw();
  303. return rc;
  304. }
  305. int slk_attr_set(const attr_t attrs, short color_pair, void *opts)
  306. {
  307. PDC_LOG(("slk_attr_set() - called\n"));
  308. return slk_attrset(attrs | COLOR_PAIR(color_pair));
  309. }
  310. static void _slk_calc(void)
  311. {
  312. int i, center, col = 0;
  313. label_length = COLS / labels;
  314. if (label_length > 31)
  315. label_length = 31;
  316. switch (label_fmt)
  317. {
  318. case 0: /* 3 - 2 - 3 F-Key layout */
  319. --label_length;
  320. slk[0].start_col = col;
  321. slk[1].start_col = (col += label_length);
  322. slk[2].start_col = (col += label_length);
  323. center = COLS / 2;
  324. slk[3].start_col = center - label_length + 1;
  325. slk[4].start_col = center + 1;
  326. col = COLS - (label_length * 3) + 1;
  327. slk[5].start_col = col;
  328. slk[6].start_col = (col += label_length);
  329. slk[7].start_col = (col += label_length);
  330. break;
  331. case 1: /* 4 - 4 F-Key layout */
  332. for (i = 0; i < 8; i++)
  333. {
  334. slk[i].start_col = col;
  335. col += label_length;
  336. if (i == 3)
  337. col = COLS - (label_length * 4) + 1;
  338. }
  339. break;
  340. case 2: /* 4 4 4 F-Key layout */
  341. case 3: /* 4 4 4 F-Key layout with index */
  342. for (i = 0; i < 4; i++)
  343. {
  344. slk[i].start_col = col;
  345. col += label_length;
  346. }
  347. center = COLS / 2;
  348. slk[4].start_col = center - (label_length * 2) + 1;
  349. slk[5].start_col = center - label_length + 1;
  350. slk[6].start_col = center + 1;
  351. slk[7].start_col = center + label_length + 1;
  352. col = COLS - (label_length * 4) + 1;
  353. for (i = 8; i < 12; i++)
  354. {
  355. slk[i].start_col = col;
  356. col += label_length;
  357. }
  358. break;
  359. default: /* 5 - 5 F-Key layout */
  360. for (i = 0; i < 10; i++)
  361. {
  362. slk[i].start_col = col;
  363. col += label_length;
  364. if (i == 4)
  365. col = COLS - (label_length * 5) + 1;
  366. }
  367. }
  368. --label_length;
  369. /* make sure labels are all in window */
  370. _redraw();
  371. }
  372. void PDC_slk_initialize(void)
  373. {
  374. if (slk)
  375. {
  376. if (label_fmt == 3)
  377. {
  378. SP->slklines = 2;
  379. label_line = 1;
  380. }
  381. else
  382. SP->slklines = 1;
  383. if (!SP->slk_winptr)
  384. {
  385. SP->slk_winptr = newwin(SP->slklines, COLS,
  386. LINES - SP->slklines, 0);
  387. if (!SP->slk_winptr)
  388. return;
  389. wattrset(SP->slk_winptr, A_REVERSE);
  390. }
  391. _slk_calc();
  392. /* if we have an index line, display it now */
  393. if (label_fmt == 3)
  394. {
  395. chtype save_attr;
  396. int i;
  397. save_attr = SP->slk_winptr->_attrs;
  398. wattrset(SP->slk_winptr, A_NORMAL);
  399. wmove(SP->slk_winptr, 0, 0);
  400. whline(SP->slk_winptr, 0, COLS);
  401. for (i = 0; i < labels; i++)
  402. mvwprintw(SP->slk_winptr, 0, slk[i].start_col, "F%d", i + 1);
  403. SP->slk_winptr->_attrs = save_attr;
  404. }
  405. touchwin(SP->slk_winptr);
  406. }
  407. }
  408. void PDC_slk_free(void)
  409. {
  410. if (slk)
  411. {
  412. if (SP->slk_winptr)
  413. {
  414. delwin(SP->slk_winptr);
  415. SP->slk_winptr = (WINDOW *)NULL;
  416. }
  417. free(slk);
  418. slk = (struct SLK *)NULL;
  419. label_length = 0;
  420. labels = 0;
  421. label_fmt = 0;
  422. label_line = 0;
  423. hidden = FALSE;
  424. }
  425. }
  426. int PDC_mouse_in_slk(int y, int x)
  427. {
  428. int i;
  429. PDC_LOG(("PDC_mouse_in_slk() - called: y->%d x->%d\n", y, x));
  430. /* If the line on which the mouse was clicked is NOT the last line
  431. of the screen, we are not interested in it. */
  432. if (!slk || !SP->slk_winptr || (y != SP->slk_winptr->_begy + label_line))
  433. return 0;
  434. for (i = 0; i < labels; i++)
  435. if (x >= slk[i].start_col && x < (slk[i].start_col + label_length))
  436. return i + 1;
  437. return 0;
  438. }
  439. #ifdef PDC_WIDE
  440. int slk_wset(int labnum, const wchar_t *label, int justify)
  441. {
  442. PDC_LOG(("slk_wset() - called\n"));
  443. if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
  444. return ERR;
  445. labnum--;
  446. if (!label || !(*label))
  447. {
  448. /* Clear the label */
  449. *slk[labnum].label = 0;
  450. slk[labnum].format = 0;
  451. slk[labnum].len = 0;
  452. }
  453. else
  454. {
  455. int i, j = 0;
  456. /* Skip leading spaces */
  457. while (label[j] == L' ')
  458. j++;
  459. /* Copy it */
  460. for (i = 0; i < label_length; i++)
  461. {
  462. chtype ch = label[i + j];
  463. slk[labnum].label[i] = ch;
  464. if (!ch)
  465. break;
  466. }
  467. /* Drop trailing spaces */
  468. while ((i + j) && (label[i + j - 1] == L' '))
  469. i--;
  470. slk[labnum].label[i] = 0;
  471. slk[labnum].format = justify;
  472. slk[labnum].len = i;
  473. }
  474. _drawone(labnum);
  475. return OK;
  476. }
  477. wchar_t *slk_wlabel(int labnum)
  478. {
  479. static wchar_t temp[33];
  480. chtype *p;
  481. int i;
  482. PDC_LOG(("slk_wlabel() - called\n"));
  483. if (labnum < 1 || labnum > labels)
  484. return (wchar_t *)0;
  485. for (i = 0, p = slk[labnum - 1].label; *p; i++)
  486. temp[i] = *p++;
  487. temp[i] = '\0';
  488. return temp;
  489. }
  490. #endif