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