41ef9abb9513141db20f94b69087d9edfd5d7e80
[people/xl0/gpxe.git] / src / hci / mucurses / slk.c
1 #include <curses.h>
2 #include <stddef.h>
3 #include <malloc.h>
4 #include <string.h>
5 #include "core.h"
6
7 /** @file
8  *
9  * Soft label key functions
10  */
11
12 #define MIN_SPACE_SIZE 2
13
14 struct _softlabel {
15         // label string
16         char *label;
17         /* Format of soft label 
18            0: left justify
19            1: centre justify
20            2: right justify
21          */
22         unsigned short fmt;
23 };
24
25 struct _softlabelkeys {
26         struct _softlabel fkeys[12];
27         attr_t attrs;
28         /* Soft label layout format
29            0: 3-2-3
30            1: 4-4
31            2: 4-4-4
32            3: 4-4-4 with index line
33         */
34         unsigned short fmt;
35         unsigned short max_label_len;
36         unsigned short maj_space_len;
37         unsigned short num_labels;
38         unsigned short num_spaces;
39         unsigned short *spaces;
40 };
41
42 struct _softlabelkeys *slks;
43
44 /*
45   I either need to break the primitives here, or write a collection of
46   functions specifically for SLKs that directly access the screen
47   functions - since this technically isn't part of stdscr, I think
48   this should be ok...
49  */
50
51 static void _movetoslk ( void ) {
52         stdscr->scr->movetoyx( stdscr->scr, LINES, 0 );
53 }
54
55 /**
56  * Return the attribute used for the soft function keys
57  *
58  * @ret attrs   the current attributes of the soft function keys
59  */
60 attr_t slk_attr ( void ) {
61         return ( slks == NULL ? 0 : slks->attrs );
62 }
63
64 /**
65  * Turn off soft function key attributes
66  *
67  * @v attrs     attribute bit mask
68  * @ret rc      return status code
69  */
70 int slk_attroff ( const chtype attrs ) {
71         if ( slks == NULL ) 
72                 return ERR;
73         slks->attrs &= ~( attrs & A_ATTRIBUTES );
74         return OK;
75 }
76
77 /**
78  * Turn on soft function key attributes
79  *
80  * @v attrs     attribute bit mask
81  * @ret rc      return status code
82  */
83 int slk_attron ( const chtype attrs ) {
84         if ( slks == NULL )
85                 return ERR;
86         slks->attrs |= ( attrs & A_ATTRIBUTES );
87         return OK;
88 }
89
90 /**
91  * Set soft function key attributes
92  *
93  * @v attrs     attribute bit mask
94  * @ret rc      return status code
95  */
96 int slk_attrset ( const chtype attrs ) {
97         if ( slks == NULL ) 
98                 return ERR;
99         slks->attrs = ( attrs & A_ATTRIBUTES );
100         return OK;
101 }
102
103 /**
104  * Turn off soft function key attributes
105  *
106  * @v attrs     attribute bit mask
107  * @v *opts     undefined (for future implementation)
108  * @ret rc      return status code
109  */
110 int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
111         return slk_attroff( attrs );
112 }
113
114 /**
115  * Turn on soft function key attributes
116  *
117  * @v attrs     attribute bit mask
118  * @v *opts     undefined (for future implementation)
119  * @ret rc      return status code
120  */
121 int slk_attr_on ( attr_t attrs, void *opts __unused ) {
122         return slk_attron( attrs );
123 }
124
125 /**
126  * Set soft function key attributes
127  *
128  * @v attrs                     attribute bit mask
129  * @v colour_pair_number        colour pair integer
130  * @v *opts                     undefined (for future implementation)
131  * @ret rc                      return status code
132  */
133 int slk_attr_set ( const attr_t attrs, short colour_pair_number,
134                    void *opts __unused ) {
135         if ( slks == NULL ) 
136                 return ERR;
137
138         if ( ( unsigned short )colour_pair_number > COLORS )
139                 return ERR;
140
141         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
142                 ( attrs & A_ATTRIBUTES );
143         return OK;
144 }
145
146 /**
147  * Clear the soft function key labels from the screen
148  *
149  * @ret rc      return status code
150  */
151 int slk_clear ( void ) {
152         if ( slks == NULL )
153                 return ERR;
154         return 0;
155 }
156
157 /**
158  * Set soft label colour pair
159  */
160 int slk_colour ( short colour_pair_number ) {
161         if ( slks == NULL ) 
162                 return ERR;
163         if ( ( unsigned short )colour_pair_number > COLORS )
164                 return ERR;
165
166         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
167                 | ( slks->attrs & A_ATTRIBUTES );
168
169         return OK;
170 }
171
172 /**
173  * Initialise the soft function keys
174  *
175  * @v fmt       format of keys
176  * @ret rc      return status code
177  */
178 int slk_init ( int fmt ) {
179         unsigned short nmaj, nmin, nblocks, available_width;
180
181         if ( (unsigned)fmt > 3 ) {
182                 return ERR;
183         }
184
185         slks = malloc(sizeof(struct _softlabelkeys));
186         slks->attrs = A_DEFAULT;
187         slks->fmt = fmt;
188         switch(fmt) {
189         case 0:
190                 nblocks = 8; nmaj = 2; nmin = 5;
191                 slks->spaces = calloc(2, sizeof(unsigned short));
192                 slks->spaces[0] = 2; slks->spaces[1] = 4;
193                 break;
194         case 1:
195                 nblocks = 8; nmaj = 1; nmin = 6;
196                 slks->spaces = calloc(1, sizeof(unsigned short));
197                 slks->spaces[0] = 3;
198                 break;
199         case 2:
200                 // same allocations as format 3
201         case 3:
202                 nblocks = 12; nmaj = 2; nmin = 9;
203                 slks->spaces = calloc(2, sizeof(unsigned short));
204                 slks->spaces[0] = 3; slks->spaces[1] = 7;
205                 break;
206         }
207
208         // determine maximum label length and major space size
209         available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
210         slks->max_label_len = available_width / nblocks;
211         slks->maj_space_len = ( available_width % nblocks ) / nmaj;
212         slks->num_spaces = nmaj;
213
214         // strip a line from the screen
215         LINES -= 1;
216
217         return OK;
218 }
219
220 /**
221  * Return the label for the specified soft key
222  *
223  * @v labnum    soft key identifier
224  * @ret label   return label
225  */
226 char* slk_label ( int labnum ) {
227         if ( slks == NULL ) 
228                 return NULL;
229
230         return slks->fkeys[labnum].label;
231 }
232
233 /**
234  * Restore soft function key labels to the screen
235  *
236  * @ret rc      return status code
237  */
238 int slk_restore ( void ) {
239         unsigned short i, j,
240                 *next_space, *last_space;
241         chtype space_ch;
242         char c;
243
244         if ( slks == NULL ) 
245                 return ERR;
246
247         _movetoslk();
248
249         space_ch = (int)' ' | slks->attrs;
250         next_space = &(slks->spaces[0]);
251         last_space = &(slks->spaces[slks->num_spaces-1]);
252
253         for ( i = 0; i < slks->num_labels ; i++ ) {
254                 while ( ( c = *(slks->fkeys[i].label++) ) != '\0' ) {
255                         stdscr->scr->putc( stdscr->scr, (int)c | slks->attrs );
256                 }
257                 if ( i == *next_space ) {
258                         for ( j = 0; j < slks->maj_space_len; j++ )
259                                 stdscr->scr->putc( stdscr->scr, space_ch );
260                         if ( next_space < last_space )
261                                 next_space++;
262                 } else {
263                         stdscr->scr->putc( stdscr->scr, space_ch );
264                 }
265         }
266
267         return OK;
268 }
269
270 /**
271  * Configure specified soft key
272  *
273  * @v labnum    soft label position to configure
274  * @v *label    string to use as soft key label
275  * @v fmt       justification format of label
276  * @ret rc      return status code
277  */
278 int slk_set ( int labnum, const char *label, int fmt ) {
279         if ( slks == NULL ) 
280                 return ERR;
281         if ( (unsigned short)labnum > 12 )
282                 return ERR;
283         if ( (unsigned short)fmt >= 3 )
284                 return ERR;
285         if ( strlen(label) > slks->max_label_len )
286                 return ERR;
287
288         strcpy( slks->fkeys[labnum].label, label );
289         slks->fkeys[labnum].fmt = fmt;
290
291         return OK;
292 }