118 lines
2.7 KiB
C
118 lines
2.7 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define TABSTOP 8
|
|
#define WIDTH 80
|
|
// the RATIO can't be less than 1/2
|
|
#define RATIO 2.0/3.0
|
|
#define BREAKSTR "-"
|
|
|
|
int bstrlen = strlen(BREAKSTR);
|
|
|
|
void fold(int width, int maxind);
|
|
void flush_wbuff(int wbi, char wbuff[]);
|
|
int insert_break(char buff[], int wbi);
|
|
int is_blank(char c);
|
|
int mv_cur(int n, char c);
|
|
|
|
/* fold input, takes one optional argument for max line width (excl \n) */
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int w;
|
|
|
|
if (argc < 2 || (w = atoi(argv[1])) < 2)
|
|
fold(WIDTH, RATIO * WIDTH);
|
|
else
|
|
fold(w, RATIO * w);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* folds input lines to length, where minw <= length <= 'width'
|
|
* if a line has no blank spaces after 'minw' chars a BREAKSTR is inserted */
|
|
void fold(int width, int minw)
|
|
{
|
|
int c, n = 0; // n=0 is start of line
|
|
int wbi = 0; // word buffer index
|
|
char wbuff[width - minw]; // word buffer for words over minw
|
|
|
|
while ((c = getchar()) != EOF) {
|
|
n = mv_cur(n, c);
|
|
|
|
if (c == '\n' || (n >= width+1 && is_blank(c))) {
|
|
// handle newlines
|
|
flush_wbuff(wbi, wbuff);
|
|
putchar('\n');
|
|
n = wbi = 0;
|
|
continue;
|
|
}
|
|
|
|
if (n <= minw) // always print chars before minw
|
|
putchar(c);
|
|
else if (n <= width) {
|
|
/* add word (optionaly leading blank) after minw to wbuff
|
|
* empty buffer if new blank is found */
|
|
if (is_blank(c)) {
|
|
flush_wbuff(wbi, wbuff);
|
|
wbi = 0;
|
|
}
|
|
wbuff[wbi] = c;
|
|
++wbi;
|
|
} else { // one char over edge, c != ' '
|
|
n = insert_break(wbuff, wbi) + 1;
|
|
putchar(c);
|
|
wbi = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void flush_wbuff(int wbi, char wbuff[])
|
|
{
|
|
printf("%.*s", wbi, wbuff);
|
|
}
|
|
|
|
/* print buff and insert line break where its most fitting,
|
|
* return new cursor position
|
|
* '\n' is inserted before the last word or 'BREAKSTR\n' is inserted */
|
|
int insert_break(char wbuff[], int wbi)
|
|
{
|
|
int i;
|
|
|
|
if (wbi == 0) {
|
|
putchar('\n');
|
|
return 0;
|
|
}
|
|
|
|
if (is_blank(wbuff[0])) {
|
|
putchar('\n');
|
|
for (i=1; i < wbi; ++i)
|
|
putchar(wbuff[i]);
|
|
return wbi - 1;
|
|
}
|
|
|
|
|
|
|
|
flush_wbuff(wbi-bstrlen, wbuff);
|
|
printf("%s\n", BREAKSTR);
|
|
for (i = wbi-bstrlen; i < wbi; ++i)
|
|
putchar(wbuff[i]);
|
|
return bstrlen;
|
|
}
|
|
|
|
/* return new cursor position */
|
|
int mv_cur(int n, char c)
|
|
{
|
|
if (c == '\t')
|
|
return n + (TABSTOP - n % TABSTOP);
|
|
else if (c == '\b')
|
|
return n;
|
|
return n+1;
|
|
}
|
|
|
|
int is_blank(char c)
|
|
{
|
|
return (c == ' ' || c == '\t');
|
|
}
|
|
|