72fff96d9b3153238bb04812e17b7c64b57f8bc1
[ncurses.git] / ncurses / base / lib_slk.c
1 /****************************************************************************
2  * Copyright (c) 1998-2000,2002 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  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
31  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32  ****************************************************************************/
33
34 /*
35  *      lib_slk.c
36  *      Soft key routines.
37  */
38
39 #include <curses.priv.h>
40
41 #include <ctype.h>
42 #include <term.h>               /* num_labels, label_*, plab_norm */
43
44 MODULE_ID("$Id: lib_slk.c,v 1.24 2002/09/28 17:46:40 tom Exp $")
45
46 /*
47  * We'd like to move these into the screen context structure, but cannot,
48  * because slk_init() is called before initscr()/newterm().
49  */
50 NCURSES_EXPORT_VAR(int)
51 _nc_slk_format = 0;             /* one more than format specified in slk_init() */
52
53 /*
54  * Paint the info line for the PC style SLK emulation.
55  *
56  */
57 static void
58 slk_paint_info(WINDOW *win)
59 {
60     if (win && SP->slk_format == 4) {
61         int i;
62
63         mvwhline(win, 0, 0, 0, getmaxx(win));
64         wmove(win, 0, 0);
65
66         for (i = 0; i < SP->_slk->maxlab; i++) {
67             mvwprintw(win, 0, SP->_slk->ent[i].x, "F%d", i + 1);
68         }
69     }
70 }
71
72 /*
73  * Initialize soft labels.
74  * Called from newterm()
75  */
76 NCURSES_EXPORT(int)
77 _nc_slk_initialize(WINDOW *stwin, int cols)
78 {
79     int i, x;
80     int res = OK;
81     char *p;
82     unsigned max_length;
83
84     T(("slk_initialize()"));
85
86     if (SP->_slk) {             /* we did this already, so simply return */
87         return (OK);
88     } else if ((SP->_slk = typeCalloc(SLK, 1)) == 0)
89         return (ERR);
90
91     SP->_slk->ent = NULL;
92     SP->_slk->buffer = NULL;
93     SP->_slk->attr = A_STANDOUT;
94
95     SP->_slk->maxlab = ((num_labels > 0)
96                         ? num_labels
97                         : MAX_SKEY(_nc_slk_format));
98     SP->_slk->maxlen = ((num_labels > 0)
99                         ? label_width * label_height
100                         : MAX_SKEY_LEN(_nc_slk_format));
101     SP->_slk->labcnt = ((SP->_slk->maxlab < MAX_SKEY(_nc_slk_format))
102                         ? MAX_SKEY(_nc_slk_format)
103                         : SP->_slk->maxlab);
104
105     if (SP->_slk->maxlen <= 0
106         || SP->_slk->labcnt <= 0
107         || (SP->_slk->ent = typeCalloc(slk_ent,
108                                        (unsigned) SP->_slk->labcnt)) == NULL)
109         goto exception;
110
111     max_length = SP->_slk->maxlen;
112     p = SP->_slk->buffer = (char *) calloc((unsigned) (2 * SP->_slk->labcnt),
113                                            (1 + max_length));
114     if (SP->_slk->buffer == NULL)
115         goto exception;
116
117     for (i = 0; i < SP->_slk->labcnt; i++) {
118         SP->_slk->ent[i].text = p;
119         p += (1 + max_length);
120         SP->_slk->ent[i].form_text = p;
121         p += (1 + max_length);
122         memset(SP->_slk->ent[i].form_text, ' ', max_length);
123         SP->_slk->ent[i].visible = (i < SP->_slk->maxlab);
124     }
125     if (_nc_slk_format >= 3) {  /* PC style */
126         int gap = (cols - 3 * (3 + 4 * max_length)) / 2;
127
128         if (gap < 1)
129             gap = 1;
130
131         for (i = x = 0; i < SP->_slk->maxlab; i++) {
132             SP->_slk->ent[i].x = x;
133             x += max_length;
134             x += (i == 3 || i == 7) ? gap : 1;
135         }
136         slk_paint_info(stwin);
137     } else {
138         if (_nc_slk_format == 2) {      /* 4-4 */
139             int gap = cols - (SP->_slk->maxlab * max_length) - 6;
140
141             if (gap < 1)
142                 gap = 1;
143             for (i = x = 0; i < SP->_slk->maxlab; i++) {
144                 SP->_slk->ent[i].x = x;
145                 x += max_length;
146                 x += (i == 3) ? gap : 1;
147             }
148         } else {
149             if (_nc_slk_format == 1) {  /* 1 -> 3-2-3 */
150                 int gap = (cols - (SP->_slk->maxlab * max_length) - 5)
151                 / 2;
152
153                 if (gap < 1)
154                     gap = 1;
155                 for (i = x = 0; i < SP->_slk->maxlab; i++) {
156                     SP->_slk->ent[i].x = x;
157                     x += max_length;
158                     x += (i == 2 || i == 4) ? gap : 1;
159                 }
160             } else
161                 goto exception;
162         }
163     }
164     SP->_slk->dirty = TRUE;
165     if ((SP->_slk->win = stwin) == NULL) {
166       exception:
167         if (SP->_slk) {
168             FreeIfNeeded(SP->_slk->buffer);
169             FreeIfNeeded(SP->_slk->ent);
170             free(SP->_slk);
171             SP->_slk = (SLK *) 0;
172             res = (ERR);
173         }
174     }
175
176     /* We now reset the format so that the next newterm has again
177      * per default no SLK keys and may call slk_init again to
178      * define a new layout. (juergen 03-Mar-1999)
179      */
180     SP->slk_format = _nc_slk_format;
181     _nc_slk_format = 0;
182     return (res);
183 }
184
185 /*
186  * Restore the soft labels on the screen.
187  */
188 NCURSES_EXPORT(int)
189 slk_restore(void)
190 {
191     T((T_CALLED("slk_restore()")));
192
193     if (SP->_slk == NULL)
194         return (ERR);
195     SP->_slk->hidden = FALSE;
196     SP->_slk->dirty = TRUE;
197     /* we have to repaint info line eventually */
198     slk_paint_info(SP->_slk->win);
199
200     returnCode(slk_refresh());
201 }