/*++ /* NAME /* line_wrap 3 /* SUMMARY /* wrap long lines upon output /* SYNOPSIS /* #include /* /* void line_wrap(string, len, indent, output_fn, context) /* const char *buf; /* int len; /* int indent; /* void (*output_fn)(const char *str, int len, int indent, void *context); /* void *context; /* DESCRIPTION /* The \fBline_wrap\fR routine outputs the specified string via /* the specified output function, and attempts to keep output lines /* shorter than the specified length. The routine does not attempt to /* break long words that do not fit on a single line. Upon output, /* trailing whitespace is stripped. /* /* Arguments /* .IP string /* The input, which cannot contain any newline characters. /* .IP len /* The desired maximal output line length. /* .IP indent /* The desired amount of indentation of the second etc. output lines /* with respect to the first output line. A negative indent causes /* only the first line to be indented; a positive indent causes all /* but the first line to be indented. A zero count causes no indentation. /* .IP output_fn /* The output function that is called with as arguments a string /* pointer, a string length, a non-negative indentation count, and /* application context. A typical implementation looks like this: /* .sp /* .nf /* .na void print(const char *str, int len, int indent, void *context) { VSTREAM *fp = (VSTREAM *) context; vstream_fprintf(fp, "%*s%.*s", indent, "", len, str); } /* .fi /* .ad /* .IP context /* Application context that is passed on to the output function. /* For example, a VSTREAM pointer, or a structure that contains /* a VSTREAM pointer. /* BUGS /* No tab expansion and no backspace processing. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /*--*/ /* System library. */ #include #include #include /* Utility library. */ #include /* line_wrap - wrap long lines upon output */ void line_wrap(const char *str, int len, int indent, LINE_WRAP_FN output_fn, void *context) { const char *start_line; const char *word; const char *next_word; const char *next_space; int line_len; int curr_len; int curr_indent; if (indent < 0) { curr_indent = -indent; curr_len = len + indent; } else { curr_indent = 0; curr_len = len; } /* * At strategic positions, output what we have seen, after stripping off * trailing blanks. */ for (start_line = word = str; word != 0; word = next_word) { next_space = word + strcspn(word, " \t"); if (word > start_line) { if (next_space - start_line > curr_len) { line_len = word - start_line; while (line_len > 0 && ISSPACE(start_line[line_len - 1])) line_len--; output_fn(start_line, line_len, curr_indent, context); while (*word && ISSPACE(*word)) word++; if (start_line == str) { curr_indent += indent; curr_len -= indent; } start_line = word; } } next_word = *next_space ? next_space + 1 : 0; } line_len = strlen(start_line); while (line_len > 0 && ISSPACE(start_line[line_len - 1])) line_len--; output_fn(start_line, line_len, curr_indent, context); }