#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;
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);
mlen = wctomb(mbs, *wp);
if (mlen == -1) {
wp++;
} else {
for (i = 0; i < mlen; i++)
(void) putc(mbs[i], fp);
wp++;
if (wlen >= 0)
n += wlen;
else
n++;
}
}
continue;
}
if (iswspace(*wp)) {
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))) {
wlen = wcwidth(*wp);
if (n + wlen > width) {
*copy++ = *wp++;
n = width + 1;
goto fold;
} else {
n += wlen;
bdg = wdbindf(*wp,
*(wp + 1), 1);
*copy++ = *wp++;
if (bdg < 5) {
lastword = wp;
lastend = copy;
wordcnt++;
}
}
} else {
wlen = wcwidth(*wp);
if (wlen > 0) {
if (n + wlen > width) {
*copy++ = *wp++;
n = width + 1;
goto fold;
} else {
n += wlen;
}
} else {
n++;
}
*copy++ = *wp++;
}
}
} else {
if (iswprint(*wp) && iswprint(*(wp + 1))) {
wlen = wcwidth(*wp);
if (n + wlen > width) {
*copy++ = *wp++;
n = width + 1;
goto fold;
}
n += wlen;
bdg = wdbindf(*wp, *(wp + 1), 1);
*copy++ = *wp++;
if (bdg < 5) {
lastword = wp;
lastend = copy;
wordcnt++;
}
} else {
wlen = wcwidth(*wp);
if (wlen > 0) {
if (n + wlen > width) {
*copy++ = *wp++;
n = width + 1;
goto fold;
} else {
n += wlen;
}
} else {
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);
}