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(void)
81 fputs(USAGE_HEADER
, out
);
82 fprintf(out
, _(" %s [options] [<file>...]\n"), program_invocation_short_name
);
84 fputs(USAGE_SEPARATOR
, out
);
85 fputs(_("Filter nroff output for CRT previewing.\n"), out
);
87 fputs(USAGE_OPTIONS
, out
);
88 fputs(_(" -, --no-underlining suppress all underlining\n"), out
);
89 fputs(_(" -2, --half-lines print all half-lines\n"), out
);
91 fputs(USAGE_SEPARATOR
, out
);
92 printf(USAGE_HELP_OPTIONS(25));
94 printf(USAGE_MAN_TAIL("colcrt(1)"));
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
);
167 while (getwc(ctl
->f
) != L
'\n') {
170 if (ferror(ctl
->f
) || feof(ctl
->f
))
172 new_pos
= ftell(ctl
->f
);
173 if (old_pos
== new_pos
) {
174 if (fseek(ctl
->f
, 1, SEEK_CUR
) < 1)
187 col
= rubchars(ctl
, col
, 1);
191 col
= rubchars(ctl
, col
, 2);
197 output_lines(ctl
, col
);
200 output_lines(ctl
, col
);
204 for (/* nothing */; col
% 8 && col
< OUTPUT_COLS
; col
++) {
205 ctl
->line
[col
] = L
' ';
210 ctl
->line
[col
] = L
' ';
211 if (!ctl
->no_underlining
) {
212 ctl
->need_line_under
= 1;
213 ctl
->line_under
[col
] = L
'-';
227 int main(int argc
, char **argv
)
229 struct colcrt_control ctl
= { NULL
};
231 enum { NO_UL_OPTION
= CHAR_MAX
+ 1 };
233 static const struct option longopts
[] = {
234 {"no-underlining", no_argument
, NULL
, NO_UL_OPTION
},
235 {"half-lines", no_argument
, NULL
, '2'},
236 {"version", no_argument
, NULL
, 'V'},
237 {"help", no_argument
, NULL
, 'h'},
241 setlocale(LC_ALL
, "");
242 bindtextdomain(PACKAGE
, LOCALEDIR
);
244 close_stdout_atexit();
246 /* Take care of lonely hyphen option. */
247 for (opt
= 0; opt
< argc
; opt
++) {
248 if (argv
[opt
][0] == '-' && argv
[opt
][1] == '\0') {
249 ctl
.no_underlining
= 1;
251 memmove(argv
+ opt
, argv
+ opt
+ 1,
252 sizeof(char *) * (argc
- opt
));
257 while ((opt
= getopt_long(argc
, argv
, "2Vh", longopts
, NULL
)) != -1) {
260 ctl
.no_underlining
= 1;
267 print_version(EXIT_SUCCESS
);
271 errtryhelp(EXIT_FAILURE
);
279 wmemset(ctl
.line
, L
'\0', OUTPUT_COLS
);
280 wmemset(ctl
.line_under
, L
' ', OUTPUT_COLS
);
283 if (!(ctl
.f
= fopen(*argv
, "r")))
284 err(EXIT_FAILURE
, _("cannot open %s"), *argv
);