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 (c) 1995-1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /* LINTLIBRARY */
28 
29 /*
30  * slk.c
31  *
32  * XCurses Library
33  *
34  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
35  *
36  */
37 
38 #if M_RCSID
39 #ifndef lint
40 static char rcsID[] =
41 "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
42 "libxcurses/src/libc/xcurses/rcs/slk.c 1.9 1998/05/20 17:26:23 "
43 "cbates Exp $";
44 #endif
45 #endif
46 
47 #include <private.h>
48 #include <string.h>
49 
50 int	__m_slk_labels_on;
51 int	__m_slk_touched = 0;
52 /*
53  * Flag for initialisation soft label keys once setupterm() has been called.
54  */
55 int
slk_init(int fmt)56 slk_init(int fmt)
57 {
58 	int	code = ERR;
59 
60 	if (0 <= fmt && fmt <= 1) {
61 		__m_slk_format = fmt;
62 		__m_slk_labels_on = 1;
63 		code = OK;
64 	}
65 
66 	return (code);
67 }
68 
69 int
slk_attron(const chtype at)70 slk_attron(const chtype at)
71 {
72 	int	code = OK;
73 
74 	if (__m_screen->_slk._w != NULL)
75 		code = wattron(__m_screen->_slk._w, (int) at);
76 
77 	return (code);
78 }
79 
80 int
slk_attroff(const chtype at)81 slk_attroff(const chtype at)
82 {
83 	int	code = OK;
84 
85 	if (__m_screen->_slk._w != NULL)
86 		code = wattroff(__m_screen->_slk._w, (int) at);
87 
88 	return (code);
89 }
90 
91 int
slk_attrset(const chtype at)92 slk_attrset(const chtype at)
93 {
94 	int	code = OK;
95 
96 	if (__m_screen->_slk._w != NULL)
97 		code = wattrset(__m_screen->_slk._w, (int) at);
98 
99 	return (code);
100 }
101 
102 int
slk_attr_off(const attr_t at,void * opts)103 slk_attr_off(const attr_t at, void *opts)
104 {
105 	int	code = OK;
106 
107 	if (__m_screen->_slk._w != NULL)
108 		code = wattr_off(__m_screen->_slk._w, at, opts);
109 
110 	return (code);
111 }
112 
113 int
slk_attr_on(const attr_t at,void * opts)114 slk_attr_on(const attr_t at, void *opts)
115 {
116 	int	code = OK;
117 
118 	if (__m_screen->_slk._w != NULL)
119 		code = wattr_on(__m_screen->_slk._w, at, opts);
120 
121 	return (code);
122 }
123 
124 int
slk_attr_set(const attr_t at,short co,void * opts)125 slk_attr_set(const attr_t at, short co, void *opts)
126 {
127 	int	code = OK;
128 
129 	if (__m_screen->_slk._w != NULL)
130 		code = wattr_set(__m_screen->_slk._w, at, co, opts);
131 
132 	return (code);
133 }
134 
135 int
slk_color(short co)136 slk_color(short co)
137 {
138 	int	code = OK;
139 
140 	if (__m_screen->_slk._w != NULL)
141 		code = wcolor_set(__m_screen->_slk._w, co, (void *) 0);
142 
143 	return (code);
144 }
145 
146 int
slk_touch(void)147 slk_touch(void)
148 {
149 	int	code = OK;
150 	WINDOW	*w = __m_screen->_slk._w;
151 
152 	if (w != NULL) {
153 		code = wtouchln(w, 0, 1, 1);
154 		wtouchln_hard(w, 0, 1);
155 	} else
156 		__m_slk_touched = 1;
157 
158 	return (code);
159 }
160 
161 /*
162  * These label start columns assume 80 columns in order to
163  * fit 8 _slk._labels of 8 columns.
164  */
165 static const int	format[][8] = {
166 	{ 0, 9, 18, 31, 40, 53, 62, 71 },
167 	{ 0, 9, 18, 27, 44, 53, 62, 71 },
168 };
169 
170 #define	_LABEL_LENGTH_MALLOC	\
171 	(MB_LEN_MAX * ((1 + _M_CCHAR_MAX) * 8) + 1)
172 
173 void
__m_slk_set_all(void)174 __m_slk_set_all(void)
175 {
176 	int	i;
177 
178 	for (i = 0; i < 8; ++i) {
179 		if (__m_screen->_slk._labels[i] != NULL) {
180 			(void) slk_set(i + 1, __m_screen->_slk._labels[i],
181 				__m_screen->_slk._justify[i]);
182 		}
183 	}
184 }
185 
186 int
__m_slk_clear(int kluge)187 __m_slk_clear(int kluge)
188 {
189 	int	i;
190 	int	index;
191 	int	code = ERR;
192 
193 	if (__m_screen->_slk._w != NULL) {
194 		cchar_t	_bg = __m_screen->_slk._w->_bg;
195 		if (kluge) {
196 			/* Test suite expects spaces to have FG attributes */
197 			__m_screen->_slk._w->_bg = __m_screen->_slk._w->_fg;
198 		}
199 		for (index = 0; index < 8; ++index) {
200 			i = format[__m_slk_format][index];
201 			(void) __m_cc_erase(__m_screen->_slk._w,
202 				0, i, 0, i + 7);
203 		}
204 		__m_screen->_slk._w->_bg = _bg;		/* Restore ... */
205 
206 	} else if (plab_norm != NULL) {
207 		for (index = 0; index < 8; ++index) {
208 			char	*p;
209 			p = __m_screen->_slk._saved[index];
210 			if (!p) {
211 				p = (char *)malloc(_LABEL_LENGTH_MALLOC);
212 				if (p == NULL)
213 					goto error;
214 				__m_screen->_slk._saved[index] = p;
215 			}
216 			(void) strcpy(p, (kluge) ? "" : "        ");
217 		}
218 	}
219 	if (__m_screen->_slk._w != NULL) {
220 		code = wrefresh(__m_screen->_slk._w);
221 	} else {
222 		__m_slk_labels_on = 0;
223 		code = slk_refresh();
224 	}
225 
226 error:
227 	return (code);
228 }
229 
230 int
slk_clear(void)231 slk_clear(void)
232 {
233 	return (__m_slk_clear(0));
234 }
235 
236 int
slk_restore(void)237 slk_restore(void)
238 {
239 	int	code;
240 
241 	__m_slk_set_all();
242 	__m_slk_labels_on = 1;
243 	code = slk_refresh();
244 	return (code);
245 }
246 
247 int
slk_noutrefresh(void)248 slk_noutrefresh(void)
249 {
250 	int	code;
251 
252 	if (__m_screen->_slk._w != NULL)
253 		code = wnoutrefresh(__m_screen->_slk._w);
254 	else {
255 		if (__m_slk_touched) {
256 			__m_slk_set_all();
257 			__m_slk_touched = 0;
258 		}
259 		if (__m_slk_labels_on) {
260 			if (label_on != NULL) {
261 				(void) TPUTS(label_on, 1, __m_outc);
262 			}
263 		} else {
264 			if (label_off != NULL) {
265 				(void) TPUTS(label_off, 1, __m_outc);
266 			}
267 		}
268 		(void) fflush(__m_screen->_of);
269 		code = OK;
270 	}
271 
272 	return (code);
273 }
274 
275 int
slk_refresh(void)276 slk_refresh(void)
277 {
278 	int	code;
279 
280 	if ((code = slk_noutrefresh()) == OK)
281 		code = doupdate();
282 
283 	return (code);
284 }
285 
286 void
__m_slk_doupdate(void)287 __m_slk_doupdate(void)
288 {
289 	if ((__m_screen->_slk._w == NULL) && plab_norm) {
290 		int	index;
291 		for (index = 0; index < 8; index++) {
292 			char	*s = __m_screen->_slk._saved[index];
293 			if (s) {
294 				(void) TPUTS(tparm(plab_norm, (long) index+1,
295 					(long) s, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
296 					1, __m_outc);
297 			}
298 		}
299 	}
300 }
301 
302 char *
slk_label(int index)303 slk_label(int index)
304 {
305 	char	*label;
306 
307 	if (index < 1 || 8 < index) {
308 		label = NULL;
309 	} else {
310 		label = __m_screen->_slk._labels[index-1];
311 	}
312 	return (label);
313 }
314 
315 int
slk_set(int index,const char * label,int justify)316 slk_set(int index, const char *label, int justify)
317 {
318 	int	code = ERR;
319 	wchar_t	wcs[_M_CCHAR_MAX * 8 + 1];
320 
321 	if ((label == NULL) || *label == '\0')
322 		label = "        ";
323 	if (mbstowcs(wcs, label, sizeof (wcs)) != (size_t)-1)
324 		code = slk_wset(index, wcs, justify);
325 
326 	return (code);
327 }
328 
329 int
slk_wset(int index,const wchar_t * label,int justify)330 slk_wset(int index, const wchar_t *label, int justify)
331 {
332 	cchar_t	cc;
333 	int	i, width, code = ERR;
334 	wchar_t	wcs[_M_CCHAR_MAX * 8 + 1], *wp;
335 	char	mbs[_LABEL_LENGTH_MALLOC];
336 	char	tmbs[_LABEL_LENGTH_MALLOC];
337 	int	ww = 0;
338 	int	left1, left2;
339 	static const char	*spcs = "        ";
340 
341 	if (index < 1 || 8 < index || justify < 0 || 2 < justify)
342 		goto error1;
343 
344 	index--;	/* Shift from {1..8} to {0..7} */
345 
346 	if (label == NULL)
347 		label = L"";
348 
349 	/* Copy the characters that fill the first 8 columns of the label. */
350 	for (wp = wcs, width = 0; *label != '\0'; label += i, wp += cc._n) {
351 		if ((i = __m_wcs_cc(label, A_NORMAL, 0, &cc)) < 0)
352 			goto error1;
353 
354 		ww += __m_cc_width(&cc);
355 		if (ww > 8)
356 			break;
357 		else
358 			width = ww;
359 
360 		(void) wcsncpy(wp, cc._wc, cc._n);
361 	}
362 	*wp = '\0';
363 
364 	if (wcstombs(tmbs, wcs, sizeof (mbs)) == (size_t) -1)
365 		goto error1;
366 
367 	if (width == 8) {
368 		(void) strcpy(mbs, tmbs);
369 	} else {
370 		switch (justify) {
371 		case 0:
372 			(void) strcpy(mbs, tmbs);
373 			(void) strncat(mbs, spcs, (8 - width));
374 			*(mbs + strlen(tmbs) + (8 - width)) = '\0';
375 			break;
376 		case 1:
377 			left1 = (8 - width) / 2;
378 			(void) strncpy(mbs, spcs, left1);
379 			(void) strcpy(mbs + left1, tmbs);
380 			left2 = 8 - width - left1;
381 			(void) strncat(mbs, spcs, left2);
382 			*(mbs + left1 + strlen(tmbs) + left2) = '\0';
383 			break;
384 		case 2:
385 			left1 = 8 - width;
386 			(void) strncpy(mbs, spcs, left1);
387 			(void) strcpy(mbs + left1, tmbs);
388 			break;
389 		}
390 	}
391 
392 	/* Remember the new label. */
393 	__m_screen->_slk._justify[index] = (short) justify;
394 
395 	if (__m_screen->_slk._labels[index] != NULL)
396 		free(__m_screen->_slk._labels[index]);
397 	if ((__m_screen->_slk._labels[index] = strdup(tmbs)) == NULL)
398 		goto error1;
399 
400 	if (plab_norm != NULL) {
401 		char	*p;
402 		p = __m_screen->_slk._saved[index];
403 		if (!p) {
404 			p = (char *)malloc(_LABEL_LENGTH_MALLOC);
405 			if (p == NULL)
406 				goto error1;
407 			__m_screen->_slk._saved[index] = p;
408 		}
409 		(void) strcpy(p, mbs);
410 	}
411 
412 	__m_slk_labels_on = 1;
413 
414 	if (__m_screen->_slk._w != NULL) {
415 		cchar_t	_bg = __m_screen->_slk._w->_bg;
416 		/* Write the justified label into the slk window. */
417 		i = format[__m_slk_format][index];
418 		__m_screen->_slk._w->_bg = __m_screen->_slk._w->_fg;
419 		(void) __m_cc_erase(__m_screen->_slk._w, 0, i, 0, i + 7);
420 		__m_screen->_slk._w->_bg = _bg;		/* Restore ... */
421 
422 		(void) mvwaddstr(__m_screen->_slk._w, 0, i, mbs);
423 	}
424 
425 	code = OK;
426 error1:
427 	return (code);
428 }
429