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