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