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.

slk.c 7.6KB

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