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