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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #include <curses.h>
  2. #include <stddef.h>
  3. #include <malloc.h>
  4. #include <string.h>
  5. #include "core.h"
  6. /** @file
  7. *
  8. * Soft label key functions
  9. */
  10. #define MIN_SPACE_SIZE 2
  11. struct _softlabel {
  12. // label string
  13. char *label;
  14. /* Format of soft label
  15. 0: left justify
  16. 1: centre justify
  17. 2: right justify
  18. */
  19. unsigned short fmt;
  20. };
  21. struct _softlabelkeys {
  22. struct _softlabel *fkeys;
  23. attr_t attrs;
  24. /* Soft label layout format
  25. 0: 3-2-3
  26. 1: 4-4
  27. 2: 4-4-4
  28. 3: 4-4-4 with index line
  29. */
  30. unsigned short fmt;
  31. unsigned short max_label_len;
  32. unsigned short maj_space_len;
  33. unsigned short num_labels;
  34. unsigned short num_spaces;
  35. unsigned short *spaces;
  36. };
  37. struct _softlabelkeys *slks;
  38. static unsigned short pos_x;
  39. /*
  40. I either need to break the primitives here, or write a collection of
  41. functions specifically for SLKs that directly access the screen
  42. functions - since this technically isn't part of stdscr, I think
  43. this should be ok...
  44. */
  45. static void _movetoslk ( void ) {
  46. stdscr->scr->movetoyx( stdscr->scr, LINES, 0 );
  47. }
  48. static void _print_label ( struct _softlabel sl ) {
  49. unsigned short i = 0;
  50. int space_ch;
  51. char *str = malloc((size_t)slks->max_label_len);
  52. space_ch = ' ';
  53. // protect against gaps in the soft label keys array
  54. if ( sl.label == NULL ) {
  55. memset( str, space_ch, (size_t)(slks->max_label_len) );
  56. } else {
  57. /* we need to pad the label with varying amounts of leading
  58. pad depending on the format of the label */
  59. if ( sl.fmt == 1 ) {
  60. memset( str, space_ch,
  61. (size_t)(slks->max_label_len
  62. - strlen(sl.label)) / 2 );
  63. }
  64. if ( sl.fmt == 2 ) {
  65. memset( str, space_ch,
  66. (size_t)(slks->max_label_len
  67. - strlen(sl.label)) );
  68. }
  69. strcat(str,sl.label);
  70. // post-padding
  71. memset(str+strlen(str), space_ch,
  72. (size_t)(slks->max_label_len - strlen(str)) );
  73. str[slks->max_label_len] = '\0';
  74. }
  75. // print the formatted label
  76. for ( ; i < slks->max_label_len; i++ ) {
  77. stdscr->scr->putc( stdscr->scr, (chtype)str[i] | slks->attrs );
  78. }
  79. }
  80. /**
  81. * Return the attribute used for the soft function keys
  82. *
  83. * @ret attrs the current attributes of the soft function keys
  84. */
  85. attr_t slk_attr ( void ) {
  86. return ( slks == NULL ? 0 : slks->attrs );
  87. }
  88. /**
  89. * Turn off soft function key attributes
  90. *
  91. * @v attrs attribute bit mask
  92. * @ret rc return status code
  93. */
  94. int slk_attroff ( const chtype attrs ) {
  95. if ( slks == NULL )
  96. return ERR;
  97. slks->attrs &= ~( attrs & A_ATTRIBUTES );
  98. return OK;
  99. }
  100. /**
  101. * Turn on soft function key attributes
  102. *
  103. * @v attrs attribute bit mask
  104. * @ret rc return status code
  105. */
  106. int slk_attron ( const chtype attrs ) {
  107. if ( slks == NULL )
  108. return ERR;
  109. slks->attrs |= ( attrs & A_ATTRIBUTES );
  110. return OK;
  111. }
  112. /**
  113. * Set soft function key attributes
  114. *
  115. * @v attrs attribute bit mask
  116. * @ret rc return status code
  117. */
  118. int slk_attrset ( const chtype attrs ) {
  119. if ( slks == NULL )
  120. return ERR;
  121. slks->attrs = ( attrs & A_ATTRIBUTES );
  122. return OK;
  123. }
  124. /**
  125. * Turn off soft function key attributes
  126. *
  127. * @v attrs attribute bit mask
  128. * @v *opts undefined (for future implementation)
  129. * @ret rc return status code
  130. */
  131. int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
  132. return slk_attroff( attrs );
  133. }
  134. /**
  135. * Turn on soft function key attributes
  136. *
  137. * @v attrs attribute bit mask
  138. * @v *opts undefined (for future implementation)
  139. * @ret rc return status code
  140. */
  141. int slk_attr_on ( attr_t attrs, void *opts __unused ) {
  142. return slk_attron( attrs );
  143. }
  144. /**
  145. * Set soft function key attributes
  146. *
  147. * @v attrs attribute bit mask
  148. * @v colour_pair_number colour pair integer
  149. * @v *opts undefined (for future implementation)
  150. * @ret rc return status code
  151. */
  152. int slk_attr_set ( const attr_t attrs, short colour_pair_number,
  153. void *opts __unused ) {
  154. if ( slks == NULL )
  155. return ERR;
  156. if ( ( unsigned short )colour_pair_number > COLORS )
  157. return ERR;
  158. slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
  159. ( attrs & A_ATTRIBUTES );
  160. return OK;
  161. }
  162. /**
  163. * Clear the soft function key labels from the screen
  164. *
  165. * @ret rc return status code
  166. */
  167. int slk_clear ( void ) {
  168. chtype space_ch;
  169. if ( slks == NULL )
  170. return ERR;
  171. _movetoslk();
  172. pos_x = 0;
  173. space_ch = (chtype)' ' | slks->attrs;
  174. for ( ; pos_x < COLS; pos_x++ )
  175. stdscr->scr->putc( stdscr->scr, space_ch );
  176. return OK;
  177. }
  178. /**
  179. * Set soft label colour pair
  180. */
  181. int slk_colour ( short colour_pair_number ) {
  182. if ( slks == NULL )
  183. return ERR;
  184. if ( ( unsigned short )colour_pair_number > COLORS )
  185. return ERR;
  186. slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
  187. | ( slks->attrs & A_ATTRIBUTES );
  188. return OK;
  189. }
  190. /**
  191. * Initialise the soft function keys
  192. *
  193. * @v fmt format of keys
  194. * @ret rc return status code
  195. */
  196. int slk_init ( int fmt ) {
  197. unsigned short nmaj, nmin, nblocks, available_width;
  198. if ( (unsigned)fmt > 3 ) {
  199. return ERR;
  200. }
  201. slks = malloc(sizeof(struct _softlabelkeys));
  202. slks->attrs = A_DEFAULT;
  203. slks->fmt = fmt;
  204. switch(fmt) {
  205. case 0:
  206. nblocks = 8; nmaj = 2; nmin = 5;
  207. slks->spaces = calloc(2, sizeof(unsigned short));
  208. slks->spaces[0] = 2; slks->spaces[1] = 4;
  209. break;
  210. case 1:
  211. nblocks = 8; nmaj = 1; nmin = 6;
  212. slks->spaces = calloc(1, sizeof(unsigned short));
  213. slks->spaces[0] = 3;
  214. break;
  215. case 2:
  216. // same allocations as format 3
  217. case 3:
  218. nblocks = 12; nmaj = 2; nmin = 9;
  219. slks->spaces = calloc(2, sizeof(unsigned short));
  220. slks->spaces[0] = 3; slks->spaces[1] = 7;
  221. break;
  222. default:
  223. nblocks = 0; nmaj = 0; nmin = 0;
  224. break;
  225. }
  226. // determine maximum label length and major space size
  227. available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
  228. slks->max_label_len = available_width / nblocks;
  229. slks->maj_space_len = MIN_SPACE_SIZE +
  230. ( available_width % nblocks ) / nmaj;
  231. slks->num_spaces = nmaj;
  232. slks->num_labels = nblocks;
  233. slks->fkeys = calloc( nblocks, sizeof(struct _softlabel) );
  234. // strip a line from the screen
  235. LINES -= 1;
  236. return OK;
  237. }
  238. /**
  239. * Return the label for the specified soft key
  240. *
  241. * @v labnum soft key identifier
  242. * @ret label return label
  243. */
  244. char* slk_label ( int labnum ) {
  245. if ( slks == NULL )
  246. return NULL;
  247. return slks->fkeys[labnum].label;
  248. }
  249. /**
  250. * Restore soft function key labels to the screen
  251. *
  252. * @ret rc return status code
  253. */
  254. int slk_restore ( void ) {
  255. unsigned short i, j,
  256. *next_space, *last_space;
  257. chtype space_ch;
  258. if ( slks == NULL )
  259. return ERR;
  260. pos_x = 0;
  261. _movetoslk();
  262. space_ch = (chtype)' ' | slks->attrs;
  263. next_space = &(slks->spaces[0]);
  264. last_space = &(slks->spaces[slks->num_spaces-1]);
  265. for ( i = 0; i < slks->num_labels ; i++ ) {
  266. _print_label( slks->fkeys[i] );
  267. pos_x += slks->max_label_len;
  268. if ( i == *next_space ) {
  269. for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
  270. stdscr->scr->putc( stdscr->scr, space_ch );
  271. if ( next_space < last_space )
  272. next_space++;
  273. } else {
  274. if ( pos_x < COLS )
  275. stdscr->scr->putc( stdscr->scr, space_ch );
  276. pos_x++;
  277. }
  278. }
  279. return OK;
  280. }
  281. /**
  282. * Configure specified soft key
  283. *
  284. * @v labnum soft label position to configure
  285. * @v *label string to use as soft key label
  286. * @v fmt justification format of label
  287. * @ret rc return status code
  288. */
  289. int slk_set ( int labnum, const char *label, int fmt ) {
  290. if ( slks == NULL )
  291. return ERR;
  292. if ( (unsigned short)labnum >= slks->num_labels )
  293. return ERR;
  294. if ( (unsigned short)fmt >= 3 )
  295. return ERR;
  296. slks->fkeys[labnum].label = malloc((size_t)slks->max_label_len + 1);
  297. strncpy(slks->fkeys[labnum].label, label, (size_t)slks->max_label_len);
  298. slks->fkeys[labnum].fmt = fmt;
  299. return OK;
  300. }