]> git.ipfire.org Git - thirdparty/util-linux.git/blame - text-utils/colcrt.c
libblkid: make example more robust
[thirdparty/util-linux.git] / text-utils / colcrt.c
CommitLineData
6dbe3af9 1/*
79c10142
KZ
2 * Copyright (C) 2016 Sami Kerola <kerolasa@iki.fi>
3 * Copyright (C) 2016 Karel Zak <kzak@redhat.com>
4 *
6dbe3af9
KZ
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
eb63b9b8 37/*
b50945d4 38 * 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
79c10142 39 * added Native Language Support
eb63b9b8 40 * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
79c10142 41 * modified to work correctly in multi-byte locales
eb63b9b8 42 */
7eda085c 43
6dbe3af9 44#include <stdio.h>
66ee8158 45#include <stdlib.h>
e71daef2 46#include <getopt.h>
fd6b7a7f 47
ea4ccc9e 48#include "nls.h"
e71daef2 49#include "c.h"
9ea8ded3 50#include "widechar.h"
b87cbe84 51#include "closestream.h"
12707a49 52#include "fgetwc_or_err.h"
eb63b9b8 53
6dbe3af9
KZ
54/*
55 * colcrt - replaces col for crts with new nroff esp. when using tbl.
56 * Bill Joy UCB July 14, 1977
57 *
ea4ccc9e 58 * This filter uses the up and down sequences generated by the new
6dbe3af9
KZ
59 * nroff when used with tbl and by \u \d and \r.
60 * General overstriking doesn't work correctly.
61 * Underlining is split onto multiple lines, etc.
62 *
63 * Option - suppresses all underlining.
64 * Option -2 forces printing of all half lines.
65 */
66
ea4ccc9e 67enum { OUTPUT_COLS = 132 };
6dbe3af9 68
ea4ccc9e 69struct colcrt_control {
79c10142
KZ
70 FILE *f;
71 wchar_t line[OUTPUT_COLS + 1];
72 wchar_t line_under[OUTPUT_COLS + 1];
73 unsigned int print_nl:1,
74 need_line_under:1,
75 no_underlining:1,
76 half_lines:1;
ea4ccc9e 77};
e71daef2 78
86be6a32 79static void __attribute__((__noreturn__)) usage(void)
ea4ccc9e 80{
86be6a32 81 FILE *out = stdout;
ea4ccc9e
SK
82 fputs(USAGE_HEADER, out);
83 fprintf(out, _(" %s [options] [<file>...]\n"), program_invocation_short_name);
79c10142 84
ea4ccc9e
SK
85 fputs(USAGE_SEPARATOR, out);
86 fputs(_("Filter nroff output for CRT previewing.\n"), out);
79c10142 87
ea4ccc9e
SK
88 fputs(USAGE_OPTIONS, out);
89 fputs(_(" -, --no-underlining suppress all underlining\n"), out);
90 fputs(_(" -2, --half-lines print all half-lines\n"), out);
79c10142 91
ea4ccc9e 92 fputs(USAGE_SEPARATOR, out);
bad4c729 93 fprintf(out, USAGE_HELP_OPTIONS(25));
79c10142 94
bad4c729 95 fprintf(out, USAGE_MAN_TAIL("colcrt(1)"));
79c10142 96
86be6a32 97 exit(EXIT_SUCCESS);
ea4ccc9e 98}
6dbe3af9 99
ea4ccc9e
SK
100static void trim_trailing_spaces(wchar_t *s)
101{
102 size_t size;
103 wchar_t *end;
7eda085c 104
ea4ccc9e
SK
105 size = wcslen(s);
106 if (!size)
107 return;
108 end = s + size - 1;
109 while (s <= end && iswspace(*end))
110 end--;
111 *(end + 1) = L'\0';
112}
e71daef2 113
e71daef2 114
ea4ccc9e
SK
115static void output_lines(struct colcrt_control *ctl, int col)
116{
117 /* first line */
118 trim_trailing_spaces(ctl->line);
119 fputws(ctl->line, stdout);
79c10142 120
ea4ccc9e
SK
121 if (ctl->print_nl)
122 fputwc(L'\n', stdout);
123 if (!ctl->half_lines && !ctl->no_underlining)
124 ctl->print_nl = 0;
79c10142 125
ea4ccc9e 126 wmemset(ctl->line, L'\0', OUTPUT_COLS);
79c10142 127
ea4ccc9e
SK
128 /* second line */
129 if (ctl->need_line_under) {
130 ctl->need_line_under = 0;
131 ctl->line_under[col] = L'\0';
132 trim_trailing_spaces(ctl->line_under);
133 fputws(ctl->line_under, stdout);
134 fputwc(L'\n', stdout);
135 wmemset(ctl->line_under, L' ', OUTPUT_COLS);
79c10142 136
ea4ccc9e
SK
137 } else if (ctl->half_lines && 0 < col)
138 fputwc(L'\n', stdout);
6dbe3af9
KZ
139}
140
ea4ccc9e
SK
141static int rubchars(struct colcrt_control *ctl, int col, int n)
142{
143 while (0 < n && 0 < col) {
144 ctl->line[col] = L'\0';
145 ctl->line_under[col] = L' ';
146 n--;
147 col--;
148 }
149 return col;
150}
151
152static void colcrt(struct colcrt_control *ctl)
153{
154 int col;
d3565072 155 wint_t c = 0;
962a7dc3 156 long old_pos;
66ee8158 157
ea4ccc9e
SK
158 ctl->print_nl = 1;
159 if (ctl->half_lines)
160 fputwc(L'\n', stdout);
79c10142 161
ea4ccc9e
SK
162 for (col = 0; /* nothing */; col++) {
163 if (OUTPUT_COLS - 1 < col) {
164 output_lines(ctl, col);
165 errno = 0;
962a7dc3 166 old_pos = ftell(ctl->f);
d3565072 167
12707a49 168 while (fgetwc_or_err(ctl->f) != L'\n') {
d3565072
KZ
169 long new_pos;
170
171 if (ferror(ctl->f) || feof(ctl->f))
ea4ccc9e 172 return;
d3565072
KZ
173 new_pos = ftell(ctl->f);
174 if (old_pos == new_pos) {
175 if (fseek(ctl->f, 1, SEEK_CUR) < 1)
176 return;
177 } else
178 old_pos = new_pos;
ea4ccc9e
SK
179 }
180 col = -1;
181 continue;
66ee8158 182 }
12707a49 183 c = fgetwc_or_err(ctl->f);
66ee8158 184 switch (c) {
ea4ccc9e 185 case 033: /* ESC */
12707a49 186 c = fgetwc_or_err(ctl->f);
ea4ccc9e
SK
187 if (c == L'8') {
188 col = rubchars(ctl, col, 1);
66ee8158
KZ
189 continue;
190 }
ea4ccc9e
SK
191 if (c == L'7') {
192 col = rubchars(ctl, col, 2);
66ee8158
KZ
193 continue;
194 }
ea4ccc9e
SK
195 continue;
196 case WEOF:
197 ctl->print_nl = 0;
198 output_lines(ctl, col);
199 return;
200 case L'\n':
201 output_lines(ctl, col);
202 col = -1;
203 continue;
204 case L'\t':
205 for (/* nothing */; col % 8 && col < OUTPUT_COLS; col++) {
206 ctl->line[col] = L' ';
66ee8158 207 }
ea4ccc9e
SK
208 col--;
209 continue;
210 case L'_':
211 ctl->line[col] = L' ';
212 if (!ctl->no_underlining) {
213 ctl->need_line_under = 1;
214 ctl->line_under[col] = L'-';
66ee8158
KZ
215 }
216 continue;
ea4ccc9e
SK
217 default:
218 if (!iswprint(c)) {
219 col--;
220 continue;
221 }
222 ctl->print_nl = 1;
223 ctl->line[col] = c;
66ee8158
KZ
224 }
225 }
226}
227
ea4ccc9e 228int main(int argc, char **argv)
6dbe3af9 229{
87918040 230 struct colcrt_control ctl = { NULL };
ea4ccc9e
SK
231 int opt;
232 enum { NO_UL_OPTION = CHAR_MAX + 1 };
6dbe3af9 233
ea4ccc9e
SK
234 static const struct option longopts[] = {
235 {"no-underlining", no_argument, NULL, NO_UL_OPTION},
236 {"half-lines", no_argument, NULL, '2'},
237 {"version", no_argument, NULL, 'V'},
238 {"help", no_argument, NULL, 'h'},
239 {NULL, 0, NULL, 0}
240 };
6dbe3af9 241
ea4ccc9e
SK
242 setlocale(LC_ALL, "");
243 bindtextdomain(PACKAGE, LOCALEDIR);
244 textdomain(PACKAGE);
2c308875 245 close_stdout_atexit();
79c10142 246
ea4ccc9e 247 /* Take care of lonely hyphen option. */
79c10142 248 for (opt = 0; opt < argc; opt++) {
ea4ccc9e
SK
249 if (argv[opt][0] == '-' && argv[opt][1] == '\0') {
250 ctl.no_underlining = 1;
251 argc--;
252 memmove(argv + opt, argv + opt + 1,
253 sizeof(char *) * (argc - opt));
254 opt--;
66ee8158 255 }
79c10142
KZ
256 }
257
258 while ((opt = getopt_long(argc, argv, "2Vh", longopts, NULL)) != -1) {
ea4ccc9e
SK
259 switch (opt) {
260 case NO_UL_OPTION:
261 ctl.no_underlining = 1;
262 break;
263 case '2':
264 ctl.half_lines = 1;
265 break;
2c308875 266
ea4ccc9e 267 case 'V':
2c308875 268 print_version(EXIT_SUCCESS);
ea4ccc9e 269 case 'h':
86be6a32 270 usage();
ea4ccc9e 271 default:
677ec86c 272 errtryhelp(EXIT_FAILURE);
6dbe3af9 273 }
79c10142
KZ
274 }
275
ea4ccc9e
SK
276 argc -= optind;
277 argv += optind;
79c10142 278
ea4ccc9e
SK
279 do {
280 wmemset(ctl.line, L'\0', OUTPUT_COLS);
281 wmemset(ctl.line_under, L' ', OUTPUT_COLS);
79c10142 282
ea4ccc9e 283 if (argc > 0) {
79c10142
KZ
284 if (!(ctl.f = fopen(*argv, "r")))
285 err(EXIT_FAILURE, _("cannot open %s"), *argv);
ea4ccc9e
SK
286 argc--;
287 argv++;
288 } else
289 ctl.f = stdin;
79c10142 290
ea4ccc9e
SK
291 colcrt(&ctl);
292 if (ctl.f != stdin)
293 fclose(ctl.f);
294 } while (argc > 0);
79c10142 295
ea4ccc9e 296 return EXIT_SUCCESS;
e71daef2 297}