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