summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common/puttext.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libadm/common/puttext.c')
-rw-r--r--usr/src/lib/libadm/common/puttext.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/puttext.c b/usr/src/lib/libadm/common/puttext.c
new file mode 100644
index 0000000000..71870a8078
--- /dev/null
+++ b/usr/src/lib/libadm/common/puttext.c
@@ -0,0 +1,307 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*LINTLIBRARY*/
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.2 */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "libadm.h"
+
+#define MWIDTH 256
+#define WIDTH 60
+
+int
+puttext(FILE *fp, char *str, int lmarg, int rmarg)
+{
+ wchar_t *wstr, *wp;
+ wchar_t *copy, *lastword, *lastend, temp[MWIDTH+1];
+ size_t len, ret;
+ int width, i, n, force, wordcnt;
+ int wlen, mlen, bdg;
+ char mbs[MB_LEN_MAX];
+ char mbtemp[(MWIDTH+1) * MB_LEN_MAX];
+
+ width = rmarg ? (rmarg - lmarg) : (WIDTH - lmarg);
+ if (width > MWIDTH)
+ width = MWIDTH;
+
+ if (!str || !*str)
+ return (width);
+
+ len = strlen(str);
+ wstr = (wchar_t *)malloc(sizeof (wchar_t) * (len + 1));
+ if (wstr == NULL)
+ return (width);
+
+ ret = mbstowcs(wstr, (const char *)str, len + 1);
+ if (ret == (size_t)-1) {
+ free(wstr);
+ return (width);
+ }
+
+ wp = wstr;
+
+ if (*wp == L'!') {
+ wp++;
+ force = 1;
+ for (i = 0; i < lmarg; i++)
+ (void) putc(' ', fp);
+ } else {
+ while (iswspace(*wp))
+ ++wp; /* eat leading white space */
+ force = 0;
+ }
+
+ wordcnt = 0;
+ n = 0;
+ copy = temp;
+ lastword = wp;
+ lastend = NULL;
+ do {
+ if (force) {
+ if (*wp == L'\n') {
+ (void) putc('\n', fp);
+ for (i = 0; i < lmarg; i++)
+ (void) putc(' ', fp);
+ wp++;
+ n = 0;
+ } else {
+ wlen = wcwidth(*wp);
+ /*
+ * Using putc instead of fputwc here to avoid
+ * mixing up the byte stream and the wide stream
+ * for fp.
+ */
+ mlen = wctomb(mbs, *wp);
+ if (mlen == -1) {
+ /*
+ * wctomb failed
+ * nothing will be outputted
+ */
+ wp++;
+ } else {
+ for (i = 0; i < mlen; i++)
+ (void) putc(mbs[i], fp);
+ wp++;
+ /*
+ * if wlen is a negative value (*wp is not printable),
+ * add 1 to n. (non-printable char shares 1 column.
+ */
+ if (wlen >= 0)
+ n += wlen;
+ else
+ n++;
+ }
+ }
+ continue;
+ }
+ if (iswspace(*wp)) {
+ /* eat multiple tabs/nl after whitespace */
+ while ((*++wp == L'\t') || (*wp == '\n'));
+ wordcnt++;
+ lastword = wp;
+ lastend = copy;
+ *copy++ = L' ';
+ n++;
+ } else if (*wp == L'\\') {
+ if (*(wp + 1) == L'n') {
+ wordcnt++;
+ n = width + 1;
+ wp += 2;
+ lastword = wp;
+ lastend = copy;
+ } else if (*(wp + 1) == L't') {
+ wordcnt++;
+ do {
+ *copy++ = L' ';
+ } while (++n % 8);
+ n++;
+ wp += 2;
+ lastword = wp;
+ lastend = copy;
+ } else if (*(wp + 1) == L' ') {
+ *copy++ = L' ';
+ wp += 2;
+ n++;
+ } else {
+ if (iswprint(*wp) && iswprint(*(wp + 1))) {
+ /*
+ * Only if both *wp and *(wp +1) are printable,
+ * tries to check the binding weight between them.
+ */
+ wlen = wcwidth(*wp);
+ if (n + wlen > width) {
+ /*
+ * if (n + wlen) is larger than width, *wp will be
+ * put to the next line.
+ */
+ *copy++ = *wp++;
+ n = width + 1;
+ goto fold;
+ } else {
+ n += wlen;
+ bdg = wdbindf(*wp,
+ *(wp + 1), 1);
+ *copy++ = *wp++;
+ if (bdg < 5) {
+ /*
+ * binding weight between *wp and *(wp + 1) is
+ * enough small to fold the line there.
+ */
+ lastword = wp;
+ lastend = copy;
+ wordcnt++;
+ }
+ }
+ } else {
+ wlen = wcwidth(*wp);
+ if (wlen > 0) {
+ /*
+ * *wp is printable
+ */
+ if (n + wlen > width) {
+ /*
+ * if (n + wlen) is larger than width, *wp will
+ * be put to the next line.
+ */
+ *copy++ = *wp++;
+ n = width + 1;
+ goto fold;
+ } else {
+ n += wlen;
+ }
+ } else {
+ /*
+ * *wp is not printable, and shares 1 column.
+ */
+ n++;
+ }
+ *copy++ = *wp++;
+ }
+ }
+ } else {
+ if (iswprint(*wp) && iswprint(*(wp + 1))) {
+ /*
+ * Only if both *wp and *(wp + 1) are printable,
+ * tries to check the binding weight between them.
+ */
+ wlen = wcwidth(*wp);
+ if (n + wlen > width) {
+ /*
+ * if (n + wlen) is larger than width, *wp will be
+ * put to the next line.
+ */
+ *copy++ = *wp++;
+ n = width + 1;
+ goto fold;
+ }
+ n += wlen;
+ bdg = wdbindf(*wp, *(wp + 1), 1);
+ *copy++ = *wp++;
+ if (bdg < 5) {
+ /*
+ * binding weight between *wp and *(wp + 1) is
+ * enough small to fold the line there.
+ */
+ lastword = wp;
+ lastend = copy;
+ wordcnt++;
+ }
+ } else {
+ wlen = wcwidth(*wp);
+ if (wlen > 0) {
+ /*
+ * *wp is printable
+ */
+ if (n + wlen > width) {
+ /*
+ * if (n + wlen) is larger than width, *wp will
+ * be put to the next line.
+ */
+ *copy++ = *wp++;
+ n = width + 1;
+ goto fold;
+ } else {
+ n += wlen;
+ }
+ } else {
+ /*
+ * *wp is not printable, and shares 1 column.
+ */
+ n++;
+ }
+ *copy++ = *wp++;
+ }
+ }
+
+fold:
+ if (n >= width) {
+ if (lastend)
+ *lastend = L'\0';
+ else
+ *copy = L'\0';
+ for (i = 0; i < lmarg; i++)
+ (void) putc(' ', fp);
+ mlen = wcstombs(mbtemp, temp, MWIDTH+1);
+ for (i = 0; i < mlen; i++)
+ (void) putc(mbtemp[i], fp);
+ (void) putc('\n', fp);
+
+ lastend = NULL;
+ copy = temp;
+ if (wordcnt)
+ wp = lastword;
+
+ wordcnt = 0;
+ n = 0;
+ if (!force) {
+ while (iswspace(*wp))
+ wp++;
+ }
+ }
+ } while (*wp != L'\0');
+ if (!force) {
+ *copy = L'\0';
+ for (i = 0; i < lmarg; i++)
+ (void) putc(' ', fp);
+ mlen = wcstombs(mbtemp, temp, MWIDTH+1);
+ for (i = 0; i < mlen; i++)
+ (void) putc(mbtemp[i], fp);
+ }
+ free(wstr);
+ return (width - n - !force);
+}