1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
24*7c478bd9Sstevel@tonic-gate
25*7c478bd9Sstevel@tonic-gate
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
28*7c478bd9Sstevel@tonic-gate * All rights reserved.
29*7c478bd9Sstevel@tonic-gate */
30*7c478bd9Sstevel@tonic-gate
31*7c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <stdio.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #include <wchar.h>
38*7c478bd9Sstevel@tonic-gate #include <libintl.h>
39*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
40*7c478bd9Sstevel@tonic-gate #include <string.h>
41*7c478bd9Sstevel@tonic-gate #include <limits.h>
42*7c478bd9Sstevel@tonic-gate #include "libadm.h"
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate #define MWIDTH 256
45*7c478bd9Sstevel@tonic-gate #define WIDTH 60
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate int
puttext(FILE * fp,char * str,int lmarg,int rmarg)48*7c478bd9Sstevel@tonic-gate puttext(FILE *fp, char *str, int lmarg, int rmarg)
49*7c478bd9Sstevel@tonic-gate {
50*7c478bd9Sstevel@tonic-gate wchar_t *wstr, *wp;
51*7c478bd9Sstevel@tonic-gate wchar_t *copy, *lastword, *lastend, temp[MWIDTH+1];
52*7c478bd9Sstevel@tonic-gate size_t len, ret;
53*7c478bd9Sstevel@tonic-gate int width, i, n, force, wordcnt;
54*7c478bd9Sstevel@tonic-gate int wlen, mlen, bdg;
55*7c478bd9Sstevel@tonic-gate char mbs[MB_LEN_MAX];
56*7c478bd9Sstevel@tonic-gate char mbtemp[(MWIDTH+1) * MB_LEN_MAX];
57*7c478bd9Sstevel@tonic-gate
58*7c478bd9Sstevel@tonic-gate width = rmarg ? (rmarg - lmarg) : (WIDTH - lmarg);
59*7c478bd9Sstevel@tonic-gate if (width > MWIDTH)
60*7c478bd9Sstevel@tonic-gate width = MWIDTH;
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate if (!str || !*str)
63*7c478bd9Sstevel@tonic-gate return (width);
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gate len = strlen(str);
66*7c478bd9Sstevel@tonic-gate wstr = (wchar_t *)malloc(sizeof (wchar_t) * (len + 1));
67*7c478bd9Sstevel@tonic-gate if (wstr == NULL)
68*7c478bd9Sstevel@tonic-gate return (width);
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate ret = mbstowcs(wstr, (const char *)str, len + 1);
71*7c478bd9Sstevel@tonic-gate if (ret == (size_t)-1) {
72*7c478bd9Sstevel@tonic-gate free(wstr);
73*7c478bd9Sstevel@tonic-gate return (width);
74*7c478bd9Sstevel@tonic-gate }
75*7c478bd9Sstevel@tonic-gate
76*7c478bd9Sstevel@tonic-gate wp = wstr;
77*7c478bd9Sstevel@tonic-gate
78*7c478bd9Sstevel@tonic-gate if (*wp == L'!') {
79*7c478bd9Sstevel@tonic-gate wp++;
80*7c478bd9Sstevel@tonic-gate force = 1;
81*7c478bd9Sstevel@tonic-gate for (i = 0; i < lmarg; i++)
82*7c478bd9Sstevel@tonic-gate (void) putc(' ', fp);
83*7c478bd9Sstevel@tonic-gate } else {
84*7c478bd9Sstevel@tonic-gate while (iswspace(*wp))
85*7c478bd9Sstevel@tonic-gate ++wp; /* eat leading white space */
86*7c478bd9Sstevel@tonic-gate force = 0;
87*7c478bd9Sstevel@tonic-gate }
88*7c478bd9Sstevel@tonic-gate
89*7c478bd9Sstevel@tonic-gate wordcnt = 0;
90*7c478bd9Sstevel@tonic-gate n = 0;
91*7c478bd9Sstevel@tonic-gate copy = temp;
92*7c478bd9Sstevel@tonic-gate lastword = wp;
93*7c478bd9Sstevel@tonic-gate lastend = NULL;
94*7c478bd9Sstevel@tonic-gate do {
95*7c478bd9Sstevel@tonic-gate if (force) {
96*7c478bd9Sstevel@tonic-gate if (*wp == L'\n') {
97*7c478bd9Sstevel@tonic-gate (void) putc('\n', fp);
98*7c478bd9Sstevel@tonic-gate for (i = 0; i < lmarg; i++)
99*7c478bd9Sstevel@tonic-gate (void) putc(' ', fp);
100*7c478bd9Sstevel@tonic-gate wp++;
101*7c478bd9Sstevel@tonic-gate n = 0;
102*7c478bd9Sstevel@tonic-gate } else {
103*7c478bd9Sstevel@tonic-gate wlen = wcwidth(*wp);
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate * Using putc instead of fputwc here to avoid
106*7c478bd9Sstevel@tonic-gate * mixing up the byte stream and the wide stream
107*7c478bd9Sstevel@tonic-gate * for fp.
108*7c478bd9Sstevel@tonic-gate */
109*7c478bd9Sstevel@tonic-gate mlen = wctomb(mbs, *wp);
110*7c478bd9Sstevel@tonic-gate if (mlen == -1) {
111*7c478bd9Sstevel@tonic-gate /*
112*7c478bd9Sstevel@tonic-gate * wctomb failed
113*7c478bd9Sstevel@tonic-gate * nothing will be outputted
114*7c478bd9Sstevel@tonic-gate */
115*7c478bd9Sstevel@tonic-gate wp++;
116*7c478bd9Sstevel@tonic-gate } else {
117*7c478bd9Sstevel@tonic-gate for (i = 0; i < mlen; i++)
118*7c478bd9Sstevel@tonic-gate (void) putc(mbs[i], fp);
119*7c478bd9Sstevel@tonic-gate wp++;
120*7c478bd9Sstevel@tonic-gate /*
121*7c478bd9Sstevel@tonic-gate * if wlen is a negative value (*wp is not printable),
122*7c478bd9Sstevel@tonic-gate * add 1 to n. (non-printable char shares 1 column.
123*7c478bd9Sstevel@tonic-gate */
124*7c478bd9Sstevel@tonic-gate if (wlen >= 0)
125*7c478bd9Sstevel@tonic-gate n += wlen;
126*7c478bd9Sstevel@tonic-gate else
127*7c478bd9Sstevel@tonic-gate n++;
128*7c478bd9Sstevel@tonic-gate }
129*7c478bd9Sstevel@tonic-gate }
130*7c478bd9Sstevel@tonic-gate continue;
131*7c478bd9Sstevel@tonic-gate }
132*7c478bd9Sstevel@tonic-gate if (iswspace(*wp)) {
133*7c478bd9Sstevel@tonic-gate /* eat multiple tabs/nl after whitespace */
134*7c478bd9Sstevel@tonic-gate while ((*++wp == L'\t') || (*wp == '\n'));
135*7c478bd9Sstevel@tonic-gate wordcnt++;
136*7c478bd9Sstevel@tonic-gate lastword = wp;
137*7c478bd9Sstevel@tonic-gate lastend = copy;
138*7c478bd9Sstevel@tonic-gate *copy++ = L' ';
139*7c478bd9Sstevel@tonic-gate n++;
140*7c478bd9Sstevel@tonic-gate } else if (*wp == L'\\') {
141*7c478bd9Sstevel@tonic-gate if (*(wp + 1) == L'n') {
142*7c478bd9Sstevel@tonic-gate wordcnt++;
143*7c478bd9Sstevel@tonic-gate n = width + 1;
144*7c478bd9Sstevel@tonic-gate wp += 2;
145*7c478bd9Sstevel@tonic-gate lastword = wp;
146*7c478bd9Sstevel@tonic-gate lastend = copy;
147*7c478bd9Sstevel@tonic-gate } else if (*(wp + 1) == L't') {
148*7c478bd9Sstevel@tonic-gate wordcnt++;
149*7c478bd9Sstevel@tonic-gate do {
150*7c478bd9Sstevel@tonic-gate *copy++ = L' ';
151*7c478bd9Sstevel@tonic-gate } while (++n % 8);
152*7c478bd9Sstevel@tonic-gate n++;
153*7c478bd9Sstevel@tonic-gate wp += 2;
154*7c478bd9Sstevel@tonic-gate lastword = wp;
155*7c478bd9Sstevel@tonic-gate lastend = copy;
156*7c478bd9Sstevel@tonic-gate } else if (*(wp + 1) == L' ') {
157*7c478bd9Sstevel@tonic-gate *copy++ = L' ';
158*7c478bd9Sstevel@tonic-gate wp += 2;
159*7c478bd9Sstevel@tonic-gate n++;
160*7c478bd9Sstevel@tonic-gate } else {
161*7c478bd9Sstevel@tonic-gate if (iswprint(*wp) && iswprint(*(wp + 1))) {
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate * Only if both *wp and *(wp +1) are printable,
164*7c478bd9Sstevel@tonic-gate * tries to check the binding weight between them.
165*7c478bd9Sstevel@tonic-gate */
166*7c478bd9Sstevel@tonic-gate wlen = wcwidth(*wp);
167*7c478bd9Sstevel@tonic-gate if (n + wlen > width) {
168*7c478bd9Sstevel@tonic-gate /*
169*7c478bd9Sstevel@tonic-gate * if (n + wlen) is larger than width, *wp will be
170*7c478bd9Sstevel@tonic-gate * put to the next line.
171*7c478bd9Sstevel@tonic-gate */
172*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
173*7c478bd9Sstevel@tonic-gate n = width + 1;
174*7c478bd9Sstevel@tonic-gate goto fold;
175*7c478bd9Sstevel@tonic-gate } else {
176*7c478bd9Sstevel@tonic-gate n += wlen;
177*7c478bd9Sstevel@tonic-gate bdg = wdbindf(*wp,
178*7c478bd9Sstevel@tonic-gate *(wp + 1), 1);
179*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
180*7c478bd9Sstevel@tonic-gate if (bdg < 5) {
181*7c478bd9Sstevel@tonic-gate /*
182*7c478bd9Sstevel@tonic-gate * binding weight between *wp and *(wp + 1) is
183*7c478bd9Sstevel@tonic-gate * enough small to fold the line there.
184*7c478bd9Sstevel@tonic-gate */
185*7c478bd9Sstevel@tonic-gate lastword = wp;
186*7c478bd9Sstevel@tonic-gate lastend = copy;
187*7c478bd9Sstevel@tonic-gate wordcnt++;
188*7c478bd9Sstevel@tonic-gate }
189*7c478bd9Sstevel@tonic-gate }
190*7c478bd9Sstevel@tonic-gate } else {
191*7c478bd9Sstevel@tonic-gate wlen = wcwidth(*wp);
192*7c478bd9Sstevel@tonic-gate if (wlen > 0) {
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate * *wp is printable
195*7c478bd9Sstevel@tonic-gate */
196*7c478bd9Sstevel@tonic-gate if (n + wlen > width) {
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate * if (n + wlen) is larger than width, *wp will
199*7c478bd9Sstevel@tonic-gate * be put to the next line.
200*7c478bd9Sstevel@tonic-gate */
201*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
202*7c478bd9Sstevel@tonic-gate n = width + 1;
203*7c478bd9Sstevel@tonic-gate goto fold;
204*7c478bd9Sstevel@tonic-gate } else {
205*7c478bd9Sstevel@tonic-gate n += wlen;
206*7c478bd9Sstevel@tonic-gate }
207*7c478bd9Sstevel@tonic-gate } else {
208*7c478bd9Sstevel@tonic-gate /*
209*7c478bd9Sstevel@tonic-gate * *wp is not printable, and shares 1 column.
210*7c478bd9Sstevel@tonic-gate */
211*7c478bd9Sstevel@tonic-gate n++;
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate } else {
217*7c478bd9Sstevel@tonic-gate if (iswprint(*wp) && iswprint(*(wp + 1))) {
218*7c478bd9Sstevel@tonic-gate /*
219*7c478bd9Sstevel@tonic-gate * Only if both *wp and *(wp + 1) are printable,
220*7c478bd9Sstevel@tonic-gate * tries to check the binding weight between them.
221*7c478bd9Sstevel@tonic-gate */
222*7c478bd9Sstevel@tonic-gate wlen = wcwidth(*wp);
223*7c478bd9Sstevel@tonic-gate if (n + wlen > width) {
224*7c478bd9Sstevel@tonic-gate /*
225*7c478bd9Sstevel@tonic-gate * if (n + wlen) is larger than width, *wp will be
226*7c478bd9Sstevel@tonic-gate * put to the next line.
227*7c478bd9Sstevel@tonic-gate */
228*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
229*7c478bd9Sstevel@tonic-gate n = width + 1;
230*7c478bd9Sstevel@tonic-gate goto fold;
231*7c478bd9Sstevel@tonic-gate }
232*7c478bd9Sstevel@tonic-gate n += wlen;
233*7c478bd9Sstevel@tonic-gate bdg = wdbindf(*wp, *(wp + 1), 1);
234*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
235*7c478bd9Sstevel@tonic-gate if (bdg < 5) {
236*7c478bd9Sstevel@tonic-gate /*
237*7c478bd9Sstevel@tonic-gate * binding weight between *wp and *(wp + 1) is
238*7c478bd9Sstevel@tonic-gate * enough small to fold the line there.
239*7c478bd9Sstevel@tonic-gate */
240*7c478bd9Sstevel@tonic-gate lastword = wp;
241*7c478bd9Sstevel@tonic-gate lastend = copy;
242*7c478bd9Sstevel@tonic-gate wordcnt++;
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate } else {
245*7c478bd9Sstevel@tonic-gate wlen = wcwidth(*wp);
246*7c478bd9Sstevel@tonic-gate if (wlen > 0) {
247*7c478bd9Sstevel@tonic-gate /*
248*7c478bd9Sstevel@tonic-gate * *wp is printable
249*7c478bd9Sstevel@tonic-gate */
250*7c478bd9Sstevel@tonic-gate if (n + wlen > width) {
251*7c478bd9Sstevel@tonic-gate /*
252*7c478bd9Sstevel@tonic-gate * if (n + wlen) is larger than width, *wp will
253*7c478bd9Sstevel@tonic-gate * be put to the next line.
254*7c478bd9Sstevel@tonic-gate */
255*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
256*7c478bd9Sstevel@tonic-gate n = width + 1;
257*7c478bd9Sstevel@tonic-gate goto fold;
258*7c478bd9Sstevel@tonic-gate } else {
259*7c478bd9Sstevel@tonic-gate n += wlen;
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate } else {
262*7c478bd9Sstevel@tonic-gate /*
263*7c478bd9Sstevel@tonic-gate * *wp is not printable, and shares 1 column.
264*7c478bd9Sstevel@tonic-gate */
265*7c478bd9Sstevel@tonic-gate n++;
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate *copy++ = *wp++;
268*7c478bd9Sstevel@tonic-gate }
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate fold:
272*7c478bd9Sstevel@tonic-gate if (n >= width) {
273*7c478bd9Sstevel@tonic-gate if (lastend)
274*7c478bd9Sstevel@tonic-gate *lastend = L'\0';
275*7c478bd9Sstevel@tonic-gate else
276*7c478bd9Sstevel@tonic-gate *copy = L'\0';
277*7c478bd9Sstevel@tonic-gate for (i = 0; i < lmarg; i++)
278*7c478bd9Sstevel@tonic-gate (void) putc(' ', fp);
279*7c478bd9Sstevel@tonic-gate mlen = wcstombs(mbtemp, temp, MWIDTH+1);
280*7c478bd9Sstevel@tonic-gate for (i = 0; i < mlen; i++)
281*7c478bd9Sstevel@tonic-gate (void) putc(mbtemp[i], fp);
282*7c478bd9Sstevel@tonic-gate (void) putc('\n', fp);
283*7c478bd9Sstevel@tonic-gate
284*7c478bd9Sstevel@tonic-gate lastend = NULL;
285*7c478bd9Sstevel@tonic-gate copy = temp;
286*7c478bd9Sstevel@tonic-gate if (wordcnt)
287*7c478bd9Sstevel@tonic-gate wp = lastword;
288*7c478bd9Sstevel@tonic-gate
289*7c478bd9Sstevel@tonic-gate wordcnt = 0;
290*7c478bd9Sstevel@tonic-gate n = 0;
291*7c478bd9Sstevel@tonic-gate if (!force) {
292*7c478bd9Sstevel@tonic-gate while (iswspace(*wp))
293*7c478bd9Sstevel@tonic-gate wp++;
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate } while (*wp != L'\0');
297*7c478bd9Sstevel@tonic-gate if (!force) {
298*7c478bd9Sstevel@tonic-gate *copy = L'\0';
299*7c478bd9Sstevel@tonic-gate for (i = 0; i < lmarg; i++)
300*7c478bd9Sstevel@tonic-gate (void) putc(' ', fp);
301*7c478bd9Sstevel@tonic-gate mlen = wcstombs(mbtemp, temp, MWIDTH+1);
302*7c478bd9Sstevel@tonic-gate for (i = 0; i < mlen; i++)
303*7c478bd9Sstevel@tonic-gate (void) putc(mbtemp[i], fp);
304*7c478bd9Sstevel@tonic-gate }
305*7c478bd9Sstevel@tonic-gate free(wstr);
306*7c478bd9Sstevel@tonic-gate return (width - n - !force);
307*7c478bd9Sstevel@tonic-gate }
308