These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / hci / mucurses / slk.c
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 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
15
16 #define MIN_SPACE_SIZE 2
17
18 #define SLK_MAX_LABEL_LEN 8
19
20 #define SLK_MAX_NUM_LABELS 12
21
22 #define SLK_MAX_NUM_SPACES 2
23
24 struct _softlabel {
25         // label string
26         char label[SLK_MAX_LABEL_LEN];
27         /* Format of soft label 
28            0: left justify
29            1: centre justify
30            2: right justify
31          */
32         unsigned int fmt;
33 };
34
35 struct _softlabelkeys {
36         struct _softlabel fkeys[SLK_MAX_NUM_LABELS];
37         attr_t attrs;
38         /* Soft label layout format
39            0: 3-2-3
40            1: 4-4
41            2: 4-4-4
42            3: 4-4-4 with index line
43         */
44         unsigned int fmt;
45         unsigned int max_label_len;
46         unsigned int maj_space_len;
47         unsigned int num_labels;
48         unsigned int num_spaces;
49         unsigned int spaces[SLK_MAX_NUM_SPACES];
50         struct cursor_pos saved_cursor;
51         attr_t saved_attrs;
52         short saved_pair;
53 };
54
55 static struct _softlabelkeys *slks;
56
57 /*
58   I either need to break the primitives here, or write a collection of
59   functions specifically for SLKs that directly access the screen
60   functions - since this technically isn't part of stdscr, I think
61   this should be ok...
62  */
63
64 static void _enter_slk ( void ) {
65         _store_curs_pos ( stdscr, &slks->saved_cursor );
66         wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL );
67         LINES++;
68         wmove ( stdscr, LINES, 0 );
69         wattrset ( stdscr, slks->attrs );
70 }
71
72 static void _leave_slk ( void ) {
73         LINES--;
74         wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL );
75         _restore_curs_pos ( stdscr, &slks->saved_cursor );
76 }
77
78 static void _print_label ( struct _softlabel sl ) {
79         int space_ch;
80         char str[SLK_MAX_LABEL_LEN + 1];
81
82         assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN );
83         space_ch = ' ';
84
85         // protect against gaps in the soft label keys array
86         if ( sl.label == NULL ) {
87                 memset( str, space_ch, (size_t)(slks->max_label_len) );
88         } else {
89                 /* we need to pad the label with varying amounts of leading
90                    pad depending on the format of the label */
91                 if ( sl.fmt == 1 ) {
92                         memset( str, space_ch, 
93                                 (size_t)(slks->max_label_len 
94                                          - strlen(sl.label)) / 2 );
95                 }
96                 if ( sl.fmt == 2 ) {
97                         memset( str, space_ch,
98                                 (size_t)(slks->max_label_len 
99                                          - strlen(sl.label)) );
100                 }
101                 strcat(str,sl.label);
102                 
103                 // post-padding
104                 memset(str+strlen(str), space_ch,
105                        (size_t)(slks->max_label_len - strlen(str)) );
106         }
107
108         // print the formatted label
109         _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
110 }
111
112 /**
113  * Return the attribute used for the soft function keys
114  *
115  * @ret attrs   the current attributes of the soft function keys
116  */
117 attr_t slk_attr ( void ) {
118         return ( slks == NULL ? 0 : slks->attrs );
119 }
120
121 /**
122  * Turn off soft function key attributes
123  *
124  * @v attrs     attribute bit mask
125  * @ret rc      return status code
126  */
127 int slk_attroff ( const chtype attrs ) {
128         if ( slks == NULL ) 
129                 return ERR;
130         slks->attrs &= ~( attrs & A_ATTRIBUTES );
131         return OK;
132 }
133
134 /**
135  * Turn on soft function key attributes
136  *
137  * @v attrs     attribute bit mask
138  * @ret rc      return status code
139  */
140 int slk_attron ( const chtype attrs ) {
141         if ( slks == NULL )
142                 return ERR;
143         slks->attrs |= ( attrs & A_ATTRIBUTES );
144         return OK;
145 }
146
147 /**
148  * Set soft function key attributes
149  *
150  * @v attrs     attribute bit mask
151  * @ret rc      return status code
152  */
153 int slk_attrset ( const chtype attrs ) {
154         if ( slks == NULL ) 
155                 return ERR;
156         slks->attrs = ( attrs & A_ATTRIBUTES );
157         return OK;
158 }
159
160 /**
161  * Turn off soft function key attributes
162  *
163  * @v attrs     attribute bit mask
164  * @v *opts     undefined (for future implementation)
165  * @ret rc      return status code
166  */
167 int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
168         return slk_attroff( attrs );
169 }
170
171 /**
172  * Turn on soft function key attributes
173  *
174  * @v attrs     attribute bit mask
175  * @v *opts     undefined (for future implementation)
176  * @ret rc      return status code
177  */
178 int slk_attr_on ( attr_t attrs, void *opts __unused ) {
179         return slk_attron( attrs );
180 }
181
182 /**
183  * Set soft function key attributes
184  *
185  * @v attrs                     attribute bit mask
186  * @v colour_pair_number        colour pair integer
187  * @v *opts                     undefined (for future implementation)
188  * @ret rc                      return status code
189  */
190 int slk_attr_set ( const attr_t attrs, short colour_pair_number,
191                    void *opts __unused ) {
192         if ( slks == NULL ) 
193                 return ERR;
194
195         if ( ( unsigned short )colour_pair_number > COLORS )
196                 return ERR;
197
198         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
199                 ( attrs & A_ATTRIBUTES );
200         return OK;
201 }
202
203 /**
204  * Clear the soft function key labels from the screen
205  *
206  * @ret rc      return status code
207  */
208 int slk_clear ( void ) {
209         if ( slks == NULL )
210                 return ERR;
211
212         _enter_slk();
213         wclrtoeol ( stdscr );
214         _leave_slk();
215
216         return OK;
217 }
218
219 /**
220  * Set soft label colour pair
221  */
222 int slk_colour ( short colour_pair_number ) {
223         if ( slks == NULL ) 
224                 return ERR;
225         if ( ( unsigned short )colour_pair_number > COLORS )
226                 return ERR;
227
228         slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
229                 | ( slks->attrs & A_ATTRIBUTES );
230
231         return OK;
232 }
233
234 /**
235  * Initialise the soft function keys
236  *
237  * @v fmt       format of keys
238  * @ret rc      return status code
239  */
240 int slk_init ( int fmt ) {
241         unsigned short nmaj, nmin, nblocks, available_width;
242
243         if ( (unsigned)fmt > 3 ) {
244                 return ERR;
245         }
246
247         /* There seems to be no API call to free this data structure... */
248         if ( ! slks )
249                 slks = calloc(1,sizeof(*slks));
250         if ( ! slks )
251                 return ERR;
252
253         slks->attrs = A_DEFAULT;
254         slks->fmt = fmt;
255         switch(fmt) {
256         case 0:
257                 nblocks = 8; nmaj = 2; nmin = 5;
258                 slks->spaces[0] = 2; slks->spaces[1] = 4;
259                 break;
260         case 1:
261                 nblocks = 8; nmaj = 1; nmin = 6;
262                 slks->spaces[0] = 3;
263                 break;
264         case 2:
265                 // same allocations as format 3
266         case 3:
267                 nblocks = 12; nmaj = 2; nmin = 9;
268                 slks->spaces[0] = 3; slks->spaces[1] = 7;
269                 break;
270         default:
271                 nblocks = 0; nmaj = 0; nmin = 0;
272                 break;
273         }
274
275         // determine maximum label length and major space size
276         available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
277         slks->max_label_len = available_width / nblocks;
278         slks->maj_space_len = MIN_SPACE_SIZE + 
279                 ( available_width % nblocks ) / nmaj;
280         slks->num_spaces = nmaj;
281         slks->num_labels = nblocks;
282
283         // strip a line from the screen
284         LINES -= 1;
285
286         return OK;
287 }
288
289 /**
290  * Return the label for the specified soft key
291  *
292  * @v labnum    soft key identifier
293  * @ret label   return label
294  */
295 char* slk_label ( int labnum ) {
296         if ( slks == NULL ) 
297                 return NULL;
298
299         return slks->fkeys[labnum].label;
300 }
301
302 /**
303  * Restore soft function key labels to the screen
304  *
305  * @ret rc      return status code
306  */
307 int slk_restore ( void ) {
308         unsigned int i, j, pos_x,
309                 *next_space, *last_space;
310         chtype space_ch;
311
312         if ( slks == NULL )
313                 return ERR;
314
315         pos_x = 0;
316
317         _enter_slk();
318
319         space_ch = (chtype)' ' | slks->attrs;
320         next_space = &(slks->spaces[0]);
321         last_space = &(slks->spaces[slks->num_spaces-1]);
322
323         for ( i = 0; i < slks->num_labels ; i++ ) {
324                 _print_label( slks->fkeys[i] );
325                 pos_x += slks->max_label_len;
326
327                 if ( i == *next_space ) {
328                         for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
329                                 _wputch ( stdscr, space_ch, NOWRAP );
330                         if ( next_space < last_space )
331                                 next_space++;
332                 } else {
333                         if ( pos_x < COLS )
334                                 _wputch ( stdscr, space_ch, NOWRAP );
335                         pos_x++;
336                 }
337         }
338
339         _leave_slk();
340
341         return OK;
342 }
343
344 /**
345  * Configure specified soft key
346  *
347  * @v labnum    soft label position to configure
348  * @v *label    string to use as soft key label
349  * @v fmt       justification format of label
350  * @ret rc      return status code
351  */
352 int slk_set ( int labnum, const char *label, int fmt ) {
353         if ( slks == NULL ) 
354                 return ERR;
355         if ( (unsigned short)labnum >= slks->num_labels )
356                 return ERR;
357         if ( (unsigned short)fmt >= 3 )
358                 return ERR;
359
360         strncpy(slks->fkeys[labnum].label, label,
361                 sizeof(slks->fkeys[labnum].label));
362         slks->fkeys[labnum].fmt = fmt;
363
364         return OK;
365 }