Module Name: src Committed By: roy Date: Tue Jan 24 17:27:30 UTC 2017
Modified Files: src/distrib/sets/lists/comp: mi src/lib/libcurses: Makefile curses.h curses_private.h resize.c ripoffline.c screen.c Added Files: src/lib/libcurses: curses_slk.3 slk.c Log Message: Implement POSIX Curses Soft Label Key functions. To generate a diff of this commit: cvs rdiff -u -r1.2102 -r1.2103 src/distrib/sets/lists/comp/mi cvs rdiff -u -r1.83 -r1.84 src/lib/libcurses/Makefile cvs rdiff -u -r1.120 -r1.121 src/lib/libcurses/curses.h cvs rdiff -u -r1.59 -r1.60 src/lib/libcurses/curses_private.h cvs rdiff -u -r0 -r1.1 src/lib/libcurses/curses_slk.3 src/lib/libcurses/slk.c cvs rdiff -u -r1.25 -r1.26 src/lib/libcurses/resize.c cvs rdiff -u -r1.2 -r1.3 src/lib/libcurses/ripoffline.c cvs rdiff -u -r1.29 -r1.30 src/lib/libcurses/screen.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/comp/mi diff -u src/distrib/sets/lists/comp/mi:1.2102 src/distrib/sets/lists/comp/mi:1.2103 --- src/distrib/sets/lists/comp/mi:1.2102 Wed Jan 11 12:02:24 2017 +++ src/distrib/sets/lists/comp/mi Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.2102 2017/01/11 12:02:24 joerg Exp $ +# $NetBSD: mi,v 1.2103 2017/01/24 17:27:30 roy Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. ./etc/mtree/set.comp comp-sys-root @@ -5739,6 +5739,7 @@ ./usr/share/man/cat3/curses_scanw.0 comp-c-catman .cat ./usr/share/man/cat3/curses_screen.0 comp-c-catman .cat ./usr/share/man/cat3/curses_scroll.0 comp-c-catman .cat +./usr/share/man/cat3/curses_slk.0 comp-c-catman .cat ./usr/share/man/cat3/curses_standout.0 comp-c-catman .cat ./usr/share/man/cat3/curses_termcap.0 comp-c-catman .cat ./usr/share/man/cat3/curses_touch.0 comp-c-catman .cat @@ -9008,6 +9009,22 @@ ./usr/share/man/cat3/sl_find.0 comp-c-catman .cat ./usr/share/man/cat3/sl_free.0 comp-c-catman .cat ./usr/share/man/cat3/sl_init.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attroff.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attr_off.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attron.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attr_on.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attrset.0 comp-c-catman .cat +./usr/share/man/cat3/slk_attr_set.0 comp-c-catman .cat +./usr/share/man/cat3/slk_clear.0 comp-c-catman .cat +./usr/share/man/cat3/slk_color.0 comp-c-catman .cat +./usr/share/man/cat3/slk_init.0 comp-c-catman .cat +./usr/share/man/cat3/slk_label.0 comp-c-catman .cat +./usr/share/man/cat3/slk_noutrefresh.0 comp-c-catman .cat +./usr/share/man/cat3/slk_refresh.0 comp-c-catman .cat +./usr/share/man/cat3/slk_restore.0 comp-c-catman .cat +./usr/share/man/cat3/slk_set.0 comp-c-catman .cat +./usr/share/man/cat3/slk_touch.0 comp-c-catman .cat +./usr/share/man/cat3/slk_wset.0 comp-c-catman .cat ./usr/share/man/cat3/sleep.0 comp-c-catman .cat ./usr/share/man/cat3/snprintb.0 comp-c-catman .cat ./usr/share/man/cat3/snprintb_m.0 comp-c-catman .cat @@ -13134,6 +13151,7 @@ ./usr/share/man/html3/curses_scanw.html comp-c-htmlman html ./usr/share/man/html3/curses_screen.html comp-c-htmlman html ./usr/share/man/html3/curses_scroll.html comp-c-htmlman html +./usr/share/man/html3/curses_slk.html comp-c-htmlman html ./usr/share/man/html3/curses_standout.html comp-c-htmlman html ./usr/share/man/html3/curses_termcap.html comp-c-htmlman html ./usr/share/man/html3/curses_touch.html comp-c-htmlman html @@ -16339,6 +16357,22 @@ ./usr/share/man/html3/sl_find.html comp-c-htmlman html ./usr/share/man/html3/sl_free.html comp-c-htmlman html ./usr/share/man/html3/sl_init.html comp-c-htmlman html +./usr/share/man/html3/slk_attroff.html comp-c-htmlman html +./usr/share/man/html3/slk_attr_off.html comp-c-htmlman html +./usr/share/man/html3/slk_attron.html comp-c-htmlman html +./usr/share/man/html3/slk_attr_on.html comp-c-htmlman html +./usr/share/man/html3/slk_attrset.html comp-c-htmlman html +./usr/share/man/html3/slk_attr_set.html comp-c-htmlman html +./usr/share/man/html3/slk_clear.html comp-c-htmlman html +./usr/share/man/html3/slk_color.html comp-c-htmlman html +./usr/share/man/html3/slk_init.html comp-c-htmlman html +./usr/share/man/html3/slk_label.html comp-c-htmlman html +./usr/share/man/html3/slk_noutrefresh.html comp-c-htmlman html +./usr/share/man/html3/slk_refresh.html comp-c-htmlman html +./usr/share/man/html3/slk_restore.html comp-c-htmlman html +./usr/share/man/html3/slk_set.html comp-c-htmlman html +./usr/share/man/html3/slk_touch.html comp-c-htmlman html +./usr/share/man/html3/slk_wset.html comp-c-htmlman html ./usr/share/man/html3/sleep.html comp-c-htmlman html ./usr/share/man/html3/snprintb.html comp-c-htmlman html ./usr/share/man/html3/snprintb_m.html comp-c-htmlman html @@ -20436,6 +20470,7 @@ ./usr/share/man/man3/curses_scanw.3 comp-c-man .man ./usr/share/man/man3/curses_screen.3 comp-c-man .man ./usr/share/man/man3/curses_scroll.3 comp-c-man .man +./usr/share/man/man3/curses_slk.3 comp-c-man .man ./usr/share/man/man3/curses_standout.3 comp-c-man .man ./usr/share/man/man3/curses_termcap.3 comp-c-man .man ./usr/share/man/man3/curses_touch.3 comp-c-man .man @@ -23701,6 +23736,22 @@ ./usr/share/man/man3/sl_find.3 comp-c-man .man ./usr/share/man/man3/sl_free.3 comp-c-man .man ./usr/share/man/man3/sl_init.3 comp-c-man .man +./usr/share/man/man3/slk_attroff.3 comp-c-man .man +./usr/share/man/man3/slk_attr_off.3 comp-c-man .man +./usr/share/man/man3/slk_attron.3 comp-c-man .man +./usr/share/man/man3/slk_attr_on.3 comp-c-man .man +./usr/share/man/man3/slk_attrset.3 comp-c-man .man +./usr/share/man/man3/slk_attr_set.3 comp-c-man .man +./usr/share/man/man3/slk_clear.3 comp-c-man .man +./usr/share/man/man3/slk_color.3 comp-c-man .man +./usr/share/man/man3/slk_init.3 comp-c-man .man +./usr/share/man/man3/slk_label.3 comp-c-man .man +./usr/share/man/man3/slk_noutrefresh.3 comp-c-man .man +./usr/share/man/man3/slk_refresh.3 comp-c-man .man +./usr/share/man/man3/slk_restore.3 comp-c-man .man +./usr/share/man/man3/slk_set.3 comp-c-man .man +./usr/share/man/man3/slk_touch.3 comp-c-man .man +./usr/share/man/man3/slk_wset.3 comp-c-man .man ./usr/share/man/man3/sleep.3 comp-c-man .man ./usr/share/man/man3/snprintb.3 comp-c-man .man ./usr/share/man/man3/snprintb_m.3 comp-c-man .man Index: src/lib/libcurses/Makefile diff -u src/lib/libcurses/Makefile:1.83 src/lib/libcurses/Makefile:1.84 --- src/lib/libcurses/Makefile:1.83 Wed Jan 11 20:43:03 2017 +++ src/lib/libcurses/Makefile Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.83 2017/01/11 20:43:03 roy Exp $ +# $NetBSD: Makefile,v 1.84 2017/01/24 17:27:30 roy Exp $ # @(#)Makefile 8.2 (Berkeley) 1/2/94 .include <bsd.own.mk> @@ -23,7 +23,7 @@ SRCS= acs.c addbytes.c addch.c addchnstr insertln.c instr.c keypad.c keyname.c leaveok.c line.c meta.c move.c \ mvwin.c newwin.c nodelay.c notimeout.c overlay.c overwrite.c pause.c \ printw.c putchar.c refresh.c resize.c ripoffline.c scanw.c screen.c \ - scroll.c scrollok.c setterm.c standout.c syncok.c timeout.c \ + scroll.c scrollok.c setterm.c slk.c standout.c syncok.c timeout.c \ toucholap.c touchwin.c tstp.c tty.c unctrl.c underscore.c MAN= curses.3 curses_addch.3 curses_addchstr.3 curses_addstr.3 \ @@ -34,8 +34,8 @@ MAN= curses.3 curses_addch.3 curses_addc curses_inch.3 curses_input.3 curses_insertch.3 curses_insertln.3 \ curses_insdelln.3 curses_keyname.3 curses_line.3 curses_pad.3 \ curses_print.3 curses_refresh.3 curses_scanw.3 curses_screen.3 \ - curses_scroll.3 curses_standout.3 curses_termcap.3 curses_touch.3 \ - curses_tty.3 curses_underscore.3 curses_window.3 + curses_scroll.3 curses_slk.3 curses_standout.3 curses_termcap.3 \ + curses_touch.3 curses_tty.3 curses_underscore.3 curses_window.3 INCS= curses.h unctrl.h INCSDIR=/usr/include @@ -150,6 +150,14 @@ MLINKS+= curses_addch.3 addch.3 curses_a curses_cursor.3 setsyx.3 \ curses_input.3 set_escdelay.3 curses_screen.3 set_tabsize.3 \ curses_screen.3 set_term.3 curses_screen.3 setterm.3 \ + curses_slk.3 slk_attroff.3 curses_slk.3 slk_attr_off.3 \ + curses_slk.3 slk_attron.3 curses_slk.3 slk_attr_on.3 \ + curses_slk.3 slk_attrset.3 curses_slk.3 slk_attr_set.3 \ + curses_slk.3 slk_clear.3 curses_slk.3 slk_color.3 \ + curses_slk.3 slk_init.3 curses_slk.3 slk_label.3 \ + curses_slk.3 slk_noutrefresh.3 curses_slk.3 slk_refresh.3 \ + curses_slk.3 slk_restore.3 curses_slk.3 slk_set.3 \ + curses_slk.3 slk_touch.3 curses_slk.3 slk_wset.3 \ curses_standout.3 standend.3 curses_standout.3 standout.3 \ curses_color.3 start_color.3 curses_pad.3 subpad.3 \ curses_window.3 subwin.3 curses_touch.3 syncok.3 \ Index: src/lib/libcurses/curses.h diff -u src/lib/libcurses/curses.h:1.120 src/lib/libcurses/curses.h:1.121 --- src/lib/libcurses/curses.h:1.120 Tue Jan 10 10:13:24 2017 +++ src/lib/libcurses/curses.h Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: curses.h,v 1.120 2017/01/10 10:13:24 roy Exp $ */ +/* $NetBSD: curses.h,v 1.121 2017/01/24 17:27:30 roy Exp $ */ /* * Copyright (c) 1981, 1993, 1994 @@ -843,6 +843,24 @@ int wchgat(WINDOW *, int, attr_t, short, int mvchgat(int, int, int, attr_t, short, const void *); int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *); +/* Soft Label Keys. */ +int slk_attroff(const chtype); +int slk_attr_off(const attr_t, void *); +int slk_attron(const chtype); +int slk_attr_on(const attr_t, void *); +int slk_attrset(const chtype); +int slk_attr_set(const attr_t, short, void *); +int slk_clear(void); +int slk_color(short); +int slk_init(int); +char *slk_label(int); +int slk_noutrefresh(void); +int slk_refresh(void); +int slk_restore(void); +int slk_set(int, const char *, int); +int slk_touch(void); +int slk_wset(int, const wchar_t *, int); + /* wide-character support routines */ /* return ERR when HAVE_WCHAR is not defined */ /* add */ Index: src/lib/libcurses/curses_private.h diff -u src/lib/libcurses/curses_private.h:1.59 src/lib/libcurses/curses_private.h:1.60 --- src/lib/libcurses/curses_private.h:1.59 Wed Jan 11 20:43:03 2017 +++ src/lib/libcurses/curses_private.h Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: curses_private.h,v 1.59 2017/01/11 20:43:03 roy Exp $ */ +/* $NetBSD: curses_private.h,v 1.60 2017/01/24 17:27:30 roy Exp $ */ /*- * Copyright (c) 1998-2000 Brett Lymn @@ -189,6 +189,22 @@ struct __pair { typedef struct keymap keymap_t; +/* POSIX allows up to 8 columns in a label. */ +#define MAX_SLK_COLS 8 +#ifdef HAVE_WCHAR +#define MAX_SLK_LABEL sizeof(wchar_t) * MAX_SLK_COLS +#else +#define MAX_SLK_LABEL MAX_SLK_COLS +#endif +struct __slk_label { + char *text; + int justify; +#define SLK_JUSTIFY_LEFT 0 +#define SLK_JUSTIFY_CENTER 1 +#define SLK_JUSTIFY_RIGHT 2 + char label[MAX_SLK_LABEL + 1]; + int x; +}; #define MAX_RIPS 5 struct __ripoff { @@ -268,6 +284,18 @@ struct __screen { int unget_len, unget_pos; int filtered; int checkfd; + + /* soft label key */ + bool is_term_slk; + WINDOW *slk_window; + int slk_format; +#define SLK_FMT_3_2_3 0 +#define SLK_FMT_4_4 1 + int slk_nlabels; + int slk_label_len; + bool slk_hidden; + struct __slk_label *slk_labels; + #ifdef HAVE_WCHAR #define MB_LEN_MAX 8 #define MAX_CBUF_SIZE MB_LEN_MAX @@ -357,6 +385,10 @@ void __set_color(WINDOW *win, attr_t at void __set_stophandler(void); void __set_winchhandler(void); void __set_subwin(WINDOW *, WINDOW *); +int __slk_init(SCREEN *); +void __slk_free(SCREEN *); +int __slk_resize(SCREEN *, int cols); +int __slk_noutrefresh(SCREEN *); void __startwin(SCREEN *); void __stop_signal_handler(int); int __stopwin(void); @@ -365,6 +397,7 @@ void __sync(WINDOW *); int __timeout(int); int __touchline(WINDOW *, int, int, int); int __touchwin(WINDOW *); +int __unripoffline(int (*)(WINDOW *, int)); void __unsetattr(int); void __unset_color(WINDOW *win); int __waddch(WINDOW *, __LDATA *); Index: src/lib/libcurses/resize.c diff -u src/lib/libcurses/resize.c:1.25 src/lib/libcurses/resize.c:1.26 --- src/lib/libcurses/resize.c:1.25 Wed Jan 11 20:43:03 2017 +++ src/lib/libcurses/resize.c Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: resize.c,v 1.25 2017/01/11 20:43:03 roy Exp $ */ +/* $NetBSD: resize.c,v 1.26 2017/01/24 17:27:30 roy Exp $ */ /* * Copyright (c) 2001 @@ -40,7 +40,7 @@ #if 0 static char sccsid[] = "@(#)resize.c blymn 2001/08/26"; #else -__RCSID("$NetBSD: resize.c,v 1.25 2017/01/11 20:43:03 roy Exp $"); +__RCSID("$NetBSD: resize.c,v 1.26 2017/01/24 17:27:30 roy Exp $"); #endif #endif /* not lint */ @@ -173,8 +173,14 @@ resizeterm(int nlines, int ncols) * know the correct draw order. */ clearok(curscr, TRUE); - /* We know how to repaint the ripoffs */ - __ripoffresize(_cursesi_screen); + if (result == OK) { + /* We know how to repaint the ripoffs */ + __ripoffresize(_cursesi_screen); + + /* We do need to reposition our slks. */ + __slk_resize(_cursesi_screen, ncols); + __slk_noutrefresh(_cursesi_screen); + } return result; } @@ -210,6 +216,11 @@ resize_term(int nlines, int ncols) LINES = rlines; COLS = ncols; + if (_cursesi_screen->slk_window != NULL && + __resizewin(_cursesi_screen->slk_window, + _cursesi_screen->slk_window->reqy, ncols) == ERR) + return ERR; + /* tweak the flags now that we have updated the LINES and COLS */ for (list = _cursesi_screen->winlistp; list != NULL; list = list->nextp) { win = list->winp; Index: src/lib/libcurses/ripoffline.c diff -u src/lib/libcurses/ripoffline.c:1.2 src/lib/libcurses/ripoffline.c:1.3 --- src/lib/libcurses/ripoffline.c:1.2 Thu Jan 12 16:23:46 2017 +++ src/lib/libcurses/ripoffline.c Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ripoffline.c,v 1.2 2017/01/12 16:23:46 roy Exp $ */ +/* $NetBSD: ripoffline.c,v 1.3 2017/01/24 17:27:30 roy Exp $ */ /*- * Copyright (c) 2017 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: ripoffline.c,v 1.2 2017/01/12 16:23:46 roy Exp $"); +__RCSID("$NetBSD: ripoffline.c,v 1.3 2017/01/24 17:27:30 roy Exp $"); #endif /* not lint */ #include "curses.h" @@ -103,6 +103,8 @@ __ripoffscreen(SCREEN *screen, int *rtop *rtop = 0; rip = screen->ripped; for (i = 0, srip = ripoffs; i < nrips; i++, srip++) { + if (srip->nlines == 0) + continue; nlines = srip->nlines < 0 ? -srip->nlines : srip->nlines; w = __newwin(screen, nlines, 0, srip->nlines < 0 ? LINES - nlines : *rtop, @@ -151,3 +153,23 @@ __ripoffresize(SCREEN *screen) wnoutrefresh(rip->win); } } + +/* + * __unripoffline -- + * Used by __slk_init to remove the ripoffline reservation it made + * because the terminal natively supports soft label keys. + */ +int +__unripoffline(int (*init)(WINDOW *, int)) +{ + struct ripoff *rip; + int i, unripped = 0; + + for (i = 0, rip = ripoffs; i < nrips; i++, rip++) { + if (rip->init == init) { + rip->nlines = 0; + unripped++; + } + } + return unripped; +} Index: src/lib/libcurses/screen.c diff -u src/lib/libcurses/screen.c:1.29 src/lib/libcurses/screen.c:1.30 --- src/lib/libcurses/screen.c:1.29 Wed Jan 11 20:43:03 2017 +++ src/lib/libcurses/screen.c Tue Jan 24 17:27:30 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: screen.c,v 1.29 2017/01/11 20:43:03 roy Exp $ */ +/* $NetBSD: screen.c,v 1.30 2017/01/24 17:27:30 roy Exp $ */ /* * Copyright (c) 1981, 1993, 1994 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)screen.c 8.2 (blymn) 11/27/2001"; #else -__RCSID("$NetBSD: screen.c,v 1.29 2017/01/11 20:43:03 roy Exp $"); +__RCSID("$NetBSD: screen.c,v 1.30 2017/01/24 17:27:30 roy Exp $"); #endif #endif /* not lint */ @@ -179,6 +179,10 @@ newterm(char *type, FILE *outfd, FILE *i 0, 0, 0, FALSE)) == NULL) goto error_exit; + /* If Soft Label Keys are setup, they will ripoffline. */ + if (__slk_init(new_screen) == ERR) + goto error_exit; + if (__ripoffscreen(new_screen, &rtop) == ERR) goto error_exit; @@ -191,7 +195,7 @@ newterm(char *type, FILE *outfd, FILE *i __init_getch(new_screen); __init_acs(new_screen); #ifdef HAVE_WCHAR - __init_get_wch( new_screen ); + __init_get_wch(new_screen); __init_wacs(new_screen); #endif /* HAVE_WCHAR */ @@ -240,6 +244,9 @@ delscreen(SCREEN *screen) /* free the storage of the keymaps */ _cursesi_free_keymap(screen->base_keymap); + /* free the Soft Label Keys */ + __slk_free(screen); + free(screen->stdbuf); free(screen->unget_list); if (_cursesi_screen == screen) Added files: Index: src/lib/libcurses/curses_slk.3 diff -u /dev/null src/lib/libcurses/curses_slk.3:1.1 --- /dev/null Tue Jan 24 17:27:30 2017 +++ src/lib/libcurses/curses_slk.3 Tue Jan 24 17:27:30 2017 @@ -0,0 +1,244 @@ +.\" $NetBSD: curses_slk.3,v 1.1 2017/01/24 17:27:30 roy Exp $ +.\" +.\" Copyright (c) 2017 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Roy Marples. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" +.Dd January 12, 2017 +.Dt CURSES_SLK 3 +.Os +.Sh NAME +.Nm slk_attroff , +.Nm slk_attr_off , +.Nm slk_attron , +.Nm slk_attr_on , +.Nm slk_attrset , +.Nm slk_attr_set , +.Nm slk_clear , +.Nm slk_color , +.Nm slk_init , +.Nm slk_label , +.Nm slk_noutrefresh , +.Nm slk_refresh , +.Nm slk_restore , +.Nm slk_set , +.Nm slk_touch , +.Nm slk_wset +.Nd Curses soft label key routines +.Sh LIBRARY +.Lb libcurses +.Sh SYNOPSIS +.In curses.h +.Ft int +.Fn slk_attroff "const chtype attr" +.Ft int +.Fn slk_attr_off "const attr_t attr" "void *opt" +.Ft int +.Fn slk_attron "const chtype attr" +.Ft int +.Fn slk_attr_on "const attr_t attr" "void *opt" +.Ft int +.Fn slk_attrset "const chtype attr" +.Ft int +.Fn slk_attr_set "const attr_t attr" "void *opt" +.Ft void +.Fn slk_clear "void" +.Ft int +.Fn slk_color "short pair" +.Ft int +.Fn slk_init "int fmt" +.Ft char * +.Fn slk_label "int labnum" +.Ft int +.Fn slk_noutrefresh "void" +.Ft int +.Fn slk_refresh "void" +.Ft int +.Fn slk_restore "void" +.Ft int +.Fn slk_set "int labnum" "const char *label" "int justify" +.Ft int +.Fn slk_touch "void" +.Ft int +.Fn slk_wset "int labnum" "const wchar_t *label" "int justify" +.Sh DESCRIPTION +This Curses interface manipulates the set of soft function-key labels that +exist on some terminals. +For those terminals that do not have soft labels, Curses takes over the bottom +line of +.Dv stdstr , +reducing the size of +.Dv stdscr +and the value of the +.Dv LINES +external variable. +There can be up to eight labels of up to eight display columns each. +.Pp +To use soft labels, +.Fn slk_init +must be called before +.Xr initscr 3 , +.Xr newterm 3 , +or +.Xr ripoffline 3 +is called. +If +.Xr newterm 3 +eventually uses a line from +.Dv stdscr +to emulate the soft labels, then +.Fa fmt +determines how the labels are arranged on the screen from the following list: +.Bl -tag -width ERR -compact +.It 0 +indicates a 3-2-3 arrangement. +.It 1 +indicates a 4-4 arrangement. +.El +.Pp +The +.Fn slk_set +and +.Fn slk_wset +functions specify the text of soft label number +.Fa labnum , +within the range from 1 to 8 inclusive. +The +.Fa label +argument is the string to be put on the label. +The +.Fa justify +argument can have the following values to indicate how to justify +.Fa label +within the space reserved for it: +.Bl -tag -width ERR -compact +.It 0 +Left align. +.It 1 +Center align. +.It 2 +Right align. +.El +.Pp +The +.Fn slk_refresh +and +.Fn slk_noutrefresh +functions correspond to the +.Xr wrefresh 3 +and +.Xr wnoutrefresh 3 +functions. +.Pp +The +.Fn slk_label +function returns a pointer to the text displayed in the label. +.Pp +The +.Fn slk_clear +function immediately clears the soft labels from the screen. +.Pp +The +.Fn slk_restore +function immediately restores the soft labels to the screen after a call to +.Fn slk_clear . +.Pp +The +.Fn slk_touch +function forces all soft labels to be output the next time +.Fn slk_noutrefresh +or +.Fn slk_refresh +is called. +.Pp +The +.Fn slk_attron , +.Fn slk_attrset +and +.Fn slk_attroff +functions correspond to +.Xr attron 3 , +.Xr attrset 3 +and +.Xr attroff 3 . +The have an effect only if soft labels are simulated on the bottom line of the +screen. +.Pp +The +.Fn slk_attr_on , +.Fn slk_attr_set , +.Fn slk_color +and +.Fn slk_attr_off +functions correspond to +.Xr attr_on 3 , +.Xr attr_set 3 , +.Xr color_set 3 +and +.Xr attr_off 3 +and thus support the attribute constants with the WA_ prefix and color. +The have an effect only if soft labels are simulated on the bottom line of the +screen. +.Pp +The +.Fa opt +argument is reserved for future use. +Currently the application must provide a NULL pointer as +.Fa opt . +.Sh RETURN VALUES +Functions returning pointers will return +.Dv NULL +if an error is detected. +The functions that return an int will return one of the following +values: +.Pp +.Bl -tag -width ERR -compact +.It Er OK +The function completed successfully. +.It Er ERR +An error occurred in the function. +.El +.Sh SEE ALSO +.Xr terminfo 5 +.Sh NOTES +This has not been tested on a terminal with real soft label keys. +.Dv label_height , +.Dv label_width , +.Dv label_format +and +.Dv lab_f* +are currently not used. +.Sh STANDARDS +The +.Nx +Curses library complies with the X/Open Curses specification, part of the +Single Unix Specification. +.Sh HISTORY +The Curses package appeared in +.Bx 4.0 . +The soft label key functions were added in +.Nx 8.0 . Index: src/lib/libcurses/slk.c diff -u /dev/null src/lib/libcurses/slk.c:1.1 --- /dev/null Tue Jan 24 17:27:30 2017 +++ src/lib/libcurses/slk.c Tue Jan 24 17:27:30 2017 @@ -0,0 +1,808 @@ +/* $NetBSD: slk.c,v 1.1 2017/01/24 17:27:30 roy Exp $ */ + +/*- + * Copyright (c) 2017 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Roy Marples. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: slk.c,v 1.1 2017/01/24 17:27:30 roy Exp $"); +#endif /* not lint */ + +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_WCHAR +#include <wctype.h> +#endif + +#include "curses.h" +#include "curses_private.h" + +/* Terminals with real soft labels have NOT been tested. + * If you have such a device, please let us know so this comment + * can be adjusted. */ + +/* POSIX says that each label can be up to 8 columns. + * However, our implementation can allow labels to expand beyond that. */ +//#define SLK_SIZE_DYNAMIC +#ifdef SLK_SIZE_DYNAMIC +#define SLK_SIZE MAX_SLK_LABEL +#else +#define SLK_SIZE MAX_SLK_COLS +#endif + +static int slk_fmt; /* fmt of slk_init */ + +/* Safe variants of public functions. */ +static int __slk_attron(SCREEN *, const chtype); +static int __slk_attr_on(SCREEN *, const attr_t, void *); +static int __slk_attroff(SCREEN *, const chtype); +static int __slk_attr_off(SCREEN *, const attr_t, void *); +static int __slk_attrset(SCREEN *, const chtype); +static int __slk_attr_set(SCREEN *, const attr_t, short, void *opt); +static int __slk_color(SCREEN *, short); +static int __slk_clear(SCREEN *); +static char *__slk_label(SCREEN *, int); +static int __slk_restore(SCREEN *); +static int __slk_set(SCREEN *, int, const char *, int); +static int __slk_touch(SCREEN *); +static int __slk_wset(SCREEN *, int, const wchar_t *, int); + +/* Internal engine parts. */ +static int __slk_ripoffline(WINDOW *, int); +static int __slk_set_finalise(SCREEN *, int); +static int __slk_draw(SCREEN *, int); +static int __slk_redraw(SCREEN *); + +/* + * slk_init -- + * Init Soft Label Keys. + */ +int +slk_init(int fmt) +{ + + switch(fmt) { + case SLK_FMT_3_2_3: + case SLK_FMT_4_4: + break; + default: + return ERR; + } + + slk_fmt = fmt; + /* Even if the terminal supports soft label keys directly, + * we need to reserve a line. */ + return ripoffline(-1, __slk_ripoffline); +} + +/* + * slk_attron -- + * Test and set attributes on ripped off slk window. + */ +int +slk_attron(const chtype attr) +{ + + return __slk_attron(_cursesi_screen, attr); +} + +/* + * slk_attr_on -- + * Test and set wide attributes on ripped off slk window. + */ +int +slk_attr_on(const attr_t attr, void *opt) +{ + + return __slk_attr_on(_cursesi_screen, attr, opt); +} + +/* + * slk_attroff -- + * Test and unset attributes on ripped off slk window. + */ +int +slk_attroff(const chtype attr) +{ + + return __slk_attroff(_cursesi_screen, attr); +} + +/* + * slk_attr_off -- + * Test and unset wide attributes on ripped off slk window. + */ +int +slk_attr_off(const attr_t attr, void *opt) +{ + + return __slk_attr_off(_cursesi_screen, attr, opt); +} + +/* + * slk_attrset -- + * Set attributes and color pair on ripped off slk window. + */ +int +slk_attrset(const chtype attr) +{ + + return __slk_attrset(_cursesi_screen, attr); +} + +/* + * slk_attr_set -- + * Set wide attributes and color pair on ripped off slk window. + */ +int +slk_attr_set(const attr_t attr, short pair, void *opt) +{ + + return __slk_attr_set(_cursesi_screen, attr, pair, opt); +} + +/* + * slk_clear -- + * Clear slk from the current screen. + */ +int +slk_clear(void) +{ + + return __slk_clear(_cursesi_screen); +} + +/* + * slk_color -- + * Set color pair on ripped off slk window. + */ +int +slk_color(short pair) +{ + + return __slk_color(_cursesi_screen, pair); +} + +/* + * slk_label -- + * Return a pointer to the saved label for key labnum. + */ +char * +slk_label(int labnum) +{ + + return __slk_label(_cursesi_screen, labnum); +} + +/* + * slk_wnoutrefresh -- + * Add the contents of the ripped off slk window to the virtual window. + */ +int +slk_noutrefresh(void) +{ + + return __slk_noutrefresh(_cursesi_screen); +} + +/* + * slk_refresh -- + * Force a refresh for the ripped off slk window. + */ +int +slk_refresh(void) +{ + + if (slk_noutrefresh() == ERR) + return ERR; + return doupdate(); +} + +/* + * slk_restore -- + * Retore slk to the screen after a slk_clear. + */ +int +slk_restore(void) +{ + + return __slk_restore(_cursesi_screen); +} + +/* + * slk_set -- + * Sets the text of the label specified by labnum + * and how it is displayed. + */ +int +slk_set(int labnum, const char *label, int justify) +{ + + return __slk_set(_cursesi_screen, labnum, label, justify); +} + +/* + * slk_touch -- + * Sets the ripped off slk window as modified. + */ +int +slk_touch(void) +{ + + return __slk_touch(_cursesi_screen); +} + +/* + * slk_wset -- + * Sets the wide text of the label specified by labnum + * and how it is displayed. + */ +int +slk_wset(int labnum, const wchar_t *label, int justify) +{ + + return __slk_wset(_cursesi_screen, labnum, label, justify); +} + +/* + * __slk_attron -- + * Test and set attributes on ripped off slk window. + */ +static int +__slk_attron(SCREEN *screen, const chtype attr) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattron(screen->slk_window, attr); +} + +/* + * __slk_attr_on -- + * Test and set wide attributes on ripped off slk window. + */ +static int +__slk_attr_on(SCREEN *screen, const attr_t attr, void *opt) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattr_on(screen->slk_window, attr, opt); +} + +/* + * __slk_attroff -- + * Test and unset attributes on ripped off slk window. + */ +static int +__slk_attroff(SCREEN *screen, const chtype attr) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattroff(screen->slk_window, attr); +} + +/* + * __slk_attr_off -- + * Test and unset wide attributes on ripped off slk window. + */ +static int +__slk_attr_off(SCREEN *screen, const attr_t attr, void *opt) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattr_off(screen->slk_window, attr, opt); +} + +/* + * __slk_attrset -- + * Set attributes and color pair on ripped off slk window. + */ +static int +__slk_attrset(SCREEN *screen, const chtype attr) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattrset(screen->slk_window, attr); +} + +/* + * __slk_attr_set -- + * Set wide attributes and color pair on ripped off slk window. + */ +static int +__slk_attr_set(SCREEN *screen, const attr_t attr, short pair, void *opt) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wattr_set(screen->slk_window, attr, pair, opt); +} + +/* + * __slk_clear -- + * Clear slk from the current screen. + */ +static int +__slk_clear(SCREEN *screen) +{ + + assert(screen != NULL); + screen->slk_hidden = true; + if (screen->is_term_slk) { + if (t_label_off(screen->term) == NULL) + return ERR; + return ti_putp(screen->term, + ti_tiparm(screen->term, t_label_off(screen->term))); + } + if (screen->slk_window == NULL) + return ERR; + werase(screen->slk_window); + return wrefresh(screen->slk_window); +} + +/* + * __slk_color -- + * Set color pair on ripped off slk window. + */ +static int +__slk_color(SCREEN *screen, short pair) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wcolor_set(screen->slk_window, pair, NULL); +} + + +/* + * __slk_label -- + * Return a pointer to the saved label for key labnum. + */ +static char * +__slk_label(SCREEN *screen, int labnum) +{ + + assert(screen != NULL); + if (labnum < 1 || labnum > screen->slk_nlabels) + return NULL; + return screen->slk_labels[--labnum].text; +} + +/* + * __slk_wnoutrefresh -- + * Add the contents of the ripped off slk window to the virtual window. + */ +int +__slk_noutrefresh(SCREEN *screen) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return wnoutrefresh(screen->slk_window); +} + +/* + * __slk_restore -- + * Retore slk to the screen after a slk_clear. + */ +static int +__slk_restore(SCREEN *screen) +{ + + assert(screen != NULL); + screen->slk_hidden = false; + if (screen->is_term_slk) { + if (t_label_on(screen->term) == NULL) + return ERR; + return ti_putp(screen->term, + ti_tiparm(screen->term, t_label_on(screen->term))); + } + if (screen->slk_window == NULL) + return ERR; + if (__slk_redraw(screen) == ERR) + return ERR; + return wrefresh(screen->slk_window); +} + +/* + * __slk_set -- + * Sets the text of the label specified by labnum + * and how it is displayed. + */ +static int +__slk_set(SCREEN *screen, int labnum, const char *label, int justify) +{ + struct __slk_label *l; + const char *end; + size_t len; + char *text; +#ifdef HAVE_WCHAR + wchar_t wc; + size_t wc_len; +#endif + + assert(screen != NULL); + /* Check args. */ + if (labnum < 1 || labnum > screen->slk_nlabels) + return ERR; + switch(justify) { + case SLK_JUSTIFY_LEFT: + case SLK_JUSTIFY_CENTER: + case SLK_JUSTIFY_RIGHT: + break; + default: + return ERR; + } + if (label == NULL) + label = ""; + + /* Skip leading whitespace. */ + while(isspace((unsigned char)*label)) + label++; + /* Grab end. */ + end = label; + +#ifdef HAVE_WCHAR + len = 0; + while (*end != '\0') { + if ((wc_len = mbrtowc(0, end, strlen(end), &screen->sp)) == -1) + return ERR; + mbrtowc(&wc, end, wc_len, &screen->sp); + if (!iswprint((wint_t)wc)) + break; + len += wcwidth(wc); + end += wc_len; + } +#else + while(isprint((unsigned char)*end)) + end++; + len = end - label; +#endif + + /* Take a backup, in-case we can grow the label. */ + if ((text = strndup(label, len)) == NULL) + return ERR; + + /* All checks out, assign. */ + l = &screen->slk_labels[--labnum]; /* internal zero based index */ + l->text = text; + l->justify = justify; + + __slk_set_finalise(screen, labnum); + return OK; +} + +/* + * __slk_touch -- + * Sets the ripped off slk window as modified. + */ +static int +__slk_touch(SCREEN *screen) +{ + + assert(screen != NULL); + if (screen->slk_window == NULL) + return ERR; + return touchwin(screen->slk_window); +} + +/* + * __slk_wset -- + * Sets the wide text of the label specified by labnum + * and how it is displayed. + */ +static int +__slk_wset(SCREEN *screen, int labnum, const wchar_t *label, int justify) +{ +#ifdef HAVE_WCHAR + const wchar_t *olabel; + size_t len; + char *str; + int result = ERR; + + assert(screen != NULL); + olabel = label; + if ((len = wcsrtombs(NULL, &olabel, 0, &screen->sp)) == -1) + return ERR; + len++; /* We need to store the NULL character. */ + if ((str = malloc(len)) == NULL) + return ERR; + olabel = label; + if (wcsrtombs(str, &olabel, len, &screen->sp) == -1) + goto out; + result = __slk_set(screen, labnum, str, justify); +out: + free(str); + return result; +#else + return ERR; +#endif +} + + +/* + * __slk_init -- + * Allocate structures. + */ +int +__slk_init(SCREEN *screen) +{ + + __slk_free(screen); /* safety */ + + screen->slk_format = slk_fmt; + switch(screen->slk_format) { + case SLK_FMT_3_2_3: + case SLK_FMT_4_4: + screen->slk_nlabels = 8; + break; + default: /* impossible */ + return ERR; + } + + screen->slk_labels = calloc(screen->slk_nlabels, + sizeof(*screen->slk_labels)); + if (screen->slk_labels == NULL) + return ERR; + + screen->is_term_slk = + t_plab_norm(screen->term) != NULL && + t_num_labels(screen->term) > 0; + if (screen->is_term_slk) { + __unripoffline(__slk_ripoffline); + screen->slk_nlabels = t_num_labels(screen->term); + screen->slk_label_len = t_label_width(screen->term); + /* XXX label_height, label_format? */ + } + + return OK; +} + +/* + * __slk_free -- + * Free allocates resources. + */ +void +__slk_free(SCREEN *screen) +{ + int i; + + if (screen->slk_window != NULL) + delwin(screen->slk_window); + for (i = 0; i < screen->slk_nlabels; i++) + free(screen->slk_labels[i].text); + free(screen->slk_labels); +} + +/* + * __slk_ripoffline -- + * ripoffline callback to accept a WINDOW to create our keys. + */ +static int +__slk_ripoffline(WINDOW *window, int cols) +{ + + if (window == NULL) + return ERR; + assert(window->screen->slk_window == NULL); + window->screen->slk_window = window; + wattron(window, + (t_no_color_video(window->screen->term) & 1) == 0 + ? A_STANDOUT : A_REVERSE); + __slk_resize(window->screen, cols); + return OK; +} + +/* + * __slk_resize -- + * Size and position the labels in the ripped off slk window. + */ +int +__slk_resize(SCREEN *screen, int cols) +{ + int x = 0; + struct __slk_label *l; + + assert(screen != NULL); + if (screen->is_term_slk || screen->slk_nlabels == 0) + return OK; + + screen->slk_label_len = (cols / screen->slk_nlabels) - 1; + if (screen->slk_label_len > SLK_SIZE) + screen->slk_label_len = SLK_SIZE; + + l = screen->slk_labels; + + switch(screen->slk_format) { + case SLK_FMT_3_2_3: + /* Left 3 */ + (l++)->x = x; + (l++)->x = (x += screen->slk_label_len + 1); + (l++)->x = (x += screen->slk_label_len + 1); + + /* Middle 2 */ + x = cols / 2; + (l++)->x = x -(screen->slk_label_len + 1); + (l++)->x = x + 1; + + /* Right 3 */ + x = (cols - ((screen->slk_label_len + 1) * 3)) + 1; + (l++)->x = x; + (l++)->x = (x += screen->slk_label_len + 1); + (l++)->x = (x += screen->slk_label_len + 1); + break; + + case SLK_FMT_4_4: + { + int i, half; + + half = screen->slk_nlabels / 2; + for (i = 0; i < screen->slk_nlabels; i++) { + (l++)->x = x; + x += screen->slk_label_len; + /* Split labels in half */ + if (i == half - 1) + x = cols - (screen->slk_label_len * half) + 1; + } + break; + } + } + + /* Write text to the labels. */ + for (x = 0; x < screen->slk_nlabels; x++) + __slk_set_finalise(screen, x); + + return __slk_redraw(screen); +} + +/* + * __slk_set_finalise -- + * Does the grunt work of positioning and sizing the text in the label. + */ +static int +__slk_set_finalise(SCREEN *screen, int labnum) +{ + struct __slk_label *l; + size_t spc, len, x; + char *p; + + l = &screen->slk_labels[labnum]; + spc = screen->slk_label_len; + +#ifdef HAVE_WCHAR + len = 0; + if (l->text != NULL) { + wchar_t wc; + + p = l->text; + while (*p != '\0') { + if ((x = mbrtowc(0, p, strlen(p), &screen->sp)) == -1) + return ERR; + mbrtowc(&wc, p, x, &screen->sp); + if (len + wcwidth(wc) > spc) + break; + len += wcwidth(wc); + p += x; + } + } +#else + len = l->text == NULL ? 0 : strlen(l->text); + if (len > spc) + len = spc; +#endif + + switch(l->justify) { + case SLK_JUSTIFY_LEFT: + x = 0; + break; + case SLK_JUSTIFY_CENTER: + x = (spc - len) / 2; + if (x + len > spc) + x--; + break; + case SLK_JUSTIFY_RIGHT: + x = spc - len; + break; + default: + return ERR; /* impossible */ + } + + p = l->label; + if (x != 0) { + memset(p, ' ', x); + p += x; + spc -= x; + } + if (len != 0) { + memcpy(p, l->text, len); + p += len; + spc -= len; + } + if (spc != 0) { + memset(p, ' ', spc); + p += spc; + } + *p = '\0'; /* Terminate for plab_norm. */ + + return __slk_draw(screen, labnum); +} + +/* + * __slk_draw -- + * Draws the specified key. + */ +static int +__slk_draw(SCREEN *screen, int labnum) +{ + const struct __slk_label *l; + + if (screen->slk_hidden) + return OK; + + l = &screen->slk_labels[labnum]; + if (screen->is_term_slk) + return ti_putp(screen->term, + ti_tiparm(screen->term, + t_plab_norm(screen->term), labnum + 1, l->label)); + else if (screen->slk_window != NULL) + return mvwaddnstr(screen->slk_window, 0, l->x, + l->label, screen->slk_label_len); + else + return ERR; +} + +/* + * __slk_draw -- + * Draws all the keys. + */ +static int +__slk_redraw(SCREEN *screen) +{ + int i, result = OK; + + for (i = 0; i < screen->slk_nlabels; i++) { + if (__slk_draw(screen, i) == ERR) + result = ERR; + } + return result; +}