1/*++ 2/* NAME 3/* line_wrap 3 4/* SUMMARY 5/* wrap long lines upon output 6/* SYNOPSIS 7/* #include <line_wrap.h> 8/* 9/* void line_wrap(string, len, indent, output_fn, context) 10/* const char *buf; 11/* int len; 12/* int indent; 13/* void (*output_fn)(const char *str, int len, int indent, char *context); 14/* char *context; 15/* DESCRIPTION 16/* The \fBline_wrap\fR routine outputs the specified string via 17/* the specified output function, and attempts to keep output lines 18/* shorter than the specified length. The routine does not attempt to 19/* break long words that do not fit on a single line. Upon output, 20/* trailing whitespace is stripped. 21/* 22/* Arguments 23/* .IP string 24/* The input, which cannot contain any newline characters. 25/* .IP len 26/* The desired maximal output line length. 27/* .IP indent 28/* The desired amount of indentation of the second etc. output lines 29/* with respect to the first output line. A negative indent causes 30/* only the first line to be indented; a positive indent causes all 31/* but the first line to be indented. A zero count causes no indentation. 32/* .IP output_fn 33/* The output function that is called with as arguments a string 34/* pointer, a string length, a non-negative indentation count, and 35/* application context. A typical implementation looks like this: 36/* .sp 37/* .nf 38/* .na 39void print(const char *str, int len, int indent, char *context) 40{ 41 VSTREAM *fp = (VSTREAM *) context; 42 43 vstream_fprintf(fp, "%*s%.*s", indent, "", len, str); 44} 45/* .fi 46/* .ad 47/* .IP context 48/* Application context that is passed on to the output function. 49/* For example, a VSTREAM pointer, or a structure that contains 50/* a VSTREAM pointer. 51/* BUGS 52/* No tab expansion and no backspace processing. 53/* LICENSE 54/* .ad 55/* .fi 56/* The Secure Mailer license must be distributed with this software. 57/* AUTHOR(S) 58/* Wietse Venema 59/* IBM T.J. Watson Research 60/* P.O. Box 704 61/* Yorktown Heights, NY 10598, USA 62/*--*/ 63 64/* System library. */ 65 66#include <sys_defs.h> 67#include <string.h> 68#include <ctype.h> 69 70/* Utility library. */ 71 72#include <line_wrap.h> 73 74/* line_wrap - wrap long lines upon output */ 75 76void line_wrap(const char *str, int len, int indent, LINE_WRAP_FN output_fn, 77 char *context) 78{ 79 const char *start_line; 80 const char *word; 81 const char *next_word; 82 const char *next_space; 83 int line_len; 84 int curr_len; 85 int curr_indent; 86 87 if (indent < 0) { 88 curr_indent = -indent; 89 curr_len = len + indent; 90 } else { 91 curr_indent = 0; 92 curr_len = len; 93 } 94 95 /* 96 * At strategic positions, output what we have seen, after stripping off 97 * trailing blanks. 98 */ 99 for (start_line = word = str; word != 0; word = next_word) { 100 next_space = word + strcspn(word, " \t"); 101 if (word > start_line) { 102 if (next_space - start_line > curr_len) { 103 line_len = word - start_line; 104 while (line_len > 0 && ISSPACE(start_line[line_len - 1])) 105 line_len--; 106 output_fn(start_line, line_len, curr_indent, context); 107 while (*word && ISSPACE(*word)) 108 word++; 109 if (start_line == str) { 110 curr_indent += indent; 111 curr_len -= indent; 112 } 113 start_line = word; 114 } 115 } 116 next_word = *next_space ? next_space + 1 : 0; 117 } 118 line_len = strlen(start_line); 119 while (line_len > 0 && ISSPACE(start_line[line_len - 1])) 120 line_len--; 121 output_fn(start_line, line_len, curr_indent, context); 122} 123