d20fd70d8c2d750ac6acc42f42ddbeaff69221ec
[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         default:
207                 nblocks = 0; nmaj = 0; nmin = 0;
208                 break;
209         }
210
211         // determine maximum label length and major space size
212         available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
213         slks->max_label_len = available_width / nblocks;
214         slks->maj_space_len = ( available_width % nblocks ) / nmaj;
215         slks->num_spaces = nmaj;
216
217         // strip a line from the screen
218         LINES -= 1;
219
220         return OK;
221 }
222
223 /**
224  * Return the label for the specified soft key
225  *
226  * @v labnum    soft key identifier
227  * @ret label   return label
228  */
229 char* slk_label ( int labnum ) {
230         if ( slks == NULL ) 
231                 return NULL;
232
233         return slks->fkeys[labnum].label;
234 }
235
236 /**
237  * Restore soft function key labels to the screen
238  *
239  * @ret rc      return status code
240  */
241 int slk_restore ( void ) {
242         unsigned short i, j,
243                 *next_space, *last_space;
244         chtype space_ch;
245         char c;
246
247         if ( slks == NULL ) 
248                 return ERR;
249
250         _movetoslk();
251
252         space_ch = (int)' ' | slks->attrs;
253         next_space = &(slks->spaces[0]);
254         last_space = &(slks->spaces[slks->num_spaces-1]);
255
256         for ( i = 0; i < slks->num_labels ; i++ ) {
257                 while ( ( c = *(slks->fkeys[i].label++) ) != '\0' ) {
258                         stdscr->scr->putc( stdscr->scr, (int)c | slks->attrs );
259                 }
260                 if ( i == *next_space ) {
261                         for ( j = 0; j < slks->maj_space_len; j++ )
262                                 stdscr->scr->putc( stdscr->scr, space_ch );
263                         if ( next_space < last_space )
264                                 next_space++;
265                 } else {
266                         stdscr->scr->putc( stdscr->scr, space_ch );
267                 }
268         }
269
270         return OK;
271 }
272
273 /**
274  * Configure specified soft key
275  *
276  * @v labnum    soft label position to configure
277  * @v *label    string to use as soft key label
278  * @v fmt       justification format of label
279  * @ret rc      return status code
280  */
281 int slk_set ( int labnum, const char *label, int fmt ) {
282         if ( slks == NULL ) 
283                 return ERR;
284         if ( (unsigned short)labnum > 12 )
285                 return ERR;
286         if ( (unsigned short)fmt >= 3 )
287                 return ERR;
288         if ( strlen(label) > slks->max_label_len )
289                 return ERR;
290
291         strcpy( slks->fkeys[labnum].label, label );
292         slks->fkeys[labnum].fmt = fmt;
293
294         return OK;
295 }