ncurses 4.1
[ncurses.git] / ncurses / lib_slk.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
11 *        Permission is hereby granted to reproduce and distribute ncurses  *
12 *        by any means and for any fee, whether alone or as part of a       *
13 *        larger distribution, in source or in binary form, PROVIDED        *
14 *        this notice is included with any such distribution, and is not    *
15 *        removed from any of its header files. Mention of ncurses in any   *
16 *        applications linked with it is highly appreciated.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22 /*
23  *      lib_slk.c
24  *      Soft key routines.
25  */
26
27 #include <curses.priv.h>
28
29 #include <ctype.h>
30 #include <term.h>       /* num_labels, label_*, plab_norm */
31
32 MODULE_ID("$Id: lib_slk.c,v 1.11 1997/01/18 23:06:32 tom Exp $")
33
34 #define MAX_SKEY_OLD       8    /* count of soft keys */
35 #define MAX_SKEY_LEN_OLD   8    /* max length of soft key text */
36 #define MAX_SKEY_PC       12    /* This is what most PC's have */
37 #define MAX_SKEY_LEN_PC    5
38
39 #define MAX_SKEY      (SLK_STDFMT ? MAX_SKEY_OLD : MAX_SKEY_PC)
40 #define MAX_SKEY_LEN  (SLK_STDFMT ? MAX_SKEY_LEN_OLD : MAX_SKEY_LEN_PC)
41 /*
42  * We'd like to move these into the screen context structure, but cannot,
43  * because slk_init() is called before initscr()/newterm().
44  */
45 int _nc_slk_format;                     /* one more than format specified in slk_init() */
46
47 static chtype _slk_attr = A_STANDOUT;   /* soft label attribute */
48 static SLK *_slk;
49 static void slk_paint_info(WINDOW *win);
50
51 /*
52  * Fetch the label text.
53  */
54
55 char *
56 slk_label(int n)
57 {
58         T(("slk_label(%d)", n));
59
60         if (SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt)
61                 return NULL;
62         return(SP->_slk->ent[n-1].text);
63 }
64
65 /*
66  * Write the soft labels to the soft-key window.
67  */
68
69 static void
70 slk_intern_refresh(SLK *slk)
71 {
72 int i;
73         for (i = 0; i < slk->labcnt; i++) {
74                 if (slk->dirty || slk->ent[i].dirty) {
75                         if (slk->ent[i].visible) {
76 #ifdef num_labels
77                                 if (num_labels > 0 && SLK_STDFMT)
78                                 {
79                                   if (i < num_labels) {
80                                     TPUTS_TRACE("plab_norm");
81                                     putp(tparm(plab_norm, i, slk->win,slk->ent[i].form_text));
82                                   }
83                                 }
84                                 else
85 #endif /* num_labels */
86                                 {
87                                         wmove(slk->win,SLK_LINES-1,slk->ent[i].x);
88                                         wattrset(slk->win,_slk_attr);
89                                         waddnstr(slk->win,slk->ent[i].form_text, MAX_SKEY_LEN);
90                                         /* if we simulate SLK's, it's looking much more
91                                            natural to use the current ATTRIBUTE also
92                                            for the label window */
93                                         wattrset(slk->win,stdscr->_attrs);
94                                 }
95                         }
96                         slk->ent[i].dirty = FALSE;
97                 }
98         }
99         slk->dirty = FALSE;
100
101 #ifdef num_labels
102         if (num_labels > 0)
103             if (slk->hidden)
104             {
105                 TPUTS_TRACE("label_off");
106                 putp(label_off);
107             }
108             else
109             {
110                 TPUTS_TRACE("label_on");
111                 putp(label_on);
112             }
113 #endif /* num_labels */
114 }
115
116 /*
117  * Refresh the soft labels.
118  */
119
120 int
121 slk_noutrefresh(void)
122 {
123         T(("slk_noutrefresh()"));
124
125         if (SP->_slk == NULL)
126                 return(ERR);
127         if (SP->_slk->hidden)
128                 return(OK);
129         slk_intern_refresh(SP->_slk);
130         return(wnoutrefresh(SP->_slk->win));
131 }
132
133 /*
134  * Refresh the soft labels.
135  */
136
137 int
138 slk_refresh(void)
139 {
140         T(("slk_refresh()"));
141
142         if (SP->_slk == NULL)
143                 return(ERR);
144         if (SP->_slk->hidden)
145                 return(OK);
146         slk_intern_refresh(SP->_slk);
147         return(wrefresh(SP->_slk->win));
148 }
149
150 /*
151  * Restore the soft labels on the screen.
152  */
153
154 int
155 slk_restore(void)
156 {
157         T(("slk_restore()"));
158
159         if (SP->_slk == NULL)
160                 return(ERR);
161         SP->_slk->hidden = FALSE;
162         SP->_slk->dirty = TRUE;
163         /* we have to repaint info line eventually */
164         slk_paint_info(SP->_slk->win); 
165         return slk_refresh();
166 }
167
168 /*
169  * Set soft label text.
170  */
171
172 int
173 slk_set(int i, const char *astr, int format)
174 {
175 SLK *slk = SP->_slk;
176 size_t len;
177 const char *str = astr;
178 const char *p;
179
180         T(("slk_set(%d, \"%s\", %d)", i, str, format));
181
182         if (slk == NULL || i < 1 || i > slk->labcnt || format < 0 || format > 2)
183                 return(ERR);
184         if (str == NULL)
185                 str = "";
186
187         while (isspace(*str)) str++; /* skip over leading spaces  */
188         p = str;
189         while (isprint(*p)) p++;     /* The first non-print stops */
190
191         --i; /* Adjust numbering of labels */
192
193         len = (size_t)(p - str);
194         if (len > (unsigned)slk->maxlen)
195           len = slk->maxlen;
196         if (len==0)
197           slk->ent[i].text[0] = 0;
198         else
199           (void) strncpy(slk->ent[i].text, str, len);
200         memset(slk->ent[i].form_text,' ', (unsigned)slk->maxlen);
201         slk->ent[i].text[slk->maxlen] = 0;
202         /* len = strlen(slk->ent[i].text); */
203
204         switch(format) {
205         case 0: /* left-justified */
206                 memcpy(slk->ent[i].form_text,
207                        slk->ent[i].text,
208                        len);
209                 break;
210         case 1: /* centered */
211                 memcpy(slk->ent[i].form_text+(slk->maxlen - len)/2,
212                        slk->ent[i].text,
213                        len);
214                 break;
215         case 2: /* right-justified */
216                 memcpy(slk->ent[i].form_text+ slk->maxlen - len,
217                        slk->ent[i].text,
218                        len);
219                 break;
220         }
221         slk->ent[i].form_text[slk->maxlen] = 0;
222         slk->ent[i].dirty = TRUE;
223         return(OK);
224 }
225
226 /*
227  * Force the code to believe that the soft keys have been changed.
228  */
229
230 int
231 slk_touch(void)
232 {
233         T(("slk_touch()"));
234
235         if (SP->_slk == NULL)
236                 return(ERR);
237         SP->_slk->dirty = TRUE;
238         return(OK);
239 }
240
241 /*
242  * Remove soft labels from the screen.
243  */
244
245 int
246 slk_clear(void)
247 {
248         T(("slk_clear()"));
249
250         if (SP->_slk == NULL)
251                 return(ERR);
252         SP->_slk->hidden = TRUE;
253         /* For simulated SLK's it's looks much more natural to
254            inherit those attributes from the standard screen */
255         SP->_slk->win->_bkgd  = stdscr->_bkgd;
256         SP->_slk->win->_attrs = stdscr->_attrs;
257         werase(SP->_slk->win);
258         return wrefresh(SP->_slk->win);
259 }
260
261 /*
262  * Paint the info line for the PC style SLK emulation.
263  * 
264  */
265
266 static void
267 slk_paint_info(WINDOW *win)
268 {
269   if (win && _nc_slk_format==4)
270     {
271       int i;
272   
273       mvwhline (win,0,0,0,getmaxx(win));
274       wmove (win,0,0);
275       
276       for (i = 0; i < _slk->maxlab; i++) {
277         if (win && _nc_slk_format==4)
278           {
279             mvwaddch(win,0,_slk->ent[i].x,'F');
280             if (i<9)
281               waddch(win,'1'+i);
282             else
283               {
284                 waddch(win,'1');
285                 waddch(win,'0' + (i-9));
286               }
287           }
288       }
289     }
290 }
291
292 /*
293  * Initialize soft labels.
294  * Called from newterm()
295  */
296
297 int
298 _nc_slk_initialize(WINDOW *stwin, int cols)
299 {
300 int i, x;
301 char *p;
302
303         T(("slk_initialize()"));
304
305         if (_slk)
306           { /* we did this already, so simply return */
307             SP->_slk = _slk;
308             return(OK);
309           }
310         else
311           if ((SP->_slk = _slk = typeCalloc(SLK, 1)) == 0)
312             return(ERR);
313
314         _slk->ent = NULL;
315         _slk->buffer = NULL;
316
317 #ifdef num_labels
318         _slk->maxlab = (num_labels > 0) ? num_labels : MAX_SKEY;
319         _slk->maxlen = (num_labels > 0) ? label_width * label_height : MAX_SKEY_LEN;
320         _slk->labcnt = (_slk->maxlab < MAX_SKEY) ? MAX_SKEY : _slk->maxlab;
321 #else
322         _slk->labcnt = _slk->maxlab = MAX_SKEY;
323         _slk->maxlen = MAX_SKEY_LEN;
324 #endif /* num_labels */
325
326         _slk->ent = typeCalloc(slk_ent, _slk->labcnt);
327         if (_slk->ent == NULL)
328           goto exception;
329
330         p = _slk->buffer = (char*) calloc(2*_slk->labcnt,(1+_slk->maxlen));
331         if (_slk->buffer == NULL)
332           goto exception;
333
334         for (i = 0; i < _slk->labcnt; i++) {
335                 _slk->ent[i].text = p;
336                 p += (1 + _slk->maxlen);
337                 _slk->ent[i].form_text = p;
338                 p += (1 + _slk->maxlen);
339                 memset(_slk->ent[i].form_text, ' ', (unsigned)_slk->maxlen);
340                 _slk->ent[i].visible = (i < _slk->maxlab);
341         }
342         if (_nc_slk_format >= 3) /* PC style */
343           {
344             int gap = (cols - 3 * (3 + 4*_slk->maxlen))/2;
345
346             if (gap < 1)
347               gap = 1;
348
349             for (i = x = 0; i < _slk->maxlab; i++) {
350               _slk->ent[i].x = x;
351               x += _slk->maxlen;
352               x += (i==3 || i==7) ? gap : 1;
353             }
354             if (_nc_slk_format == 4)
355               slk_paint_info (stwin);
356           }
357         else {
358           if (_nc_slk_format == 2) {    /* 4-4 */
359             int gap = cols - (_slk->maxlab * _slk->maxlen) - 6;
360
361             if (gap < 1)
362                         gap = 1;
363             for (i = x = 0; i < _slk->maxlab; i++) {
364               _slk->ent[i].x = x;
365               x += _slk->maxlen;
366               x += (i == 3) ? gap : 1;
367             }
368           }
369           else
370             {
371               if (_nc_slk_format == 1) { /* 1 -> 3-2-3 */
372                 int gap = (cols - (_slk->maxlab * _slk->maxlen) - 5) / 2;
373
374                 if (gap < 1)
375                   gap = 1;
376                 for (i = x = 0; i < _slk->maxlab; i++) {
377                   _slk->ent[i].x = x;
378                   x += _slk->maxlen;
379                   x += (i == 2 || i == 4) ? gap : 1;
380                 }
381               }
382               else
383                 goto exception;
384             }
385         }
386         _slk->dirty = TRUE;
387         if ((_slk->win = stwin) == NULL)
388         {
389         exception:
390                 if (_slk)
391                 {
392                    FreeIfNeeded(_slk->buffer);
393                    FreeIfNeeded(_slk->ent);
394                    free(_slk);
395                    SP->_slk = _slk = (SLK*)0;
396                    return(ERR);
397                 }
398         }
399
400         return(OK);
401 }
402
403 /*
404  * Initialize soft labels.  Called by the user before initscr().
405  */
406
407 int
408 slk_init(int format)
409 {
410         if (format < 0 || format > 3)
411                 return(ERR);
412         _nc_slk_format = 1 + format;
413         return(OK);
414 }
415
416 /* Functions to manipulate the soft-label attribute */
417
418 int
419 slk_attrset(const attr_t attr)
420 {
421     _slk_attr = attr;
422     return(OK);
423 }
424
425 int
426 slk_attron(const attr_t attr)
427 {
428     toggle_attr_on(_slk_attr,attr);
429     return(OK);
430 }
431
432 int
433 slk_attroff(const attr_t attr)
434 {
435     toggle_attr_off(_slk_attr,attr);
436     return(OK);
437 }
438
439 attr_t
440 slk_attr(void)
441 {
442   return _slk_attr;
443 }