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;
+}

Reply via email to