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
42static 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
52int	__m_slk_labels_on;
53int	__m_slk_touched = 0;
54/*
55 * Flag for initialisation soft label keys once setupterm() has been called.
56 */
57int
58slk_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
71int
72slk_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
82int
83slk_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
93int
94slk_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
104int
105slk_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
115int
116slk_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
126int
127slk_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
137int
138slk_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
148int
149slk_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 */
167static 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
175void
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
188int
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
228error:
229	return (code);
230}
231
232int
233slk_clear(void)
234{
235	return (__m_slk_clear(0));
236}
237
238int
239slk_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
249int
250slk_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
277int
278slk_refresh(void)
279{
280	int	code;
281
282	if ((code = slk_noutrefresh()) == OK)
283		code = doupdate();
284
285	return (code);
286}
287
288void
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
304char *
305slk_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
317int
318slk_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
331int
332slk_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;
428error1:
429	return (code);
430}
431