iPXE
slk.c
Go to the documentation of this file.
00001 #include <curses.h>
00002 #include <stddef.h>
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <assert.h>
00006 #include "mucurses.h"
00007 #include "cursor.h"
00008 
00009 /** @file
00010  *
00011  * Soft label key functions
00012  */
00013 
00014 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00015 
00016 #define MIN_SPACE_SIZE 2
00017 
00018 #define SLK_MAX_LABEL_LEN 8
00019 
00020 #define SLK_MAX_NUM_LABELS 12
00021 
00022 #define SLK_MAX_NUM_SPACES 2
00023 
00024 struct _softlabel {
00025         // label string
00026         char label[SLK_MAX_LABEL_LEN];
00027         /* Format of soft label 
00028            0: left justify
00029            1: centre justify
00030            2: right justify
00031          */
00032         unsigned int fmt;
00033 };
00034 
00035 struct _softlabelkeys {
00036         struct _softlabel fkeys[SLK_MAX_NUM_LABELS];
00037         attr_t attrs;
00038         /* Soft label layout format
00039            0: 3-2-3
00040            1: 4-4
00041            2: 4-4-4
00042            3: 4-4-4 with index line
00043         */
00044         unsigned int fmt;
00045         unsigned int max_label_len;
00046         unsigned int maj_space_len;
00047         unsigned int num_labels;
00048         unsigned int num_spaces;
00049         unsigned int spaces[SLK_MAX_NUM_SPACES];
00050         struct cursor_pos saved_cursor;
00051         attr_t saved_attrs;
00052         short saved_pair;
00053 };
00054 
00055 static struct _softlabelkeys *slks;
00056 
00057 /*
00058   I either need to break the primitives here, or write a collection of
00059   functions specifically for SLKs that directly access the screen
00060   functions - since this technically isn't part of stdscr, I think
00061   this should be ok...
00062  */
00063 
00064 static void _enter_slk ( void ) {
00065         _store_curs_pos ( stdscr, &slks->saved_cursor );
00066         wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL );
00067         LINES++;
00068         wmove ( stdscr, LINES, 0 );
00069         wattrset ( stdscr, slks->attrs );
00070 }
00071 
00072 static void _leave_slk ( void ) {
00073         LINES--;
00074         wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL );
00075         _restore_curs_pos ( stdscr, &slks->saved_cursor );
00076 }
00077 
00078 static void _print_label ( struct _softlabel sl ) {
00079         int space_ch;
00080         char str[SLK_MAX_LABEL_LEN + 1];
00081 
00082         assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN );
00083         space_ch = ' ';
00084         memset ( str, 0, sizeof ( str ) );
00085 
00086         // protect against gaps in the soft label keys array
00087         if ( ! sl.label[0] ) {
00088                 memset( str, space_ch, (size_t)(slks->max_label_len) );
00089         } else {
00090                 /* we need to pad the label with varying amounts of leading
00091                    pad depending on the format of the label */
00092                 if ( sl.fmt == 1 ) {
00093                         memset( str, space_ch, 
00094                                 (size_t)(slks->max_label_len 
00095                                          - strlen(sl.label)) / 2 );
00096                 }
00097                 if ( sl.fmt == 2 ) {
00098                         memset( str, space_ch,
00099                                 (size_t)(slks->max_label_len 
00100                                          - strlen(sl.label)) );
00101                 }
00102                 strcat(str,sl.label);
00103                 
00104                 // post-padding
00105                 memset(str+strlen(str), space_ch,
00106                        (size_t)(slks->max_label_len - strlen(str)) );
00107         }
00108 
00109         // print the formatted label
00110         _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
00111 }
00112 
00113 /**
00114  * Return the attribute used for the soft function keys
00115  *
00116  * @ret attrs   the current attributes of the soft function keys
00117  */
00118 attr_t slk_attr ( void ) {
00119         return ( slks == NULL ? 0 : slks->attrs );
00120 }
00121 
00122 /**
00123  * Turn off soft function key attributes
00124  *
00125  * @v attrs     attribute bit mask
00126  * @ret rc      return status code
00127  */
00128 int slk_attroff ( const chtype attrs ) {
00129         if ( slks == NULL ) 
00130                 return ERR;
00131         slks->attrs &= ~( attrs & A_ATTRIBUTES );
00132         return OK;
00133 }
00134 
00135 /**
00136  * Turn on soft function key attributes
00137  *
00138  * @v attrs     attribute bit mask
00139  * @ret rc      return status code
00140  */
00141 int slk_attron ( const chtype attrs ) {
00142         if ( slks == NULL )
00143                 return ERR;
00144         slks->attrs |= ( attrs & A_ATTRIBUTES );
00145         return OK;
00146 }
00147 
00148 /**
00149  * Set soft function key attributes
00150  *
00151  * @v attrs     attribute bit mask
00152  * @ret rc      return status code
00153  */
00154 int slk_attrset ( const chtype attrs ) {
00155         if ( slks == NULL ) 
00156                 return ERR;
00157         slks->attrs = ( attrs & A_ATTRIBUTES );
00158         return OK;
00159 }
00160 
00161 /**
00162  * Turn off soft function key attributes
00163  *
00164  * @v attrs     attribute bit mask
00165  * @v *opts     undefined (for future implementation)
00166  * @ret rc      return status code
00167  */
00168 int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
00169         return slk_attroff( attrs );
00170 }
00171 
00172 /**
00173  * Turn on soft function key attributes
00174  *
00175  * @v attrs     attribute bit mask
00176  * @v *opts     undefined (for future implementation)
00177  * @ret rc      return status code
00178  */
00179 int slk_attr_on ( attr_t attrs, void *opts __unused ) {
00180         return slk_attron( attrs );
00181 }
00182 
00183 /**
00184  * Set soft function key attributes
00185  *
00186  * @v attrs                     attribute bit mask
00187  * @v colour_pair_number        colour pair integer
00188  * @v *opts                     undefined (for future implementation)
00189  * @ret rc                      return status code
00190  */
00191 int slk_attr_set ( const attr_t attrs, short colour_pair_number,
00192                    void *opts __unused ) {
00193         if ( slks == NULL ) 
00194                 return ERR;
00195 
00196         if ( ( unsigned short )colour_pair_number > COLORS )
00197                 return ERR;
00198 
00199         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
00200                 ( attrs & A_ATTRIBUTES );
00201         return OK;
00202 }
00203 
00204 /**
00205  * Clear the soft function key labels from the screen
00206  *
00207  * @ret rc      return status code
00208  */
00209 int slk_clear ( void ) {
00210         if ( slks == NULL )
00211                 return ERR;
00212 
00213         _enter_slk();
00214         wclrtoeol ( stdscr );
00215         _leave_slk();
00216 
00217         return OK;
00218 }
00219 
00220 /**
00221  * Set soft label colour pair
00222  */
00223 int slk_colour ( short colour_pair_number ) {
00224         if ( slks == NULL ) 
00225                 return ERR;
00226         if ( ( unsigned short )colour_pair_number > COLORS )
00227                 return ERR;
00228 
00229         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
00230                 | ( slks->attrs & A_ATTRIBUTES );
00231 
00232         return OK;
00233 }
00234 
00235 /**
00236  * Initialise the soft function keys
00237  *
00238  * @v fmt       format of keys
00239  * @ret rc      return status code
00240  */
00241 int slk_init ( int fmt ) {
00242         unsigned short nmaj, nmin, nblocks, available_width;
00243 
00244         if ( (unsigned)fmt > 3 ) {
00245                 return ERR;
00246         }
00247 
00248         /* There seems to be no API call to free this data structure... */
00249         if ( ! slks )
00250                 slks = calloc(1,sizeof(*slks));
00251         if ( ! slks )
00252                 return ERR;
00253 
00254         slks->attrs = A_DEFAULT;
00255         slks->fmt = fmt;
00256         switch(fmt) {
00257         case 0:
00258                 nblocks = 8; nmaj = 2; nmin = 5;
00259                 slks->spaces[0] = 2; slks->spaces[1] = 4;
00260                 break;
00261         case 1:
00262                 nblocks = 8; nmaj = 1; nmin = 6;
00263                 slks->spaces[0] = 3;
00264                 break;
00265         case 2:
00266                 // same allocations as format 3
00267         case 3:
00268                 nblocks = 12; nmaj = 2; nmin = 9;
00269                 slks->spaces[0] = 3; slks->spaces[1] = 7;
00270                 break;
00271         default:
00272                 return ERR;
00273         }
00274 
00275         // determine maximum label length and major space size
00276         available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
00277         slks->max_label_len = available_width / nblocks;
00278         slks->maj_space_len = MIN_SPACE_SIZE + 
00279                 ( available_width % nblocks ) / nmaj;
00280         slks->num_spaces = nmaj;
00281         slks->num_labels = nblocks;
00282 
00283         // strip a line from the screen
00284         LINES -= 1;
00285 
00286         return OK;
00287 }
00288 
00289 /**
00290  * Return the label for the specified soft key
00291  *
00292  * @v labnum    soft key identifier
00293  * @ret label   return label
00294  */
00295 char* slk_label ( int labnum ) {
00296         if ( slks == NULL ) 
00297                 return NULL;
00298 
00299         return slks->fkeys[labnum].label;
00300 }
00301 
00302 /**
00303  * Restore soft function key labels to the screen
00304  *
00305  * @ret rc      return status code
00306  */
00307 int slk_restore ( void ) {
00308         unsigned int i, j, pos_x,
00309                 *next_space, *last_space;
00310         chtype space_ch;
00311 
00312         if ( slks == NULL )
00313                 return ERR;
00314 
00315         pos_x = 0;
00316 
00317         _enter_slk();
00318 
00319         space_ch = (chtype)' ' | slks->attrs;
00320         next_space = &(slks->spaces[0]);
00321         last_space = &(slks->spaces[slks->num_spaces-1]);
00322 
00323         for ( i = 0; i < slks->num_labels ; i++ ) {
00324                 _print_label( slks->fkeys[i] );
00325                 pos_x += slks->max_label_len;
00326 
00327                 if ( i == *next_space ) {
00328                         for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
00329                                 _wputch ( stdscr, space_ch, NOWRAP );
00330                         if ( next_space < last_space )
00331                                 next_space++;
00332                 } else {
00333                         if ( pos_x < COLS )
00334                                 _wputch ( stdscr, space_ch, NOWRAP );
00335                         pos_x++;
00336                 }
00337         }
00338 
00339         _leave_slk();
00340 
00341         return OK;
00342 }
00343 
00344 /**
00345  * Configure specified soft key
00346  *
00347  * @v labnum    soft label position to configure
00348  * @v *label    string to use as soft key label
00349  * @v fmt       justification format of label
00350  * @ret rc      return status code
00351  */
00352 int slk_set ( int labnum, const char *label, int fmt ) {
00353         if ( slks == NULL ) 
00354                 return ERR;
00355         if ( (unsigned short)labnum >= slks->num_labels )
00356                 return ERR;
00357         if ( (unsigned short)fmt >= 3 )
00358                 return ERR;
00359 
00360         strncpy(slks->fkeys[labnum].label, label,
00361                 (sizeof(slks->fkeys[labnum].label) - 1));
00362         slks->fkeys[labnum].fmt = fmt;
00363 
00364         return OK;
00365 }