1 /* $NetBSD: tabs.c,v 1.1 2008/12/11 11:18:35 roy Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 2008 \
35 The NetBSD Foundation, inc. All rights reserved.");
36 __RCSID("$NetBSD: tabs.c,v 1.1 2008/12/11 11:18:35 roy Exp $");
39 #include <sys/ioctl.h>
40 #include <sys/types.h>
57 static const struct tabspec tabspecs
[] = {
58 {"a", "1,10,16,36,72"},
59 {"a2", "1,10,16,40,72"},
60 {"c", "1,8,12,16,20,55"},
61 {"c2", "1,6,10,14,49"},
62 {"c3", "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67"},
63 {"f", "1,7,11,15,19,23"},
64 {"p", "1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61"},
68 static const size_t ntabspecs
= sizeof(tabspecs
) / sizeof(tabspecs
[0]);
70 static char tbuf
[2048];
76 "usage: tabs [-n|-a|-a2|-c|-c2|-c3|-f|-p|-s|-u] [+m[n]]"
78 " tabs [-T type] [+[n]] n1[,n2,...]\n");
84 main(int argc
, char **argv
)
86 char *term
, *arg
, *tbp
, *token
, *end
, *tabs
= NULL
, *p
;
87 const char *cr
, *ct
, *st
, *ML
, *spec
= NULL
;
88 int i
, n
, inc
= 8, stops
[NSTOPS
], nstops
, last
, cols
, margin
= 0;
92 term
= getenv("TERM");
93 for (i
= 1; i
< argc
; i
++) {
94 if (argv
[i
][0] == '+') {
102 margin
= strtol(arg
, &end
, 10);
103 if (errno
!= 0 || *end
!= '\0' || margin
< 0)
105 "%s: invalid margin", arg
);
109 if (argv
[i
][0] != '-') {
116 if (arg
[0] == '-' && arg
[1] == '\0') {
117 if (argv
[i
+ 1] != '\0')
121 if (arg
[0] == 'T' && arg
[1] == '\0') {
127 if (isdigit((int)arg
[0])) {
130 "%s: invalid increament", arg
);
134 for (j
= 0; j
< ntabspecs
; j
++) {
135 if (arg
[0] == tabspecs
[j
].opt
[0] &&
136 arg
[1] == tabspecs
[j
].opt
[1]) {
137 spec
= tabspecs
[j
].spec
;
144 if (tabs
== NULL
&& spec
!= NULL
)
152 while ((token
= strsep(&p
, ", ")) != NULL
) {
155 if (nstops
>= NSTOPS
)
157 "too many tab stops (max %d)", NSTOPS
);
159 n
= strtol(token
, &end
, 10);
160 if (errno
!= 0 || *end
!= '\0' || n
<= 0)
161 errx(EXIT_FAILURE
, "%s: invalid tab stop", token
);
165 "first tab stop may not be relative");
169 errx(EXIT_FAILURE
, "tab stops may not go backwards");
170 last
= stops
[nstops
++] = n
;
174 errx(EXIT_FAILURE
, "no value for $TERM and -T not given");
175 switch (tgetent(tbuf
, term
)) {
177 err(EXIT_FAILURE
, "termcap database");
179 errx(EXIT_FAILURE
, "%s: no termcap entry", term
);
182 cr
= tgetstr("cr", &tbp
);
185 ct
= tgetstr("ct", &tbp
);
187 errx(EXIT_FAILURE
, "terminal cannot clear tabs");
188 st
= tgetstr("st", &tbp
);
190 errx(EXIT_FAILURE
, "terminal cannot set tabs");
191 ML
= tgetstr("ML", &tbp
);
193 /* Clear existing tabs */
194 tputs(cr
, 1, putchar
);
195 tputs(ct
, 1, putchar
);
196 tputs(cr
, 1, putchar
);
199 printf("%*s", margin
, "");
200 tputs(ML
, 1, putchar
);
201 } else if (margin
!= 0)
202 warnx("terminal cannot set left margin");
205 printf("%*s", stops
[0] - 1, "");
206 tputs(st
, 1, putchar
);
207 for (i
= 1; i
< nstops
; i
++) {
208 printf("%*s", stops
[i
] - stops
[i
- 1], "");
209 tputs(st
, 1, putchar
);
211 } else if (inc
> 0) {
213 term
= getenv("COLUMNS");
216 cols
= strtol(term
, &end
, 10);
217 if (errno
!= 0 || *end
!= '\0' || cols
< 0)
221 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) == 0)
224 cols
= tgetnum("co");
227 warnx("terminal does not specify number"
228 "columns; defaulting to %d",
233 for (i
= 0; i
< cols
/ inc
; i
++) {
234 printf("%*s", inc
, "");
235 tputs(st
, 1, putchar
);
238 tputs(cr
, 1, putchar
);