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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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_OR_UBDL );
  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. memset ( str, 0, sizeof ( str ) );
  71. // protect against gaps in the soft label keys array
  72. if ( ! sl.label[0] ) {
  73. memset( str, space_ch, (size_t)(slks->max_label_len) );
  74. } else {
  75. /* we need to pad the label with varying amounts of leading
  76. pad depending on the format of the label */
  77. if ( sl.fmt == 1 ) {
  78. memset( str, space_ch,
  79. (size_t)(slks->max_label_len
  80. - strlen(sl.label)) / 2 );
  81. }
  82. if ( sl.fmt == 2 ) {
  83. memset( str, space_ch,
  84. (size_t)(slks->max_label_len
  85. - strlen(sl.label)) );
  86. }
  87. strcat(str,sl.label);
  88. // post-padding
  89. memset(str+strlen(str), space_ch,
  90. (size_t)(slks->max_label_len - strlen(str)) );
  91. }
  92. // print the formatted label
  93. _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
  94. }
  95. /**
  96. * Return the attribute used for the soft function keys
  97. *
  98. * @ret attrs the current attributes of the soft function keys
  99. */
  100. attr_t slk_attr ( void ) {
  101. return ( slks == NULL ? 0 : slks->attrs );
  102. }
  103. /**
  104. * Turn off soft function key attributes
  105. *
  106. * @v attrs attribute bit mask
  107. * @ret rc return status code
  108. */
  109. int slk_attroff ( const chtype attrs ) {
  110. if ( slks == NULL )
  111. return ERR;
  112. slks->attrs &= ~( attrs & A_ATTRIBUTES );
  113. return OK;
  114. }
  115. /**
  116. * Turn on soft function key attributes
  117. *
  118. * @v attrs attribute bit mask
  119. * @ret rc return status code
  120. */
  121. int slk_attron ( const chtype attrs ) {
  122. if ( slks == NULL )
  123. return ERR;
  124. slks->attrs |= ( attrs & A_ATTRIBUTES );
  125. return OK;
  126. }
  127. /**
  128. * Set soft function key attributes
  129. *
  130. * @v attrs attribute bit mask
  131. * @ret rc return status code
  132. */
  133. int slk_attrset ( const chtype attrs ) {
  134. if ( slks == NULL )
  135. return ERR;
  136. slks->attrs = ( attrs & A_ATTRIBUTES );
  137. return OK;
  138. }
  139. /**
  140. * Turn off soft function key attributes
  141. *
  142. * @v attrs attribute bit mask
  143. * @v *opts undefined (for future implementation)
  144. * @ret rc return status code
  145. */
  146. int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
  147. return slk_attroff( attrs );
  148. }
  149. /**
  150. * Turn on soft function key attributes
  151. *
  152. * @v attrs attribute bit mask
  153. * @v *opts undefined (for future implementation)
  154. * @ret rc return status code
  155. */
  156. int slk_attr_on ( attr_t attrs, void *opts __unused ) {
  157. return slk_attron( attrs );
  158. }
  159. /**
  160. * Set soft function key attributes
  161. *
  162. * @v attrs attribute bit mask
  163. * @v colour_pair_number colour pair integer
  164. * @v *opts undefined (for future implementation)
  165. * @ret rc return status code
  166. */
  167. int slk_attr_set ( const attr_t attrs, short colour_pair_number,
  168. void *opts __unused ) {
  169. if ( slks == NULL )
  170. return ERR;
  171. if ( ( unsigned short )colour_pair_number > COLORS )
  172. return ERR;
  173. slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
  174. ( attrs & A_ATTRIBUTES );
  175. return OK;
  176. }
  177. /**
  178. * Clear the soft function key labels from the screen
  179. *
  180. * @ret rc return status code
  181. */
  182. int slk_clear ( void ) {
  183. if ( slks == NULL )
  184. return ERR;
  185. _enter_slk();
  186. wclrtoeol ( stdscr );
  187. _leave_slk();
  188. return OK;
  189. }
  190. /**
  191. * Set soft label colour pair
  192. */
  193. int slk_colour ( short colour_pair_number ) {
  194. if ( slks == NULL )
  195. return ERR;
  196. if ( ( unsigned short )colour_pair_number > COLORS )
  197. return ERR;
  198. slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
  199. | ( slks->attrs & A_ATTRIBUTES );
  200. return OK;
  201. }
  202. /**
  203. * Initialise the soft function keys
  204. *
  205. * @v fmt format of keys
  206. * @ret rc return status code
  207. */
  208. int slk_init ( int fmt ) {
  209. unsigned short nmaj, nmin, nblocks, available_width;
  210. if ( (unsigned)fmt > 3 ) {
  211. return ERR;
  212. }
  213. /* There seems to be no API call to free this data structure... */
  214. if ( ! slks )
  215. slks = calloc(1,sizeof(*slks));
  216. if ( ! slks )
  217. return ERR;
  218. slks->attrs = A_DEFAULT;
  219. slks->fmt = fmt;
  220. switch(fmt) {
  221. case 0:
  222. nblocks = 8; nmaj = 2; nmin = 5;
  223. slks->spaces[0] = 2; slks->spaces[1] = 4;
  224. break;
  225. case 1:
  226. nblocks = 8; nmaj = 1; nmin = 6;
  227. slks->spaces[0] = 3;
  228. break;
  229. case 2:
  230. // same allocations as format 3
  231. case 3:
  232. nblocks = 12; nmaj = 2; nmin = 9;
  233. slks->spaces[0] = 3; slks->spaces[1] = 7;
  234. break;
  235. default:
  236. nblocks = 0; nmaj = 0; nmin = 0;
  237. break;
  238. }
  239. // determine maximum label length and major space size
  240. available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
  241. slks->max_label_len = available_width / nblocks;
  242. slks->maj_space_len = MIN_SPACE_SIZE +
  243. ( available_width % nblocks ) / nmaj;
  244. slks->num_spaces = nmaj;
  245. slks->num_labels = nblocks;
  246. // strip a line from the screen
  247. LINES -= 1;
  248. return OK;
  249. }
  250. /**
  251. * Return the label for the specified soft key
  252. *
  253. * @v labnum soft key identifier
  254. * @ret label return label
  255. */
  256. char* slk_label ( int labnum ) {
  257. if ( slks == NULL )
  258. return NULL;
  259. return slks->fkeys[labnum].label;
  260. }
  261. /**
  262. * Restore soft function key labels to the screen
  263. *
  264. * @ret rc return status code
  265. */
  266. int slk_restore ( void ) {
  267. unsigned int i, j, pos_x,
  268. *next_space, *last_space;
  269. chtype space_ch;
  270. if ( slks == NULL )
  271. return ERR;
  272. pos_x = 0;
  273. _enter_slk();
  274. space_ch = (chtype)' ' | slks->attrs;
  275. next_space = &(slks->spaces[0]);
  276. last_space = &(slks->spaces[slks->num_spaces-1]);
  277. for ( i = 0; i < slks->num_labels ; i++ ) {
  278. _print_label( slks->fkeys[i] );
  279. pos_x += slks->max_label_len;
  280. if ( i == *next_space ) {
  281. for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
  282. _wputch ( stdscr, space_ch, NOWRAP );
  283. if ( next_space < last_space )
  284. next_space++;
  285. } else {
  286. if ( pos_x < COLS )
  287. _wputch ( stdscr, space_ch, NOWRAP );
  288. pos_x++;
  289. }
  290. }
  291. _leave_slk();
  292. return OK;
  293. }
  294. /**
  295. * Configure specified soft key
  296. *
  297. * @v labnum soft label position to configure
  298. * @v *label string to use as soft key label
  299. * @v fmt justification format of label
  300. * @ret rc return status code
  301. */
  302. int slk_set ( int labnum, const char *label, int fmt ) {
  303. if ( slks == NULL )
  304. return ERR;
  305. if ( (unsigned short)labnum >= slks->num_labels )
  306. return ERR;
  307. if ( (unsigned short)fmt >= 3 )
  308. return ERR;
  309. strncpy(slks->fkeys[labnum].label, label,
  310. (sizeof(slks->fkeys[labnum].label) - 1));
  311. slks->fkeys[labnum].fmt = fmt;
  312. return OK;
  313. }