9 * MuCurses: lightweight xcurses implementation for PXE ROMs
17 unsigned short _LINES;
18 unsigned short _COLOURS;
19 unsigned int *_COLOUR_PAIRS; /* basically this is an array, but as its
20 length is determined only when initscr
21 is run, I can only think to make it a
22 pointer and malloc the array into being
30 /* Format of soft label
40 struct _softlabelkeys {
41 struct _softlabel fkeys[12];
44 unsigned int maxlablen;
47 struct _softlabelkeys *slks;
63 * Write a single character rendition to a window
65 * @v *win window in which to write
66 * @v ch character rendition to write
67 * @v wrap wrap "switch"
69 static void _wputch ( WINDOW *win, chtype ch, int wrap ) {
70 /* make sure we set the screen cursor to the right position
72 win->scr->movetoyx( win->scr, win->ori_y + win->curs_y,
73 win->ori_x + win->curs_x );
74 win->scr->putc(win->scr, ch);
75 if ( ++(win->curs_x) == win->width ) {
78 /* specification says we should really scroll,
79 but we have no buffer to scroll with, so we
80 can only overwrite back at the beginning of
82 if ( ++(win->curs_y) == win->height )
91 * Write a chtype string to a window
93 * @v *win window in which to write
94 * @v *chstr chtype string
95 * @v wrap wrap "switch"
96 * @v n write at most n chtypes
98 static void _wputchstr ( WINDOW *win, const chtype *chstr, int wrap, int n ) {
99 for ( ; *chstr && n-- ; chstr++ ) {
100 _wputch(win,*chstr,wrap);
105 * Write a standard c-style string to a window
107 * @v *win window in which to write
109 * @v wrap wrap "switch"
110 * @v n write at most n chars from *str
112 static void _wputstr ( WINDOW *win, const char *str, int wrap, int n ) {
113 for ( ; *str && n-- ; str++ ) {
114 _wputch( win, *str | win->attrs, wrap );
119 * Restore cursor position from encoded backup variable
121 * @v *win window on which to operate
122 * @v *pos pointer to struct in which original cursor position is stored
124 static void _restore_curs_pos ( WINDOW *win, struct cursor_pos *pos ){
125 win->curs_y = pos->y;
126 win->curs_x = pos->x;
127 win->scr->movetoyx ( win->scr, win->curs_y, win->curs_x );
131 * Store cursor position for later restoration
133 * @v *win window on which to operate
134 * @v *pos pointer to struct in which to store cursor position
136 static void _store_curs_pos ( WINDOW *win, struct cursor_pos *pos ) {
137 pos->y = win->curs_y;
138 pos->x = win->curs_x;
142 * Move a window's cursor to the specified position
144 * @v *win window to be operated on
147 * @ret rc return status code
149 int wmove ( WINDOW *win, int y, int x ) {
150 /* chech for out-of-bounds errors */
151 if ( ( ( (unsigned)x - win->ori_x ) > win->width ) ||
152 ( ( (unsigned)y - win->ori_y ) > win->height ) ) {
158 win->scr->movetoyx( win->scr, win->ori_y + win->curs_y,
159 win->ori_x + win->curs_x );
165 * get terminal baud rate
167 * @ret bps return baud rate in bits per second
169 int baudrate ( void ) {
174 * Audible (or visual) signal
176 * @ret rc return status code
184 * Draw borders from single-byte characters and renditions around a
187 * @v *win window to be bordered
188 * @v verch vertical chtype
189 * @v horch horizontal chtype
190 * @ret rc return status code
192 int box ( WINDOW *win, chtype verch, chtype horch ) {
193 int corner = '+' | win->attrs; /* default corner character */
194 return wborder( win, verch, verch, horch, horch,
195 corner, corner, corner, corner );
199 * Indicates whether the underlying terminal device is capable of
200 * having colours redefined
202 * @ret bool returns boolean
204 bool can_change_colour ( void ) {
209 * Identify the RGB components of a given colour value
211 * @v colour colour value
212 * @v *red address to store red component
213 * @v *green address to store green component
214 * @v *blue address to store blue component
215 * @ret rc return status code
217 int colour_content ( short colour, short *red, short *green, short *blue ) {
218 /* we do not have a particularly large range of colours (3
219 primary, 3 secondary and black), so let's just put in a
223 *red = 0; *green = 0; *blue = 0;
226 *red = 0; *green = 0; *blue = 1000;
229 *red = 0; *green = 1000; *blue = 0;
232 *red = 0; *green = 1000; *blue = 1000;
235 *red = 1000; *green = 0; *blue = 0;
238 *red = 1000; *green = 0; *blue = 1000;
241 *red = 1000; *green = 1000; *blue = 0;
250 * @v *win pointer to window being deleted
251 * @ret rc return status code
253 int delwin ( WINDOW *win ) {
256 /* must free descendants first, but I haven't implemented descendants yet
265 * Get the background rendition attributes for a window
267 * @v *win subject window
268 * @ret ch chtype rendition representation
270 inline chtype getbkgd ( WINDOW *win ) {
275 * Initialise console environment
277 * @ret *win return pointer to stdscr
279 WINDOW *initscr ( void ) {
280 /* determine console size */
281 /* initialise screen */
284 /* set previously unknown window attributes */
292 * @v nlines number of lines
293 * @v ncols number of columns
294 * @v begin_y column origin
295 * @v begin_x line origin
296 * @ret *win return pointer to new window
298 WINDOW *newwin ( int nlines, int ncols, int begin_y, int begin_x ) {
299 WINDOW *win = calloc( 1, sizeof(WINDOW) );
300 win->ori_y = begin_y;
301 win->ori_x = begin_x;
302 win->height = nlines;
304 win->scr = stdscr->scr;
311 * Return the attribute used for the soft function keys
313 * @ret attrs the current attributes of the soft function keys
315 attr_t slk_attr ( void ) {
316 return ( slks == NULL ? 0 : slks->attrs );
320 * Turn off soft function key attributes
322 * @v attrs attribute bit mask
323 * @ret rc return status code
325 int slk_attroff ( const chtype attrs ) {
328 slks->attrs &= ~( attrs & A_ATTRIBUTES );
333 * Turn on soft function key attributes
335 * @v attrs attribute bit mask
336 * @ret rc return status code
338 int slk_attron ( const chtype attrs ) {
341 slks->attrs |= ( attrs & A_ATTRIBUTES );
346 * Set soft function key attributes
348 * @v attrs attribute bit mask
349 * @ret rc return status code
351 int slk_attrset ( const chtype attrs ) {
354 slks->attrs = ( attrs & A_ATTRIBUTES );
359 * Turn off soft function key attributes
361 * @v attrs attribute bit mask
362 * @v *opts undefined (for future implementation)
363 * @ret rc return status code
365 int slk_attr_off ( const attr_t attrs, void *opts __unused ) {
366 return slk_attroff( attrs );
370 * Turn on soft function key attributes
372 * @v attrs attribute bit mask
373 * @v *opts undefined (for future implementation)
374 * @ret rc return status code
376 int slk_attr_on ( attr_t attrs, void *opts __unused ) {
377 return slk_attron( attrs );
381 * Set soft function key attributes
383 * @v attrs attribute bit mask
384 * @v colour_pair_number colour pair integer
385 * @v *opts undefined (for future implementation)
386 * @ret rc return status code
388 int slk_attr_set ( const attr_t attrs, short colour_pair_number,
389 void *opts __unused ) {
393 if ( ( unsigned short )colour_pair_number > COLORS )
396 slks->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
397 ( attrs & A_ATTRIBUTES );
402 * Clear the soft function key labels from the screen
404 * @ret rc return status code
406 int slk_clear ( void ) {
410 wmove(stdscr,stdscr->height-1,0);
416 * Initialise the soft function keys
418 * @v fmt format of keys
419 * @ret rc return status code
421 int slk_init ( int fmt ) {
422 if ( (unsigned)fmt > 3 ) {
426 slks = malloc(sizeof(struct _softlabelkeys));
427 slks->attrs = A_DEFAULT;
434 * Return the label for the specified soft key
436 * @v labnum soft key identifier
437 * @ret label return label
439 char* slk_label ( int labnum ) {
443 return slks->fkeys[labnum].label;
447 * Restore soft function key labels to the screen
449 * @ret rc return status code
451 int slk_restore ( void ) {
459 * Configure specified soft key
461 * @v labnum soft label position to configure
462 * @v *label string to use as soft key label
463 * @v fmt justification format of label
464 * @ret rc return status code
466 int slk_set ( int labnum, const char *label, int fmt ) {
469 if ( labnum == 0 || (unsigned)labnum > 12 )
471 if ( (unsigned)fmt >= 3 )
473 if ( strlen(label) > slks->maxlablen )
476 strcpy( slks->fkeys[labnum].label, label );
477 slks->fkeys[labnum].fmt = fmt;
482 struct printw_context {
483 struct printf_context ctx;
487 static void _printw_handler ( struct printf_context *ctx, unsigned int c ) {
488 struct printw_context *wctx =
489 container_of ( ctx, struct printw_context, ctx );
491 _wputch( wctx->win, c | wctx->win->attrs, WRAP );
495 * Print formatted output in a window
497 * @v *win subject window
498 * @v *fmt formatted string
499 * @v varglist argument list
500 * @ret rc return status code
502 int vw_printw ( WINDOW *win, const char *fmt, va_list varglist ) {
503 struct printw_context wctx = {
505 .ctx = { .handler = _printw_handler, },
508 vcprintf ( &(wctx.ctx), fmt, varglist );
513 * Add a single-byte character and rendition to a window and advance
516 * @v *win window to be rendered in
517 * @v ch character to be added at cursor
518 * @ret rc return status code
520 int waddch ( WINDOW *win, const chtype ch ) {
521 _wputch( win, ch, WRAP );
526 * Add string of single-byte characters and renditions to a window
528 * @v *win window to be rendered in
529 * @v *chstr pointer to first chtype in "string"
530 * @v n max number of chars from chstr to render
531 * @ret rc return status code
533 int waddchnstr ( WINDOW *win, const chtype *chstr, int n ) {
534 struct cursor_pos pos;
536 _store_curs_pos( win, &pos );
537 _wputchstr( win, chstr, NOWRAP, n );
538 _restore_curs_pos( win, &pos );
543 * Add string of single-byte characters to a window
545 * @v *win window to be rendered in
546 * @v *str standard c-style string
547 * @v n max number of chars from string to render
548 * @ret rc return status code
550 int waddnstr ( WINDOW *win, const char *str, int n ) {
551 _wputstr( win, str, WRAP, n );
556 * Turn off attributes in a window
558 * @v win subject window
559 * @v attrs attributes to enable
560 * @ret rc return status code
562 int wattroff ( WINDOW *win, int attrs ) {
563 win->attrs &= ~attrs;
568 * Turn on attributes in a window
570 * @v win subject window
571 * @v attrs attributes to enable
572 * @ret rc return status code
574 int wattron ( WINDOW *win, int attrs ) {
580 * Set attributes in a window
582 * @v win subject window
583 * @v attrs attributes to enable
584 * @ret rc return status code
586 int wattrset ( WINDOW *win, int attrs ) {
587 win->attrs = ( attrs | ( win->attrs & A_COLOR ) );
592 * Get attributes and colour pair information
594 * @v *win window to obtain information from
595 * @v *attrs address in which to store attributes
596 * @v *pair address in which to store colour pair
597 * @v *opts undefined (for future implementation)
598 * @ret rc return status cude
600 int wattr_get ( WINDOW *win, attr_t *attrs, short *pair,
601 void *opts __unused ) {
602 *attrs = win->attrs & A_ATTRIBUTES;
603 *pair = (short)(( win->attrs & A_COLOR ) >> CPAIR_SHIFT);
608 * Turn off attributes in a window
610 * @v *win subject window
611 * @v attrs attributes to toggle
612 * @v *opts undefined (for future implementation)
613 * @ret rc return status code
615 int wattr_off ( WINDOW *win, attr_t attrs,
616 void *opts __unused ) {
617 wattroff( win, attrs );
622 * Turn on attributes in a window
624 * @v *win subject window
625 * @v attrs attributes to toggle
626 * @v *opts undefined (for future implementation)
627 * @ret rc return status code
629 int wattr_on ( WINDOW *win, attr_t attrs,
630 void *opts __unused ) {
631 wattron( win, attrs );
636 * Set attributes and colour pair information in a window
638 * @v *win subject window
639 * @v attrs attributes to set
640 * @v cpair colour pair to set
641 * @v *opts undefined (for future implementation)
642 * @ret rc return status code
644 int wattr_set ( WINDOW *win, attr_t attrs, short cpair,
645 void *opts __unused ) {
646 wattrset( win, attrs | ( ( (unsigned short)cpair ) << CPAIR_SHIFT ) );
651 * Draw borders from single-byte characters and renditions around a
654 * @v *win window to be bordered
659 * @v tl top left corner
660 * @v tr top right corner
661 * @v bl bottom left corner
662 * @v br bottom right corner
663 * @ret rc return status code
665 int wborder ( WINDOW *win, chtype ls, chtype rs,
666 chtype ts, chtype bs, chtype tl,
667 chtype tr, chtype bl, chtype br ) {
671 _wputch(win,tl,WRAP);
672 while ( ( win->width - 1 ) - win->curs_x ) {
673 _wputch(win,ts,WRAP);
675 _wputch(win,tr,WRAP);
677 while ( ( win->height - 1 ) - win->curs_y ) {
678 _wputch(win,ls,WRAP);
679 wmove(win,win->curs_y,(win->width)-1);
680 _wputch(win,rs,WRAP);
683 _wputch(win,bl,WRAP);
684 while ( ( win->width -1 ) - win->curs_x ) {
685 _wputch(win,bs,WRAP);
687 _wputch(win,br,NOWRAP); /* do not wrap last char to leave
688 cursor in last position */
694 * Clear a window to the bottom
696 * @v *win subject window
697 * @ret rc return status code
699 int wclrtobot ( WINDOW *win ) {
700 struct cursor_pos pos;
702 _store_curs_pos( win, &pos );
704 _wputch( win, (unsigned)' ', WRAP );
705 } while ( win->curs_y + win->curs_x );
706 _restore_curs_pos( win, &pos );
712 * Clear a window to the end of the current line
714 * @v *win subject window
715 * @ret rc return status code
717 int wclrtoeol ( WINDOW *win ) {
718 struct cursor_pos pos;
720 _store_curs_pos( win, &pos );
721 while ( ( win->curs_y - pos.y ) == 0 ) {
722 _wputch( win, (unsigned)' ', WRAP );
724 _restore_curs_pos( win, &pos );
730 * Set colour pair for a window
732 * @v *win subject window
733 * @v colour_pair_number colour pair integer
734 * @v *opts undefined (for future implementation)
735 * @ret rc return status code
737 int wcolour_set ( WINDOW *win, short colour_pair_number,
738 void *opts __unused ) {
739 if ( ( unsigned short )colour_pair_number > COLORS )
742 win->attrs = ( (unsigned short)colour_pair_number << CPAIR_SHIFT ) |
743 ( win->attrs & A_ATTRIBUTES );
748 * Delete character under the cursor in a window
750 * @v *win subject window
751 * @ret rc return status code
753 int wdelch ( WINDOW *win ) {
754 struct cursor_pos pos;
756 _store_curs_pos( win, &pos );
757 _wputch( win, (unsigned)' ', NOWRAP );
758 _restore_curs_pos( win, &pos );
764 * Delete line under a window's cursor
766 * @v *win subject window
767 * @ret rc return status code
769 int wdeleteln ( WINDOW *win ) {
770 /* let's just set the cursor to the beginning of the line and
771 let wclrtoeol do the work :) */
772 wmove( win, win->curs_y, 0 );
778 * Create a horizontal line in a window
780 * @v *win subject window
781 * @v ch rendition and character
782 * @v n max number of chars (wide) to render
783 * @ret rc return status code
785 int whline ( WINDOW *win, chtype ch, int n ) {
786 struct cursor_pos pos;
788 _store_curs_pos ( win, &pos );
789 while ( ( win->curs_x - win->width ) && n-- ) {
790 _wputch ( win, ch, NOWRAP );
792 _restore_curs_pos ( win, &pos );
798 * Print formatted output to a window
800 * @v *win subject window
801 * @v *fmt formatted string
802 * @v ... string arguments
803 * @ret rc return status code
805 int wprintw ( WINDOW *win, const char *fmt, ... ) {
809 va_start ( args, fmt );
810 i = vw_printw ( win, fmt, args );
816 * Create a vertical line in a window
818 * @v *win subject window
819 * @v ch rendition and character
820 * @v n max number of lines to render
821 * @ret rc return status code
823 int wvline ( WINDOW *win, chtype ch, int n ) {
824 struct cursor_pos pos;
826 _store_curs_pos ( win, &pos );
827 while ( ( win->curs_y - win->height ) && n-- ) {
828 _wputch ( win, ch, NOWRAP );
829 wmove( win, ++(win->curs_y), pos.x);
831 _restore_curs_pos ( win, &pos );