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

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