4bdf8afc45c138ff54bc183c8df693a7d98f7378
[ncurses.git] / ncurses / base / lib_slk.c
1 /****************************************************************************
2  * Copyright (c) 1998-2002,2003 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.28 2003/05/24 21:10:28 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].ent_x, "F%d", i + 1);
68         }
69     }
70 }
71
72 /*
73  * Free any memory related to soft labels, return an error.
74  */
75 static int
76 slk_failed(void)
77 {
78     if (SP->_slk) {
79         FreeIfNeeded(SP->_slk->ent);
80         free(SP->_slk);
81         SP->_slk = (SLK *) 0;
82     }
83     return ERR;
84 }
85
86 /*
87  * Initialize soft labels.
88  * Called from newterm()
89  */
90 NCURSES_EXPORT(int)
91 _nc_slk_initialize(WINDOW *stwin, int cols)
92 {
93     int i, x;
94     int res = OK;
95     unsigned max_length;
96
97     T((T_CALLED("_nc_slk_initialize()")));
98
99     if (SP->_slk) {             /* we did this already, so simply return */
100         returnCode(OK);
101     } else if ((SP->_slk = typeCalloc(SLK, 1)) == 0)
102         returnCode(ERR);
103
104     SP->_slk->ent = NULL;
105
106     /*
107      * If we use colors, vidputs() will suppress video attributes that conflict
108      * with colors.  In that case, we're still guaranteed that "reverse" would
109      * work.
110      */
111     if ((no_color_video & 1) == 0)
112         SP->_slk->attr = A_STANDOUT;
113     else
114         SP->_slk->attr = A_REVERSE;
115
116     SP->_slk->maxlab = ((num_labels > 0)
117                         ? num_labels
118                         : MAX_SKEY(_nc_slk_format));
119     SP->_slk->maxlen = ((num_labels > 0)
120                         ? label_width * label_height
121                         : MAX_SKEY_LEN(_nc_slk_format));
122     SP->_slk->labcnt = ((SP->_slk->maxlab < MAX_SKEY(_nc_slk_format))
123                         ? MAX_SKEY(_nc_slk_format)
124                         : SP->_slk->maxlab);
125
126     if (SP->_slk->maxlen <= 0
127         || SP->_slk->labcnt <= 0
128         || (SP->_slk->ent = typeCalloc(slk_ent,
129                                        (unsigned) SP->_slk->labcnt)) == NULL)
130         returnCode(slk_failed());
131
132     max_length = SP->_slk->maxlen;
133     for (i = 0; i < SP->_slk->labcnt; i++) {
134
135         if ((SP->_slk->ent[i].ent_text = (char *)_nc_doalloc(0, max_length + 1)) == 0)
136             returnCode(slk_failed());
137         memset(SP->_slk->ent[i].ent_text, 0, max_length + 1);
138
139         if ((SP->_slk->ent[i].form_text = (char *)_nc_doalloc(0, max_length + 1)) == 0)
140             returnCode(slk_failed());
141         memset(SP->_slk->ent[i].form_text, 0, max_length + 1);
142
143         memset(SP->_slk->ent[i].form_text, ' ', max_length);
144         SP->_slk->ent[i].visible = (i < SP->_slk->maxlab);
145     }
146     if (_nc_slk_format >= 3) {  /* PC style */
147         int gap = (cols - 3 * (3 + 4 * max_length)) / 2;
148
149         if (gap < 1)
150             gap = 1;
151
152         for (i = x = 0; i < SP->_slk->maxlab; i++) {
153             SP->_slk->ent[i].ent_x = x;
154             x += max_length;
155             x += (i == 3 || i == 7) ? gap : 1;
156         }
157         slk_paint_info(stwin);
158     } else {
159         if (_nc_slk_format == 2) {      /* 4-4 */
160             int gap = cols - (SP->_slk->maxlab * max_length) - 6;
161
162             if (gap < 1)
163                 gap = 1;
164             for (i = x = 0; i < SP->_slk->maxlab; i++) {
165                 SP->_slk->ent[i].ent_x = x;
166                 x += max_length;
167                 x += (i == 3) ? gap : 1;
168             }
169         } else {
170             if (_nc_slk_format == 1) {  /* 1 -> 3-2-3 */
171                 int gap = (cols - (SP->_slk->maxlab * max_length) - 5)
172                 / 2;
173
174                 if (gap < 1)
175                     gap = 1;
176                 for (i = x = 0; i < SP->_slk->maxlab; i++) {
177                     SP->_slk->ent[i].ent_x = x;
178                     x += max_length;
179                     x += (i == 2 || i == 4) ? gap : 1;
180                 }
181             } else
182                 returnCode(slk_failed());
183         }
184     }
185     SP->_slk->dirty = TRUE;
186     if ((SP->_slk->win = stwin) == NULL) {
187         returnCode(slk_failed());
188     }
189
190     /* We now reset the format so that the next newterm has again
191      * per default no SLK keys and may call slk_init again to
192      * define a new layout. (juergen 03-Mar-1999)
193      */
194     SP->slk_format = _nc_slk_format;
195     _nc_slk_format = 0;
196     returnCode(res);
197 }
198
199 /*
200  * Restore the soft labels on the screen.
201  */
202 NCURSES_EXPORT(int)
203 slk_restore(void)
204 {
205     T((T_CALLED("slk_restore()")));
206
207     if (SP->_slk == NULL)
208         return (ERR);
209     SP->_slk->hidden = FALSE;
210     SP->_slk->dirty = TRUE;
211     /* we have to repaint info line eventually */
212     slk_paint_info(SP->_slk->win);
213
214     returnCode(slk_refresh());
215 }