#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1990, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif
#ifndef lint
#if 0
static char sccsid[] = "@(#)fold.c 8.1 (Berkeley) 6/6/93";
#endif
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/usr.bin/fold/fold.c,v 1.13 2004/06/24 15:12:29 tjr Exp $");
#include <err.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#define DEFLINEWIDTH 80
void fold(int);
static int newpos(int, wint_t);
static void usage(void);
int bflag;
int sflag;
int
main(int argc, char **argv)
{
int ch;
int rval, width;
char *p;
(void) setlocale(LC_CTYPE, "");
width = -1;
while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1)
switch (ch) {
case 'b':
bflag = 1;
break;
case 's':
sflag = 1;
break;
case 'w':
if ((width = atoi(optarg)) <= 0) {
errx(1, "illegal width value");
}
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (width == -1) {
p = argv[optind - 1];
if (p[0] == '-' && p[1] == ch && !p[2])
width = atoi(++p);
else
width = atoi(argv[optind] + 1);
}
break;
default:
usage();
}
argv += optind;
argc -= optind;
if (width == -1)
width = DEFLINEWIDTH;
rval = 0;
if (!*argv)
fold(width);
else for (; *argv; ++argv)
if (!freopen(*argv, "r", stdin)) {
warn("%s", *argv);
rval = 1;
} else
fold(width);
exit(rval);
}
static void
usage(void)
{
(void)fprintf(stderr, "usage: fold [-bs] [-w width] [file ...]\n");
exit(1);
}
void
fold(int width)
{
static wchar_t *buf;
static int buf_max;
int col, i, indx, space;
wint_t ch;
col = indx = 0;
while ((ch = getwchar()) != WEOF) {
if (ch == '\n') {
wprintf(L"%.*ls\n", indx, buf);
col = indx = 0;
continue;
}
if ((col = newpos(col, ch)) > width) {
if (sflag) {
i = indx;
while (--i >= 0 && !iswblank(buf[i]))
;
space = i;
}
if (sflag && space != -1) {
space++;
wprintf(L"%.*ls\n", space, buf);
wmemmove(buf, buf + space, indx - space);
indx -= space;
col = 0;
for (i = 0; i < indx; i++)
col = newpos(col, buf[i]);
} else {
wprintf(L"%.*ls\n", indx, buf);
col = indx = 0;
}
col = newpos(col, ch);
}
if (indx + 1 > buf_max) {
buf_max += LINE_MAX;
buf = realloc(buf, sizeof(*buf) * buf_max);
if (buf == NULL)
err(1, "realloc()");
}
buf[indx++] = ch;
}
if (ferror(stdin)) {
fprintf(stderr, "Input error\n");
exit(EXIT_FAILURE);
}
if (indx != 0)
wprintf(L"%.*ls", indx, buf);
}
static int
newpos(int col, wint_t ch)
{
char buf[MB_LEN_MAX];
size_t len;
int w;
if (bflag) {
len = wcrtomb(buf, ch, NULL);
col += len;
} else
switch (ch) {
case '\b':
if (col > 0)
--col;
break;
case '\r':
col = 0;
break;
case '\t':
col = (col + 8) & ~7;
break;
default:
if ((w = wcwidth(ch)) > 0)
col += w;
break;
}
return (col);
}