| 156 | Return true if successful. */ |
| 157 | |
| 158 | static bool |
| 159 | fold_file (char const *filename, size_t width) |
| 160 | { |
| 161 | FILE *istream; |
| 162 | size_t column = 0; /* Screen column where next char will go. */ |
| 163 | idx_t offset_out = 0; /* Index in 'line_out' for next char. */ |
| 164 | static char line_out[IO_BUFSIZE]; |
| 165 | static char line_in[IO_BUFSIZE]; |
| 166 | mbbuf_t mbbuf; |
| 167 | int saved_errno; |
| 168 | |
| 169 | if (streq (filename, "-")) |
| 170 | { |
| 171 | istream = stdin; |
| 172 | have_read_stdin = true; |
| 173 | } |
| 174 | else |
| 175 | istream = fopen (filename, "r"); |
| 176 | |
| 177 | if (istream == NULL) |
| 178 | { |
| 179 | error (0, errno, "%s", quotef (filename)); |
| 180 | return false; |
| 181 | } |
| 182 | |
| 183 | fadvise (istream, FADVISE_SEQUENTIAL); |
| 184 | mbbuf_init (&mbbuf, line_in, sizeof line_in, istream); |
| 185 | |
| 186 | mcel_t g; |
| 187 | while ((g = mbbuf_get_char (&mbbuf)).ch != MBBUF_EOF) |
| 188 | { |
| 189 | if (g.ch == '\n') |
| 190 | { |
| 191 | write_out (line_out, offset_out, /*newline=*/ true); |
| 192 | column = offset_out = 0; |
| 193 | continue; |
| 194 | } |
| 195 | rescan: |
| 196 | column = adjust_column (column, g); |
| 197 | |
| 198 | if (column > width) |
| 199 | { |
| 200 | /* This character would make the line too long. |
| 201 | Print the line plus a newline, and make this character |
| 202 | start the next line. */ |
| 203 | if (break_spaces) |
| 204 | { |
| 205 | int space_length = 0; |
| 206 | idx_t logical_end = offset_out; |
| 207 | char *logical_p = line_out; |
| 208 | char *logical_lim = logical_p + logical_end; |
| 209 | |
| 210 | for (mcel_t g2; logical_p < logical_lim; logical_p += g2.len) |
| 211 | { |
| 212 | g2 = mcel_scan (logical_p, logical_lim); |
| 213 | if (c32issep (g2.ch)) |
| 214 | { |
| 215 | space_length = g2.len; |
no test coverage detected