2 * Copyright (C) 2016 Sami Kerola <kerolasa@iki.fi>
3 * Copyright (C) 2016 Karel Zak <kzak@redhat.com>
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
38 * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
39 * added Native Language Support
40 * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
41 * modified to work correctly in multi-byte locales
51 #include "closestream.h"
54 * colcrt - replaces col for crts with new nroff esp. when using tbl.
55 * Bill Joy UCB July 14, 1977
57 * This filter uses the up and down sequences generated by the new
58 * nroff when used with tbl and by \u \d and \r.
59 * General overstriking doesn't work correctly.
60 * Underlining is split onto multiple lines, etc.
62 * Option - suppresses all underlining.
63 * Option -2 forces printing of all half lines.
66 enum { OUTPUT_COLS
= 132 };
68 struct colcrt_control
{
70 wchar_t line
[OUTPUT_COLS
+ 1];
71 wchar_t line_under
[OUTPUT_COLS
+ 1];
72 unsigned int print_nl
:1,
78 static void __attribute__((__noreturn__
)) usage(FILE *out
)
80 fputs(USAGE_HEADER
, out
);
81 fprintf(out
, _(" %s [options] [<file>...]\n"), program_invocation_short_name
);
83 fputs(USAGE_SEPARATOR
, out
);
84 fputs(_("Filter nroff output for CRT previewing.\n"), out
);
86 fputs(USAGE_OPTIONS
, out
);
87 fputs(_(" -, --no-underlining suppress all underlining\n"), out
);
88 fputs(_(" -2, --half-lines print all half-lines\n"), out
);
90 fputs(USAGE_SEPARATOR
, out
);
91 fputs(USAGE_HELP
, out
);
92 fputs(USAGE_VERSION
, out
);
94 fprintf(out
, USAGE_MAN_TAIL("colcrt(1)"));
96 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
99 static void trim_trailing_spaces(wchar_t *s
)
108 while (s
<= end
&& iswspace(*end
))
114 static void output_lines(struct colcrt_control
*ctl
, int col
)
117 trim_trailing_spaces(ctl
->line
);
118 fputws(ctl
->line
, stdout
);
121 fputwc(L
'\n', stdout
);
122 if (!ctl
->half_lines
&& !ctl
->no_underlining
)
125 wmemset(ctl
->line
, L
'\0', OUTPUT_COLS
);
128 if (ctl
->need_line_under
) {
129 ctl
->need_line_under
= 0;
130 ctl
->line_under
[col
] = L
'\0';
131 trim_trailing_spaces(ctl
->line_under
);
132 fputws(ctl
->line_under
, stdout
);
133 fputwc(L
'\n', stdout
);
134 wmemset(ctl
->line_under
, L
' ', OUTPUT_COLS
);
136 } else if (ctl
->half_lines
&& 0 < col
)
137 fputwc(L
'\n', stdout
);
140 static int rubchars(struct colcrt_control
*ctl
, int col
, int n
)
142 while (0 < n
&& 0 < col
) {
143 ctl
->line
[col
] = L
'\0';
144 ctl
->line_under
[col
] = L
' ';
151 static void colcrt(struct colcrt_control
*ctl
)
159 fputwc(L
'\n', stdout
);
161 for (col
= 0; /* nothing */; col
++) {
162 if (OUTPUT_COLS
- 1 < col
) {
163 output_lines(ctl
, col
);
165 old_pos
= ftell(ctl
->f
);
166 while ((c
= getwc(ctl
->f
)) != L
'\n') {
167 long new_pos
= ftell(ctl
->f
);
168 if (old_pos
== new_pos
)
169 fseek(ctl
->f
, 1, SEEK_CUR
);
172 if (errno
== 0 && c
== WEOF
)
185 col
= rubchars(ctl
, col
, 1);
189 col
= rubchars(ctl
, col
, 2);
195 output_lines(ctl
, col
);
198 output_lines(ctl
, col
);
202 for (/* nothing */; col
% 8 && col
< OUTPUT_COLS
; col
++) {
203 ctl
->line
[col
] = L
' ';
208 ctl
->line
[col
] = L
' ';
209 if (!ctl
->no_underlining
) {
210 ctl
->need_line_under
= 1;
211 ctl
->line_under
[col
] = L
'-';
225 int main(int argc
, char **argv
)
227 struct colcrt_control ctl
= { 0 };
229 enum { NO_UL_OPTION
= CHAR_MAX
+ 1 };
231 static const struct option longopts
[] = {
232 {"no-underlining", no_argument
, NULL
, NO_UL_OPTION
},
233 {"half-lines", no_argument
, NULL
, '2'},
234 {"version", no_argument
, NULL
, 'V'},
235 {"help", no_argument
, NULL
, 'h'},
239 setlocale(LC_ALL
, "");
240 bindtextdomain(PACKAGE
, LOCALEDIR
);
242 atexit(close_stdout
);
244 /* Take care of lonely hyphen option. */
245 for (opt
= 0; opt
< argc
; opt
++) {
246 if (argv
[opt
][0] == '-' && argv
[opt
][1] == '\0') {
247 ctl
.no_underlining
= 1;
249 memmove(argv
+ opt
, argv
+ opt
+ 1,
250 sizeof(char *) * (argc
- opt
));
255 while ((opt
= getopt_long(argc
, argv
, "2Vh", longopts
, NULL
)) != -1) {
258 ctl
.no_underlining
= 1;
264 printf(UTIL_LINUX_VERSION
);
269 errtryhelp(EXIT_FAILURE
);
277 wmemset(ctl
.line
, L
'\0', OUTPUT_COLS
);
278 wmemset(ctl
.line_under
, L
' ', OUTPUT_COLS
);
281 if (!(ctl
.f
= fopen(*argv
, "r")))
282 err(EXIT_FAILURE
, _("cannot open %s"), *argv
);