Implement POSIX Curses Soft Label Key functions.

This commit is contained in:
roy 2017-01-24 17:27:30 +00:00
parent 9d818e01f4
commit a2ac1ce48c
9 changed files with 1218 additions and 16 deletions

View File

@ -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

View File

@ -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.c addnstr.c attributes.c \
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_addchstr.3 curses_addstr.3 \
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_addchstr.3 addchnstr.3 \
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 \

View File

@ -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, const void *);
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 */

View File

@ -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 attr);
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 *);

244
lib/libcurses/curses_slk.3 Normal file
View File

@ -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 .

View File

@ -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;

View File

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

View File

@ -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 *infd)
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 *infd)
__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)

808
lib/libcurses/slk.c Normal file
View File

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