Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / hci / mucurses / slk.c
diff --git a/qemu/roms/ipxe/src/hci/mucurses/slk.c b/qemu/roms/ipxe/src/hci/mucurses/slk.c
new file mode 100644 (file)
index 0000000..600658e
--- /dev/null
@@ -0,0 +1,363 @@
+#include <curses.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "mucurses.h"
+#include "cursor.h"
+
+/** @file
+ *
+ * Soft label key functions
+ */
+
+#define MIN_SPACE_SIZE 2
+
+#define SLK_MAX_LABEL_LEN 8
+
+#define SLK_MAX_NUM_LABELS 12
+
+#define SLK_MAX_NUM_SPACES 2
+
+struct _softlabel {
+       // label string
+       char label[SLK_MAX_LABEL_LEN];
+       /* Format of soft label 
+          0: left justify
+          1: centre justify
+          2: right justify
+        */
+       unsigned int fmt;
+};
+
+struct _softlabelkeys {
+       struct _softlabel fkeys[SLK_MAX_NUM_LABELS];
+       attr_t attrs;
+       /* Soft label layout format
+          0: 3-2-3
+          1: 4-4
+          2: 4-4-4
+          3: 4-4-4 with index line
+       */
+       unsigned int fmt;
+       unsigned int max_label_len;
+       unsigned int maj_space_len;
+       unsigned int num_labels;
+       unsigned int num_spaces;
+       unsigned int spaces[SLK_MAX_NUM_SPACES];
+       struct cursor_pos saved_cursor;
+       attr_t saved_attrs;
+       short saved_pair;
+};
+
+static struct _softlabelkeys *slks;
+
+/*
+  I either need to break the primitives here, or write a collection of
+  functions specifically for SLKs that directly access the screen
+  functions - since this technically isn't part of stdscr, I think
+  this should be ok...
+ */
+
+static void _enter_slk ( void ) {
+       _store_curs_pos ( stdscr, &slks->saved_cursor );
+       wattr_get ( stdscr, &slks->saved_attrs, &slks->saved_pair, NULL );
+       LINES++;
+       wmove ( stdscr, LINES, 0 );
+       wattrset ( stdscr, slks->attrs );
+}
+
+static void _leave_slk ( void ) {
+       LINES--;
+       wattr_set ( stdscr, slks->saved_attrs, slks->saved_pair, NULL );
+       _restore_curs_pos ( stdscr, &slks->saved_cursor );
+}
+
+static void _print_label ( struct _softlabel sl ) {
+       int space_ch;
+       char str[SLK_MAX_LABEL_LEN + 1];
+
+       assert ( slks->max_label_len <= SLK_MAX_LABEL_LEN );
+       space_ch = ' ';
+
+       // protect against gaps in the soft label keys array
+       if ( sl.label == NULL ) {
+               memset( str, space_ch, (size_t)(slks->max_label_len) );
+       } else {
+               /* we need to pad the label with varying amounts of leading
+                  pad depending on the format of the label */
+               if ( sl.fmt == 1 ) {
+                       memset( str, space_ch, 
+                               (size_t)(slks->max_label_len 
+                                        - strlen(sl.label)) / 2 );
+               }
+               if ( sl.fmt == 2 ) {
+                       memset( str, space_ch,
+                               (size_t)(slks->max_label_len 
+                                        - strlen(sl.label)) );
+               }
+               strcat(str,sl.label);
+               
+               // post-padding
+               memset(str+strlen(str), space_ch,
+                      (size_t)(slks->max_label_len - strlen(str)) );
+       }
+
+       // print the formatted label
+       _wputstr ( stdscr, str, NOWRAP, slks->max_label_len );
+}
+
+/**
+ * Return the attribute used for the soft function keys
+ *
+ * @ret attrs  the current attributes of the soft function keys
+ */
+attr_t slk_attr ( void ) {
+       return ( slks == NULL ? 0 : slks->attrs );
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs    attribute bit mask
+ * @ret rc     return status code
+ */
+int slk_attroff ( const chtype attrs ) {
+       if ( slks == NULL ) 
+               return ERR;
+       slks->attrs &= ~( attrs & A_ATTRIBUTES );
+       return OK;
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs    attribute bit mask
+ * @ret rc     return status code
+ */
+int slk_attron ( const chtype attrs ) {
+       if ( slks == NULL )
+               return ERR;
+       slks->attrs |= ( attrs & A_ATTRIBUTES );
+       return OK;
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs    attribute bit mask
+ * @ret rc     return status code
+ */
+int slk_attrset ( const chtype attrs ) {
+       if ( slks == NULL ) 
+               return ERR;
+       slks->attrs = ( attrs & A_ATTRIBUTES );
+       return OK;
+}
+
+/**
+ * Turn off soft function key attributes
+ *
+ * @v attrs    attribute bit mask
+ * @v *opts    undefined (for future implementation)
+ * @ret rc     return status code
+ */
+int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
+       return slk_attroff( attrs );
+}
+
+/**
+ * Turn on soft function key attributes
+ *
+ * @v attrs    attribute bit mask
+ * @v *opts    undefined (for future implementation)
+ * @ret rc     return status code
+ */
+int slk_attr_on ( attr_t attrs, void *opts __unused ) {
+       return slk_attron( attrs );
+}
+
+/**
+ * Set soft function key attributes
+ *
+ * @v attrs                    attribute bit mask
+ * @v colour_pair_number       colour pair integer
+ * @v *opts                    undefined (for future implementation)
+ * @ret rc                     return status code
+ */
+int slk_attr_set ( const attr_t attrs, short colour_pair_number,
+                  void *opts __unused ) {
+       if ( slks == NULL ) 
+               return ERR;
+
+       if ( ( unsigned short )colour_pair_number > COLORS )
+               return ERR;
+
+       slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
+               ( attrs & A_ATTRIBUTES );
+       return OK;
+}
+
+/**
+ * Clear the soft function key labels from the screen
+ *
+ * @ret rc     return status code
+ */
+int slk_clear ( void ) {
+       if ( slks == NULL )
+               return ERR;
+
+       _enter_slk();
+       wclrtoeol ( stdscr );
+       _leave_slk();
+
+       return OK;
+}
+
+/**
+ * Set soft label colour pair
+ */
+int slk_colour ( short colour_pair_number ) {
+       if ( slks == NULL ) 
+               return ERR;
+       if ( ( unsigned short )colour_pair_number > COLORS )
+               return ERR;
+
+       slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT )
+               | ( slks->attrs & A_ATTRIBUTES );
+
+       return OK;
+}
+
+/**
+ * Initialise the soft function keys
+ *
+ * @v fmt      format of keys
+ * @ret rc     return status code
+ */
+int slk_init ( int fmt ) {
+       unsigned short nmaj, nmin, nblocks, available_width;
+
+       if ( (unsigned)fmt > 3 ) {
+               return ERR;
+       }
+
+       /* There seems to be no API call to free this data structure... */
+       if ( ! slks )
+               slks = calloc(1,sizeof(*slks));
+       if ( ! slks )
+               return ERR;
+
+       slks->attrs = A_DEFAULT;
+       slks->fmt = fmt;
+       switch(fmt) {
+       case 0:
+               nblocks = 8; nmaj = 2; nmin = 5;
+               slks->spaces[0] = 2; slks->spaces[1] = 4;
+               break;
+       case 1:
+               nblocks = 8; nmaj = 1; nmin = 6;
+               slks->spaces[0] = 3;
+               break;
+       case 2:
+               // same allocations as format 3
+       case 3:
+               nblocks = 12; nmaj = 2; nmin = 9;
+               slks->spaces[0] = 3; slks->spaces[1] = 7;
+               break;
+       default:
+               nblocks = 0; nmaj = 0; nmin = 0;
+               break;
+       }
+
+       // determine maximum label length and major space size
+       available_width = COLS - ( ( MIN_SPACE_SIZE * nmaj ) + nmin );
+       slks->max_label_len = available_width / nblocks;
+       slks->maj_space_len = MIN_SPACE_SIZE + 
+               ( available_width % nblocks ) / nmaj;
+       slks->num_spaces = nmaj;
+       slks->num_labels = nblocks;
+
+       // strip a line from the screen
+       LINES -= 1;
+
+       return OK;
+}
+
+/**
+ * Return the label for the specified soft key
+ *
+ * @v labnum   soft key identifier
+ * @ret label  return label
+ */
+char* slk_label ( int labnum ) {
+       if ( slks == NULL ) 
+               return NULL;
+
+       return slks->fkeys[labnum].label;
+}
+
+/**
+ * Restore soft function key labels to the screen
+ *
+ * @ret rc     return status code
+ */
+int slk_restore ( void ) {
+       unsigned int i, j, pos_x,
+               *next_space, *last_space;
+       chtype space_ch;
+
+       if ( slks == NULL )
+               return ERR;
+
+       pos_x = 0;
+
+       _enter_slk();
+
+       space_ch = (chtype)' ' | slks->attrs;
+       next_space = &(slks->spaces[0]);
+       last_space = &(slks->spaces[slks->num_spaces-1]);
+
+       for ( i = 0; i < slks->num_labels ; i++ ) {
+               _print_label( slks->fkeys[i] );
+               pos_x += slks->max_label_len;
+
+               if ( i == *next_space ) {
+                       for ( j = 0; j < slks->maj_space_len; j++, pos_x++ )
+                               _wputch ( stdscr, space_ch, NOWRAP );
+                       if ( next_space < last_space )
+                               next_space++;
+               } else {
+                       if ( pos_x < COLS )
+                               _wputch ( stdscr, space_ch, NOWRAP );
+                       pos_x++;
+               }
+       }
+
+       _leave_slk();
+
+       return OK;
+}
+
+/**
+ * Configure specified soft key
+ *
+ * @v labnum   soft label position to configure
+ * @v *label   string to use as soft key label
+ * @v fmt      justification format of label
+ * @ret rc     return status code
+ */
+int slk_set ( int labnum, const char *label, int fmt ) {
+       if ( slks == NULL ) 
+               return ERR;
+       if ( (unsigned short)labnum >= slks->num_labels )
+               return ERR;
+       if ( (unsigned short)fmt >= 3 )
+               return ERR;
+
+       strncpy(slks->fkeys[labnum].label, label,
+               sizeof(slks->fkeys[labnum].label));
+       slks->fkeys[labnum].fmt = fmt;
+
+       return OK;
+}