#include #include #include #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'); }