1 /*******************************************************************************
2 * Copyright (c) 2013-2021, Andrés Martinelli <andmarti@gmail.com> *
3 * All rights reserved. *
4 * *
5 * This file is a part of SC-IM *
6 * *
7 * SC-IM is a spreadsheet program that is based on SC. The original authors *
8 * of SC are James Gosling and Mark Weiser, and mods were later added by *
9 * Chuck Martin. *
10 * *
11 * Redistribution and use in source and binary forms, with or without *
12 * modification, are permitted provided that the following conditions are met: *
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. *
18 * 3. All advertising materials mentioning features or use of this software *
19 * must display the following acknowledgement: *
20 * This product includes software developed by Andrés Martinelli *
21 * <andmarti@gmail.com>. *
22 * 4. Neither the name of the Andrés Martinelli nor the *
23 * names of other contributors may be used to endorse or promote products *
24 * derived from this software without specific prior written permission. *
25 * *
26 * THIS SOFTWARE IS PROVIDED BY ANDRES MARTINELLI ''AS IS'' AND ANY *
27 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
29 * DISCLAIMED. IN NO EVENT SHALL ANDRES MARTINELLI BE LIABLE FOR ANY *
30 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;*
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
36 *******************************************************************************/
37
38 /**
39 * \file main.c
40 * \author Andrés Martinelli <andmarti@gmail.com>
41 * \date 2017-07-18
42 * \brief The main file of sc-im
43 *
44 * \details This is the main file for sc-im.
45 *
46 * \see Homepage: https://github.com/andmarti1424/sc-im
47 *
48 * \bug It has been detected that libxls can produce memory leaks. One example
49 * is when you try to read a non xls file (e.g. xlsx file).
50 *
51 * \bug Extended ascii characters are not showing correctly. Compile sc-im
52 * against -lncursesw and not -lncurses.
53 */
54
55 #include <signal.h>
56 #include <unistd.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <time.h>
60 #include <fcntl.h> // for F_GETFL O_NONBLOCK F_SETFL
61 #include <locale.h>
62 #include <wchar.h>
63 #include <sys/ioctl.h> // for ioctl
64
65 #ifndef NO_WORDEXP
66 #include <wordexp.h>
67 #endif
68
69 #include "main.h"
70 #include "shift.h"
71 #include "macros.h"
72 #include "tui.h"
73 #include "input.h"
74 #include "marks.h"
75 #include "maps.h"
76 #include "yank.h"
77 #include "file.h"
78 #include "utils/dictionary.h"
79 #include "utils/string.h"
80 #include "history.h"
81 #include "conf.h"
82 #include "buffer.h"
83 #include "cmds.h"
84 #include "vmtbl.h" // for growtbl
85 #include "filter.h"
86 #include "dep_graph.h"
87
88 #ifdef UNDO
89 #include "undo.h"
90 #endif
91
92 #ifdef XLUA
93 #include "lua.h"
94 #endif
95
96 int currow = 0; /**< Current row of the selected cell. */
97 int curcol = 0; /**< Current column of the selected cell. */
98 int lastrow = 0;
99 int lastcol = 0;
100 int maxrows;
101 int maxcols;
102 unsigned char * col_hidden;
103 unsigned char * col_frozen;
104 int * fwidth;
105 int * precision;
106 int * realfmt;
107 unsigned char * row_hidden;
108 unsigned char * row_frozen;
109 unsigned char * row_format;
110 char line[FBUFLEN];
111 int modflg; /**< Indicates a change was made since last save */
112 struct ent *** tbl;
113 int shall_quit = 0;
114 unsigned int curmode;
115 unsigned int lastmode;
116 int maxrow, maxcol;
117 char curfile[PATHLEN];
118 char loadingfile[PATHLEN] = { '\0' };
119 char * exepath;
120
121 int changed;
122 int cellassign;
123 int arg = 1;
124 int brokenpipe = FALSE; /**< Set to true if SIGPIPE is received */
125 char * ascext;
126 char * tbl0ext;
127 char * tblext;
128 char * latexext;
129 char * slatexext;
130 char * texext;
131 char dpoint = '.'; /**< Default decimal point character */
132 char thsep = ','; /**< Default thousands separator character */
133 int linelim = -1;
134 int calc_order = BYROWS;
135 int optimize = 0; /**< Causes numeric expressions to be optimizedv */
136 int tbl_style = 0; /**< Headers for T command output */
137 int rndtoeven = 0;
138 int rowsinrange = 1;
139 int colsinrange = DEFWIDTH;
140 double eval_result;
141 char * seval_result;
142 FILE * fdoutput; /**< Output file descriptor (stdout or file) */
143 int rescol = RESCOL; /**< Columns reserved for row numbers */
144
145 struct block * buffer;
146 struct block * lastcmd_buffer;
147 struct dictionary * user_conf_d; /**< User's configuration dictionary */
148 struct history * commandline_history;
149 struct history * insert_history;
150 char stderr_buffer[1024] = "";
151 struct timeval startup_tv, current_tv; /**< Runtime timer */
152
153 #ifdef AUTOBACKUP
154 struct timeval lastbackup_tv; /**< Last backup timer */
155 #ifdef HAVE_PTHREAD
156 #include <pthread.h>
157 int pthread_exists = 0; /**< Return status of pthread_create */
158 pthread_t fthread;
159 #endif
160 #endif
161
162 void read_stdin();
163 extern char * rev;
164
165 /**
166 * \brief The main() function
167 *
168 * \details The main() function of sc-im. It is the first function called when
169 * the applicaiton is executed.
170 *
171 * \param[in] argc (argument count) is the number of strings pointed to by argv. This
172 * is passed to main() by the system.
173 *
174 * \param[in] argv (argument vector) is a is a one-dimensional array of strings.
175 * Each string is one of the arguments that was passed to the program. The
176 * first string is the executable's name. This is passed to main() by
177 * the system.
178 *
179 * \return 0 on success; 1 on some errors; -1 on error
180 */
181
182 // TODO Document the possible errors. Why are some things -1 while others
183 // are 1? Look for instances of exit_app(<number>).
184
main(int argc,char ** argv)185 int main (int argc, char ** argv) {
186 // Define how the file stream should be buffered. Error if unsuccessful.
187 if (setvbuf(stderr, stderr_buffer, _IOFBF, STDERRBUF) != 0) {
188 fprintf(stderr, "Error setting stderr buffer\n");
189 return -1;
190 }
191
192 // set up signals so we can catch them
193 signals();
194
195 #ifdef USELOCALE
196 // Set location dependent information. This is used by some libraries.
197 //setlocale(LC_ALL, "");
198 setlocale(LC_CTYPE, "");
199 #endif
200
201 // start configuration dictionaries
202 user_conf_d = create_dictionary();
203 store_default_config_values(); // Stores default values in user_conf_d
204
205 // Read the main() parameters and replace values in user_conf_d as necessary
206 read_argv(argc, argv);
207
208 // check if help is in argv. if so, show usage and quit
209 if (get_conf_int("help"))
210 show_usage_and_quit();
211
212 // check if version is in argv. if so, show version and quit
213 if (get_conf_int("version"))
214 show_version_and_quit();
215
216 // create command line history structure
217 if (! get_conf_int("nocurses")) {
218 #ifdef HISTORY_FILE
219 commandline_history = (struct history *) create_history(':');
220 load_history(commandline_history, ':'); // load the command history file
221 #endif
222 #ifdef INS_HISTORY_FILE
223 insert_history = (struct history *) create_history('=');
224 load_history(insert_history, '='); // load the insert history file
225 #endif
226 }
227
228 // create basic structures that will depend on the loaded file
229 create_structures();
230
231 // setup the spreadsheet arrays (tbl)
232 if (! growtbl(GROWNEW, 0, 0)) return exit_app(1);
233
234 // initiate NCURSES if that is what is wanted
235 if (! get_conf_int("nocurses")) {
236 ui_start_screen();
237
238 #ifdef USECOLORS
239 if (get_d_colors_param() == NULL) {
240 start_default_ucolors();
241 /*
242 * in case we decide to change colors
243 * this creates a dictionary and stores in it
244 * the relationship between macros and the keys values
245 * that are defined in .sc files
246 */
247 set_colors_param_dict();
248 }
249 #endif
250 }
251
252 /*
253 * If the 'output' parameter is defined, SC-IM saves its output to that file.
254 * To achieve that, we open the output file and keep it open until exit.
255 * otherwise, SC-IM will output to stdout.
256 */
257 if (get_conf_value("output") != NULL) {
258 fdoutput = fopen(get_conf_value("output"), "w+");
259 if (fdoutput == NULL) {
260 sc_error("Cannot open file: %s.", get_conf_value("output"));
261 return exit_app(-1);
262 }
263
264 if (! get_conf_int("nocurses")) { // WE MUST STOP SCREEN!
265 ui_stop_screen();
266
267 // if output is set, nocurses should always be 1 !
268 put(user_conf_d, "nocurses", "1");
269 }
270 }
271
272 #ifdef XLUA
273 doLuainit();
274 #endif
275
276 wchar_t stdin_buffer[BUFFERSIZE] = { L'\0' };
277
278 // if there was no file passed to scim executable
279 // 1. erase db !
280 if (! loadingfile[0]) erasedb();
281
282 // 2. loadrc
283 loadrc();
284
285 // 3. read sc file passed as argv
286 load_sc();
287
288 // 4. check input from stdin (pipeline)
289 // and send it to interp
290 read_stdin();
291
292
293 // change curmode to NORMAL_MODE
294 chg_mode('.');
295
296 // initiate ui
297 FILE * f;
298 if ( ! get_conf_int("nocurses")) {
299 // we show welcome screen if no spreadsheet was passed to SC-IM
300 // and no input was sent throw pipeline
301 if ( ! curfile[0] && ! wcslen(stdin_buffer)) {
302 ui_do_welcome();
303 // show mode and cell's details in status bar
304 ui_print_mode();
305 ui_show_celldetails();
306 } else {
307 ui_show_header();
308 ui_update(TRUE);
309 }
310 } else {
311 f = fopen("/dev/tty", "rw");
312 if (f == NULL) sc_error("fatal error loading stdin");
313 }
314
315 // handle input from keyboard
316 if (! get_conf_int("nocurses"))
317 buffer = (struct block *) create_buf(); // this should only take place if curses ui
318
319 wchar_t nocurses_buffer[BUFFERSIZE];
320
321 // runtime timer
322 gettimeofday(&startup_tv, NULL);
323
324 #ifdef AUTOBACKUP
325 //gettimeofday(&lastbackup_tv, NULL);
326 lastbackup_tv = (struct timeval) {0};
327 #endif
328
329 if (get_conf_value("export_csv")) {
330 export_delim(NULL, ',', 0, 0, maxrow, maxcol, 0);
331 }
332
333 if (get_conf_value("export_tab")) {
334 export_delim(NULL, '\t', 0, 0, maxrow, maxcol, 0);
335 }
336
337 if (get_conf_value("export_mkd")) {
338 export_markdown(NULL, 0, 0, maxrow, maxcol);
339 }
340
341 if (get_conf_value("export") || get_conf_value("export_txt")) {
342 export_plain(NULL, 0, 0, maxrow, maxcol);
343 }
344
345
346 while ( ! shall_quit && ! get_conf_int("quit_afterload")) {
347 // save current time for runtime timer
348 gettimeofday(¤t_tv, NULL);
349
350 // autobackup if it is time to do so
351 handle_backup();
352
353 // if we are in ncurses
354 if (! get_conf_int("nocurses")) {
355 handle_input(buffer);
356
357 // if we are not in ncurses
358 } else if (fgetws(nocurses_buffer, BUFFERSIZE, f) != NULL) {
359 sc_debug("Interp will receive: %ls", nocurses_buffer);
360 send_to_interp(nocurses_buffer);
361 }
362
363 /* shall_quit=1 means :q
364 shall_quit=2 means :q! */
365 if (shall_quit == 1 && modcheck()) shall_quit = 0;
366 }
367 if (get_conf_int("nocurses") && f != NULL) fclose(f);
368
369 return shall_quit == -1 ? exit_app(-1) : exit_app(0);
370 }
371
372 extern graphADT graph;
373
374 /**
375 * \brief Creates the structures used by the program.
376 *
377 * \return none
378 */
379
create_structures()380 void create_structures() {
381 // initiate mark array
382 create_mark_array();
383
384 // create last command buffer
385 lastcmd_buffer = (struct block *) create_buf();
386
387 // create yank list structure
388 init_yanklist();
389
390 /* Assign NULL to colformats
391 int c;
392 for (c = 0; c < COLFORMATS; c++)
393 colformat[c] = NULL;
394 */
395
396 // init calc chain graph
397 graph = GraphCreate();
398 }
399
400 /**
401 * \brief TODO Document read_stdin()
402 *
403 * \return none
404 */
405
read_stdin()406 void read_stdin() {
407 //sc_debug("reading stdin from pipeline");
408 fd_set readfds;
409 FD_ZERO(&readfds);
410 FD_SET(STDIN_FILENO, &readfds);
411 fd_set savefds = readfds;
412 struct timeval timeout;
413 timeout.tv_sec = 0;
414 timeout.tv_usec = 0;
415 FILE * f = stdin;
416 //FILE * f = fopen("/dev/tty", "rw");
417 wchar_t stdin_buffer[BUFFERSIZE] = { L'\0' };
418
419 if (select(1, &readfds, NULL, NULL, &timeout)) {
420 //sc_debug("there is data");
421 while (f != NULL && fgetws(stdin_buffer, BUFFERSIZE, f) != NULL) {
422 sc_debug("Interp will receive: %ls", stdin_buffer);
423 send_to_interp(stdin_buffer);
424 }
425 fflush(f);
426 } else {
427 //sc_debug("there is NO data");
428 }
429 readfds = savefds;
430 if (f != NULL) fclose(f);
431
432 if ( ! freopen("/dev/tty", "rw", stdin)) {
433 perror(NULL);
434 exit(-1);
435 }
436 //sc_debug("finish reading");
437 }
438
439 /**
440 * \brief Delete basic structures that depend on the loaded files.
441 *
442 * \return none
443 */
delete_structures()444 void delete_structures() {
445
446 // Free marks array
447 free_marks_array();
448
449 // Free yanklist
450 free_yanklist();
451
452 // Erase last_command buffer
453 erase_buf(lastcmd_buffer);
454
455 // Free ranges
456 free_ranges();
457
458 // Free filters
459 free_filters();
460
461 // Free undo list - from start of list
462 #ifdef UNDO
463 clear_undo_list();
464 #endif
465
466 // Free lua stuff
467 #ifdef XLUA
468 doLuaclose();
469 #endif
470
471 // free deleted ents
472 flush_saved();
473
474 // free calc chain graph
475 destroy_graph(graph);
476
477 // Free ents of tbl
478 erasedb();
479
480 // free custom_colors
481 free_custom_colors();
482 }
483
484 /**
485 * \brief Cleans things up just before exiting the program.
486 *
487 * \param[in] status
488 * \param[out] status
489 *
490 * \return status is returned unchanged
491 */
492
exit_app(int status)493 int exit_app(int status) {
494
495 // free history
496 if (! get_conf_int("nocurses")) {
497
498 #ifdef HISTORY_FILE
499 if (! save_history(commandline_history, "w")) sc_error("Could not save commandline history");
500 if (commandline_history != NULL) destroy_history(commandline_history);
501 #endif
502
503 #ifdef INS_HISTORY_FILE
504 if (! save_history(insert_history, "a")) sc_error("Could not save input mode history");
505 if (insert_history != NULL) destroy_history(insert_history);
506 #endif
507 }
508
509 // wait for autobackup thread to finish, just in case
510 #if defined(AUTOBACKUP) && defined(HAVE_PTHREAD)
511 if (pthread_exists) pthread_join (fthread, NULL);
512 #endif
513
514 // remove backup file
515 #ifdef AUTOBACKUP
516 if (strlen(curfile) && backup_exists(curfile)) remove_backup(curfile);
517 #endif
518
519 // erase structures
520 delete_structures();
521
522 // Free mappings
523 del_maps();
524
525 // Erase stdin
526 erase_buf(buffer);
527
528 // stop CURSES screen
529 if (! get_conf_int("nocurses"))
530 ui_stop_screen();
531
532 // close fdoutput
533 if (get_conf_value("output") != NULL && get_conf_value("output")[0] != '\0' && fdoutput != NULL) {
534 fclose(fdoutput);
535 }
536
537 // delete user config dictionaries
538 destroy_dictionary(user_conf_d);
539
540 return status;
541 }
542
543 /**
544 * \brief Read command line parameters and store them in a dictionary
545 *
546 * \details Read parameters passed to SC-IM executable and
547 * store them in user_conf dictionary.
548 *
549 * \param[in] argc (argument count) is the number of strings pointed to by
550 * argv.
551 * \param[in] argv (argument vector) is a one-dimensional array of strings.
552 * Each string is one of the arguments that was passed to the program. The
553 * first string is the executable's name.
554 *
555 * \return none
556 */
557
read_argv(int argc,char ** argv)558 void read_argv(int argc, char ** argv) {
559 int i;
560 for (i = 1; i < argc; i++) {
561 if ( ! strncmp(argv[i], "--", 2) ) { // it was passed a parameter
562 parse_str(user_conf_d, argv[i] + 2, 0);
563 } else { // it was passed a file
564 strncpy(loadingfile, argv[i], PATHLEN-1);
565 }
566 }
567 exepath = argv[0];
568 return;
569 }
570
571 /**
572 * \brief Attempt to load a file
573 *
574 * \return none
575 */
576
load_sc()577 void load_sc() {
578 char name[PATHLEN];
579 strcpy(name, ""); //force name to be empty
580 #ifdef NO_WORDEXP
581 size_t len;
582 #else
583 int c;
584 wordexp_t p;
585 #endif
586
587 #ifdef NO_WORDEXP
588 if ((len = strlen(loadingfile)) >= sizeof(name)) {
589 sc_info("File path too long: '%s'", loadingfile);
590 return;
591 }
592 memcpy(name, loadingfile, len+1);
593 #else
594 wordexp(loadingfile, &p, 0);
595 for (c=0; c < p.we_wordc; c++) {
596 if (c) sprintf(name + strlen(name), " ");
597 sprintf(name + strlen(name), "%s", p.we_wordv[c]);
598 }
599 wordfree(&p);
600 #endif
601
602 if (strlen(name) != 0) {
603 sc_readfile_result result = readfile(name, 0);
604 if (!get_conf_int("nocurses")) {
605 if (result == SC_READFILE_DOESNTEXIST) {
606 // It's a new record!
607 sc_info("New file: \"%s\"", name);
608 } else if (result == SC_READFILE_ERROR) {
609 sc_info("\"%s\" is not a SC-IM compatible file", name);
610 }
611 }
612 }
613 }
614
615 /**
616 * \brief Set the calculation order
617 *
618 * \return none
619 */
620
setorder(int i)621 void setorder(int i) {
622 if ((i == BYROWS) || (i == BYCOLS)) calc_order = i;
623 return;
624 }
625
626 /**
627 * \brief Set signals catched by sc-im
628 *
629 * \return none
630 */
631
signals()632 void signals() {
633 void sig_int();
634 void sig_abrt();
635 void sig_term();
636 void nopipe();
637 void sig_winchg();
638 void sig_tstp();
639 void sig_cont();
640
641 signal(SIGINT, sig_int);
642 signal(SIGABRT, sig_abrt);
643 signal(SIGTERM, sig_term); // kill
644 signal(SIGPIPE, nopipe);
645 //(void) signal(SIGALRM, time_out);
646 signal(SIGWINCH, sig_winchg);
647 //(void) signal(SIGBUS, doquit);
648 //(void) signal(SIGFPE, doquit);
649 signal(SIGTSTP, sig_tstp);
650 signal(SIGCONT, sig_cont);
651 return;
652 }
653
654 /**
655 * \brief Handles the SIGPIPE signal
656 *
657 * \return none
658 */
659
660 // TODO Possibly rename this function to sig_nopipe() for consistency
661 // with the other signal functions.
662
nopipe()663 void nopipe() {
664 sc_error("brokenpipe!");
665 brokenpipe = TRUE;
666 return;
667 }
668
669 /**
670 * \brief Handles the SIGTSTP signal
671 *
672 * \return none
673 */
674
sig_tstp()675 void sig_tstp() {
676 //sc_info("Got SIGTSTP.");
677 def_prog_mode();
678 endwin();
679 signal(SIGTSTP, SIG_DFL); /* set handler to default */
680 kill(getpid(), SIGTSTP); /* call the default handler */
681 }
682
683
684 /**
685 * \brief Handles the SIGCONT signal
686 *
687 * \return none
688 */
689
sig_cont()690 void sig_cont() {
691 signal(SIGTSTP, sig_tstp); /* set handler back to this */
692 sig_winchg();
693 reset_prog_mode();
694 refresh();
695 ui_update(TRUE);
696 //sc_info("Got SIGCONT.");
697 }
698
699 /**
700 * \brief Handles the SIGINT signal
701 *
702 * \return none
703 */
704
sig_int()705 void sig_int() {
706 if ( ! get_conf_int("debug"))
707 sc_error("Got SIGINT. Press «:q<Enter>» to quit SC-IM");
708 else
709 shall_quit = 2;
710 return;
711 }
712
713 /**
714 * \brief Handles the SIGABRT signal
715 *
716 * \return none
717 */
718
sig_abrt()719 void sig_abrt() {
720 sc_error("Error !!! Quitting SC-IM.");
721 shall_quit = -1; // error !
722 return;
723 }
724
725 /**
726 * \brief Handles the SIGABRT signal
727 *
728 * \return none
729 */
730
sig_term()731 void sig_term() {
732 sc_error("Got SIGTERM signal. Quitting SC-IM.");
733 shall_quit = 2;
734 return;
735 }
736
737 /**
738 * \brief Send the version number to standard output and quit.
739 *
740 * \return none
741 */
742
743 // TODO Split this into two commands. One prints the version number
744 // the other prints the version number along with the other information.
745
show_version_and_quit()746 void show_version_and_quit() {
747 put(user_conf_d, "nocurses", "1");
748 sc_info("SC-IM - %s", rev);
749 #ifdef NCURSES
750 sc_info("-DNCURSES");
751 #endif
752 #ifdef MAXROWS
753 sc_info("-DMAXROWS %d", MAXROWS);
754 #endif
755 #ifdef UNDO
756 sc_info("-DUNDO");
757 #endif
758 #ifdef XLS
759 sc_info("-DXLS");
760 #endif
761 #ifdef XLSX
762 sc_info("-DXLSX");
763 #endif
764 #ifdef XLSX_EXPORT
765 sc_info("-DXLSX_EXPORT");
766 #endif
767 #ifdef XLUA
768 sc_info("-DXLUA");
769 #endif
770 #ifdef DEFAULT_COPY_TO_CLIPBOARD_CMD
771 sc_info("-DDEFAULT_COPY_TO_CLIPBOARD_CMD=\"%s\"", DEFAULT_COPY_TO_CLIPBOARD_CMD);
772 #endif
773 #ifdef DEFAULT_PASTE_FROM_CLIPBOARD_CMD
774 sc_info("-DDEFAULT_PASTE_FROM_CLIPBOARD_CMD=\"%s\"", DEFAULT_PASTE_FROM_CLIPBOARD_CMD);
775 #endif
776 #ifdef DEFAULT_OPEN_FILE_UNDER_CURSOR_CMD
777 sc_info("-DDEFAULT_OPEN_FILE_UNDER_CURSOR_CMD=\"%s\"", DEFAULT_OPEN_FILE_UNDER_CURSOR_CMD);
778 #endif
779 #ifdef USELOCALE
780 sc_info("-DUSELOCALE");
781 #endif
782 #ifdef MOUSE
783 sc_info("-DMOUSE");
784 #endif
785 #ifdef USECOLORS
786 sc_info("-DUSECOLORS");
787 #endif
788 #ifdef _XOPEN_SOURCE_EXTENDED
789 sc_info("-D_XOPEN_SOURCE_EXTENDED");
790 #endif
791 #ifdef _GNU_SOURCE
792 sc_info("-D_GNU_SOURCE");
793 #endif
794 #ifdef SNAME
795 sc_info("-DSNAME=\"%s\"", SNAME);
796 #endif
797 #ifdef HELP_PATH
798 sc_info("-DHELP_PATH=\"%s\"", HELP_PATH);
799 #endif
800 #ifdef LIBDIR
801 sc_info("-DLIBDIR=\"%s\"", LIBDIR);
802 #endif
803 #ifdef DFLT_PAGER
804 sc_info("-DDFLT_PAGER=\"%s\"", DFLT_PAGER);
805 #endif
806 #ifdef DFLT_EDITOR
807 sc_info("-DDFLT_EDITOR=\"%s\"", DFLT_EDITOR);
808 #endif
809 #ifdef CONFIG_DIR
810 sc_info("-DCONFIG_DIR=\"%s\"", CONFIG_DIR);
811 #endif
812 #ifdef CONFIG_FILE
813 sc_info("-DCONFIG_FILE=\"%s\"", CONFIG_FILE);
814 #endif
815 #ifdef HISTORY_DIR
816 sc_info("-DHISTORY_DIR=\"%s\"", HISTORY_DIR);
817 #endif
818 #ifdef HISTORY_FILE
819 sc_info("-DHISTORY_FILE=\"%s\"", HISTORY_FILE);
820 #endif
821 #ifdef INS_HISTORY_FILE
822 sc_info("-DINS_HISTORY_FILE=\"%s\"", INS_HISTORY_FILE);
823 #endif
824 #ifdef HAVE_PTHREAD
825 sc_info("-DHAVE_PTHREAD");
826 #endif
827 #ifdef AUTOBACKUP
828 sc_info("-DAUTOBACKUP");
829 #endif
830 put(user_conf_d, "quit_afterload", "1");
831 }
832
833 /**
834 * \brief Print usage message to stdout text and quit
835 *
836 * \return none
837 */
838
839 // NOTE this is a quick and dirty command to search for arguments used in the sources (macOS 10.14)
840 // grep "get_conf_value(\"" -r ./src/*.c | grep get_conf_value |sed 's/"//g' |sed 's/.*get_conf_value(//g'|cut -d ')' -f1 |sort|uniq|sed 's/^/--/g'
show_usage_and_quit()841 void show_usage_and_quit(){
842 put(user_conf_d, "nocurses", "1");
843 printf("\
844 \nSC-IM - SC Improved\
845 \n\
846 \nUsage: sc-im [arguments] [file] specified file\
847 \n or: sc-im [arguments] - read text from stdin\
848 \n\
849 \nArguments:\
850 \n\
851 \n --autocalc Set variable 'autocalc'.\
852 \n --copy_to_clipboard_delimited_tab Set variable 'copy_to_clipboard_delimited_tab'\
853 \n --debug Set variable 'debug'\
854 \n --default_copy_to_clipboard_cmd=COMMAND set variable 'default_copy_from_clipboard_cmd'\
855 \n --default_paste_from_clipboard_cmd=COMMAND set variable 'default_paste_from_clipboard_cmd'\
856 \n --default_open_file_under_cursor_cmd=COMMAND set variable 'default_open_file_under_cursor_cmd'\
857 \n --export_csv Export to csv without interaction\
858 \n --export_tab Export to tab without interaction\
859 \n --export_txt Export to txt without interaction\
860 \n --export_mkd Export to markdown without interaction\
861 \n --external_functions Set variable 'external_functions'\
862 \n --half_page_scroll Set variable 'half_page_scroll'\
863 \n --ignorecase Set variable 'ignorecase'\
864 \n --import_delimited_as_text Import text as\
865 \n --newline_action={j or l} Set variable 'newline_action'\
866 \n --nocurses Run interactive but without ncurses interface.\
867 \n --numeric Set variable 'numeric'\
868 \n --numeric_decimal Set variable 'numeric_decimal'\
869 \n --output=FILE Save the results in FILE\
870 \n --overlap Set variable 'overlap variable'\
871 \n --quit_afterload Quit after loading all the files\
872 \n --show_cursor Make the screen cursor follow the active cell\
873 \n --tm_gmtoff={seconds} set gmt offset used for converting datetimes to localtime.\
874 \n --txtdelim={\",\" or \";\" or \"\\t\" or \"|\"} Sets delimiter when opening a .tab of .csv file");
875 #ifdef XLSX
876 printf("\n\
877 \n --sheet=SHEET Open SHEET when loading xlsx file. Default is 1.\
878 \n --xlsx_readformulas Set variable 'xlsx_readformulas'");
879 #endif
880 printf("\n\
881 \n --version Print version information and exit\
882 \n --help Print Help (this message) and exit\n");
883 put(user_conf_d, "quit_afterload", "1");
884 }
885