15f4613f2SJohn Marino /****************************************************************************
2*32bb5217SDaniel Fojt * Copyright 2020 Thomas E. Dickey *
3*32bb5217SDaniel Fojt * Copyright 2008-2016,2017 Free Software Foundation, Inc. *
45f4613f2SJohn Marino * *
55f4613f2SJohn Marino * Permission is hereby granted, free of charge, to any person obtaining a *
65f4613f2SJohn Marino * copy of this software and associated documentation files (the *
75f4613f2SJohn Marino * "Software"), to deal in the Software without restriction, including *
85f4613f2SJohn Marino * without limitation the rights to use, copy, modify, merge, publish, *
95f4613f2SJohn Marino * distribute, distribute with modifications, sublicense, and/or sell *
105f4613f2SJohn Marino * copies of the Software, and to permit persons to whom the Software is *
115f4613f2SJohn Marino * furnished to do so, subject to the following conditions: *
125f4613f2SJohn Marino * *
135f4613f2SJohn Marino * The above copyright notice and this permission notice shall be included *
145f4613f2SJohn Marino * in all copies or substantial portions of the Software. *
155f4613f2SJohn Marino * *
165f4613f2SJohn Marino * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
175f4613f2SJohn Marino * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
185f4613f2SJohn Marino * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
195f4613f2SJohn Marino * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
205f4613f2SJohn Marino * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
215f4613f2SJohn Marino * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
225f4613f2SJohn Marino * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
235f4613f2SJohn Marino * *
245f4613f2SJohn Marino * Except as contained in this notice, the name(s) of the above copyright *
255f4613f2SJohn Marino * holders shall not be used in advertising or otherwise to promote the *
265f4613f2SJohn Marino * sale, use or other dealings in this Software without prior written *
275f4613f2SJohn Marino * authorization. *
285f4613f2SJohn Marino ****************************************************************************/
295f4613f2SJohn Marino
305f4613f2SJohn Marino /****************************************************************************
315f4613f2SJohn Marino * Author: Thomas E. Dickey 2008 *
325f4613f2SJohn Marino ****************************************************************************/
335f4613f2SJohn Marino
345f4613f2SJohn Marino /*
355f4613f2SJohn Marino * tabs.c -- set terminal hard-tabstops
365f4613f2SJohn Marino */
375f4613f2SJohn Marino
385f4613f2SJohn Marino #define USE_LIBTINFO
395f4613f2SJohn Marino #include <progs.priv.h>
40*32bb5217SDaniel Fojt #include <tty_settings.h>
415f4613f2SJohn Marino
42*32bb5217SDaniel Fojt MODULE_ID("$Id: tabs.c,v 1.42 2020/02/02 23:34:34 tom Exp $")
435f4613f2SJohn Marino
445f4613f2SJohn Marino static void usage(void) GCC_NORETURN;
455f4613f2SJohn Marino
46*32bb5217SDaniel Fojt const char *_nc_progname;
475f4613f2SJohn Marino static int max_cols;
485f4613f2SJohn Marino
493468e90cSJohn Marino static void
failed(const char * s)503468e90cSJohn Marino failed(const char *s)
513468e90cSJohn Marino {
523468e90cSJohn Marino perror(s);
533468e90cSJohn Marino ExitProgram(EXIT_FAILURE);
543468e90cSJohn Marino }
553468e90cSJohn Marino
565f4613f2SJohn Marino static int
putch(int c)575f4613f2SJohn Marino putch(int c)
585f4613f2SJohn Marino {
595f4613f2SJohn Marino return putchar(c);
605f4613f2SJohn Marino }
615f4613f2SJohn Marino
625f4613f2SJohn Marino static void
do_tabs(int * tab_list)635f4613f2SJohn Marino do_tabs(int *tab_list)
645f4613f2SJohn Marino {
655f4613f2SJohn Marino int last = 1;
665f4613f2SJohn Marino int stop;
675f4613f2SJohn Marino
685f4613f2SJohn Marino putchar('\r');
695f4613f2SJohn Marino while ((stop = *tab_list++) > 0) {
705f4613f2SJohn Marino if (last < stop) {
715f4613f2SJohn Marino while (last++ < stop) {
725f4613f2SJohn Marino if (last > max_cols)
735f4613f2SJohn Marino break;
745f4613f2SJohn Marino putchar(' ');
755f4613f2SJohn Marino }
765f4613f2SJohn Marino }
775f4613f2SJohn Marino if (stop <= max_cols) {
785f4613f2SJohn Marino tputs(tparm(set_tab, stop), 1, putch);
795f4613f2SJohn Marino last = stop;
805f4613f2SJohn Marino } else {
815f4613f2SJohn Marino break;
825f4613f2SJohn Marino }
835f4613f2SJohn Marino }
843468e90cSJohn Marino putchar('\r');
855f4613f2SJohn Marino }
865f4613f2SJohn Marino
875f4613f2SJohn Marino static int *
decode_tabs(const char * tab_list)885f4613f2SJohn Marino decode_tabs(const char *tab_list)
895f4613f2SJohn Marino {
905f4613f2SJohn Marino int *result = typeCalloc(int, strlen(tab_list) + (unsigned) max_cols);
915f4613f2SJohn Marino int n = 0;
925f4613f2SJohn Marino int value = 0;
935f4613f2SJohn Marino int prior = 0;
945f4613f2SJohn Marino int ch;
955f4613f2SJohn Marino
963468e90cSJohn Marino if (result == 0)
973468e90cSJohn Marino failed("decode_tabs");
983468e90cSJohn Marino
995f4613f2SJohn Marino while ((ch = *tab_list++) != '\0') {
1005f4613f2SJohn Marino if (isdigit(UChar(ch))) {
1015f4613f2SJohn Marino value *= 10;
1025f4613f2SJohn Marino value += (ch - '0');
1035f4613f2SJohn Marino } else if (ch == ',') {
1045f4613f2SJohn Marino result[n] = value + prior;
1055f4613f2SJohn Marino if (n > 0 && result[n] <= result[n - 1]) {
1065f4613f2SJohn Marino fprintf(stderr,
1073468e90cSJohn Marino "%s: tab-stops are not in increasing order: %d %d\n",
108*32bb5217SDaniel Fojt _nc_progname, value, result[n - 1]);
1095f4613f2SJohn Marino free(result);
1105f4613f2SJohn Marino result = 0;
1115f4613f2SJohn Marino break;
1125f4613f2SJohn Marino }
1135f4613f2SJohn Marino ++n;
1145f4613f2SJohn Marino value = 0;
1155f4613f2SJohn Marino prior = 0;
1165f4613f2SJohn Marino } else if (ch == '+') {
1175f4613f2SJohn Marino if (n)
1185f4613f2SJohn Marino prior = result[n - 1];
1195f4613f2SJohn Marino }
1205f4613f2SJohn Marino }
1215f4613f2SJohn Marino
1225f4613f2SJohn Marino if (result != 0) {
1235f4613f2SJohn Marino /*
1245f4613f2SJohn Marino * If there is only one value, then it is an option such as "-8".
1255f4613f2SJohn Marino */
1265f4613f2SJohn Marino if ((n == 0) && (value > 0)) {
1275f4613f2SJohn Marino int step = value;
1283468e90cSJohn Marino value = 1;
1295f4613f2SJohn Marino while (n < max_cols - 1) {
1305f4613f2SJohn Marino result[n++] = value;
1315f4613f2SJohn Marino value += step;
1325f4613f2SJohn Marino }
1335f4613f2SJohn Marino }
1345f4613f2SJohn Marino
1355f4613f2SJohn Marino /*
1365f4613f2SJohn Marino * Add the last value, if any.
1375f4613f2SJohn Marino */
1385f4613f2SJohn Marino result[n++] = value + prior;
1395f4613f2SJohn Marino result[n] = 0;
1405f4613f2SJohn Marino }
1413468e90cSJohn Marino
1425f4613f2SJohn Marino return result;
1435f4613f2SJohn Marino }
1445f4613f2SJohn Marino
1455f4613f2SJohn Marino static void
print_ruler(int * tab_list)1465f4613f2SJohn Marino print_ruler(int *tab_list)
1475f4613f2SJohn Marino {
1485f4613f2SJohn Marino int last = 0;
1495f4613f2SJohn Marino int stop;
1505f4613f2SJohn Marino int n;
1515f4613f2SJohn Marino
1525f4613f2SJohn Marino /* first print a readable ruler */
1535f4613f2SJohn Marino for (n = 0; n < max_cols; n += 10) {
1545f4613f2SJohn Marino int ch = 1 + (n / 10);
1555f4613f2SJohn Marino char buffer[20];
1563468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
1573468e90cSJohn Marino "----+----%c",
1585f4613f2SJohn Marino ((ch < 10)
1595f4613f2SJohn Marino ? (ch + '0')
1605f4613f2SJohn Marino : (ch + 'A' - 10)));
1615f4613f2SJohn Marino printf("%.*s", ((max_cols - n) > 10) ? 10 : (max_cols - n), buffer);
1625f4613f2SJohn Marino }
1635f4613f2SJohn Marino putchar('\n');
1645f4613f2SJohn Marino
1655f4613f2SJohn Marino /* now, print '*' for each stop */
1665f4613f2SJohn Marino for (n = 0, last = 0; (tab_list[n] > 0) && (last < max_cols); ++n) {
1675f4613f2SJohn Marino stop = tab_list[n];
1685f4613f2SJohn Marino while (++last < stop) {
1695f4613f2SJohn Marino if (last <= max_cols) {
1705f4613f2SJohn Marino putchar('-');
1715f4613f2SJohn Marino } else {
1725f4613f2SJohn Marino break;
1735f4613f2SJohn Marino }
1745f4613f2SJohn Marino }
1755f4613f2SJohn Marino if (last <= max_cols) {
1765f4613f2SJohn Marino putchar('*');
1775f4613f2SJohn Marino last = stop;
1785f4613f2SJohn Marino } else {
1795f4613f2SJohn Marino break;
1805f4613f2SJohn Marino }
1815f4613f2SJohn Marino }
1825f4613f2SJohn Marino while (++last <= max_cols)
1835f4613f2SJohn Marino putchar('-');
1845f4613f2SJohn Marino putchar('\n');
1855f4613f2SJohn Marino }
1865f4613f2SJohn Marino
1875f4613f2SJohn Marino /*
1885f4613f2SJohn Marino * Write an '*' on each tabstop, to demonstrate whether it lines up with the
1895f4613f2SJohn Marino * ruler.
1905f4613f2SJohn Marino */
1915f4613f2SJohn Marino static void
write_tabs(int * tab_list)1925f4613f2SJohn Marino write_tabs(int *tab_list)
1935f4613f2SJohn Marino {
1945f4613f2SJohn Marino int stop;
1955f4613f2SJohn Marino
1965f4613f2SJohn Marino while ((stop = *tab_list++) > 0 && stop <= max_cols) {
1975f4613f2SJohn Marino fputs((stop == 1) ? "*" : "\t*", stdout);
1985f4613f2SJohn Marino };
1995f4613f2SJohn Marino /* also show a tab _past_ the stops */
2005f4613f2SJohn Marino if (stop < max_cols)
2015f4613f2SJohn Marino fputs("\t+", stdout);
2025f4613f2SJohn Marino putchar('\n');
2035f4613f2SJohn Marino }
2045f4613f2SJohn Marino
2055f4613f2SJohn Marino /*
2065f4613f2SJohn Marino * Trim leading/trailing blanks, as well as blanks after a comma.
2075f4613f2SJohn Marino * Convert embedded blanks to commas.
2085f4613f2SJohn Marino */
2095f4613f2SJohn Marino static char *
trimmed_tab_list(const char * source)2105f4613f2SJohn Marino trimmed_tab_list(const char *source)
2115f4613f2SJohn Marino {
2125f4613f2SJohn Marino char *result = strdup(source);
2135f4613f2SJohn Marino int ch, j, k, last;
2145f4613f2SJohn Marino
2155f4613f2SJohn Marino if (result != 0) {
2165f4613f2SJohn Marino for (j = k = last = 0; result[j] != 0; ++j) {
2175f4613f2SJohn Marino ch = UChar(result[j]);
2185f4613f2SJohn Marino if (isspace(ch)) {
2195f4613f2SJohn Marino if (last == '\0') {
2205f4613f2SJohn Marino continue;
2215f4613f2SJohn Marino } else if (isdigit(last) || last == ',') {
2225f4613f2SJohn Marino ch = ',';
2235f4613f2SJohn Marino }
2245f4613f2SJohn Marino } else if (ch == ',') {
2255f4613f2SJohn Marino ;
2265f4613f2SJohn Marino } else {
2275f4613f2SJohn Marino if (last == ',')
2285f4613f2SJohn Marino result[k++] = (char) last;
2295f4613f2SJohn Marino result[k++] = (char) ch;
2305f4613f2SJohn Marino }
2315f4613f2SJohn Marino last = ch;
2325f4613f2SJohn Marino }
2335f4613f2SJohn Marino result[k] = '\0';
2345f4613f2SJohn Marino }
2355f4613f2SJohn Marino return result;
2365f4613f2SJohn Marino }
2375f4613f2SJohn Marino
2385f4613f2SJohn Marino static bool
comma_is_needed(const char * source)2395f4613f2SJohn Marino comma_is_needed(const char *source)
2405f4613f2SJohn Marino {
2415f4613f2SJohn Marino bool result = FALSE;
2425f4613f2SJohn Marino
2435f4613f2SJohn Marino if (source != 0) {
2443468e90cSJohn Marino size_t len = strlen(source);
2455f4613f2SJohn Marino if (len != 0)
2465f4613f2SJohn Marino result = (source[len - 1] != ',');
2475f4613f2SJohn Marino } else {
2485f4613f2SJohn Marino result = FALSE;
2495f4613f2SJohn Marino }
2505f4613f2SJohn Marino return result;
2515f4613f2SJohn Marino }
2525f4613f2SJohn Marino
2535f4613f2SJohn Marino /*
2545f4613f2SJohn Marino * Add a command-line parameter to the tab-list. It can be blank- or comma-
2555f4613f2SJohn Marino * separated (or a mixture). For simplicity, empty tabs are ignored, e.g.,
2565f4613f2SJohn Marino * tabs 1,,6,11
2575f4613f2SJohn Marino * tabs 1,6,11
2585f4613f2SJohn Marino * are treated the same.
2595f4613f2SJohn Marino */
2605f4613f2SJohn Marino static const char *
add_to_tab_list(char ** append,const char * value)2615f4613f2SJohn Marino add_to_tab_list(char **append, const char *value)
2625f4613f2SJohn Marino {
2635f4613f2SJohn Marino char *result = *append;
2645f4613f2SJohn Marino char *copied = trimmed_tab_list(value);
2655f4613f2SJohn Marino
2665f4613f2SJohn Marino if (copied != 0 && *copied != '\0') {
2675f4613f2SJohn Marino const char *comma = ",";
2683468e90cSJohn Marino size_t need = 1 + strlen(copied);
2695f4613f2SJohn Marino
2705f4613f2SJohn Marino if (*copied == ',')
2715f4613f2SJohn Marino comma = "";
2725f4613f2SJohn Marino else if (!comma_is_needed(*append))
2735f4613f2SJohn Marino comma = "";
2745f4613f2SJohn Marino
2755f4613f2SJohn Marino need += strlen(comma);
2765f4613f2SJohn Marino if (*append != 0)
2775f4613f2SJohn Marino need += strlen(*append);
2785f4613f2SJohn Marino
2795f4613f2SJohn Marino result = malloc(need);
2803468e90cSJohn Marino if (result == 0)
2813468e90cSJohn Marino failed("add_to_tab_list");
2823468e90cSJohn Marino
2835f4613f2SJohn Marino *result = '\0';
2845f4613f2SJohn Marino if (*append != 0) {
2853468e90cSJohn Marino _nc_STRCPY(result, *append, need);
2865f4613f2SJohn Marino free(*append);
2875f4613f2SJohn Marino }
2883468e90cSJohn Marino _nc_STRCAT(result, comma, need);
2893468e90cSJohn Marino _nc_STRCAT(result, copied, need);
2905f4613f2SJohn Marino
2915f4613f2SJohn Marino *append = result;
2925f4613f2SJohn Marino }
2933468e90cSJohn Marino free(copied);
2945f4613f2SJohn Marino return result;
2955f4613f2SJohn Marino }
2965f4613f2SJohn Marino
2975f4613f2SJohn Marino /*
2985f4613f2SJohn Marino * Check for illegal characters in the tab-list.
2995f4613f2SJohn Marino */
3005f4613f2SJohn Marino static bool
legal_tab_list(const char * tab_list)3013468e90cSJohn Marino legal_tab_list(const char *tab_list)
3025f4613f2SJohn Marino {
3035f4613f2SJohn Marino bool result = TRUE;
3045f4613f2SJohn Marino
3055f4613f2SJohn Marino if (tab_list != 0 && *tab_list != '\0') {
3065f4613f2SJohn Marino if (comma_is_needed(tab_list)) {
3075f4613f2SJohn Marino int n, ch;
3085f4613f2SJohn Marino for (n = 0; tab_list[n] != '\0'; ++n) {
3095f4613f2SJohn Marino ch = UChar(tab_list[n]);
3105f4613f2SJohn Marino if (!(isdigit(ch) || ch == ',' || ch == '+')) {
3115f4613f2SJohn Marino fprintf(stderr,
3125f4613f2SJohn Marino "%s: unexpected character found '%c'\n",
313*32bb5217SDaniel Fojt _nc_progname, ch);
3145f4613f2SJohn Marino result = FALSE;
3155f4613f2SJohn Marino break;
3165f4613f2SJohn Marino }
3175f4613f2SJohn Marino }
3185f4613f2SJohn Marino } else {
319*32bb5217SDaniel Fojt fprintf(stderr, "%s: trailing comma found '%s'\n", _nc_progname, tab_list);
3205f4613f2SJohn Marino result = FALSE;
3215f4613f2SJohn Marino }
3225f4613f2SJohn Marino } else {
323*32bb5217SDaniel Fojt fprintf(stderr, "%s: no tab-list given\n", _nc_progname);
3245f4613f2SJohn Marino result = FALSE;
3255f4613f2SJohn Marino }
3265f4613f2SJohn Marino return result;
3275f4613f2SJohn Marino }
3285f4613f2SJohn Marino
3293468e90cSJohn Marino static char *
skip_list(char * value)3303468e90cSJohn Marino skip_list(char *value)
3313468e90cSJohn Marino {
3323468e90cSJohn Marino while (*value != '\0' &&
3333468e90cSJohn Marino (isdigit(UChar(*value)) ||
3343468e90cSJohn Marino isspace(UChar(*value)) ||
3353468e90cSJohn Marino strchr("+,", UChar(*value)) != 0)) {
3363468e90cSJohn Marino ++value;
3373468e90cSJohn Marino }
3383468e90cSJohn Marino return value;
3393468e90cSJohn Marino }
3403468e90cSJohn Marino
3415f4613f2SJohn Marino static void
usage(void)3425f4613f2SJohn Marino usage(void)
3435f4613f2SJohn Marino {
3443468e90cSJohn Marino #define DATA(s) s "\n"
3453468e90cSJohn Marino static const char msg[] =
3465f4613f2SJohn Marino {
3473468e90cSJohn Marino DATA("Usage: tabs [options] [tabstop-list]")
3483468e90cSJohn Marino DATA("")
3493468e90cSJohn Marino DATA("Options:")
3503468e90cSJohn Marino DATA(" -0 reset tabs")
3513468e90cSJohn Marino DATA(" -8 set tabs to standard interval")
3523468e90cSJohn Marino DATA(" -a Assembler, IBM S/370, first format")
3533468e90cSJohn Marino DATA(" -a2 Assembler, IBM S/370, second format")
3543468e90cSJohn Marino DATA(" -c COBOL, normal format")
3553468e90cSJohn Marino DATA(" -c2 COBOL compact format")
3563468e90cSJohn Marino DATA(" -c3 COBOL compact format extended")
3573468e90cSJohn Marino DATA(" -d debug (show ruler with expected/actual tab positions)")
3583468e90cSJohn Marino DATA(" -f FORTRAN")
3593468e90cSJohn Marino DATA(" -n no-op (do not modify terminal settings)")
3603468e90cSJohn Marino DATA(" -p PL/I")
3613468e90cSJohn Marino DATA(" -s SNOBOL")
3623468e90cSJohn Marino DATA(" -u UNIVAC 1100 Assembler")
3633468e90cSJohn Marino DATA(" -T name use terminal type 'name'")
3643468e90cSJohn Marino DATA(" -V print version")
3653468e90cSJohn Marino DATA("")
3663468e90cSJohn Marino DATA("A tabstop-list is an ordered list of column numbers, e.g., 1,11,21")
3673468e90cSJohn Marino DATA("or 1,+10,+10 which is the same.")
3685f4613f2SJohn Marino };
3693468e90cSJohn Marino #undef DATA
3705f4613f2SJohn Marino
3715f4613f2SJohn Marino fflush(stdout);
3723468e90cSJohn Marino fputs(msg, stderr);
3735f4613f2SJohn Marino ExitProgram(EXIT_FAILURE);
3745f4613f2SJohn Marino }
3755f4613f2SJohn Marino
3765f4613f2SJohn Marino int
main(int argc,char * argv[])3775f4613f2SJohn Marino main(int argc, char *argv[])
3785f4613f2SJohn Marino {
3795f4613f2SJohn Marino int rc = EXIT_FAILURE;
3805f4613f2SJohn Marino bool debug = FALSE;
3815f4613f2SJohn Marino bool no_op = FALSE;
3825f4613f2SJohn Marino int n, ch;
3835f4613f2SJohn Marino NCURSES_CONST char *term_name = 0;
3845f4613f2SJohn Marino char *append = 0;
3855f4613f2SJohn Marino const char *tab_list = 0;
386*32bb5217SDaniel Fojt TTY tty_settings;
387*32bb5217SDaniel Fojt int fd;
3885f4613f2SJohn Marino
389*32bb5217SDaniel Fojt _nc_progname = _nc_rootname(argv[0]);
390*32bb5217SDaniel Fojt
391*32bb5217SDaniel Fojt fd = save_tty_settings(&tty_settings, FALSE);
3923468e90cSJohn Marino
3935f4613f2SJohn Marino if ((term_name = getenv("TERM")) == 0)
3945f4613f2SJohn Marino term_name = "ansi+tabs";
3955f4613f2SJohn Marino
3965f4613f2SJohn Marino /* cannot use getopt, since some options are two-character */
3975f4613f2SJohn Marino for (n = 1; n < argc; ++n) {
3985f4613f2SJohn Marino char *option = argv[n];
3995f4613f2SJohn Marino switch (option[0]) {
4005f4613f2SJohn Marino case '-':
4015f4613f2SJohn Marino while ((ch = *++option) != '\0') {
4025f4613f2SJohn Marino switch (ch) {
4035f4613f2SJohn Marino case 'a':
4043468e90cSJohn Marino switch (*++option) {
4053468e90cSJohn Marino default:
4065f4613f2SJohn Marino case '\0':
4075f4613f2SJohn Marino tab_list = "1,10,16,36,72";
4083468e90cSJohn Marino option--;
4095f4613f2SJohn Marino /* Assembler, IBM S/370, first format */
4105f4613f2SJohn Marino break;
4115f4613f2SJohn Marino case '2':
4125f4613f2SJohn Marino tab_list = "1,10,16,40,72";
4135f4613f2SJohn Marino /* Assembler, IBM S/370, second format */
4145f4613f2SJohn Marino break;
4155f4613f2SJohn Marino }
4165f4613f2SJohn Marino break;
4175f4613f2SJohn Marino case 'c':
4183468e90cSJohn Marino switch (*++option) {
4193468e90cSJohn Marino default:
4205f4613f2SJohn Marino case '\0':
4215f4613f2SJohn Marino tab_list = "1,8,12,16,20,55";
4223468e90cSJohn Marino option--;
4235f4613f2SJohn Marino /* COBOL, normal format */
4245f4613f2SJohn Marino break;
4255f4613f2SJohn Marino case '2':
4265f4613f2SJohn Marino tab_list = "1,6,10,14,49";
4275f4613f2SJohn Marino /* COBOL compact format */
4285f4613f2SJohn Marino break;
4295f4613f2SJohn Marino case '3':
4305f4613f2SJohn Marino tab_list = "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67";
4315f4613f2SJohn Marino /* COBOL compact format extended */
4325f4613f2SJohn Marino break;
4335f4613f2SJohn Marino }
4345f4613f2SJohn Marino break;
4355f4613f2SJohn Marino case 'd': /* ncurses extension */
4365f4613f2SJohn Marino debug = TRUE;
4375f4613f2SJohn Marino break;
4385f4613f2SJohn Marino case 'f':
4395f4613f2SJohn Marino tab_list = "1,7,11,15,19,23";
4405f4613f2SJohn Marino /* FORTRAN */
4415f4613f2SJohn Marino break;
4425f4613f2SJohn Marino case 'n': /* ncurses extension */
4435f4613f2SJohn Marino no_op = TRUE;
4445f4613f2SJohn Marino break;
4455f4613f2SJohn Marino case 'p':
4465f4613f2SJohn Marino tab_list = "1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61";
4475f4613f2SJohn Marino /* PL/I */
4485f4613f2SJohn Marino break;
4495f4613f2SJohn Marino case 's':
4505f4613f2SJohn Marino tab_list = "1,10,55";
4515f4613f2SJohn Marino /* SNOBOL */
4525f4613f2SJohn Marino break;
4535f4613f2SJohn Marino case 'u':
4545f4613f2SJohn Marino tab_list = "1,12,20,44";
4555f4613f2SJohn Marino /* UNIVAC 1100 Assembler */
4565f4613f2SJohn Marino break;
4575f4613f2SJohn Marino case 'T':
4585f4613f2SJohn Marino ++n;
4595f4613f2SJohn Marino if (*++option != '\0') {
4605f4613f2SJohn Marino term_name = option;
4615f4613f2SJohn Marino } else {
462*32bb5217SDaniel Fojt term_name = argv[n];
4633468e90cSJohn Marino option--;
4645f4613f2SJohn Marino }
4655f4613f2SJohn Marino option += ((int) strlen(option)) - 1;
4665f4613f2SJohn Marino continue;
4673468e90cSJohn Marino case 'V':
4683468e90cSJohn Marino puts(curses_version());
4693468e90cSJohn Marino ExitProgram(EXIT_SUCCESS);
4705f4613f2SJohn Marino default:
4715f4613f2SJohn Marino if (isdigit(UChar(*option))) {
4723468e90cSJohn Marino char *copy = strdup(option);
4733468e90cSJohn Marino *skip_list(copy) = '\0';
4743468e90cSJohn Marino tab_list = copy;
4753468e90cSJohn Marino option = skip_list(option) - 1;
4765f4613f2SJohn Marino } else {
4775f4613f2SJohn Marino usage();
4785f4613f2SJohn Marino }
4795f4613f2SJohn Marino break;
4805f4613f2SJohn Marino }
4815f4613f2SJohn Marino }
4825f4613f2SJohn Marino break;
4835f4613f2SJohn Marino case '+':
4845f4613f2SJohn Marino while ((ch = *++option) != '\0') {
4855f4613f2SJohn Marino switch (ch) {
4865f4613f2SJohn Marino case 'm':
4873468e90cSJohn Marino /*
4883468e90cSJohn Marino * The "+mXXX" option is unimplemented because only the long-obsolete
4893468e90cSJohn Marino * att510d implements smgl, which is needed to support
4903468e90cSJohn Marino * this option.
4913468e90cSJohn Marino */
4925f4613f2SJohn Marino break;
4935f4613f2SJohn Marino default:
4945f4613f2SJohn Marino /* special case of relative stops separated by spaces? */
4955f4613f2SJohn Marino if (option == argv[n] + 1) {
4965f4613f2SJohn Marino tab_list = add_to_tab_list(&append, argv[n]);
4975f4613f2SJohn Marino }
4985f4613f2SJohn Marino break;
4995f4613f2SJohn Marino }
5005f4613f2SJohn Marino }
5015f4613f2SJohn Marino break;
5025f4613f2SJohn Marino default:
5035f4613f2SJohn Marino if (append != 0) {
5045f4613f2SJohn Marino if (tab_list != (const char *) append) {
5055f4613f2SJohn Marino /* one of the predefined options was used */
5065f4613f2SJohn Marino free(append);
5075f4613f2SJohn Marino append = 0;
5085f4613f2SJohn Marino }
5095f4613f2SJohn Marino }
5105f4613f2SJohn Marino tab_list = add_to_tab_list(&append, option);
5115f4613f2SJohn Marino break;
5125f4613f2SJohn Marino }
5135f4613f2SJohn Marino }
5145f4613f2SJohn Marino
515*32bb5217SDaniel Fojt setupterm(term_name, fd, (int *) 0);
5165f4613f2SJohn Marino
5175f4613f2SJohn Marino max_cols = (columns > 0) ? columns : 80;
5185f4613f2SJohn Marino
5195f4613f2SJohn Marino if (!VALID_STRING(clear_all_tabs)) {
5205f4613f2SJohn Marino fprintf(stderr,
5215f4613f2SJohn Marino "%s: terminal type '%s' cannot reset tabs\n",
522*32bb5217SDaniel Fojt _nc_progname, term_name);
5235f4613f2SJohn Marino } else if (!VALID_STRING(set_tab)) {
5245f4613f2SJohn Marino fprintf(stderr,
5255f4613f2SJohn Marino "%s: terminal type '%s' cannot set tabs\n",
526*32bb5217SDaniel Fojt _nc_progname, term_name);
5273468e90cSJohn Marino } else if (legal_tab_list(tab_list)) {
5285f4613f2SJohn Marino int *list = decode_tabs(tab_list);
5295f4613f2SJohn Marino
5305f4613f2SJohn Marino if (!no_op)
5315f4613f2SJohn Marino tputs(clear_all_tabs, 1, putch);
5325f4613f2SJohn Marino
5335f4613f2SJohn Marino if (list != 0) {
5345f4613f2SJohn Marino if (!no_op)
5355f4613f2SJohn Marino do_tabs(list);
5365f4613f2SJohn Marino if (debug) {
5375f4613f2SJohn Marino fflush(stderr);
5385f4613f2SJohn Marino printf("tabs %s\n", tab_list);
5395f4613f2SJohn Marino print_ruler(list);
5405f4613f2SJohn Marino write_tabs(list);
5415f4613f2SJohn Marino }
5425f4613f2SJohn Marino free(list);
5435f4613f2SJohn Marino } else if (debug) {
5445f4613f2SJohn Marino fflush(stderr);
5455f4613f2SJohn Marino printf("tabs %s\n", tab_list);
5465f4613f2SJohn Marino }
5475f4613f2SJohn Marino rc = EXIT_SUCCESS;
5485f4613f2SJohn Marino }
5495f4613f2SJohn Marino if (append != 0)
5505f4613f2SJohn Marino free(append);
5515f4613f2SJohn Marino ExitProgram(rc);
5525f4613f2SJohn Marino }
553