/* The source code in this file was taken from the ** 'fold' program that's part of the GNU textutils ** package, and *slightly* modified to suit Manhattan's ** needs. ** ** The original 'fold' program was written by: ** ** David MacKenzie, djm@gnu.ai.mit.edu ** ** The original source code for the unaltered 'fold' ** utility is available as part of the coreutils package ** at: ** ** http://ftp.gnu.org/pub/gnu/coreutils/ ** */ #include #include #include #include #include #include "../global.h" #include "shared_cs_util.h" #include "shared_msg_line.h" /* for CONTINUATION_CHAR */ /* Assuming the current column is COLUMN, return the column that printing C will move the cursor to. The first column is 0. */ static size_t adjust_column (size_t column, char c) { if (c == '\b') { if (column > 0) column--; } else if (c == '\r') column = 0; else if (c == '\t') column = column + 8 - column % 8; else /* if (isprint (c)) */ column++; return column; } void write_folded(FILE *fp, char *string, int width) { #define REALLOC_SIZE 250 char *ptr; register int c; size_t column = 0; /* Screen column where next char will go. */ size_t offset_out = 0; /* Index in `line_out' for next char. */ static char *line_out = NULL; static size_t allocated_out = 0; for(ptr=string; *ptr; ptr++) { c = *ptr; if(c == '\r') /* strip carriage returns */ continue; if (offset_out + 1 >= allocated_out) { line_out = realloc (line_out,REALLOC_SIZE ); if(!line_out) cs_critical_error(ERR_MALLOC_FAILED, "do_fold()"); allocated_out += REALLOC_SIZE; } if (c == '\n') { line_out[offset_out++] = c; fwrite (line_out, sizeof (char), offset_out, fp); column = offset_out = 0; continue; } rescan: column = adjust_column (column, c); if (column > width) { /* This character would make the line too long. Print the line plus a newline, and make this character start the next line. */ int found_blank = 0; size_t logical_end = offset_out; /* Look for the last blank. */ while (logical_end) { --logical_end; if ((line_out[logical_end] == ' ') || (line_out[logical_end] == '\t')) { found_blank = 1; break; } } if (found_blank) { size_t i; /* Found a blank. Don't output the part after it. */ logical_end++; fwrite (line_out, sizeof (char), (size_t) logical_end,fp); fprintf(fp,"%c", '\n'); /* Move the remainder to the beginning of the next line. The areas being copied here might overlap. */ memmove (line_out, line_out + logical_end, offset_out - logical_end); offset_out -= logical_end; for (column = i = 0; i < offset_out; i++) column = adjust_column (column, line_out[i]); goto rescan; } if (offset_out == 0) { line_out[offset_out++] = c; continue; } if(!found_blank) line_out[offset_out++] = CONTINUATION_CHAR; /* #defined in shared_msg_line.h */ line_out[offset_out++] = '\n'; fwrite (line_out, sizeof (char), (size_t) offset_out, fp); column = offset_out = 0; goto rescan; } line_out[offset_out++] = c; } if (offset_out) fwrite (line_out, sizeof (char), (size_t) offset_out, fp); if(line_out) free(line_out); #undef REALLOC_SIZE } void write_folded_text (char *fname, char *string, int width) { FILE *fp; fp = fopen(fname, "w"); if(!fp) cs_critical_error(ERR_FOPEN_WRITE_FAILED, fname); write_folded(fp, string, width); fclose(fp); }