752 lines
17 KiB
C
752 lines
17 KiB
C
/****************************************************************************
|
|
* apps/graphics/pdcurses/pdc_slk.c
|
|
* Public Domain Curses
|
|
* RCSID("$Id: slk.c,v 1.61 2008/07/13 16:08:18 wmcbrine Exp $")
|
|
*
|
|
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
|
* Adapted by: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* Adapted from the original public domain pdcurses by Gregory Nutt and
|
|
* released as part of NuttX under the 3-clause BSD license:
|
|
*
|
|
* 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.
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
|
|
* COPYRIGHT OWNER 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/* Name: slk
|
|
*
|
|
* Synopsis:
|
|
* int slk_init(int fmt);
|
|
* int slk_set(int labnum, const char *label, int justify);
|
|
* int slk_refresh(void);
|
|
* int slk_noutrefresh(void);
|
|
* char *slk_label(int labnum);
|
|
* int slk_clear(void);
|
|
* int slk_restore(void);
|
|
* int slk_touch(void);
|
|
* int slk_attron(const chtype attrs);
|
|
* int slk_attr_on(const attr_t attrs, void *opts);
|
|
* int slk_attrset(const chtype attrs);
|
|
* int slk_attr_set(const attr_t attrs, short color_pair, void *opts);
|
|
* int slk_attroff(const chtype attrs);
|
|
* int slk_attr_off(const attr_t attrs, void *opts);
|
|
* int slk_color(short color_pair);
|
|
*
|
|
* int slk_wset(int labnum, const wchar_t *label, int justify);
|
|
*
|
|
* int PDC_mouse_in_slk(int y, int x);
|
|
* void PDC_slk_free(void);
|
|
* void PDC_slk_initialize(void);
|
|
*
|
|
* wchar_t *slk_wlabel(int labnum)
|
|
*
|
|
* Description:
|
|
* These functions manipulate a window that contain Soft Label Keys
|
|
* (SLK). To use the SLK functions, a call to slk_init() must be
|
|
* made BEFORE initscr() or newterm(). slk_init() removes 1 or 2
|
|
* lines from the useable screen, depending on the format selected.
|
|
*
|
|
* The line(s) removed from the screen are used as a separate
|
|
* window, in which SLKs are displayed.
|
|
*
|
|
* slk_init() requires a single parameter which describes the
|
|
* format of the SLKs as follows:
|
|
*
|
|
* 0 3-2-3 format
|
|
* 1 4-4 format
|
|
* 2 4-4-4 format (ncurses extension)
|
|
* 3 4-4-4 format with index line (ncurses extension)
|
|
* 2 lines used
|
|
* 55 5-5 format (pdcurses format)
|
|
*
|
|
* slk_refresh(), slk_noutrefresh() and slk_touch() are analogous
|
|
* to refresh(), noutrefresh() and touch().
|
|
*
|
|
* Return Value:
|
|
* All functions return OK on success and ERR on error.
|
|
*
|
|
* Portability X/Open BSD SYS V
|
|
* slk_init Y - Y
|
|
* slk_set Y - Y
|
|
* slk_refresh Y - Y
|
|
* slk_noutrefresh Y - Y
|
|
* slk_label Y - Y
|
|
* slk_clear Y - Y
|
|
* slk_restore Y - Y
|
|
* slk_touch Y - Y
|
|
* slk_attron Y - Y
|
|
* slk_attrset Y - Y
|
|
* slk_attroff Y - Y
|
|
* slk_attr_on Y
|
|
* slk_attr_set Y
|
|
* slk_attr_off Y
|
|
* slk_wset Y
|
|
* PDC_mouse_in_slk - - -
|
|
* PDC_slk_free - - -
|
|
* PDC_slk_initialize - - -
|
|
* slk_wlabel - - -
|
|
*/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "curspriv.h"
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
enum
|
|
{
|
|
LABEL_NORMAL = 8, LABEL_EXTENDED = 10, LABEL_NCURSES_EXTENDED = 12
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static int label_length = 0;
|
|
static int labels = 0;
|
|
static int label_fmt = 0;
|
|
static int label_line = 0;
|
|
static bool hidden = false;
|
|
|
|
static struct SLK
|
|
{
|
|
chtype label[32];
|
|
int len;
|
|
int format;
|
|
int start_col;
|
|
} *slk = (struct SLK *)NULL;
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/* slk_init() is the slk initialization routine.
|
|
* This must be called before initscr().
|
|
*
|
|
* label_fmt = 0, 1 or 55.
|
|
* 0 = 3-2-3 format
|
|
* 1 = 4 - 4 format
|
|
* 2 = 4-4-4 format (ncurses extension for PC 12 function keys)
|
|
* 3 = 4-4-4 format (ncurses extension for PC 12 function keys -
|
|
* with index line)
|
|
* 55 = 5 - 5 format (extended for PC, 10 function keys)
|
|
*/
|
|
|
|
int slk_init(int fmt)
|
|
{
|
|
PDC_LOG(("slk_init() - called\n"));
|
|
|
|
if (SP)
|
|
{
|
|
return ERR;
|
|
}
|
|
|
|
switch (fmt)
|
|
{
|
|
case 0: /* 3 - 2 - 3 */
|
|
labels = LABEL_NORMAL;
|
|
break;
|
|
|
|
case 1: /* 4 - 4 */
|
|
labels = LABEL_NORMAL;
|
|
break;
|
|
|
|
case 2: /* 4 4 4 */
|
|
labels = LABEL_NCURSES_EXTENDED;
|
|
break;
|
|
|
|
case 3: /* 4 4 4 with index */
|
|
labels = LABEL_NCURSES_EXTENDED;
|
|
break;
|
|
|
|
case 55: /* 5 - 5 */
|
|
labels = LABEL_EXTENDED;
|
|
break;
|
|
|
|
default:
|
|
return ERR;
|
|
}
|
|
|
|
label_fmt = fmt;
|
|
|
|
slk = calloc(labels, sizeof(struct SLK));
|
|
if (!slk)
|
|
{
|
|
labels = 0;
|
|
}
|
|
|
|
return slk ? OK : ERR;
|
|
}
|
|
|
|
/* Draw a single button */
|
|
|
|
static void _drawone(int num)
|
|
{
|
|
int col;
|
|
int slen;
|
|
int i;
|
|
|
|
if (hidden)
|
|
{
|
|
return;
|
|
}
|
|
|
|
slen = slk[num].len;
|
|
|
|
switch (slk[num].format)
|
|
{
|
|
case 0: /* LEFT */
|
|
col = 0;
|
|
break;
|
|
|
|
case 1: /* CENTER */
|
|
col = (label_length - slen) / 2;
|
|
|
|
if (col + slen > label_length)
|
|
{
|
|
--col;
|
|
}
|
|
|
|
break;
|
|
|
|
default: /* RIGHT */
|
|
col = label_length - slen;
|
|
break;
|
|
}
|
|
|
|
wmove(SP->slk_winptr, label_line, slk[num].start_col);
|
|
|
|
for (i = 0; i < label_length; ++i)
|
|
{
|
|
waddch(SP->slk_winptr, (i >= col && i < (col + slen)) ?
|
|
slk[num].label[i - col] : ' ');
|
|
}
|
|
}
|
|
|
|
/* Redraw each button */
|
|
|
|
static void _redraw(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < labels; ++i)
|
|
{
|
|
_drawone(i);
|
|
}
|
|
}
|
|
|
|
/* slk_set() Used to set a slk label to a string.
|
|
*
|
|
* labnum = 1 - 8 (or 10) (number of the label)
|
|
* label = string (8 or 7 bytes total), or NULL
|
|
* justify = 0 : left, 1 : center, 2 : right
|
|
*/
|
|
|
|
int slk_set(int labnum, const char *label, int justify)
|
|
{
|
|
#ifdef CONFIG_PDCURSES_WIDE
|
|
wchar_t wlabel[32];
|
|
|
|
PDC_mbstowcs(wlabel, label, 31);
|
|
return slk_wset(labnum, wlabel, justify);
|
|
#else
|
|
PDC_LOG(("slk_set() - called\n"));
|
|
|
|
if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
|
|
{
|
|
return ERR;
|
|
}
|
|
|
|
labnum--;
|
|
|
|
if (!label || !(*label))
|
|
{
|
|
/* Clear the label */
|
|
|
|
*slk[labnum].label = 0;
|
|
slk[labnum].format = 0;
|
|
slk[labnum].len = 0;
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
|
|
/* Skip leading spaces */
|
|
|
|
while (label[j] == ' ')
|
|
{
|
|
j++;
|
|
}
|
|
|
|
/* Copy it */
|
|
|
|
for (i = 0; i < label_length; i++)
|
|
{
|
|
chtype ch = label[i + j];
|
|
|
|
slk[labnum].label[i] = ch;
|
|
|
|
if (!ch)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Drop trailing spaces */
|
|
|
|
while ((i + j) && (label[i + j - 1] == ' '))
|
|
{
|
|
i--;
|
|
}
|
|
|
|
slk[labnum].label[i] = 0;
|
|
slk[labnum].format = justify;
|
|
slk[labnum].len = i;
|
|
}
|
|
|
|
_drawone(labnum);
|
|
return OK;
|
|
#endif
|
|
}
|
|
|
|
int slk_refresh(void)
|
|
{
|
|
PDC_LOG(("slk_refresh() - called\n"));
|
|
|
|
return (slk_noutrefresh() == ERR) ? ERR : doupdate();
|
|
}
|
|
|
|
int slk_noutrefresh(void)
|
|
{
|
|
PDC_LOG(("slk_noutrefresh() - called\n"));
|
|
|
|
return wnoutrefresh(SP->slk_winptr);
|
|
}
|
|
|
|
char *slk_label(int labnum)
|
|
{
|
|
static char temp[33];
|
|
#ifdef CONFIG_PDCURSES_WIDE
|
|
wchar_t *wtemp = slk_wlabel(labnum);
|
|
|
|
PDC_wcstombs(temp, wtemp, 32);
|
|
#else
|
|
chtype *p;
|
|
int i;
|
|
|
|
PDC_LOG(("slk_label() - called\n"));
|
|
|
|
if (labnum < 1 || labnum > labels)
|
|
{
|
|
return (char *)0;
|
|
}
|
|
|
|
for (i = 0, p = slk[labnum - 1].label; *p; i++)
|
|
{
|
|
temp[i] = *p++;
|
|
}
|
|
|
|
temp[i] = '\0';
|
|
#endif
|
|
|
|
return temp;
|
|
}
|
|
|
|
int slk_clear(void)
|
|
{
|
|
PDC_LOG(("slk_clear() - called\n"));
|
|
|
|
hidden = true;
|
|
werase(SP->slk_winptr);
|
|
return wrefresh(SP->slk_winptr);
|
|
}
|
|
|
|
int slk_restore(void)
|
|
{
|
|
PDC_LOG(("slk_restore() - called\n"));
|
|
|
|
hidden = false;
|
|
_redraw();
|
|
return wrefresh(SP->slk_winptr);
|
|
}
|
|
|
|
int slk_touch(void)
|
|
{
|
|
PDC_LOG(("slk_touch() - called\n"));
|
|
|
|
return touchwin(SP->slk_winptr);
|
|
}
|
|
|
|
int slk_attron(const chtype attrs)
|
|
{
|
|
int rc;
|
|
|
|
PDC_LOG(("slk_attron() - called\n"));
|
|
|
|
rc = wattron(SP->slk_winptr, attrs);
|
|
_redraw();
|
|
return rc;
|
|
}
|
|
|
|
int slk_attr_on(const attr_t attrs, void *opts)
|
|
{
|
|
PDC_LOG(("slk_attr_on() - called\n"));
|
|
|
|
return slk_attron(attrs);
|
|
}
|
|
|
|
int slk_attroff(const chtype attrs)
|
|
{
|
|
int rc;
|
|
|
|
PDC_LOG(("slk_attroff() - called\n"));
|
|
|
|
rc = wattroff(SP->slk_winptr, attrs);
|
|
_redraw();
|
|
return rc;
|
|
}
|
|
|
|
int slk_attr_off(const attr_t attrs, void *opts)
|
|
{
|
|
PDC_LOG(("slk_attr_off() - called\n"));
|
|
|
|
return slk_attroff(attrs);
|
|
}
|
|
|
|
int slk_attrset(const chtype attrs)
|
|
{
|
|
int rc;
|
|
|
|
PDC_LOG(("slk_attrset() - called\n"));
|
|
|
|
rc = wattrset(SP->slk_winptr, attrs);
|
|
_redraw();
|
|
return rc;
|
|
}
|
|
|
|
int slk_color(short color_pair)
|
|
{
|
|
int rc;
|
|
|
|
PDC_LOG(("slk_color() - called\n"));
|
|
|
|
rc = wcolor_set(SP->slk_winptr, color_pair, NULL);
|
|
_redraw();
|
|
return rc;
|
|
}
|
|
|
|
int slk_attr_set(const attr_t attrs, short color_pair, void *opts)
|
|
{
|
|
PDC_LOG(("slk_attr_set() - called\n"));
|
|
|
|
return slk_attrset(attrs | COLOR_PAIR(color_pair));
|
|
}
|
|
|
|
static void _slk_calc(void)
|
|
{
|
|
int i, center, col = 0;
|
|
label_length = COLS / labels;
|
|
|
|
if (label_length > 31)
|
|
{
|
|
label_length = 31;
|
|
}
|
|
|
|
switch (label_fmt)
|
|
{
|
|
case 0: /* 3 - 2 - 3 F-Key layout */
|
|
|
|
--label_length;
|
|
|
|
slk[0].start_col = col;
|
|
slk[1].start_col = (col += label_length);
|
|
slk[2].start_col = (col += label_length);
|
|
|
|
center = COLS / 2;
|
|
|
|
slk[3].start_col = center - label_length + 1;
|
|
slk[4].start_col = center + 1;
|
|
|
|
col = COLS - (label_length * 3) + 1;
|
|
|
|
slk[5].start_col = col;
|
|
slk[6].start_col = (col += label_length);
|
|
slk[7].start_col = (col += label_length);
|
|
break;
|
|
|
|
case 1: /* 4 - 4 F-Key layout */
|
|
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
slk[i].start_col = col;
|
|
col += label_length;
|
|
|
|
if (i == 3)
|
|
{
|
|
col = COLS - (label_length * 4) + 1;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 2: /* 4 4 4 F-Key layout */
|
|
case 3: /* 4 4 4 F-Key layout with index */
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
slk[i].start_col = col;
|
|
col += label_length;
|
|
}
|
|
|
|
center = COLS / 2;
|
|
|
|
slk[4].start_col = center - (label_length * 2) + 1;
|
|
slk[5].start_col = center - label_length - 1;
|
|
slk[6].start_col = center + 1;
|
|
slk[7].start_col = center + label_length + 1;
|
|
|
|
col = COLS - (label_length * 4) + 1;
|
|
|
|
for (i = 8; i < 12; i++)
|
|
{
|
|
slk[i].start_col = col;
|
|
col += label_length;
|
|
}
|
|
|
|
break;
|
|
|
|
default: /* 5 - 5 F-Key layout */
|
|
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
slk[i].start_col = col;
|
|
col += label_length;
|
|
|
|
if (i == 4)
|
|
{
|
|
col = COLS - (label_length * 5) + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
--label_length;
|
|
|
|
/* make sure labels are all in window */
|
|
|
|
_redraw();
|
|
}
|
|
|
|
void PDC_slk_initialize(void)
|
|
{
|
|
if (slk)
|
|
{
|
|
if (label_fmt == 3)
|
|
{
|
|
SP->slklines = 2;
|
|
label_line = 1;
|
|
}
|
|
else
|
|
{
|
|
SP->slklines = 1;
|
|
}
|
|
|
|
if (!SP->slk_winptr)
|
|
{
|
|
if (!(SP->slk_winptr = newwin(SP->slklines, COLS,
|
|
LINES - SP->slklines, 0)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
wattrset(SP->slk_winptr, A_REVERSE);
|
|
}
|
|
|
|
_slk_calc();
|
|
|
|
/* If we have an index line, display it now */
|
|
|
|
if (label_fmt == 3)
|
|
{
|
|
chtype save_attr;
|
|
int i;
|
|
|
|
save_attr = SP->slk_winptr->_attrs;
|
|
wattrset(SP->slk_winptr, A_NORMAL);
|
|
wmove(SP->slk_winptr, 0, 0);
|
|
whline(SP->slk_winptr, 0, COLS);
|
|
|
|
for (i = 0; i < labels; i++)
|
|
{
|
|
mvwprintw(SP->slk_winptr, 0, slk[i].start_col, "F%d", i + 1);
|
|
}
|
|
|
|
SP->slk_winptr->_attrs = save_attr;
|
|
}
|
|
|
|
touchwin(SP->slk_winptr);
|
|
}
|
|
}
|
|
|
|
void PDC_slk_free(void)
|
|
{
|
|
if (slk)
|
|
{
|
|
if (SP->slk_winptr)
|
|
{
|
|
delwin(SP->slk_winptr);
|
|
SP->slk_winptr = (WINDOW *) NULL;
|
|
}
|
|
|
|
free(slk);
|
|
slk = (struct SLK *)NULL;
|
|
|
|
label_length = 0;
|
|
labels = 0;
|
|
label_fmt = 0;
|
|
label_line = 0;
|
|
hidden = false;
|
|
}
|
|
}
|
|
|
|
int PDC_mouse_in_slk(int y, int x)
|
|
{
|
|
int i;
|
|
|
|
PDC_LOG(("PDC_mouse_in_slk() - called: y->%d x->%d\n", y, x));
|
|
|
|
/* If the line on which the mouse was clicked is NOT the last line of the
|
|
* screen, we are not interested in it.
|
|
*/
|
|
|
|
if (!slk || !SP->slk_winptr || (y != SP->slk_winptr->_begy + label_line))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < labels; i++)
|
|
{
|
|
if (x >= slk[i].start_col && x < (slk[i].start_col + label_length))
|
|
{
|
|
return i + 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_PDCURSES_WIDE
|
|
int slk_wset(int labnum, const wchar_t * label, int justify)
|
|
{
|
|
PDC_LOG(("slk_wset() - called\n"));
|
|
|
|
if (labnum < 1 || labnum > labels || justify < 0 || justify > 2)
|
|
{
|
|
return ERR;
|
|
}
|
|
|
|
labnum--;
|
|
|
|
if (!label || !(*label))
|
|
{
|
|
/* Clear the label */
|
|
|
|
*slk[labnum].label = 0;
|
|
slk[labnum].format = 0;
|
|
slk[labnum].len = 0;
|
|
}
|
|
else
|
|
{
|
|
int i, j = 0;
|
|
|
|
/* Skip leading spaces */
|
|
|
|
while (label[j] == L' ')
|
|
{
|
|
j++;
|
|
}
|
|
|
|
/* Copy it */
|
|
|
|
for (i = 0; i < label_length; i++)
|
|
{
|
|
chtype ch = label[i + j];
|
|
|
|
slk[labnum].label[i] = ch;
|
|
|
|
if (!ch)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Drop trailing spaces */
|
|
|
|
while ((i + j) && (label[i + j - 1] == L' '))
|
|
{
|
|
i--;
|
|
}
|
|
|
|
slk[labnum].label[i] = 0;
|
|
slk[labnum].format = justify;
|
|
slk[labnum].len = i;
|
|
}
|
|
|
|
_drawone(labnum);
|
|
return OK;
|
|
}
|
|
|
|
wchar_t *slk_wlabel(int labnum)
|
|
{
|
|
static wchar_t temp[33];
|
|
chtype *p;
|
|
int i;
|
|
|
|
PDC_LOG(("slk_wlabel() - called\n"));
|
|
|
|
if (labnum < 1 || labnum > labels)
|
|
{
|
|
return (wchar_t *) 0;
|
|
}
|
|
|
|
for (i = 0, p = slk[labnum - 1].label; *p; i++)
|
|
{
|
|
temp[i] = *p++;
|
|
}
|
|
|
|
temp[i] = '\0';
|
|
return temp;
|
|
}
|
|
#endif
|