lib_slk.c revision 166124
1/****************************************************************************
2 * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc.              *
3 *                                                                          *
4 * Permission is hereby granted, free of charge, to any person obtaining a  *
5 * copy of this software and associated documentation files (the            *
6 * "Software"), to deal in the Software without restriction, including      *
7 * without limitation the rights to use, copy, modify, merge, publish,      *
8 * distribute, distribute with modifications, sublicense, and/or sell       *
9 * copies of the Software, and to permit persons to whom the Software is    *
10 * furnished to do so, subject to the following conditions:                 *
11 *                                                                          *
12 * The above copyright notice and this permission notice shall be included  *
13 * in all copies or substantial portions of the Software.                   *
14 *                                                                          *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22 *                                                                          *
23 * Except as contained in this notice, the name(s) of the above copyright   *
24 * holders shall not be used in advertising or otherwise to promote the     *
25 * sale, use or other dealings in this Software without prior written       *
26 * authorization.                                                           *
27 ****************************************************************************/
28
29/****************************************************************************
30 *  Authors:                                                                *
31 *          Gerhard Fuernkranz                      1993 (original)         *
32 *          Zeyd M. Ben-Halim                       1992,1995 (sic)         *
33 *          Eric S. Raymond                                                 *
34 *          Juergen Pfeifer                         1996-on                 *
35 *          Thomas E. Dickey                                                *
36 ****************************************************************************/
37
38/*
39 *	lib_slk.c
40 *	Soft key routines.
41 */
42
43#include <curses.priv.h>
44
45#include <ctype.h>
46#include <term.h>		/* num_labels, label_*, plab_norm */
47
48MODULE_ID("$Id: lib_slk.c,v 1.30 2005/01/08 21:56:36 tom Exp $")
49
50/*
51 * We'd like to move these into the screen context structure, but cannot,
52 * because slk_init() is called before initscr()/newterm().
53 */
54NCURSES_EXPORT_VAR(int)
55_nc_slk_format = 0;		/* one more than format specified in slk_init() */
56
57/*
58 * Paint the info line for the PC style SLK emulation.
59 *
60 */
61static void
62slk_paint_info(WINDOW *win)
63{
64    if (win && SP->slk_format == 4) {
65	int i;
66
67	mvwhline(win, 0, 0, 0, getmaxx(win));
68	wmove(win, 0, 0);
69
70	for (i = 0; i < SP->_slk->maxlab; i++) {
71	    mvwprintw(win, 0, SP->_slk->ent[i].ent_x, "F%d", i + 1);
72	}
73    }
74}
75
76/*
77 * Free any memory related to soft labels, return an error.
78 */
79static int
80slk_failed(void)
81{
82    if (SP->_slk) {
83	FreeIfNeeded(SP->_slk->ent);
84	free(SP->_slk);
85	SP->_slk = (SLK *) 0;
86    }
87    return ERR;
88}
89
90/*
91 * Initialize soft labels.
92 * Called from newterm()
93 */
94NCURSES_EXPORT(int)
95_nc_slk_initialize(WINDOW *stwin, int cols)
96{
97    int i, x;
98    int res = OK;
99    unsigned max_length;
100
101    T((T_CALLED("_nc_slk_initialize()")));
102
103    if (SP->_slk) {		/* we did this already, so simply return */
104	returnCode(OK);
105    } else if ((SP->_slk = typeCalloc(SLK, 1)) == 0)
106	returnCode(ERR);
107
108    SP->_slk->ent = NULL;
109
110    /*
111     * If we use colors, vidputs() will suppress video attributes that conflict
112     * with colors.  In that case, we're still guaranteed that "reverse" would
113     * work.
114     */
115    if ((no_color_video & 1) == 0)
116	SetAttr(SP->_slk->attr, A_STANDOUT);
117    else
118	SetAttr(SP->_slk->attr, A_REVERSE);
119
120    SP->_slk->maxlab = ((num_labels > 0)
121			? num_labels
122			: MAX_SKEY(_nc_slk_format));
123    SP->_slk->maxlen = ((num_labels > 0)
124			? label_width * label_height
125			: MAX_SKEY_LEN(_nc_slk_format));
126    SP->_slk->labcnt = ((SP->_slk->maxlab < MAX_SKEY(_nc_slk_format))
127			? MAX_SKEY(_nc_slk_format)
128			: SP->_slk->maxlab);
129
130    if (SP->_slk->maxlen <= 0
131	|| SP->_slk->labcnt <= 0
132	|| (SP->_slk->ent = typeCalloc(slk_ent,
133				       (unsigned) SP->_slk->labcnt)) == NULL)
134	returnCode(slk_failed());
135
136    max_length = SP->_slk->maxlen;
137    for (i = 0; i < SP->_slk->labcnt; i++) {
138	size_t used = max_length + 1;
139
140	if ((SP->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used)) == 0)
141	    returnCode(slk_failed());
142	memset(SP->_slk->ent[i].ent_text, 0, used);
143
144	if ((SP->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used)) == 0)
145	    returnCode(slk_failed());
146	memset(SP->_slk->ent[i].form_text, 0, used);
147
148	memset(SP->_slk->ent[i].form_text, ' ', max_length);
149	SP->_slk->ent[i].visible = (i < SP->_slk->maxlab);
150    }
151    if (_nc_slk_format >= 3) {	/* PC style */
152	int gap = (cols - 3 * (3 + 4 * max_length)) / 2;
153
154	if (gap < 1)
155	    gap = 1;
156
157	for (i = x = 0; i < SP->_slk->maxlab; i++) {
158	    SP->_slk->ent[i].ent_x = x;
159	    x += max_length;
160	    x += (i == 3 || i == 7) ? gap : 1;
161	}
162	slk_paint_info(stwin);
163    } else {
164	if (_nc_slk_format == 2) {	/* 4-4 */
165	    int gap = cols - (SP->_slk->maxlab * max_length) - 6;
166
167	    if (gap < 1)
168		gap = 1;
169	    for (i = x = 0; i < SP->_slk->maxlab; i++) {
170		SP->_slk->ent[i].ent_x = x;
171		x += max_length;
172		x += (i == 3) ? gap : 1;
173	    }
174	} else {
175	    if (_nc_slk_format == 1) {	/* 1 -> 3-2-3 */
176		int gap = (cols - (SP->_slk->maxlab * max_length) - 5)
177		/ 2;
178
179		if (gap < 1)
180		    gap = 1;
181		for (i = x = 0; i < SP->_slk->maxlab; i++) {
182		    SP->_slk->ent[i].ent_x = x;
183		    x += max_length;
184		    x += (i == 2 || i == 4) ? gap : 1;
185		}
186	    } else
187		returnCode(slk_failed());
188	}
189    }
190    SP->_slk->dirty = TRUE;
191    if ((SP->_slk->win = stwin) == NULL) {
192	returnCode(slk_failed());
193    }
194
195    /* We now reset the format so that the next newterm has again
196     * per default no SLK keys and may call slk_init again to
197     * define a new layout. (juergen 03-Mar-1999)
198     */
199    SP->slk_format = _nc_slk_format;
200    _nc_slk_format = 0;
201    returnCode(res);
202}
203
204/*
205 * Restore the soft labels on the screen.
206 */
207NCURSES_EXPORT(int)
208slk_restore(void)
209{
210    T((T_CALLED("slk_restore()")));
211
212    if (SP->_slk == NULL)
213	return (ERR);
214    SP->_slk->hidden = FALSE;
215    SP->_slk->dirty = TRUE;
216    /* we have to repaint info line eventually */
217    slk_paint_info(SP->_slk->win);
218
219    returnCode(slk_refresh());
220}
221