161ba55bcSBaptiste Daroussin /*-
261ba55bcSBaptiste Daroussin * SPDX-License-Identifier: BSD-2-Clause
361ba55bcSBaptiste Daroussin *
4*a6d8be45SAlfonso S. Siciliano * Copyright (c) 2021-2024 Alfonso Sabato Siciliano
561ba55bcSBaptiste Daroussin *
661ba55bcSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
761ba55bcSBaptiste Daroussin * modification, are permitted provided that the following conditions
861ba55bcSBaptiste Daroussin * are met:
961ba55bcSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright
1061ba55bcSBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
1161ba55bcSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright
1261ba55bcSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
1361ba55bcSBaptiste Daroussin * documentation and/or other materials provided with the distribution.
1461ba55bcSBaptiste Daroussin *
1561ba55bcSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1661ba55bcSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1761ba55bcSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1861ba55bcSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1961ba55bcSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2061ba55bcSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2161ba55bcSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2261ba55bcSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2361ba55bcSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2461ba55bcSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2561ba55bcSBaptiste Daroussin * SUCH DAMAGE.
2661ba55bcSBaptiste Daroussin */
2761ba55bcSBaptiste Daroussin
2861ba55bcSBaptiste Daroussin #include <getopt.h>
2961ba55bcSBaptiste Daroussin #include <limits.h>
3061ba55bcSBaptiste Daroussin #include <locale.h>
3161ba55bcSBaptiste Daroussin #include <signal.h>
3261ba55bcSBaptiste Daroussin #include <stdarg.h>
3361ba55bcSBaptiste Daroussin #include <stdlib.h>
3461ba55bcSBaptiste Daroussin #include <stdio.h>
3561ba55bcSBaptiste Daroussin #include <string.h>
3661ba55bcSBaptiste Daroussin #include <term.h>
3761ba55bcSBaptiste Daroussin
3861ba55bcSBaptiste Daroussin #include <bsddialog.h>
3961ba55bcSBaptiste Daroussin #include <bsddialog_theme.h>
4061ba55bcSBaptiste Daroussin
4161ba55bcSBaptiste Daroussin #include "util.h"
4261ba55bcSBaptiste Daroussin
4361ba55bcSBaptiste Daroussin #define EXITCODE(retval) (exitcodes[retval + 1].value)
4461ba55bcSBaptiste Daroussin #define UNUSED_PAR(x) UNUSED_ ## x __attribute__((__unused__))
4561ba55bcSBaptiste Daroussin
4661ba55bcSBaptiste Daroussin static void custom_text(struct options *opt, char *text, char *buf);
4761ba55bcSBaptiste Daroussin
4861ba55bcSBaptiste Daroussin /* Exit codes */
4961ba55bcSBaptiste Daroussin struct exitcode {
5061ba55bcSBaptiste Daroussin const char *name;
5161ba55bcSBaptiste Daroussin int value;
5261ba55bcSBaptiste Daroussin };
5361ba55bcSBaptiste Daroussin
5461ba55bcSBaptiste Daroussin static struct exitcode exitcodes[14] = {
5561ba55bcSBaptiste Daroussin { "BSDDIALOG_ERROR", 255 },
5661ba55bcSBaptiste Daroussin { "BSDDIALOG_OK", 0 },
5761ba55bcSBaptiste Daroussin { "BSDDIALOG_CANCEL", 1 },
5861ba55bcSBaptiste Daroussin { "BSDDIALOG_HELP", 2 },
5961ba55bcSBaptiste Daroussin { "BSDDIALOG_EXTRA", 3 },
6061ba55bcSBaptiste Daroussin { "BSDDIALOG_TIMEOUT", 4 },
6161ba55bcSBaptiste Daroussin { "BSDDIALOG_ESC", 5 },
6261ba55bcSBaptiste Daroussin { "BSDDIALOG_LEFT1", 6 },
6361ba55bcSBaptiste Daroussin { "BSDDIALOG_LEFT2", 7 },
6461ba55bcSBaptiste Daroussin { "BSDDIALOG_LEFT3", 8 },
6561ba55bcSBaptiste Daroussin { "BSDDIALOG_RIGHT1", 9 },
6661ba55bcSBaptiste Daroussin { "BSDDIALOG_RIGHT2", 10 },
6761ba55bcSBaptiste Daroussin { "BSDDIALOG_RIGHT3", 11 },
6861ba55bcSBaptiste Daroussin { "BSDDIALOG_ITEM_HELP", 2 } /* like HELP by default */
6961ba55bcSBaptiste Daroussin };
7061ba55bcSBaptiste Daroussin
set_exit_code(int lib_retval,int exitcode)7161ba55bcSBaptiste Daroussin void set_exit_code(int lib_retval, int exitcode)
7261ba55bcSBaptiste Daroussin {
7361ba55bcSBaptiste Daroussin exitcodes[lib_retval + 1].value = exitcode;
7461ba55bcSBaptiste Daroussin }
7561ba55bcSBaptiste Daroussin
7661ba55bcSBaptiste Daroussin /* Error */
exit_error(bool usage,const char * fmt,...)7761ba55bcSBaptiste Daroussin void exit_error(bool usage, const char *fmt, ...)
7861ba55bcSBaptiste Daroussin {
7961ba55bcSBaptiste Daroussin va_list arg_ptr;
8061ba55bcSBaptiste Daroussin
8161ba55bcSBaptiste Daroussin if (bsddialog_inmode())
8261ba55bcSBaptiste Daroussin bsddialog_end();
8361ba55bcSBaptiste Daroussin printf("Error: ");
8461ba55bcSBaptiste Daroussin va_start(arg_ptr, fmt);
8561ba55bcSBaptiste Daroussin vprintf(fmt, arg_ptr);
8661ba55bcSBaptiste Daroussin va_end(arg_ptr);
8761ba55bcSBaptiste Daroussin printf(".\n\n");
8861ba55bcSBaptiste Daroussin if (usage) {
8961ba55bcSBaptiste Daroussin printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
9061ba55bcSBaptiste Daroussin printf("for more information.\n");
9161ba55bcSBaptiste Daroussin }
9261ba55bcSBaptiste Daroussin
9361ba55bcSBaptiste Daroussin exit (EXITCODE(BSDDIALOG_ERROR));
9461ba55bcSBaptiste Daroussin }
9561ba55bcSBaptiste Daroussin
error_args(const char * dialog,int argc,char ** argv)9661ba55bcSBaptiste Daroussin void error_args(const char *dialog, int argc, char **argv)
9761ba55bcSBaptiste Daroussin {
9861ba55bcSBaptiste Daroussin int i;
9961ba55bcSBaptiste Daroussin
10061ba55bcSBaptiste Daroussin if (bsddialog_inmode())
10161ba55bcSBaptiste Daroussin bsddialog_end();
10261ba55bcSBaptiste Daroussin printf("Error: %s unexpected argument%s:", dialog, argc > 1 ? "s" : "");
10361ba55bcSBaptiste Daroussin for (i = 0; i < argc; i++)
10461ba55bcSBaptiste Daroussin printf(" \"%s\"", argv[i]);
10561ba55bcSBaptiste Daroussin printf(".\n\n");
10661ba55bcSBaptiste Daroussin printf("See \'bsddialog --help\' or \'man 1 bsddialog\' ");
10761ba55bcSBaptiste Daroussin printf("for more information.\n");
10861ba55bcSBaptiste Daroussin
10961ba55bcSBaptiste Daroussin exit (EXITCODE(BSDDIALOG_ERROR));
11061ba55bcSBaptiste Daroussin }
11161ba55bcSBaptiste Daroussin
11261ba55bcSBaptiste Daroussin /* init */
sigint_handler(int UNUSED_PAR (sig))11361ba55bcSBaptiste Daroussin static void sigint_handler(int UNUSED_PAR(sig))
11461ba55bcSBaptiste Daroussin {
11561ba55bcSBaptiste Daroussin bsddialog_end();
11661ba55bcSBaptiste Daroussin
11761ba55bcSBaptiste Daroussin exit(EXITCODE(BSDDIALOG_ERROR));
11861ba55bcSBaptiste Daroussin }
11961ba55bcSBaptiste Daroussin
start_bsddialog_mode(void)12061ba55bcSBaptiste Daroussin static void start_bsddialog_mode(void)
12161ba55bcSBaptiste Daroussin {
12261ba55bcSBaptiste Daroussin if (bsddialog_inmode())
12361ba55bcSBaptiste Daroussin return;
12461ba55bcSBaptiste Daroussin if (bsddialog_init() != BSDDIALOG_OK)
12561ba55bcSBaptiste Daroussin exit_error(false, bsddialog_geterror());
12661ba55bcSBaptiste Daroussin
12761ba55bcSBaptiste Daroussin signal(SIGINT, sigint_handler);
12861ba55bcSBaptiste Daroussin }
12961ba55bcSBaptiste Daroussin
getenv_exitcodes(void)13061ba55bcSBaptiste Daroussin static void getenv_exitcodes(void)
13161ba55bcSBaptiste Daroussin {
13261ba55bcSBaptiste Daroussin int i;
13361ba55bcSBaptiste Daroussin int value;
13461ba55bcSBaptiste Daroussin char *envvalue;
13561ba55bcSBaptiste Daroussin
13661ba55bcSBaptiste Daroussin for (i = 0; i < 10; i++) {
13761ba55bcSBaptiste Daroussin envvalue = getenv(exitcodes[i].name);
13861ba55bcSBaptiste Daroussin if (envvalue == NULL || envvalue[0] == '\0')
13961ba55bcSBaptiste Daroussin continue;
14061ba55bcSBaptiste Daroussin value = (int)strtol(envvalue, NULL, 10);
14161ba55bcSBaptiste Daroussin exitcodes[i].value = value;
14261ba55bcSBaptiste Daroussin /* ITEM_HELP follows HELP without explicit setting */
14361ba55bcSBaptiste Daroussin if (i == BSDDIALOG_HELP + 1)
14461ba55bcSBaptiste Daroussin exitcodes[BSDDIALOG_ITEM_HELP + 1].value = value;
14561ba55bcSBaptiste Daroussin }
14661ba55bcSBaptiste Daroussin }
14761ba55bcSBaptiste Daroussin
14861ba55bcSBaptiste Daroussin /*
14961ba55bcSBaptiste Daroussin * bsddialog utility: TUI widgets and dialogs.
15061ba55bcSBaptiste Daroussin */
main(int argc,char * argv[argc])15161ba55bcSBaptiste Daroussin int main(int argc, char *argv[argc])
15261ba55bcSBaptiste Daroussin {
15361ba55bcSBaptiste Daroussin bool startup;
15461ba55bcSBaptiste Daroussin int i, rows, cols, retval, parsed, nargc, firstoptind;
15561ba55bcSBaptiste Daroussin char *text, **nargv, *pn;
15661ba55bcSBaptiste Daroussin struct bsddialog_conf conf;
15761ba55bcSBaptiste Daroussin struct options opt;
15861ba55bcSBaptiste Daroussin
15961ba55bcSBaptiste Daroussin setlocale(LC_ALL, "");
16061ba55bcSBaptiste Daroussin getenv_exitcodes();
16161ba55bcSBaptiste Daroussin firstoptind = optind;
16261ba55bcSBaptiste Daroussin pn = argv[0];
16361ba55bcSBaptiste Daroussin retval = BSDDIALOG_OK;
16461ba55bcSBaptiste Daroussin
16561ba55bcSBaptiste Daroussin for (i = 0; i < argc; i++) {
16661ba55bcSBaptiste Daroussin if (strcmp(argv[i], "--version") == 0) {
16761ba55bcSBaptiste Daroussin printf("Version: %s\n", LIBBSDDIALOG_VERSION);
16861ba55bcSBaptiste Daroussin return (BSDDIALOG_OK);
16961ba55bcSBaptiste Daroussin }
17061ba55bcSBaptiste Daroussin if (strcmp(argv[i], "--help") == 0) {
17161ba55bcSBaptiste Daroussin usage();
17261ba55bcSBaptiste Daroussin return (BSDDIALOG_OK);
17361ba55bcSBaptiste Daroussin }
17461ba55bcSBaptiste Daroussin }
17561ba55bcSBaptiste Daroussin
17661ba55bcSBaptiste Daroussin startup = true;
17761ba55bcSBaptiste Daroussin while (true) {
17861ba55bcSBaptiste Daroussin parsed = parseargs(argc, argv, &conf, &opt);
17961ba55bcSBaptiste Daroussin nargc = argc - parsed;
18061ba55bcSBaptiste Daroussin nargv = argv + parsed;
18161ba55bcSBaptiste Daroussin argc = parsed - optind;
18261ba55bcSBaptiste Daroussin argv += optind;
18361ba55bcSBaptiste Daroussin
18461ba55bcSBaptiste Daroussin if (opt.mandatory_dialog && opt.dialogbuilder == NULL)
18561ba55bcSBaptiste Daroussin exit_error(true, "expected a --<dialog>");
18661ba55bcSBaptiste Daroussin
18761ba55bcSBaptiste Daroussin if (opt.dialogbuilder == NULL && argc > 0)
18861ba55bcSBaptiste Daroussin error_args("(no --<dialog>)", argc, argv);
18961ba55bcSBaptiste Daroussin
19061ba55bcSBaptiste Daroussin /* --print-maxsize or --print-version */
19161ba55bcSBaptiste Daroussin if (opt.mandatory_dialog == false && opt.clearscreen == false &&
19261ba55bcSBaptiste Daroussin opt.savethemefile == NULL && opt.dialogbuilder == NULL) {
19361ba55bcSBaptiste Daroussin retval = BSDDIALOG_OK;
19461ba55bcSBaptiste Daroussin break;
19561ba55bcSBaptiste Daroussin }
19661ba55bcSBaptiste Daroussin
19761ba55bcSBaptiste Daroussin /* --<dialog>, --save-theme or clear-screen */
19861ba55bcSBaptiste Daroussin text = NULL; /* useless inits, fix compiler warnings */
19961ba55bcSBaptiste Daroussin rows = BSDDIALOG_AUTOSIZE;
20061ba55bcSBaptiste Daroussin cols = BSDDIALOG_AUTOSIZE;
20161ba55bcSBaptiste Daroussin if (opt.dialogbuilder != NULL) {
20261ba55bcSBaptiste Daroussin if (argc < 3)
20361ba55bcSBaptiste Daroussin exit_error(true,
20461ba55bcSBaptiste Daroussin "expected <text> <rows> <cols>");
20561ba55bcSBaptiste Daroussin if ((text = strdup(argv[0])) == NULL)
20661ba55bcSBaptiste Daroussin exit_error(false, "cannot allocate <text>");
20761ba55bcSBaptiste Daroussin if (opt.dialogbuilder != textbox_builder)
20861ba55bcSBaptiste Daroussin custom_text(&opt, argv[0], text);
20961ba55bcSBaptiste Daroussin rows = (int)strtol(argv[1], NULL, 10);
21061ba55bcSBaptiste Daroussin cols = (int)strtol(argv[2], NULL, 10);
21161ba55bcSBaptiste Daroussin argc -= 3;
21261ba55bcSBaptiste Daroussin argv += 3;
21361ba55bcSBaptiste Daroussin }
21461ba55bcSBaptiste Daroussin
21561ba55bcSBaptiste Daroussin /* bsddialog terminal mode (first iteration) */
21661ba55bcSBaptiste Daroussin start_bsddialog_mode();
21761ba55bcSBaptiste Daroussin
21861ba55bcSBaptiste Daroussin if (opt.screen_mode != NULL) {
21961ba55bcSBaptiste Daroussin opt.screen_mode = tigetstr(opt.screen_mode);
22061ba55bcSBaptiste Daroussin if (opt.screen_mode != NULL &&
22161ba55bcSBaptiste Daroussin opt.screen_mode != (char*)-1) {
22261ba55bcSBaptiste Daroussin tputs(opt.screen_mode, 1, putchar);
22361ba55bcSBaptiste Daroussin fflush(stdout);
22461ba55bcSBaptiste Daroussin bsddialog_refresh();
22561ba55bcSBaptiste Daroussin }
22661ba55bcSBaptiste Daroussin }
22761ba55bcSBaptiste Daroussin
22861ba55bcSBaptiste Daroussin /* theme */
22961ba55bcSBaptiste Daroussin if (startup)
23061ba55bcSBaptiste Daroussin startuptheme();
23161ba55bcSBaptiste Daroussin startup = false;
23261ba55bcSBaptiste Daroussin if ((int)opt.theme >= 0)
23361ba55bcSBaptiste Daroussin setdeftheme(opt.theme);
23461ba55bcSBaptiste Daroussin if (opt.loadthemefile != NULL)
23561ba55bcSBaptiste Daroussin loadtheme(opt.loadthemefile, false);
23661ba55bcSBaptiste Daroussin if (opt.bikeshed)
23761ba55bcSBaptiste Daroussin bikeshed(&conf);
23861ba55bcSBaptiste Daroussin if (opt.savethemefile != NULL)
23961ba55bcSBaptiste Daroussin savetheme(opt.savethemefile);
24061ba55bcSBaptiste Daroussin
24161ba55bcSBaptiste Daroussin /* backtitle and dialog */
24261ba55bcSBaptiste Daroussin if (opt.dialogbuilder == NULL)
24361ba55bcSBaptiste Daroussin break;
24461ba55bcSBaptiste Daroussin if (opt.backtitle != NULL)
24561ba55bcSBaptiste Daroussin if (bsddialog_backtitle(&conf, opt.backtitle))
24661ba55bcSBaptiste Daroussin exit_error(false, bsddialog_geterror());
24761ba55bcSBaptiste Daroussin retval = opt.dialogbuilder(&conf, text, rows, cols, argc, argv,
24861ba55bcSBaptiste Daroussin &opt);
24961ba55bcSBaptiste Daroussin free(text);
25061ba55bcSBaptiste Daroussin if (retval == BSDDIALOG_ERROR)
25161ba55bcSBaptiste Daroussin exit_error(false, bsddialog_geterror());
25261ba55bcSBaptiste Daroussin if (conf.get_height != NULL && conf.get_width != NULL)
25361ba55bcSBaptiste Daroussin dprintf(opt.output_fd, "DialogSize: %d, %d\n",
25461ba55bcSBaptiste Daroussin *conf.get_height, *conf.get_width);
25561ba55bcSBaptiste Daroussin if (opt.clearscreen)
25661ba55bcSBaptiste Daroussin bsddialog_clear(0);
25761ba55bcSBaptiste Daroussin opt.clearscreen = false;
25861ba55bcSBaptiste Daroussin /* --and-dialog ends loop with Cancel or ESC */
25961ba55bcSBaptiste Daroussin if (retval == BSDDIALOG_CANCEL || retval == BSDDIALOG_ESC)
26061ba55bcSBaptiste Daroussin break;
26161ba55bcSBaptiste Daroussin argc = nargc;
26261ba55bcSBaptiste Daroussin argv = nargv;
26361ba55bcSBaptiste Daroussin if (argc <= 0)
26461ba55bcSBaptiste Daroussin break;
26561ba55bcSBaptiste Daroussin /* prepare next parseargs() call */
26661ba55bcSBaptiste Daroussin argc++;
26761ba55bcSBaptiste Daroussin argv--;
26861ba55bcSBaptiste Daroussin argv[0] = pn;
26961ba55bcSBaptiste Daroussin optind = firstoptind;
27061ba55bcSBaptiste Daroussin }
27161ba55bcSBaptiste Daroussin
27261ba55bcSBaptiste Daroussin if (bsddialog_inmode()) {
27361ba55bcSBaptiste Daroussin /* --clear-screen can be a single option */
27461ba55bcSBaptiste Daroussin if (opt.clearscreen)
27561ba55bcSBaptiste Daroussin bsddialog_clear(0);
27661ba55bcSBaptiste Daroussin bsddialog_end();
27761ba55bcSBaptiste Daroussin }
27861ba55bcSBaptiste Daroussin /* end bsddialog terminal mode */
27961ba55bcSBaptiste Daroussin
28061ba55bcSBaptiste Daroussin return (EXITCODE(retval));
28161ba55bcSBaptiste Daroussin }
28261ba55bcSBaptiste Daroussin
custom_text(struct options * opt,char * text,char * buf)28361ba55bcSBaptiste Daroussin void custom_text(struct options *opt, char *text, char *buf)
28461ba55bcSBaptiste Daroussin {
28561ba55bcSBaptiste Daroussin bool trim, crwrap;
28661ba55bcSBaptiste Daroussin int i, j;
28761ba55bcSBaptiste Daroussin
28861ba55bcSBaptiste Daroussin if (strstr(text, "\\n") == NULL) {
28961ba55bcSBaptiste Daroussin /* "hasnl" mode */
29061ba55bcSBaptiste Daroussin trim = true;
29161ba55bcSBaptiste Daroussin crwrap = true;
29261ba55bcSBaptiste Daroussin } else {
29361ba55bcSBaptiste Daroussin trim = false;
29461ba55bcSBaptiste Daroussin crwrap = opt->cr_wrap;
29561ba55bcSBaptiste Daroussin }
29661ba55bcSBaptiste Daroussin if (opt->text_unchanged) {
29761ba55bcSBaptiste Daroussin trim = false;
29861ba55bcSBaptiste Daroussin crwrap = true;
29961ba55bcSBaptiste Daroussin }
30061ba55bcSBaptiste Daroussin
30161ba55bcSBaptiste Daroussin i = j = 0;
30261ba55bcSBaptiste Daroussin while (text[i] != '\0') {
30361ba55bcSBaptiste Daroussin switch (text[i]) {
30461ba55bcSBaptiste Daroussin case '\\':
30561ba55bcSBaptiste Daroussin buf[j] = '\\';
30661ba55bcSBaptiste Daroussin switch (text[i+1]) {
30761ba55bcSBaptiste Daroussin case 'n': /* implicitly in "hasnl" mode */
30861ba55bcSBaptiste Daroussin buf[j] = '\n';
30961ba55bcSBaptiste Daroussin i++;
31061ba55bcSBaptiste Daroussin if (text[i+1] == '\n')
31161ba55bcSBaptiste Daroussin i++;
31261ba55bcSBaptiste Daroussin break;
31361ba55bcSBaptiste Daroussin case 't':
31461ba55bcSBaptiste Daroussin if (opt->tab_escape) {
31561ba55bcSBaptiste Daroussin buf[j] = '\t';
31661ba55bcSBaptiste Daroussin } else {
31761ba55bcSBaptiste Daroussin j++;
31861ba55bcSBaptiste Daroussin buf[j] = 't';
31961ba55bcSBaptiste Daroussin }
32061ba55bcSBaptiste Daroussin i++;
32161ba55bcSBaptiste Daroussin break;
32261ba55bcSBaptiste Daroussin }
32361ba55bcSBaptiste Daroussin break;
32461ba55bcSBaptiste Daroussin case '\n':
32561ba55bcSBaptiste Daroussin buf[j] = crwrap ? '\n' : ' ';
32661ba55bcSBaptiste Daroussin break;
32761ba55bcSBaptiste Daroussin case '\t':
32861ba55bcSBaptiste Daroussin buf[j] = opt->text_unchanged ? '\t' : ' ';
32961ba55bcSBaptiste Daroussin break;
33061ba55bcSBaptiste Daroussin default:
33161ba55bcSBaptiste Daroussin buf[j] = text[i];
33261ba55bcSBaptiste Daroussin }
33361ba55bcSBaptiste Daroussin i++;
33461ba55bcSBaptiste Daroussin if (!trim || buf[j] != ' ' || j == 0 || buf[j-1] != ' ')
33561ba55bcSBaptiste Daroussin j++;
33661ba55bcSBaptiste Daroussin }
33761ba55bcSBaptiste Daroussin buf[j] = '\0';
33861ba55bcSBaptiste Daroussin }
339