[e16e8f2] | 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 | } |
---|