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 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