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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
41 
42 /*LINTLIBRARY*/
43 
44 #include	<sys/types.h>
45 #include	<stdlib.h>
46 #include	"curses_inc.h"
47 
48 /*
49  * Initialize usage of soft labels
50  * This routine should be called before each call of newscreen
51  * or initscr to initialize for the next terminal.
52  *
53  * ng:	number of groupings. If gp is NULL, it denotes one
54  * 	of two default groupings:
55  * 	0:	- - -   - -   - - -
56  * 	1:      - - - -     - - - -
57  * gp:	groupings.
58  */
59 
60 static	void	_init_slk_func(void);
61 static  int	_slk_setpos(int, short *);
62 static	int	_ngroups, _groups[LABMAX];
63 
64 int
65 slk_start(int ng, int *gp)
66 {
67 	int	i = 0, j = 0;
68 
69 	if (gp == NULL) {
70 		switch (ng) {
71 			case 2 :
72 				_ngroups = 2;
73 				_groups[0] = 4;
74 				_groups[1] = 4;
75 				break;
76 
77 			case 3 :
78 no_format :
79 				_ngroups = 3;
80 				_groups[0] = 3;
81 				_groups[1] = 2;
82 				_groups[2] = 3;
83 				break;
84 
85 			default :
86 				if (label_format) {
87 				    int		k;
88 				    char	ch1[3], *ch = label_format;
89 
90 					/*CONSTCOND*/
91 					while (TRUE) {
92 						if ((*ch == ',') ||
93 						    (*ch == '\0')) {
94 							ch1[i] = '\0';
95 							if ((k = atoi(ch1)) <=
96 							    0)
97 								goto err;
98 							_groups[j++] = k;
99 							i = 0;
100 							if (*ch == '\0') {
101 								break;
102 							}
103 						} else
104 							ch1[i++] = *ch++;
105 					}
106 				} else
107 					goto no_format;
108 				break;
109 		}
110 	} else {
111 		for (; i < ng; i++) {
112 			if ((j += gp[i]) > LABMAX)
113 err :
114 				return (ERR);
115 			_groups[i] = gp[i];
116 		}
117 		_ngroups = ng;
118 	}
119 
120 	/* signal newscreen() */
121 	_slk_init = _init_slk_func;
122 	return (OK);
123 }
124 
125 static	void
126 _init_slk_func(void)
127 {
128 	int	i, len, num;
129 	SLK_MAP	*slk;
130 	char	*cp, *ep;
131 	WINDOW	*win;
132 
133 	/* clear this out to ready for next time */
134 	_slk_init = NULL;
135 
136 	/* get space for slk structure */
137 	if ((slk = (SLK_MAP *) malloc(sizeof (SLK_MAP))) == NULL) {
138 		curs_errno = CURS_BAD_MALLOC;
139 #ifdef	DEBUG
140 		strcpy(curs_parm_err, "_init_slk_func");
141 #endif	/* DEBUG */
142 		return;
143 	}
144 
145 	/* compute actual number of labels */
146 	num = 0;
147 	for (i = 0; i < _ngroups; i++)
148 		num += _groups[i];
149 
150 	/* max label length */
151 	if (plab_norm && (label_height * label_width >= LABLEN) &&
152 	    (num_labels >= num)) {
153 		win = NULL;
154 		goto next;
155 	} else {
156 		if ((win = newwin(1, COLS, LINES - 1, 0)) == NULL)
157 			goto err;
158 		win->_leave = TRUE;
159 		(void) wattrset(win, A_REVERSE | A_DIM);
160 
161 		/* remove one line from the screen */
162 		LINES = --SP->lsize;
163 		if ((len = (COLS - 1) / (num + 1)) > LABLEN) {
164 next :
165 			len = LABLEN;
166 		}
167 	}
168 
169 	/* positions to place labels */
170 	if (len <= 0 || num <= 0 || (_slk_setpos(len, slk->_labx) == ERR)) {
171 		if (win != NULL)
172 			(void) delwin(win);
173 err :
174 		free(slk);
175 	} else {
176 		/* LINTED */
177 		slk->_num = (short) num;
178 		/* LINTED */
179 		slk->_len = (short) len;
180 
181 		for (i = 0; i < num; ++i) {
182 			cp = slk->_ldis[i];
183 			ep = cp + len;
184 			for (; cp < ep; ++cp)
185 				*cp = ' ';
186 			*ep = '\0';
187 			slk->_lval[i][0] = '\0';
188 			slk->_lch[i] = TRUE;
189 		}
190 
191 		slk->_changed = TRUE;
192 		slk->_win = win;
193 
194 		_do_slk_ref = _slk_update;
195 		_do_slk_tch = slk_touch;
196 		_do_slk_noref = slk_noutrefresh;
197 
198 		SP->slk = slk;
199 	}
200 }
201 
202 
203 /*
204  * Compute placements of labels. The general idea is to spread
205  * the groups out evenly. This routine is designed for the day
206  * when > 8 labels and other kinds of groupings may be desired.
207  *
208  * The main assumption behind the algorithm is that the total
209  * # of labels in all the groups is <= LABMAX.
210  *
211  * len: length of a label
212  * labx: to return the coords of the labels.
213  */
214 
215 static int
216 _slk_setpos(int len, short *labx)
217 {
218 	int	i, k, n, spread, left, begadd;
219 	int	grpx[LABMAX];
220 
221 	/* compute starting coords for each group */
222 	grpx[0] = 0;
223 	if (_ngroups > 1) {
224 		/* spacing between groups */
225 		for (i = 0, n = 0; i < _ngroups; ++i)
226 			n += _groups[i] * (len + 1) - 1;
227 		if ((spread = (COLS - (n + 1))/(_ngroups - 1)) <= 0)
228 			return (ERR);
229 		left = (COLS-(n + 1)) % (_ngroups - 1);
230 		begadd = (_ngroups / 2) - (left / 2);
231 
232 		/* coords of groups */
233 		for (i = 1; i < _ngroups; ++i) {
234 			grpx[i] = grpx[i - 1] + (_groups[i - 1] *
235 			    (len + 1) - 1) + spread;
236 			if (left > 0 && i > begadd) {
237 				grpx[i]++;
238 				left--;
239 			}
240 		}
241 	}
242 
243 	/* now set coords of each label */
244 	n = 0;
245 	for (i = 0; i < _ngroups; ++i)
246 		for (k = 0; k < _groups[i]; ++k)
247 			labx[n++] = grpx[i] + k * (len + 1);
248 	return (OK);
249 }
250