/************************************************************************
* This file is part of PDCurses. PDCurses is public domain software; *
* you may use it for any purpose. This software is provided AS IS with *
* NO WARRANTY whatsoever. *
* *
* If you use PDCurses in an application, an acknowledgement would be *
* appreciated, but is not mandatory. If you make corrections or *
* enhancements to PDCurses, please forward them to the current *
* maintainer for the benefit of other users. *
* *
* See the file maintain.er for details of the current maintainer. *
************************************************************************/
#include <curspriv.h>
RCSID("$Id: slk.c,v 1.57 2007/06/22 10:01:10 wmcbrine Exp $")
/*man-start**************************************************************
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)
The functions slk_refresh(), slk_noutrefresh() and slk_touch()
are analagous to refresh(), noutrefresh() and touch() functions.
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 - - -
**man-end****************************************************************/
#include <stdlib.h>
enum { LABEL_NORMAL = 8, LABEL_EXTENDED = 10, LABEL_NCURSES_EXTENDED = 12 };
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;
/* 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 i, col, slen;
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;
}
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 PDC_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, 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 PDC_WIDE
wchar_t *wtemp = slk_wlabel(labnum);
PDC_wcstombs(temp, wtemp, 32);
temp[32] = '\0';
#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)) == (WINDOW *)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 PDC_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
|