| #include <curses.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <assert.h> |
| #include "mucurses.h" |
| #include "cursor.h" |
| |
| /** @file |
| * |
| * Soft label key functions |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| #define MIN_SPACE_SIZE 2 |
| |
| #define SLK_MAX_LABEL_LEN 8 |
| |
| #define SLK_MAX_NUM_LABELS 12 |
| |
| #define SLK_MAX_NUM_SPACES 2 |
| |
| struct _softlabel { |
| // label string |
| char label[SLK_MAX_LABEL_LEN]; |
| /* Format of soft label |
| 0: left justify |
| 1: centre justify |
| 2: right justify |
| */ |
| unsigned int fmt; |
| }; |
| |
| struct _softlabelkeys { |
| struct _softlabel fkeys[SLK_MAX_NUM_LABELS]; |
| attr_t attrs; |
| /* Soft label layout format |
| 0: 3-2-3 |
| 1: 4-4 |
| 2: 4-4-4 |
| 3: 4-4-4 with index line |
| */ |
| unsigned int fmt; |
| unsigned int max_label_len; |
| unsigned int maj_space_len; |
| unsigned int num_labels; |
| unsigned int num_spaces; |
| unsigned int spaces[SLK_MAX_NUM_SPACES]; |
| struct cursor_pos saved_cursor; |
| attr_t saved_attrs; |
| short saved_pair; |
| }; |
| |
| static struct _softlabelkeys *slks; |
| |
| /* |
| I either need to break the primitives here, or write a collection of |
| functions specifically for SLKs that directly access the screen |
| functions - since this technically isn't part of stdscr, I think |
| this should be ok... |
| */ |
| |
| static void _enter_slk ( void ) { |
| _store_curs_pos ( stdscr, &slks->saved_cursor ); |
| wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL ); |
| LINES++; |
| wmove ( stdscr, LINES, 0 ); |
| wattrset ( stdscr, slks->attrs ); |
| } |
| |
| static void _leave_slk ( void ) { |
| LINES--; |
| wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL ); |
| _restore_curs_pos ( stdscr, &slks->saved_cursor ); |
| } |
| |
| static void _print_label ( struct _softlabel sl ) { |
| int space_ch; |
| char str[SLK_MAX_LABEL_LEN + 1]; |
| |
| assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN ); |
| space_ch = ' '; |
| memset ( str, 0, sizeof ( str ) ); |
| |
| // protect against gaps in the soft label keys array |
| if ( ! sl.label[0] ) { |
| memset( str, space_ch, (size_t)(slks->max_label_len) ); |
| } else { |
| /* we need to pad the label with varying amounts of leading |
| pad depending on the format of the label */ |
| if ( sl.fmt == 1 ) { |
| memset( str, space_ch, |
| (size_t)(slks->max_label_len |
| - strlen(sl.label)) / 2 ); |
| } |
| if ( sl.fmt == 2 ) { |
| memset( str, space_ch, |
| (size_t)(slks->max_label_len |
| - strlen(sl.label)) ); |
| } |
| strcat(str,sl.label); |
| |
| // post-padding |
| memset(str+strlen(str), space_ch, |
| (size_t)(slks->max_label_len - strlen(str)) ); |
| } |
| |
| // print the formatted label |
| _wputstr ( stdscr, str, NOWRAP, slks->max_label_len ); |
| } |
| |
| /** |
| * Return the attribute used for the soft function keys |
| * |
| * @ret attrs the current attributes of the soft function keys |
| */ |
| attr_t slk_attr ( void ) { |
| return ( slks == NULL ? 0 : slks->attrs ); |
| } |
| |
| /** |
| * Turn off soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @ret rc return status code |
| */ |
| int slk_attroff ( const chtype attrs ) { |
| if ( slks == NULL ) |
| return ERR; |
| slks->attrs &= ~( attrs & A_ATTRIBUTES ); |
| return OK; |
| } |
| |
| /** |
| * Turn on soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @ret rc return status code |
| */ |
| int slk_attron ( const chtype attrs ) { |
| if ( slks == NULL ) |
| return ERR; |
| slks->attrs |= ( attrs & A_ATTRIBUTES ); |
| return OK; |
| } |
| |
| /** |
| * Set soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @ret rc return status code |
| */ |
| int slk_attrset ( const chtype attrs ) { |
| if ( slks == NULL ) |
| return ERR; |
| slks->attrs = ( attrs & A_ATTRIBUTES ); |
| return OK; |
| } |
| |
| /** |
| * Turn off soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @v *opts undefined (for future implementation) |
| * @ret rc return status code |
| */ |
| int slk_attr_off ( const attr_t attrs, void *opts __unused ) { |
| return slk_attroff( attrs ); |
| } |
| |
| /** |
| * Turn on soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @v *opts undefined (for future implementation) |
| * @ret rc return status code |
| */ |
| int slk_attr_on ( attr_t attrs, void *opts __unused ) { |
| return slk_attron( attrs ); |
| } |
| |
| /** |
| * Set soft function key attributes |
| * |
| * @v attrs attribute bit mask |
| * @v colour_pair_number colour pair integer |
| * @v *opts undefined (for future implementation) |
| * @ret rc return status code |
| */ |
| int slk_attr_set ( const attr_t attrs, short colour_pair_number, |
| void *opts __unused ) { |
| if ( slks == NULL ) |
| return ERR; |
| |
| if ( ( unsigned short )colour_pair_number > COLORS ) |
| return ERR; |
| |
| slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) | |
| ( attrs & A_ATTRIBUTES ); |
| return OK; |
| } |
| |
| /** |
| * Clear the soft function key labels from the screen |
| * |
| * @ret rc return status code |
| */ |
| int slk_clear ( void ) { |
| if ( slks == NULL ) |
| return ERR; |
| |
| _enter_slk(); |
| wclrtoeol ( stdscr ); |
| _leave_slk(); |
| |
| return OK; |
| } |
| |
| /** |
| * Set soft label colour pair |
| */ |
| int slk_colour ( short colour_pair_number ) { |
| if ( slks == NULL ) |
| return ERR; |
| if ( ( unsigned short )colour_pair_number > COLORS ) |
| return ERR; |
| |
| slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
| | ( slks->attrs & A_ATTRIBUTES ); |
| |
| return OK; |
| } |
| |
| /** |
| * Initialise the soft function keys |
| * |
| * @v fmt format of keys |
| * @ret rc return status code |
| */ |
| int slk_init ( int fmt ) { |
| unsigned short nmaj, nmin, nblocks, available_width; |
| |
| if ( (unsigned)fmt > 3 ) { |
| return ERR; |
| } |
| |
| /* There seems to be no API call to free this data structure... */ |
| if ( ! slks ) |
| slks = calloc(1,sizeof(*slks)); |
| if ( ! slks ) |
| return ERR; |
| |
| slks->attrs = A_DEFAULT; |
| slks->fmt = fmt; |
| switch(fmt) { |
| case 0: |
| nblocks = 8; nmaj = 2; nmin = 5; |
| slks->spaces[0] = 2; slks->spaces[1] = 4; |
| break; |
| case 1: |
| nblocks = 8; nmaj = 1; nmin = 6; |
| slks->spaces[0] = 3; |
| break; |
| case 2: |
| // same allocations as format 3 |
| case 3: |
| nblocks = 12; nmaj = 2; nmin = 9; |
| slks->spaces[0] = 3; slks->spaces[1] = 7; |
| break; |
| default: |
| return ERR; |
| } |
| |
| // determine maximum label length and major space size |
| available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin ); |
| slks->max_label_len = available_width / nblocks; |
| slks->maj_space_len = MIN_SPACE_SIZE + |
| ( available_width % nblocks ) / nmaj; |
| slks->num_spaces = nmaj; |
| slks->num_labels = nblocks; |
| |
| // strip a line from the screen |
| LINES -= 1; |
| |
| return OK; |
| } |
| |
| /** |
| * Return the label for the specified soft key |
| * |
| * @v labnum soft key identifier |
| * @ret label return label |
| */ |
| char* slk_label ( int labnum ) { |
| if ( slks == NULL ) |
| return NULL; |
| |
| return slks->fkeys[labnum].label; |
| } |
| |
| /** |
| * Restore soft function key labels to the screen |
| * |
| * @ret rc return status code |
| */ |
| int slk_restore ( void ) { |
| unsigned int i, j, pos_x, |
| *next_space, *last_space; |
| chtype space_ch; |
| |
| if ( slks == NULL ) |
| return ERR; |
| |
| pos_x = 0; |
| |
| _enter_slk(); |
| |
| space_ch = (chtype)' ' | slks->attrs; |
| next_space = &(slks->spaces[0]); |
| last_space = &(slks->spaces[slks->num_spaces-1]); |
| |
| for ( i = 0; i < slks->num_labels ; i++ ) { |
| _print_label( slks->fkeys[i] ); |
| pos_x += slks->max_label_len; |
| |
| if ( i == *next_space ) { |
| for ( j = 0; j < slks->maj_space_len; j++, pos_x++ ) |
| _wputch ( stdscr, space_ch, NOWRAP ); |
| if ( next_space < last_space ) |
| next_space++; |
| } else { |
| if ( pos_x < COLS ) |
| _wputch ( stdscr, space_ch, NOWRAP ); |
| pos_x++; |
| } |
| } |
| |
| _leave_slk(); |
| |
| return OK; |
| } |
| |
| /** |
| * Configure specified soft key |
| * |
| * @v labnum soft label position to configure |
| * @v *label string to use as soft key label |
| * @v fmt justification format of label |
| * @ret rc return status code |
| */ |
| int slk_set ( int labnum, const char *label, int fmt ) { |
| if ( slks == NULL ) |
| return ERR; |
| if ( (unsigned short)labnum >= slks->num_labels ) |
| return ERR; |
| if ( (unsigned short)fmt >= 3 ) |
| return ERR; |
| |
| strncpy(slks->fkeys[labnum].label, label, |
| (sizeof(slks->fkeys[labnum].label) - 1)); |
| slks->fkeys[labnum].fmt = fmt; |
| |
| return OK; |
| } |