4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 * col - filter reverse carraige motions
54 wchar_t lbuff
[LINELN
], *line
;
55 wchar_t *lbuffend
= lbuff
+ LINELN
- 1;
56 wchar_t ws_blank
[2] = {' ', 0};
57 char esc_chars
, underline
, temp_off
, smart
;
58 int bflag
, xflag
, fflag
, pflag
;
66 #define USAGEMSG "usage:\tcol [-bfxp]\n"
68 static void outc(wchar_t);
69 static void store(int);
70 static void fetch(int);
71 static void emit(wchar_t *, int);
72 static void incr(void);
73 static void decr(void);
74 static void wsinsert(wchar_t *, int);
75 static void incr_line(int);
76 static int wcscrwidth(wchar_t);
79 main(int argc
, char **argv
)
87 static char fbuff
[BUFSIZ
];
89 setbuf(stdout
, fbuff
);
90 (void) setlocale(LC_ALL
, "");
91 #if !defined(TEXT_DOMAIN)
92 #define TEXT_DOMAIN "SYS_TEST"
94 (void) textdomain(TEXT_DOMAIN
);
97 while ((opt
= getopt(argc
, argv
, "bfxp")) != EOF
)
113 (void) fprintf(stderr
, gettext(USAGEMSG
));
119 (void) fprintf(stderr
, gettext(USAGEMSG
));
123 for (ll
= 0; ll
< PL
; ll
++)
126 smart
= temp_off
= underline
= esc_chars
= '\0';
133 while ((c
= getwchar()) != EOF
) {
134 if (underline
&& temp_off
&& c
> ' ') {
141 *line
= temp_off
= '\0';
148 if (underline
&& !temp_off
) {
169 case '7': /* reverse full line feed */
174 case '8': /* reverse half line feed */
186 case '9': /* forward half line feed */
199 if (pflag
) { /* pass through esc */
208 if (c
== 'Y' && underline
)
209 underline
= temp_off
= '\0';
255 if (iswprint(c
)) { /* if printable */
261 * EUC (apply SO only when there can
262 * be corresponding character in CS1)
264 else if (iswascii(c
)) {
266 n
= mbtowc(&wc
, &byte
, 1);
267 if (!iswcntrl(c
) && !iswspace(c
) &&
270 cp
+= wcscrwidth(wc
);
280 if ((cp
+ 1) > LINELN
) {
281 (void) fprintf(stderr
,
282 gettext("col: Line too long\n"));
290 for (i
= 0; i
< PL
; i
++)
291 if (page
[(mustwr
+i
)%PL
] != 0)
292 emit(page
[(mustwr
+i
) % PL
], mustwr
+i
-PL
);
293 emit(ws_blank
, (llh
+ 1) & -2);
301 int width
, widthl
, widthc
;
304 char esc_chars
= '\0';
324 /* if ( ! esc_chars ) */
328 lp
+= wcscrwidth(*line
);
332 while (*line
== '\b') {
334 * EUC (For a multi-column character, backspace characters
335 * are assumed to be used like "__^H^HXX", where "XX"
336 * represents a two-column character, and a backspace
337 * always goes back by one column.)
339 for (n
= 0; *line
== '\b'; incr_line(1)) {
343 while (n
> 0 && lp
< cp
) {
353 widthc
= wcscrwidth(c
);
354 widthl
= wcscrwidth(*line
);
355 if (bflag
|| (*line
== '\0') || *line
== ' ') {
356 if (*line
== '\0' || widthl
== widthc
) {
358 } else if (widthl
> widthc
) {
363 for (i
= 0; i
< n
; i
++) {
371 if (line
< lbuffend
) {
372 for (p1
= line
+1; n
> 0 && p1
< lbuffend
;
373 n
-= wcscrwidth(i
)) {
378 (void) wcscpy(line
+1, p1
);
380 (void) fprintf(stderr
,
381 gettext("col: Line too long.\n"));
385 (void) fprintf(stderr
,
386 gettext("col: Line too long.\n"));
391 if (smart
&& (widthl
== 1) && (widthc
== 1)) {
392 wchar_t c1
, c2
, c3
, c4
, c5
, c6
, c7
;
424 if ((widthl
== 1) && (widthc
== 1)) {
441 width
= (widthc
> widthl
) ? widthc
: widthl
;
442 for (i
= 0; i
< width
; i
+= wcscrwidth(c1
)) {
446 wsinsert(line
, width
+ (width
- widthc
+ 1));
447 for (i
= 0; i
< width
; i
++) {
453 for (i
= widthc
; i
< width
; i
++) {
469 free((char *)page
[lno
]);
470 page
[lno
] = (wchar_t *)malloc((unsigned)(wcslen(lbuff
) + 2)
472 if (page
[lno
] == 0) {
473 /* fprintf(stderr, "%s: no storage\n", pgmname); */
476 (void) wcscpy(page
[lno
], lbuff
);
491 (void) wcscpy(line
, page
[lno
]);
495 emit(wchar_t *s
, int lineno
)
497 static int cline
= 0;
501 char chr
[MB_LEN_MAX
+ 1];
504 static int gflag
= 0;
511 while (cline
< lineno
- 1) {
512 (void) putchar('\n');
516 if (cline
!= lineno
) {
522 (void) putchar('\r');
527 while (*p
++ == ' ') {
528 if ((++ncp
& 7) == 0 && !xflag
) {
530 (void) putchar('\t');
540 if (wctomb(chr
, *p
) == 1) {
541 if (gflag
!= (*chr
& GREEK
) &&
543 isascii(*chr
^ (gflag
^ GREEK
)) &&
544 !iscntrl(*chr
^ (gflag
^ GREEK
)) &&
545 !isspace(*chr
^ (gflag
^ GREEK
))) {
556 if (wctomb(chr
, (wchar_t)c
) == 1) {
557 cshifted
= (*chr
^ GREEK
);
558 if (isascii(cshifted
) &&
559 !iscntrl(cshifted
) &&
561 (void) putchar(*chr
& ~GREEK
);
567 if (*(p
-2) && *(p
-2) == ESC
) {
572 pcp
+= wcscrwidth(c
);
585 if (ll
>= mustwr
&& page
[ll
%PL
]) {
586 emit(page
[ll
%PL
], ll
- PL
);
588 free((char *)page
[ll
%PL
]);
597 if (ll
> mustwr
- PL
) {
604 wsinsert(wchar_t *s
, int n
)
616 * incr_line - increments line pointer and checks for array out of bounds
617 * amt: assumed to be >= 1
618 * exit on error to avoid line pointer accessing out of the array
623 if (line
< lbuffend
- amt
+ 1) {
626 (void) fprintf(stderr
, gettext("col: Line too long.\n"));
633 wcscrwidth(wchar_t wc
)
639 * if wc is a null character, needs to
640 * return 1 instead of 0.