xref: /illumos-gate/usr/src/lib/libcurses/screen/slk_start.c (revision 9164a50bf932130cbb5097a16f6986873ce0e6e5)
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
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
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
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