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 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 */ 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 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 */ 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 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 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 */ 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 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