1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*LINTLIBRARY*/
41
42 #include <sys/types.h>
43 #include <stdlib.h>
44 #include "curses_inc.h"
45
46 /*
47 * Initialize usage of soft labels
48 * This routine should be called before each call of newscreen
49 * or initscr to initialize for the next terminal.
50 *
51 * ng: number of groupings. If gp is NULL, it denotes one
52 * of two default groupings:
53 * 0: - - - - - - - -
54 * 1: - - - - - - - -
55 * gp: groupings.
56 */
57
58 static void _init_slk_func(void);
59 static int _slk_setpos(int, short *);
60 static int _ngroups, _groups[LABMAX];
61
62 int
slk_start(int ng,int * gp)63 slk_start(int ng, int *gp)
64 {
65 int i = 0, j = 0;
66
67 if (gp == NULL) {
68 switch (ng) {
69 case 2 :
70 _ngroups = 2;
71 _groups[0] = 4;
72 _groups[1] = 4;
73 break;
74
75 case 3 :
76 no_format :
77 _ngroups = 3;
78 _groups[0] = 3;
79 _groups[1] = 2;
80 _groups[2] = 3;
81 break;
82
83 default :
84 if (label_format) {
85 int k;
86 char ch1[3], *ch = label_format;
87
88 /*CONSTCOND*/
89 while (TRUE) {
90 if ((*ch == ',') ||
91 (*ch == '\0')) {
92 ch1[i] = '\0';
93 if ((k = atoi(ch1)) <=
94 0)
95 goto err;
96 _groups[j++] = k;
97 i = 0;
98 if (*ch == '\0') {
99 break;
100 }
101 } else
102 ch1[i++] = *ch++;
103 }
104 } else
105 goto no_format;
106 break;
107 }
108 } else {
109 for (; i < ng; i++) {
110 if ((j += gp[i]) > LABMAX)
111 err :
112 return (ERR);
113 _groups[i] = gp[i];
114 }
115 _ngroups = ng;
116 }
117
118 /* signal newscreen() */
119 _slk_init = _init_slk_func;
120 return (OK);
121 }
122
123 static void
_init_slk_func(void)124 _init_slk_func(void)
125 {
126 int i, len, num;
127 SLK_MAP *slk;
128 char *cp, *ep;
129 WINDOW *win;
130
131 /* clear this out to ready for next time */
132 _slk_init = NULL;
133
134 /* get space for slk structure */
135 if ((slk = (SLK_MAP *) malloc(sizeof (SLK_MAP))) == NULL) {
136 curs_errno = CURS_BAD_MALLOC;
137 #ifdef DEBUG
138 strcpy(curs_parm_err, "_init_slk_func");
139 #endif /* DEBUG */
140 return;
141 }
142
143 /* compute actual number of labels */
144 num = 0;
145 for (i = 0; i < _ngroups; i++)
146 num += _groups[i];
147
148 /* max label length */
149 if (plab_norm && (label_height * label_width >= LABLEN) &&
150 (num_labels >= num)) {
151 win = NULL;
152 goto next;
153 } else {
154 if ((win = newwin(1, COLS, LINES - 1, 0)) == NULL)
155 goto err;
156 win->_leave = TRUE;
157 (void) wattrset(win, A_REVERSE | A_DIM);
158
159 /* remove one line from the screen */
160 LINES = --SP->lsize;
161 if ((len = (COLS - 1) / (num + 1)) > LABLEN) {
162 next :
163 len = LABLEN;
164 }
165 }
166
167 /* positions to place labels */
168 if (len <= 0 || num <= 0 || (_slk_setpos(len, slk->_labx) == ERR)) {
169 if (win != NULL)
170 (void) delwin(win);
171 err :
172 free(slk);
173 } else {
174 /* LINTED */
175 slk->_num = (short) num;
176 /* LINTED */
177 slk->_len = (short) len;
178
179 for (i = 0; i < num; ++i) {
180 cp = slk->_ldis[i];
181 ep = cp + len;
182 for (; cp < ep; ++cp)
183 *cp = ' ';
184 *ep = '\0';
185 slk->_lval[i][0] = '\0';
186 slk->_lch[i] = TRUE;
187 }
188
189 slk->_changed = TRUE;
190 slk->_win = win;
191
192 _do_slk_ref = _slk_update;
193 _do_slk_tch = slk_touch;
194 _do_slk_noref = slk_noutrefresh;
195
196 SP->slk = slk;
197 }
198 }
199
200
201 /*
202 * Compute placements of labels. The general idea is to spread
203 * the groups out evenly. This routine is designed for the day
204 * when > 8 labels and other kinds of groupings may be desired.
205 *
206 * The main assumption behind the algorithm is that the total
207 * # of labels in all the groups is <= LABMAX.
208 *
209 * len: length of a label
210 * labx: to return the coords of the labels.
211 */
212
213 static int
_slk_setpos(int len,short * labx)214 _slk_setpos(int len, short *labx)
215 {
216 int i, k, n, spread, left, begadd;
217 int grpx[LABMAX];
218
219 /* compute starting coords for each group */
220 grpx[0] = 0;
221 if (_ngroups > 1) {
222 /* spacing between groups */
223 for (i = 0, n = 0; i < _ngroups; ++i)
224 n += _groups[i] * (len + 1) - 1;
225 if ((spread = (COLS - (n + 1))/(_ngroups - 1)) <= 0)
226 return (ERR);
227 left = (COLS-(n + 1)) % (_ngroups - 1);
228 begadd = (_ngroups / 2) - (left / 2);
229
230 /* coords of groups */
231 for (i = 1; i < _ngroups; ++i) {
232 grpx[i] = grpx[i - 1] + (_groups[i - 1] *
233 (len + 1) - 1) + spread;
234 if (left > 0 && i > begadd) {
235 grpx[i]++;
236 left--;
237 }
238 }
239 }
240
241 /* now set coords of each label */
242 n = 0;
243 for (i = 0; i < _ngroups; ++i)
244 for (k = 0; k < _groups[i]; ++k)
245 labx[n++] = grpx[i] + k * (len + 1);
246 return (OK);
247 }
248