xref: /titanic_53/usr/src/lib/libxcurses/src/tabs/tabs.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1996, by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  *	tabs.c
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  *	Copyright 1990, 1992 by Mortice Kern Systems Inc.  All rights reserved.
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  *	PORTABILITY:
35*7c478bd9Sstevel@tonic-gate  *	POSIX.2a UPE full support
36*7c478bd9Sstevel@tonic-gate  *	SVID 3 full support except +m option is stubbed
37*7c478bd9Sstevel@tonic-gate  *	XPG full support except +m option is stubbed
38*7c478bd9Sstevel@tonic-gate  *
39*7c478bd9Sstevel@tonic-gate  *	SYNOPSIS:
40*7c478bd9Sstevel@tonic-gate  *	tabs [-T term] [+m[n]] [-n]
41*7c478bd9Sstevel@tonic-gate  *	tabs [-T term] [+m[n]] -t tablist
42*7c478bd9Sstevel@tonic-gate  *	tabs [-T term] [+m[n]] n1[,n2,...]
43*7c478bd9Sstevel@tonic-gate  *	tabs [-T term] [+m[n]] tabspec
44*7c478bd9Sstevel@tonic-gate  *
45*7c478bd9Sstevel@tonic-gate  *	DESCRIPTION:
46*7c478bd9Sstevel@tonic-gate  *	The tabs utility shall display a series of characters that first clears
47*7c478bd9Sstevel@tonic-gate  *	the hardware terminal tab settings and then initializes the tab stops
48*7c478bd9Sstevel@tonic-gate  *	at the specified positions.
49*7c478bd9Sstevel@tonic-gate  *
50*7c478bd9Sstevel@tonic-gate  *	The phrase "tab-stop position N" shall be taken to mean that, from the
51*7c478bd9Sstevel@tonic-gate  *	start of a line of output, tabbing to position N shall cause the next
52*7c478bd9Sstevel@tonic-gate  *	character output to be in the (N+1)th column position on that line.
53*7c478bd9Sstevel@tonic-gate  *	The maximum number of tab stops allowed is terminal dependent.
54*7c478bd9Sstevel@tonic-gate  *
55*7c478bd9Sstevel@tonic-gate  *	'tabspec' is one of the following:
56*7c478bd9Sstevel@tonic-gate  *
57*7c478bd9Sstevel@tonic-gate  *	Assembler:
58*7c478bd9Sstevel@tonic-gate  *	-a	1,10,16,36,72
59*7c478bd9Sstevel@tonic-gate  *	-a2	1,10,16,40,72
60*7c478bd9Sstevel@tonic-gate  *	-u	1,12,20,44
61*7c478bd9Sstevel@tonic-gate  *
62*7c478bd9Sstevel@tonic-gate  *	COBOL:
63*7c478bd9Sstevel@tonic-gate  *	-c	1,8,12,16,20,55
64*7c478bd9Sstevel@tonic-gate  *	-c2	1,6,10,14,49
65*7c478bd9Sstevel@tonic-gate  *	-c3	1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67
66*7c478bd9Sstevel@tonic-gate  *
67*7c478bd9Sstevel@tonic-gate  *	FORTRAN:
68*7c478bd9Sstevel@tonic-gate  *	-f	1,7,11,15,19,23
69*7c478bd9Sstevel@tonic-gate  *
70*7c478bd9Sstevel@tonic-gate  *	PL/I:
71*7c478bd9Sstevel@tonic-gate  *	-p	1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61
72*7c478bd9Sstevel@tonic-gate  *
73*7c478bd9Sstevel@tonic-gate  *	SNOBOL:
74*7c478bd9Sstevel@tonic-gate  *	-s	1,10,55
75*7c478bd9Sstevel@tonic-gate  *
76*7c478bd9Sstevel@tonic-gate  *
77*7c478bd9Sstevel@tonic-gate  *	EXIT STATUS:
78*7c478bd9Sstevel@tonic-gate  *	0	successful completion.
79*7c478bd9Sstevel@tonic-gate  *
80*7c478bd9Sstevel@tonic-gate  *	>0	An error occured.
81*7c478bd9Sstevel@tonic-gate  */
82*7c478bd9Sstevel@tonic-gate #ifdef M_RCSID
83*7c478bd9Sstevel@tonic-gate #ifndef lint
84*7c478bd9Sstevel@tonic-gate static char rcsID[] = "$Id: tabs.c 1.20 1995/09/21 21:00:28 ant Exp $";
85*7c478bd9Sstevel@tonic-gate #endif
86*7c478bd9Sstevel@tonic-gate #endif
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate #include <mks.h>
89*7c478bd9Sstevel@tonic-gate #include <curses.h>
90*7c478bd9Sstevel@tonic-gate #define SINGLE	1		/* only one terminal to be concerned about */
91*7c478bd9Sstevel@tonic-gate #include <term.h>
92*7c478bd9Sstevel@tonic-gate #include <ctype.h>
93*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
94*7c478bd9Sstevel@tonic-gate #include <stdio.h>
95*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
96*7c478bd9Sstevel@tonic-gate #include <string.h>
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate extern char *_cmdname;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate /* Exit Status */
102*7c478bd9Sstevel@tonic-gate #define SUCCESS		0
103*7c478bd9Sstevel@tonic-gate #define NOT_DEFINED	1
104*7c478bd9Sstevel@tonic-gate #define USAGE		2
105*7c478bd9Sstevel@tonic-gate #define BAD_TERMINAL	3
106*7c478bd9Sstevel@tonic-gate #define NOT_VALID	4
107*7c478bd9Sstevel@tonic-gate #define ERROR		5
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate #define NO_FORM	0
110*7c478bd9Sstevel@tonic-gate #define N_FORM	1	/* tabs [-T term] [+m[n]] [-<n>] */
111*7c478bd9Sstevel@tonic-gate #define T_FORM	2	/* tabs [-T term] [+m[n]] -t tablist */
112*7c478bd9Sstevel@tonic-gate #define P_FORM	3	/* tabs [-T term] [+m[n]] n1[,n2,...]  and
113*7c478bd9Sstevel@tonic-gate 			 * tabs [-T term] [+m[n]] tabspec
114*7c478bd9Sstevel@tonic-gate 			 */
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate static int form = NO_FORM;
118*7c478bd9Sstevel@tonic-gate static int n_width = 8;
119*7c478bd9Sstevel@tonic-gate static int margin = 0;
120*7c478bd9Sstevel@tonic-gate static wchar_t *tablist;
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate typedef struct {
123*7c478bd9Sstevel@tonic-gate 	char *option;
124*7c478bd9Sstevel@tonic-gate 	char *list;
125*7c478bd9Sstevel@tonic-gate } predefined;
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate static predefined tabspec[] = {
128*7c478bd9Sstevel@tonic-gate 	{ "a", "1,10,16,36,72" },
129*7c478bd9Sstevel@tonic-gate 	{ "a2", "1,10,16,40,72" },
130*7c478bd9Sstevel@tonic-gate 	{ "u", "1,12,20,44" },
131*7c478bd9Sstevel@tonic-gate 	{ "c", "1,8,12,16,20,55" },
132*7c478bd9Sstevel@tonic-gate 	{ "c2", "1,6,10,14,49" },
133*7c478bd9Sstevel@tonic-gate 	{ "c3", "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67" },
134*7c478bd9Sstevel@tonic-gate 	{ "f", "1,7,11,15,19,23" },
135*7c478bd9Sstevel@tonic-gate 	{ "p", "1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61" },
136*7c478bd9Sstevel@tonic-gate 	{ "s", "1,10,55" },
137*7c478bd9Sstevel@tonic-gate 	{ NULL, NULL }
138*7c478bd9Sstevel@tonic-gate };
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate static char *term_name;
141*7c478bd9Sstevel@tonic-gate static char dumb_term[] = "dumb";
142*7c478bd9Sstevel@tonic-gate static char missing_tablist[] = m_textstr(1828, "Missing tab list after -t.\n", "E");
143*7c478bd9Sstevel@tonic-gate static char missing_terminal[] = m_textstr(1829, "Missing terminal type after -T.\n", "E");
144*7c478bd9Sstevel@tonic-gate static char unknown_option[] = m_textstr(433, "Unknown option \"-%s\".\n", "E option");
145*7c478bd9Sstevel@tonic-gate static char bad_list[] = m_textstr(1830, "Illegal tabs in \"%s\".\n", "E tablist");
146*7c478bd9Sstevel@tonic-gate static char no_margins[] = m_textstr(1831, "Cannot set margins on terminal \"%s\".\n", "E term");
147*7c478bd9Sstevel@tonic-gate static char no_tabs[] = m_textstr(1832, "Cannot set tabs on terminal \"%s\".\n", "E term");
148*7c478bd9Sstevel@tonic-gate static char not_ascending[] = m_textstr(1833, "\"%s\" are not in ascending order.\n", "E tablist");
149*7c478bd9Sstevel@tonic-gate static char usage_msg[] = m_textstr(1834, "\
150*7c478bd9Sstevel@tonic-gate Usage: tabs [-T term] [+m[n]] [-n]\n\
151*7c478bd9Sstevel@tonic-gate        tabs [-T term] [+m[n]] -t <tablist>\n\
152*7c478bd9Sstevel@tonic-gate        tabs [-T term] [+m[n]] n1[,n2,...]\n\
153*7c478bd9Sstevel@tonic-gate        tabs [-T term] [+m[n]] -a|a2|u|c|c2|c3|f|p|s\n", "U");
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate STATREF int do_tabs ANSI((void));
157*7c478bd9Sstevel@tonic-gate STATREF void err_msg ANSI((char *fmt, ...));	/* GENTEXT: err_msg */
158*7c478bd9Sstevel@tonic-gate STATREF void mvcol ANSI((int oc, int nc));
159*7c478bd9Sstevel@tonic-gate STATREF void set_every ANSI((int n));
160*7c478bd9Sstevel@tonic-gate STATREF void set_tab_at ANSI((int x));
161*7c478bd9Sstevel@tonic-gate STATREF int usage ANSI((void));
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate /*f
165*7c478bd9Sstevel@tonic-gate  * mainline for tabs
166*7c478bd9Sstevel@tonic-gate  */
167*7c478bd9Sstevel@tonic-gate int
main(argc,argv)168*7c478bd9Sstevel@tonic-gate main(argc, argv)
169*7c478bd9Sstevel@tonic-gate int argc;
170*7c478bd9Sstevel@tonic-gate char **argv;
171*7c478bd9Sstevel@tonic-gate {
172*7c478bd9Sstevel@tonic-gate 	char *ap;
173*7c478bd9Sstevel@tonic-gate 	int i;
174*7c478bd9Sstevel@tonic-gate 	int err_code;
175*7c478bd9Sstevel@tonic-gate 	predefined *p;
176*7c478bd9Sstevel@tonic-gate 	setlocale(LC_ALL, "");
177*7c478bd9Sstevel@tonic-gate 	_cmdname = m_cmdname(*argv);
178*7c478bd9Sstevel@tonic-gate 	if ((term_name = getenv("TERM")) == NULL)
179*7c478bd9Sstevel@tonic-gate 		term_name = dumb_term;
180*7c478bd9Sstevel@tonic-gate 	while (0 < --argc && (**++argv == '-' || **argv == '+')) {
181*7c478bd9Sstevel@tonic-gate 		ap = &argv[0][1];
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 		/* Check for standard io '-' */
184*7c478bd9Sstevel@tonic-gate 		if (*ap == '\0')
185*7c478bd9Sstevel@tonic-gate 			break;
186*7c478bd9Sstevel@tonic-gate 		/* End option list '--'? */
187*7c478bd9Sstevel@tonic-gate 		if (*ap == '-' && ap[1] == '\0') {
188*7c478bd9Sstevel@tonic-gate 			++argv;
189*7c478bd9Sstevel@tonic-gate 			--argc;
190*7c478bd9Sstevel@tonic-gate 			break;
191*7c478bd9Sstevel@tonic-gate 		}
192*7c478bd9Sstevel@tonic-gate 		if (**argv == '-') {
193*7c478bd9Sstevel@tonic-gate 			/* '-xyz...' or '-xyzF<parm>' or '-xyzF <parm>' */
194*7c478bd9Sstevel@tonic-gate 			for (;*ap != '\0'; ++ap) {
195*7c478bd9Sstevel@tonic-gate 				switch (*ap) {
196*7c478bd9Sstevel@tonic-gate 				case 't':
197*7c478bd9Sstevel@tonic-gate 					if (form != NO_FORM)
198*7c478bd9Sstevel@tonic-gate 						return (usage());
199*7c478bd9Sstevel@tonic-gate 					form = T_FORM;
200*7c478bd9Sstevel@tonic-gate 					if (*++ap != '\0') {
201*7c478bd9Sstevel@tonic-gate 						tablist = m_mbstowcsdup(ap);
202*7c478bd9Sstevel@tonic-gate 						break;
203*7c478bd9Sstevel@tonic-gate 					} else if (1 < argc) {
204*7c478bd9Sstevel@tonic-gate 						tablist = m_mbstowcsdup(*++argv);
205*7c478bd9Sstevel@tonic-gate 						--argc;
206*7c478bd9Sstevel@tonic-gate 						break;
207*7c478bd9Sstevel@tonic-gate 					}
208*7c478bd9Sstevel@tonic-gate 					err_msg(missing_tablist);
209*7c478bd9Sstevel@tonic-gate 					return (usage());
210*7c478bd9Sstevel@tonic-gate 					break;
211*7c478bd9Sstevel@tonic-gate 				case 'T':
212*7c478bd9Sstevel@tonic-gate 					/* '-T<term>' or '-T <term>' */
213*7c478bd9Sstevel@tonic-gate 					if (*++ap != '\0') {
214*7c478bd9Sstevel@tonic-gate 						term_name = ap;
215*7c478bd9Sstevel@tonic-gate 						break;
216*7c478bd9Sstevel@tonic-gate 					} else if (1 < argc) {
217*7c478bd9Sstevel@tonic-gate 						term_name = *++argv;
218*7c478bd9Sstevel@tonic-gate 						--argc;
219*7c478bd9Sstevel@tonic-gate 						break;
220*7c478bd9Sstevel@tonic-gate 					}
221*7c478bd9Sstevel@tonic-gate 					err_msg(missing_terminal);
222*7c478bd9Sstevel@tonic-gate 					return (usage());
223*7c478bd9Sstevel@tonic-gate 				default:
224*7c478bd9Sstevel@tonic-gate 					if (isdigit(*ap)) {
225*7c478bd9Sstevel@tonic-gate 						if (form != NO_FORM)
226*7c478bd9Sstevel@tonic-gate 							return (usage());
227*7c478bd9Sstevel@tonic-gate 						form = N_FORM;
228*7c478bd9Sstevel@tonic-gate 						n_width =  *ap - '0';
229*7c478bd9Sstevel@tonic-gate 						continue;
230*7c478bd9Sstevel@tonic-gate 					}
231*7c478bd9Sstevel@tonic-gate 					for (p = tabspec;
232*7c478bd9Sstevel@tonic-gate 					     p->option != NULL
233*7c478bd9Sstevel@tonic-gate 					     && strcmp(p->option, ap) != 0;
234*7c478bd9Sstevel@tonic-gate 					     ++p)
235*7c478bd9Sstevel@tonic-gate 						;
236*7c478bd9Sstevel@tonic-gate 					if (p->option != NULL) {
237*7c478bd9Sstevel@tonic-gate 						form = P_FORM;
238*7c478bd9Sstevel@tonic-gate 						tablist = m_mbstowcsdup(p->list);
239*7c478bd9Sstevel@tonic-gate 						break;
240*7c478bd9Sstevel@tonic-gate 					}
241*7c478bd9Sstevel@tonic-gate 					err_msg(unknown_option, ap);
242*7c478bd9Sstevel@tonic-gate 					return (usage());
243*7c478bd9Sstevel@tonic-gate 				}
244*7c478bd9Sstevel@tonic-gate 				break;
245*7c478bd9Sstevel@tonic-gate 			}
246*7c478bd9Sstevel@tonic-gate 		} else {
247*7c478bd9Sstevel@tonic-gate 			/* All '+' options. */
248*7c478bd9Sstevel@tonic-gate 			if (*ap == 'm') {
249*7c478bd9Sstevel@tonic-gate 				margin = (int) strtol(++ap, NULL, 0);
250*7c478bd9Sstevel@tonic-gate 				if (margin == 0)
251*7c478bd9Sstevel@tonic-gate 					margin = 10;
252*7c478bd9Sstevel@tonic-gate 			} else {
253*7c478bd9Sstevel@tonic-gate 				err_msg(unknown_option, ap);
254*7c478bd9Sstevel@tonic-gate 				return (usage());
255*7c478bd9Sstevel@tonic-gate 			}
256*7c478bd9Sstevel@tonic-gate 		}
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 	if (form == NO_FORM) {
259*7c478bd9Sstevel@tonic-gate 		switch (argc) {
260*7c478bd9Sstevel@tonic-gate 		case 0:
261*7c478bd9Sstevel@tonic-gate 			form = N_FORM;
262*7c478bd9Sstevel@tonic-gate 			break;
263*7c478bd9Sstevel@tonic-gate 		case 1:
264*7c478bd9Sstevel@tonic-gate 			form = P_FORM;
265*7c478bd9Sstevel@tonic-gate 			tablist = m_mbstowcsdup(*argv);
266*7c478bd9Sstevel@tonic-gate 			break;
267*7c478bd9Sstevel@tonic-gate 		default:
268*7c478bd9Sstevel@tonic-gate 			return (usage());
269*7c478bd9Sstevel@tonic-gate 		}
270*7c478bd9Sstevel@tonic-gate 	} else if (0 < argc) {
271*7c478bd9Sstevel@tonic-gate 		return (usage());
272*7c478bd9Sstevel@tonic-gate 	}
273*7c478bd9Sstevel@tonic-gate 	(void) setupterm(term_name, fileno(stdout), &err_code);
274*7c478bd9Sstevel@tonic-gate 	switch (err_code) {
275*7c478bd9Sstevel@tonic-gate 	case 1:
276*7c478bd9Sstevel@tonic-gate 		break;
277*7c478bd9Sstevel@tonic-gate 	case 0:
278*7c478bd9Sstevel@tonic-gate 		err_msg(m_textstr(202, "Unknown terminal \"%s\".\n", "E term"), term_name);
279*7c478bd9Sstevel@tonic-gate 		return (BAD_TERMINAL);
280*7c478bd9Sstevel@tonic-gate 	case -1:
281*7c478bd9Sstevel@tonic-gate 		err_msg(m_textstr(203, "No terminfo database.\n", "E"));
282*7c478bd9Sstevel@tonic-gate 		return (BAD_TERMINAL);
283*7c478bd9Sstevel@tonic-gate 	}
284*7c478bd9Sstevel@tonic-gate 	if (save_cursor != NULL)
285*7c478bd9Sstevel@tonic-gate 		putp(save_cursor);
286*7c478bd9Sstevel@tonic-gate 	err_code = do_tabs();
287*7c478bd9Sstevel@tonic-gate 	if (restore_cursor != NULL)
288*7c478bd9Sstevel@tonic-gate 		putp(restore_cursor);
289*7c478bd9Sstevel@tonic-gate 	else
290*7c478bd9Sstevel@tonic-gate 		mvcol(0, 0);
291*7c478bd9Sstevel@tonic-gate 	return (err_code);
292*7c478bd9Sstevel@tonic-gate }
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate /*f
295*7c478bd9Sstevel@tonic-gate  * actually do tabs
296*7c478bd9Sstevel@tonic-gate  */
297*7c478bd9Sstevel@tonic-gate STATIC int
do_tabs()298*7c478bd9Sstevel@tonic-gate do_tabs()
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	int oc = 0;
301*7c478bd9Sstevel@tonic-gate 	int nc = 0;
302*7c478bd9Sstevel@tonic-gate 	wchar_t *p = tablist;
303*7c478bd9Sstevel@tonic-gate 	if (clear_all_tabs == NULL || set_tab == NULL) {
304*7c478bd9Sstevel@tonic-gate 		err_msg(no_tabs, term_name);
305*7c478bd9Sstevel@tonic-gate 		return (NOT_DEFINED);
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 	mvcol(0, 0);
308*7c478bd9Sstevel@tonic-gate 	putp(clear_all_tabs);
309*7c478bd9Sstevel@tonic-gate #if 0	/* margins are not yet supported in terminfo */
310*7c478bd9Sstevel@tonic-gate 	if (clear_margins == NULL || set_left_margin == NULL) {
311*7c478bd9Sstevel@tonic-gate 		err_msg(no_margins, term_name);
312*7c478bd9Sstevel@tonic-gate 		return (NOT_DEFINED);
313*7c478bd9Sstevel@tonic-gate 	} else {
314*7c478bd9Sstevel@tonic-gate 		putp(clear_margins);
315*7c478bd9Sstevel@tonic-gate 		mvcol(0, margin);
316*7c478bd9Sstevel@tonic-gate 		putp(set_left_margin);
317*7c478bd9Sstevel@tonic-gate 	}
318*7c478bd9Sstevel@tonic-gate #endif
319*7c478bd9Sstevel@tonic-gate 	switch (form) {
320*7c478bd9Sstevel@tonic-gate 	case N_FORM:
321*7c478bd9Sstevel@tonic-gate 		if (0 < n_width)
322*7c478bd9Sstevel@tonic-gate 			set_every(n_width);
323*7c478bd9Sstevel@tonic-gate 		break;
324*7c478bd9Sstevel@tonic-gate 	case T_FORM:
325*7c478bd9Sstevel@tonic-gate 		nc = (int) wcstol(p, &p, 0);
326*7c478bd9Sstevel@tonic-gate 		if (p == tablist || nc < 0) {
327*7c478bd9Sstevel@tonic-gate 			err_msg(bad_list, tablist);
328*7c478bd9Sstevel@tonic-gate 			return (NOT_VALID);
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 		if (*p == '\0') {
331*7c478bd9Sstevel@tonic-gate 			set_every(nc);
332*7c478bd9Sstevel@tonic-gate 			break;
333*7c478bd9Sstevel@tonic-gate 		}
334*7c478bd9Sstevel@tonic-gate 		do {
335*7c478bd9Sstevel@tonic-gate 			if (nc <= oc) {
336*7c478bd9Sstevel@tonic-gate 				err_msg(not_ascending, tablist);
337*7c478bd9Sstevel@tonic-gate 				return (NOT_VALID);
338*7c478bd9Sstevel@tonic-gate 			}
339*7c478bd9Sstevel@tonic-gate 			if (*p != '\0' && *p != ',' && !iswblank(*p)) {
340*7c478bd9Sstevel@tonic-gate 				err_msg(bad_list, tablist);
341*7c478bd9Sstevel@tonic-gate 				return (NOT_VALID);
342*7c478bd9Sstevel@tonic-gate 			}
343*7c478bd9Sstevel@tonic-gate 			++p;
344*7c478bd9Sstevel@tonic-gate 			oc = nc;
345*7c478bd9Sstevel@tonic-gate 			set_tab_at(nc);
346*7c478bd9Sstevel@tonic-gate 			nc = (int) wcstol(p, &p, 0);
347*7c478bd9Sstevel@tonic-gate 		} while (nc != 0);
348*7c478bd9Sstevel@tonic-gate 		break;
349*7c478bd9Sstevel@tonic-gate 	case P_FORM:
350*7c478bd9Sstevel@tonic-gate 		if (*p == '+' || *p == '-') {
351*7c478bd9Sstevel@tonic-gate 			err_msg(bad_list, tablist);
352*7c478bd9Sstevel@tonic-gate 			return (NOT_VALID);
353*7c478bd9Sstevel@tonic-gate 		}
354*7c478bd9Sstevel@tonic-gate 		for (;;) {
355*7c478bd9Sstevel@tonic-gate 			nc += (int) wcstol(p, &p, 0);
356*7c478bd9Sstevel@tonic-gate 			if (nc == 0)
357*7c478bd9Sstevel@tonic-gate 				break;
358*7c478bd9Sstevel@tonic-gate 			if (nc <= oc) {
359*7c478bd9Sstevel@tonic-gate 				err_msg(not_ascending, tablist);
360*7c478bd9Sstevel@tonic-gate 				return (NOT_VALID);
361*7c478bd9Sstevel@tonic-gate 			}
362*7c478bd9Sstevel@tonic-gate 			if (*p != '\0' && *p != ',' && !iswblank(*p)) {
363*7c478bd9Sstevel@tonic-gate 				err_msg(bad_list, tablist);
364*7c478bd9Sstevel@tonic-gate 				return (NOT_VALID);
365*7c478bd9Sstevel@tonic-gate 			}
366*7c478bd9Sstevel@tonic-gate 			++p;
367*7c478bd9Sstevel@tonic-gate 			oc = nc;
368*7c478bd9Sstevel@tonic-gate 			set_tab_at(nc);
369*7c478bd9Sstevel@tonic-gate 			if (*p == '+')
370*7c478bd9Sstevel@tonic-gate 				++p;
371*7c478bd9Sstevel@tonic-gate 			else
372*7c478bd9Sstevel@tonic-gate 				nc = 0;
373*7c478bd9Sstevel@tonic-gate 		}
374*7c478bd9Sstevel@tonic-gate 		break;
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 	return (SUCCESS);
377*7c478bd9Sstevel@tonic-gate }
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate /*f
380*7c478bd9Sstevel@tonic-gate  *	Set a tab every n columns starting with column 0.
381*7c478bd9Sstevel@tonic-gate  */
382*7c478bd9Sstevel@tonic-gate STATIC void
set_every(n)383*7c478bd9Sstevel@tonic-gate set_every(n)
384*7c478bd9Sstevel@tonic-gate int n;
385*7c478bd9Sstevel@tonic-gate {
386*7c478bd9Sstevel@tonic-gate 	int x;
387*7c478bd9Sstevel@tonic-gate 	for (x = 0; x < columns; x += n)
388*7c478bd9Sstevel@tonic-gate 		set_tab_at(x);
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate /*f
392*7c478bd9Sstevel@tonic-gate  *	Set tab at column x. Assume that cursor has been positioned at the
393*7c478bd9Sstevel@tonic-gate  *	start of the line before settiing the first tab.
394*7c478bd9Sstevel@tonic-gate  */
395*7c478bd9Sstevel@tonic-gate STATIC void
set_tab_at(x)396*7c478bd9Sstevel@tonic-gate set_tab_at(x)
397*7c478bd9Sstevel@tonic-gate int x;
398*7c478bd9Sstevel@tonic-gate {
399*7c478bd9Sstevel@tonic-gate 	static int col = 0;
400*7c478bd9Sstevel@tonic-gate 	mvcol(col, x);
401*7c478bd9Sstevel@tonic-gate 	putp(set_tab);
402*7c478bd9Sstevel@tonic-gate 	col = x;
403*7c478bd9Sstevel@tonic-gate }
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate /*f
406*7c478bd9Sstevel@tonic-gate  *	Move the cursor on the current row from column 'col' to column 'x'.
407*7c478bd9Sstevel@tonic-gate  *	We can't use mvcur() because we have no idea what row we're on.
408*7c478bd9Sstevel@tonic-gate  */
409*7c478bd9Sstevel@tonic-gate STATIC void
mvcol(oc,nc)410*7c478bd9Sstevel@tonic-gate mvcol(oc, nc)
411*7c478bd9Sstevel@tonic-gate int oc, nc;
412*7c478bd9Sstevel@tonic-gate {
413*7c478bd9Sstevel@tonic-gate 	int diff = nc - oc;
414*7c478bd9Sstevel@tonic-gate 	if (nc == 0) {
415*7c478bd9Sstevel@tonic-gate 		putchar('\r');
416*7c478bd9Sstevel@tonic-gate 	} else if (column_address != NULL) {
417*7c478bd9Sstevel@tonic-gate 		putp(tparm(column_address, nc, 0, 0, 0, 0, 0, 0, 0, 0));
418*7c478bd9Sstevel@tonic-gate 	} else if (parm_right_cursor != NULL) {
419*7c478bd9Sstevel@tonic-gate 		putp(tparm(parm_right_cursor, diff, 0, 0, 0, 0, 0, 0, 0, 0));
420*7c478bd9Sstevel@tonic-gate 	} else if (cursor_right != NULL) {
421*7c478bd9Sstevel@tonic-gate 		while (diff--)
422*7c478bd9Sstevel@tonic-gate 			putp(cursor_right);
423*7c478bd9Sstevel@tonic-gate 	} else {
424*7c478bd9Sstevel@tonic-gate 		while (diff--)
425*7c478bd9Sstevel@tonic-gate 			putchar(' ');
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate /*f
430*7c478bd9Sstevel@tonic-gate  * usage message for tabs
431*7c478bd9Sstevel@tonic-gate  */
432*7c478bd9Sstevel@tonic-gate STATIC int
usage()433*7c478bd9Sstevel@tonic-gate usage()
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, m_strmsg(usage_msg));
436*7c478bd9Sstevel@tonic-gate 	return (USAGE);
437*7c478bd9Sstevel@tonic-gate }
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate /*f
440*7c478bd9Sstevel@tonic-gate  * display error message
441*7c478bd9Sstevel@tonic-gate  */
442*7c478bd9Sstevel@tonic-gate STATIC void
VARARG1(char *,fmt)443*7c478bd9Sstevel@tonic-gate err_msg VARARG1(char*, fmt)
444*7c478bd9Sstevel@tonic-gate {
445*7c478bd9Sstevel@tonic-gate 	va_list ap;
446*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", _cmdname);
447*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
448*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, m_strmsg(fmt), ap);
449*7c478bd9Sstevel@tonic-gate 	va_end(ap);
450*7c478bd9Sstevel@tonic-gate }
451