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 cmds_command.c
40  * \author Andrés Martinelli <andmarti@gmail.com>
41  * \date 2017-07-18
42  * \brief TODO Write a tbrief file description.
43  */
44 
45 #include <string.h>
46 #include <wchar.h>
47 #include <stdlib.h>
48 #include <ctype.h>         // for isprint()
49 
50 #ifndef NO_WORDEXP
51 #include <wordexp.h>
52 #endif
53 
54 #include "sc.h"            // for rescol
55 #include "conf.h"
56 #include "cmds_command.h"
57 #include "cmds_edit.h"
58 #include "cmds.h"
59 #include "utils/string.h"
60 #include "utils/dictionary.h"
61 #include "tui.h"
62 #include "file.h"
63 #include "main.h"
64 #include "interp.h"
65 #include "hide_show.h"
66 #include "exec.h"
67 #include "help.h"
68 #include "marks.h"
69 #include "filter.h"
70 #include "maps.h"
71 #include "xls.h"
72 #include "xlsx.h"
73 #include "cmds_visual.h"
74 #include "plot.h"
75 
76 #ifdef UNDO
77 #include "undo.h"
78 #endif
79 
80 extern char * rev;
81 extern struct dictionary * user_conf_d;
82 
83 wchar_t inputline[BUFFERSIZE];
84 extern wchar_t interp_line[BUFFERSIZE];
85 int inputline_pos; /**< Position in window. Some chars has 2 chars width */
86 // see https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms
87 int real_inputline_pos; /**<  Real position in inputline */
88 
89 static wchar_t * valid_commands[] = {
90 L"!",
91 L"addfilter",
92 L"autojus",
93 L"ccopy",
94 L"cellcolor",
95 L"cmap",
96 L"cnoremap",
97 L"color",
98 L"cpaste",
99 L"cunmap",
100 L"datefmt",
101 L"define_color",
102 L"delfilter",
103 L"delfilters",
104 L"e csv",
105 L"e! csv",
106 L"e mkd",
107 L"e! mkd",
108 L"e tab",
109 L"e! tab",
110 L"e tex",
111 L"e! tex",
112 L"e txt",
113 L"e! txt",
114 L"e xlsx",
115 L"e! xlsx",
116 L"fcopy",
117 L"file",
118 L"fill",
119 L"filteroff",
120 L"filteron",
121 L"format",
122 L"formatcol",
123 L"formatrow",
124 L"freezecol",
125 L"freezerow",
126 L"fsum",
127 L"h",
128 L"help",
129 L"hiddencols",
130 L"hiddenrows",
131 L"hidecol",
132 L"hiderow",
133 L"imap",
134 L"inoremap",
135 L"int",
136 L"iunmap",
137 L"load!",
138 L"load",
139 L"lock",
140 L"nmap",
141 L"nnoremap",
142 L"nunmap",
143 L"pad",
144 L"plot",
145 L"plotedit",
146 L"q!",
147 L"q",
148 L"quit!",
149 L"quit",
150 L"redefine_color",
151 L"refresh",
152 L"set",
153 L"showcol",
154 L"showcols",
155 L"showfilters",
156 L"showmaps",
157 L"showrow",
158 L"showrows",
159 L"sort",
160 L"strtonum",
161 L"subtotal",
162 L"trigger",
163 L"unformat",
164 L"unfreezecol",
165 L"unfreezerow",
166 L"unlock",
167 L"untrigger",
168 L"valueize",
169 L"version",
170 L"vmap",
171 L"vnoremap",
172 L"vunmap",
173 L"w",
174 L"wq",
175 L"x",
176 (wchar_t *) 0
177 };
178 
179 /**
180  * \brief TODO Document do_commandmode()
181  *
182  * \param[in] sb
183  *
184  * \return none
185  */
186 
do_commandmode(struct block * sb)187 void do_commandmode(struct block * sb) {
188 
189     // If a visual selected range exists
190     int p = is_range_selected();
191     struct srange * sr = NULL;
192     if (p != -1) sr = get_range_by_pos(p);
193 
194 
195     /*
196      * Normal KEY handlers for this MODE
197      */
198     if (sb->value == OKEY_BS || sb->value == OKEY_BS2) {  // BS
199         if ( ! wcslen(inputline) || ! real_inputline_pos ) return;
200         int l = wcwidth(inputline[real_inputline_pos - 1]);
201         real_inputline_pos--;
202         del_wchar(inputline, real_inputline_pos);
203         inputline_pos -= l;
204         ui_show_header();
205 
206 #ifdef HISTORY_FILE
207         if (commandline_history->pos == 0)
208             del_wchar(get_line_from_history(commandline_history, commandline_history->pos), real_inputline_pos); // Clean history
209 #endif
210         ui_show_header();
211         return;
212 
213     } else if (sb->value == OKEY_LEFT) {   // LEFT
214         if (inputline_pos) {
215             real_inputline_pos--;
216             int l = wcwidth(inputline[real_inputline_pos]);
217             inputline_pos -= l;
218         }
219         ui_show_header();
220         return;
221 
222     } else if (sb->value == OKEY_RIGHT) {  // RIGHT
223         int max = wcswidth(inputline, wcslen(inputline));
224         if (inputline_pos < max) {
225             int l = wcwidth(inputline[real_inputline_pos++]);
226             inputline_pos += l;
227         }
228         ui_show_header();
229         return;
230 
231     } else if (sb->value == OKEY_DEL) {    // DEL
232         if (inputline_pos > wcswidth(inputline, wcslen(inputline))) return;
233         del_wchar(inputline, real_inputline_pos);
234 
235 #ifdef HISTORY_FILE
236         if (commandline_history->pos == 0)
237             del_wchar(get_line_from_history(commandline_history, commandline_history->pos), real_inputline_pos); // Clean history
238 #endif
239         ui_show_header();
240         return;
241 
242 #ifdef HISTORY_FILE
243     } else if (sb->value == OKEY_UP || sb->value == ctl('p') ||         // UP
244                sb->value == OKEY_DOWN || sb->value == ctl('n')) {       // DOWN
245 
246         int delta = 0, k = 0, i, cmp;
247         if (sb->value == OKEY_UP || sb->value == ctl('p')) {            // up
248             for (i=commandline_history->pos; -i+1 < commandline_history->len; i--, k--)
249                 if (wcslen(get_line_from_history(commandline_history, 0))) {
250                     if (! (cmp = wcsncmp(inputline, get_line_from_history(commandline_history, i-1), wcslen(get_line_from_history(commandline_history, 0))))) {
251                         k--;
252                         break;
253                     } else if (commandline_history->len == 2-i && cmp) {
254                         k=0;
255                         break;
256                     }
257                 } else if (!wcslen(get_line_from_history(commandline_history, 0))) {
258                     k--;
259                     break;
260                 }
261         } else if (sb->value == OKEY_DOWN || sb->value == ctl('n')) {   // down
262             for (i=commandline_history->pos; i != 0; i++, k++)
263                 if (wcslen(get_line_from_history(commandline_history, 0))) {
264                     if (! (cmp = wcsncmp(inputline, get_line_from_history(commandline_history, i+1), wcslen(get_line_from_history(commandline_history, 0))))) {
265                         k++;
266                         break;
267                     } else if (commandline_history->pos == 0 && cmp) {
268                         k=0;
269                         break;
270                     }
271                 } else if (!wcslen(get_line_from_history(commandline_history, 0))) {
272                     k++;
273                     break;
274                 }
275         }
276         delta += k;
277         commandline_history->pos += delta;
278         wcscpy(inputline, get_line_from_history(commandline_history, commandline_history->pos));
279         inputline_pos = wcswidth(inputline, real_inputline_pos);
280         ui_show_header();
281         return;
282 #endif
283 
284     } else if (sb->value == ctl('v') ) {  // VISUAL SUBMODE
285         visual_submode = ':';
286         chg_mode('v');
287         start_visualmode(currow, curcol, currow, curcol);
288         return;
289 
290     } else if (sb->value == ctl('r') && get_bufsize(sb) == 2 &&        // C-r      // FIXME ???
291         (sb->pnext->value - (L'a' - 1) < 1 || sb->pnext->value > 26)) {
292         wchar_t cline [BUFFERSIZE];
293         int i, r = get_mark(sb->pnext->value)->row;
294         if (r != -1) {
295             swprintf(cline, BUFFERSIZE, L"%s%d", coltoa(get_mark(sb->pnext->value)->col), r);
296         } else {
297             swprintf(cline, BUFFERSIZE, L"%s%d:", coltoa(get_mark(sb->pnext->value)->rng->tlcol), get_mark(sb->pnext->value)->rng->tlrow);
298             swprintf(cline + wcslen(cline), BUFFERSIZE, L"%s%d", coltoa(get_mark(sb->pnext->value)->rng->brcol), get_mark(sb->pnext->value)->rng->brrow);
299         }
300         for(i = 0; i < wcslen(cline); i++) ins_in_line(cline[i]);
301 
302 #ifdef HISTORY_FILE
303         if (commandline_history->pos == 0) {          // Only if editing the new command
304             wchar_t * sl = get_line_from_history(commandline_history, 0);
305             wcscat(sl, cline);                        // Insert into history
306         }
307 #endif
308         ui_show_header();
309         return;
310 
311     } else if (sb->value == ctl('f')) {               // C-f
312         wchar_t cline [BUFFERSIZE];
313         int i;
314         struct ent * p1 = *ATBL(tbl, currow, curcol);
315         if (! p1 || ! p1->format) {
316             sc_error("cell has no format");
317             return;
318         }
319         swprintf(cline, BUFFERSIZE, L"%s", p1->format);
320         for (i = 0; i < wcslen(cline); i++) ins_in_line(cline[i]);
321 
322 #ifdef HISTORY_FILE
323         if (commandline_history->pos == 0) {          // Only if editing the new command
324             wchar_t * sl = get_line_from_history(commandline_history, 0);
325             wcscat(sl, cline);                        // Insert into history
326         }
327 #endif
328         ui_show_header();
329         return;
330 
331     } else if ( sb->value == ctl('w') || sb->value == ctl('b') ||
332                 sb->value == OKEY_HOME || sb->value == OKEY_END) {
333         switch (sb->value) {
334         case ctl('w'):
335             real_inputline_pos = for_word(1, 0, 1) + 1;   // E
336             break;
337         case ctl('b'):
338             real_inputline_pos = back_word(1);            // B
339             break;
340         case OKEY_HOME:
341             real_inputline_pos = 0;                       // 0
342             break;
343         case OKEY_END:
344             real_inputline_pos = wcslen(inputline);       // $
345             break;
346         }
347         inputline_pos = wcswidth(inputline, real_inputline_pos);
348         ui_show_header();
349         return;
350 
351     } else if (sb->value == '\t') {                  // TAB completion
352         int i, clen = (sizeof(valid_commands) / sizeof(char *)) - 1;
353 
354         if (! get_comp()) copy_to_curcmd(inputline); // keep original cmd
355 
356         for (i = 0; i < clen; i++) {
357             if ( ! wcscmp(inputline, valid_commands[i]) ) {
358                 wcscpy(inputline, get_curcmd());
359                 continue;
360             }
361             if ( ! wcsncmp(inputline, valid_commands[i], wcslen(inputline))
362                ) {
363                 wcscpy(inputline, valid_commands[i]);
364                 real_inputline_pos = wcslen(inputline);
365                 inputline_pos = wcswidth(inputline, real_inputline_pos);
366                 set_comp(1);
367                 break;
368             }
369         }
370 
371         // Restore inputline content
372         if (i == clen) {
373             wcscpy(inputline, get_curcmd());
374             real_inputline_pos = wcslen(inputline);
375             inputline_pos = wcswidth(inputline, real_inputline_pos);
376             set_comp(0);
377         }
378 
379         ui_show_header();
380         return;
381 
382     } else if (sc_isprint(sb->value)) {               //  Write new char
383         ins_in_line(sb->value);
384         ui_show_header();
385 
386 #ifdef HISTORY_FILE
387         if (commandline_history->pos == 0) {          // Only if editing the new command
388             wchar_t * sl = get_line_from_history(commandline_history, 0);
389             add_wchar(sl, sb->value, real_inputline_pos-1); // Insert into history
390         }
391 #endif
392         return;
393 
394 
395     /*
396      * CONFIRM A COMMAND PRESSING ENTER
397      */
398     } else if (find_val(sb, OKEY_ENTER)) {
399 
400         if ( ! wcscmp(inputline, L"refresh")) {
401             sig_winchg();
402 
403         } else if ( ! wcscmp(inputline, L"help") || ! wcscmp(inputline, L"h") ) {
404             help();
405 
406         } else if ( ! wcscmp(inputline, L"q!") || ! wcscmp(inputline, L"quit!") ) {
407             shall_quit = 2;
408 
409         } else if ( ! wcscmp(inputline, L"q") || ! wcscmp(inputline, L"quit") ) {
410             shall_quit = 1;
411 
412         } else if ( ! wcsncmp(inputline, L"autojus", 7) ) {
413             wchar_t cline [BUFFERSIZE];
414             wcscpy(cline, inputline);
415             int c = curcol, cf = curcol;
416             if (p != -1) {
417                 c = sr->tlcol;
418                 cf = sr->brcol;
419             }
420             if ( p != -1 || ! wcscmp(inputline, L"autojus")) {
421                 swprintf(cline, BUFFERSIZE, L"autojus %s:", coltoa(c));
422                 swprintf(cline + wcslen(cline), BUFFERSIZE, L"%s", coltoa(cf));
423             }
424             send_to_interp(cline);
425 
426         } else if ( ! wcsncmp(inputline, L"define_color", 12) ) {
427             send_to_interp(inputline);
428 
429         } else if ( ! wcsncmp(inputline, L"redefine_color", 14) ) {
430             send_to_interp(inputline);
431 
432         } else if ( ! wcsncmp(inputline, L"load", 4) ) {
433             char name [BUFFERSIZE];
434             int name_ok = 0;
435             int force_rewrite = 0;
436             #ifndef NO_WORDEXP
437             size_t len;
438             wordexp_t p;
439             #endif
440 
441             wcstombs(name, inputline, BUFFERSIZE);
442             if ( ! wcsncmp(inputline, L"load! ", 6) ) {
443                 force_rewrite = 1;
444                 del_range_chars(name, 4, 4);
445             }
446 
447             del_range_chars(name, 0, 4);
448             if ( ! strlen(name) ) {
449                 sc_error("Path to file to load is missing !");
450             } else if ( modflg && ! force_rewrite ) {
451                 sc_error("Changes were made since last save. Use '!' to force the load");
452             } else {
453                 #ifdef NO_WORDEXP
454                 name_ok = 1;
455                 #else
456                 wordexp(name, &p, 0);
457                 if ( p.we_wordc < 1 ) {
458                     sc_error("Failed expanding filepath");
459 
460                 } else if ( (len = strlen(p.we_wordv[0])) >= sizeof(name) ) {
461                     sc_error("File path too long");
462                     wordfree(&p);
463                 } else {
464                     memcpy(name, p.we_wordv[0], len+1);
465                     name_ok = 1;
466                     wordfree(&p);
467                 }
468                 #endif
469             }
470 
471             if ( name_ok ) {
472                 if ( ! file_exists(name)) {
473                     sc_error("File %s does not exists!", name);
474                 } else {
475                     delete_structures();
476                     create_structures();
477                     readfile(name, 0);
478 
479                     if (! get_conf_int("nocurses")) {
480                       ui_show_header();
481                     }
482                 }
483             }
484         } else if ( ! wcsncmp(inputline, L"hiderow ", 8) ||
485                     ! wcsncmp(inputline, L"showrow ", 8) ||
486                     ! wcsncmp(inputline, L"showcol ", 8) ||
487                     ! wcsncmp(inputline, L"hidecol ", 8)
488                   ) {
489             send_to_interp(inputline);
490 
491         } else if ( ! wcsncmp(inputline, L"showrows", 8) ) {
492             if (p != -1) { // only continue if there is a selected range
493                 int r, arg;
494                 sr = get_range_by_pos(p);
495                 r = sr->tlrow;
496                 arg = sr->brrow - sr->tlrow + 1;
497                 show_row(r, arg);
498             }
499 
500         } else if ( ! wcsncmp(inputline, L"showcols", 8) ) {
501             if (p != -1) { // only continue if there is a selected range
502                 int r, arg;
503                 sr = get_range_by_pos(p);
504                 r = sr->tlcol;
505                 arg = sr->brcol - sr->tlcol + 1;
506                 show_col(r, arg);
507             }
508 
509         // range lock / unlock
510         } else if ( ! wcsncmp(inputline, L"lock", 4) || ! wcsncmp(inputline, L"unlock", 6) ||
511                     ! wcsncmp(inputline, L"valueize", 8) ) {
512             int r = currow, c = curcol, rf = currow, cf = curcol;
513             if (p != -1) {
514                 c = sr->tlcol;
515                 r = sr->tlrow;
516                 rf = sr->brrow;
517                 cf = sr->brcol;
518             }
519             if ( ! wcsncmp(inputline, L"lock", 4) ) lock_cells(lookat(r, c), lookat(rf, cf));
520             else if ( ! wcsncmp(inputline, L"unlock", 6) ) unlock_cells(lookat(r, c), lookat(rf, cf));
521             else if ( ! wcsncmp(inputline, L"valueize", 8) ) valueize_area(r, c, rf, cf);
522 
523         } else if ( ! wcsncmp(inputline, L"datefmt", 7)) {
524             wcscpy(interp_line, inputline);
525 
526             int r = currow, c = curcol, rf = currow, cf = curcol;
527             if (p != -1) { // in case there is a range selected
528                 c = sr->tlcol;
529                 r = sr->tlrow;
530                 rf = sr->brrow;
531                 cf = sr->brcol;
532             }
533             wchar_t cline [BUFFERSIZE];
534             wcscpy(cline, interp_line);
535             int found = wstr_in_wstr(interp_line, L"\"");
536             if (found != -1) {
537                 del_range_wchars(cline, 0, found-1);
538                 swprintf(interp_line, BUFFERSIZE, L"datefmt %s%d:", coltoa(c), r);
539                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d %ls", coltoa(cf), rf, cline);
540                 send_to_interp(interp_line);
541             }
542 
543         } else if ( ! wcsncmp(inputline, L"sort ", 5) ) {
544             wcscpy(interp_line, inputline);
545             if (p != -1) { // in case there is a range selected
546                 wchar_t cline [BUFFERSIZE];
547                 wcscpy(cline, interp_line);
548                 int found = wstr_in_wstr(interp_line, L"\"");
549                 if (found != -1) {
550                     del_range_wchars(cline, 0, found-1);
551                     swprintf(interp_line, BUFFERSIZE, L"sort %s%d:", coltoa(sr->tlcol), sr->tlrow);
552                     swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d %ls", coltoa(sr->brcol), sr->brrow, cline);
553                 }
554             }
555             sc_info("Sorting..");
556             send_to_interp(interp_line);
557             sc_info("Done.");
558 
559         } else if ( ! wcsncmp(inputline, L"subtotal ", 9) ) {
560             int r = currow, c = curcol, rf = currow, cf = curcol, pos, cancel = 0;
561             if (p != -1) {
562                 c = sr->tlcol;
563                 r = sr->tlrow;
564                 rf = sr->brrow;
565                 cf = sr->brcol;
566             }
567             if (any_locked_cells(r, c, rf, cf)) {
568                 sc_error("Locked cells encountered. Nothing changed");
569             } else {
570                 wchar_t line [BUFFERSIZE];
571                 wcscpy(line, inputline);
572                 del_range_wchars(line, 0, 8);
573                 if (
574                     (pos = wstr_in_wstr(line, L"@sum")) != -1 ||
575                     (pos = wstr_in_wstr(line, L"@avg")) != -1 ||
576                     (pos = wstr_in_wstr(line, L"@max")) != -1 ||
577                     (pos = wstr_in_wstr(line, L"@min")) != -1 ) {
578                     add_wchar(line, L'\"', pos);
579                     add_wchar(line, L'\"', pos+5);
580                 } else if (
581                     (pos = wstr_in_wstr(line, L"@prod")) != -1) {
582                     add_wchar(line, L'\"', pos);
583                     add_wchar(line, L'\"', pos+6);
584                 } else if (
585                     (pos = wstr_in_wstr(line, L"@count"))  != -1) {
586                     add_wchar(line, L'\"', pos);
587                     add_wchar(line, L'\"', pos+7);
588                 } else if (
589                     (pos = wstr_in_wstr(line, L"@stddev")) != -1) {
590                     add_wchar(line, L'\"', pos);
591                     add_wchar(line, L'\"', pos+8);
592                 } else {
593                     sc_error("Please specify a function to apply the subtotals");
594                     cancel = 1;
595                 }
596                 if (!cancel) {
597                     swprintf(interp_line, BUFFERSIZE, L"subtotal %s%d:", coltoa(c), r);
598                     swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d ", coltoa(cf), rf);
599                     swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", line);
600                     send_to_interp(interp_line);
601                     unselect_ranges();
602                 }
603             }
604 
605         } else if ( ! wcsncmp(inputline, L"freezecol", 9) ) {
606             if (p != -1) {
607                 swprintf(interp_line, BUFFERSIZE, L"freeze %s:", coltoa(sr->tlcol));
608                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s", coltoa(sr->brcol));
609             } else if (! wcscmp(inputline, L"freezecol")) {
610                 swprintf(interp_line, BUFFERSIZE, L"freeze %s", coltoa(curcol));
611             } else
612                 swprintf(interp_line, BUFFERSIZE, L"freeze %ls", &inputline[9]);
613             send_to_interp(interp_line);
614 
615         } else if ( ! wcsncmp(inputline, L"freezerow", 9) ) {
616             if (p != -1) {
617                 swprintf(interp_line, BUFFERSIZE, L"freeze %d:%d", sr->tlrow, sr->brrow);
618             } else if (! wcscmp(inputline, L"freezerow")) {
619                 swprintf(interp_line, BUFFERSIZE, L"freeze %d", currow);
620             } else
621                 swprintf(interp_line, BUFFERSIZE, L"freeze %ls", &inputline[9]);
622             send_to_interp(interp_line);
623 
624         } else if ( ! wcsncmp(inputline, L"unfreezecol", 11) ) {
625             if (p != -1) {
626                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %s:", coltoa(sr->tlcol));
627                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s", coltoa(sr->brcol));
628             } else if (! wcscmp(inputline, L"unfreezecol")) {
629                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %s", coltoa(curcol));
630             } else
631                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %ls", &inputline[11]);
632             send_to_interp(interp_line);
633 
634         } else if ( ! wcsncmp(inputline, L"unfreezerow", 11) ) {
635             if (p != -1) {
636                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %d:%d", sr->tlrow, sr->brrow);
637             } else if (! wcscmp(inputline, L"unfreezerow")) {
638                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %d", currow);
639             } else
640                 swprintf(interp_line, BUFFERSIZE, L"unfreeze %ls", &inputline[11]);
641             send_to_interp(interp_line);
642 
643         } else if ( ! wcsncmp(inputline, L"addfilter", 9) ) {
644             wchar_t cline [BUFFERSIZE];
645             char line [BUFFERSIZE];
646             wcscpy(cline, inputline);
647             int found;
648             if ((found = wstr_in_wstr(cline, L"\"")) != -1) {
649                 del_range_wchars(cline, wcslen(cline), wcslen(cline));
650                 del_range_wchars(cline, 0, found);
651                 wcstombs(line, cline, BUFFERSIZE);
652                 add_filter(line);
653                 line[strlen(line)-1]='\0'; // remove last "
654                 sc_info("Added filter: %s", line);
655             }
656 
657         } else if ( ! wcsncmp(inputline, L"delfilter ", 10) ) {
658             wchar_t cline [BUFFERSIZE];
659             char line [BUFFERSIZE];
660             wcscpy(cline, inputline);
661             del_range_wchars(cline, 0, 9);
662             wcstombs(line, cline, BUFFERSIZE);
663             int id = atoi(line);
664             if (del_filter(id) == 0) sc_info("Removed filter: %d", id);
665 
666         } else if ( ! wcsncmp(inputline, L"delfilters", 10) ) {
667             if (free_filters() == 0) sc_info("Removed filters");
668 
669         } else if ( ! wcsncmp(inputline, L"filteron", 8) ) {
670             wcscpy(interp_line, inputline);
671             if ( ! wcscmp(inputline, L"filteron") && p == -1) { // If there is no selected range and no range in inputline passed
672                 sc_error("Please specify a range or select one");
673             } else if (p != -1) {
674                 wchar_t cline [BUFFERSIZE];
675                 wcscpy(cline, interp_line);
676                 swprintf(interp_line, BUFFERSIZE, L"filteron %s%d:", coltoa(sr->tlcol), sr->tlrow);
677                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d", coltoa(sr->brcol), sr->brrow);
678                 send_to_interp(interp_line);
679             } else { // no range selected. range passed in inputline
680                 send_to_interp(interp_line);
681             }
682 
683         } else if ( ! wcsncmp(inputline, L"filteroff", 9) ) {
684             disable_filters();
685 
686         } else if ( ! wcsncmp(inputline, L"hiddenrows", 10)) {
687             show_hiddenrows();
688 
689         } else if ( ! wcsncmp(inputline, L"hiddencols", 10)) {
690             show_hiddencols();
691 
692         } else if ( ! wcsncmp(inputline, L"showfilters", 11)) {
693             show_filters();
694 
695         } else if ( ! wcsncmp(inputline, L"int ", 4) ) { // send cmd to interpreter
696             wcscpy(interp_line, inputline);
697             del_range_wchars(interp_line, 0, 3);
698             send_to_interp(interp_line);
699 
700         } else if ( ! wcsncmp(inputline, L"fill ", 5) ) {
701             interp_line[0]=L'\0';
702             int r = currow, c = curcol, rf = currow, cf = curcol;
703             if (p != -1) {
704                 c = sr->tlcol;
705                 r = sr->tlrow;
706                 rf = sr->brrow;
707                 cf = sr->brcol;
708                 swprintf(interp_line, BUFFERSIZE, L"fill %s%d:", coltoa(c), r);
709                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d ", coltoa(cf), rf);
710             }
711 
712             if (any_locked_cells(r, c, rf, cf)) {
713                 swprintf(interp_line, BUFFERSIZE, L"");
714                 sc_error("Locked cells encountered. Nothing changed");
715             } else {
716                 if (p != -1)
717                     swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", &inputline[5]);
718                 else
719                     swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", inputline);
720                 send_to_interp(interp_line);
721             }
722 
723         } else if ( ! wcsncmp(inputline, L"formatrow ", 10) ) {
724             int r = currow, rf = currow, i;
725             if (p != -1) {
726                 r = sr->tlrow;
727                 rf = sr->brrow;
728             }
729 #ifdef UNDO
730             int changed = 0, fmt_ori;
731             create_undo_action();
732 #endif
733             for (i=r; i<=rf;i++) {
734 #ifdef UNDO
735                 fmt_ori = row_format[i];
736                 add_undo_row_format(i, 'R', row_format[i]);
737 #endif
738                 swprintf(interp_line, BUFFERSIZE, L"format %d %ls", i, &inputline[10]);
739                 send_to_interp(interp_line);
740 #ifdef UNDO
741                 if (fmt_ori != row_format[i]) changed = 1;
742                 add_undo_row_format(i, 'A', row_format[i]);
743 #endif
744             }
745 #ifdef UNDO
746             if (! changed) dismiss_undo_item(NULL);
747             else end_undo_action();
748 #endif
749 
750         } else if ( ! wcsncmp(inputline, L"formatcol ", 10) ) {
751             int c = curcol, cf = curcol, i;
752             if (p != -1) {
753                 c = sr->tlcol;
754                 cf = sr->brcol;
755             }
756 #ifdef UNDO
757             int changed = 0;
758             int fwidth_ori;
759             int precision_ori;
760             int realfmt_ori;
761             create_undo_action();
762 #endif
763             for (i=c; i<=cf;i++) {
764 #ifdef UNDO
765                 fwidth_ori = fwidth[i];
766                 precision_ori = precision[i];
767                 realfmt_ori = realfmt[i];
768                 add_undo_col_format(i, 'R', fwidth[i], precision[i], realfmt[i]);
769 #endif
770                 swprintf(interp_line, BUFFERSIZE, L"format %s", coltoa(i));
771                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L" %ls", &inputline[10]);
772                 send_to_interp(interp_line);
773 #ifdef UNDO
774                 if (fwidth[i] != fwidth_ori || precision[i] != precision_ori || realfmt[i] != realfmt_ori) changed = 1;
775                 add_undo_col_format(i, 'A', fwidth[i], precision[i], realfmt[i]);
776 #endif
777             }
778 #ifdef UNDO
779             if (! changed) dismiss_undo_item(NULL);
780             else end_undo_action();
781 #endif
782 
783         } else if ( ! wcsncmp(inputline, L"format ", 7) ) {
784             int r = currow, c = curcol, rf = currow, cf = curcol;
785             if (p != -1) {
786                 c = sr->tlcol;
787                 r = sr->tlrow;
788                 rf = sr->brrow;
789                 cf = sr->brcol;
790                 swprintf(interp_line, BUFFERSIZE, L"fmt %s%d:", coltoa(c), r);
791                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d", coltoa(cf), rf);
792             } else
793                 swprintf(interp_line, BUFFERSIZE, L"fmt %s%d", coltoa(c), r);
794 
795             if (any_locked_cells(r, c, rf, cf)) {
796                 sc_error("Locked cells encountered. Nothing changed");
797             } else {
798                 int l = wcslen(interp_line);
799                 swprintf(interp_line + l, BUFFERSIZE, L"%ls", inputline);
800                 del_range_wchars(interp_line, l, l + 5);
801                 #ifdef UNDO
802                 create_undo_action();
803                 copy_to_undostruct(r, c, rf, cf, UNDO_DEL, IGNORE_DEPS, NULL);
804                 #endif
805                 send_to_interp(interp_line);
806                 #ifdef UNDO
807                 copy_to_undostruct(r, c, rf, cf, UNDO_ADD, IGNORE_DEPS, NULL);
808                 end_undo_action();
809                 #endif
810             }
811 
812         } else if ( ! wcsncmp(inputline, L"ccopy", 5) ) {
813             int r = currow, c = curcol, rf = currow, cf = curcol;
814             if (p != -1) {
815                 c = sr->tlcol;
816                 r = sr->tlrow;
817                 rf = sr->brrow;
818                 cf = sr->brcol;
819             }
820             swprintf(interp_line, BUFFERSIZE, L"ccopy %s%d:", coltoa(c), r);
821             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d", coltoa(cf), rf);
822             send_to_interp(interp_line);
823 
824         } else if ( ! wcsncmp(inputline, L"strtonum", 8) ) {
825             int r = currow, c = curcol, rf = currow, cf = curcol;
826             if (p != -1) {
827                 c = sr->tlcol;
828                 r = sr->tlrow;
829                 rf = sr->brrow;
830                 cf = sr->brcol;
831             }
832             swprintf(interp_line, BUFFERSIZE, L"strtonum %s%d:", coltoa(c), r);
833             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d", coltoa(cf), rf);
834             send_to_interp(interp_line);
835 
836         } else if ( ! wcsncmp(inputline, L"cpaste", 6) ) {
837             swprintf(interp_line, BUFFERSIZE, L"cpaste");
838             send_to_interp(interp_line);
839 
840         } else if ( ! wcsncmp(inputline, L"cellcolor ", 10) ) {
841             #ifdef USECOLORS
842             interp_line[0]=L'\0';
843             wchar_t line [BUFFERSIZE];
844             wcscpy(line, inputline);
845             del_range_wchars(line, 0, 9);
846             swprintf(interp_line, BUFFERSIZE, L"cellcolor ");
847             if (p != -1) {
848                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L" %s%d:", coltoa(sr->tlcol), sr->tlrow);
849                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d ", coltoa(sr->brcol), sr->brrow);
850             }
851             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", line);
852             send_to_interp(interp_line);
853             #else
854             sc_error("Color support not compiled in");
855             chg_mode('.');
856             inputline[0] = L'\0';
857             #endif
858 
859         } else if ( ! wcsncmp(inputline, L"unformat", 8) ) {
860             #ifdef USECOLORS
861             interp_line[0]=L'\0';
862             wchar_t line [BUFFERSIZE];
863             wcscpy(line, inputline);
864             del_range_wchars(line, 0, 7);
865             swprintf(interp_line, BUFFERSIZE, L"unformat");
866             if (p != -1) {
867                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L" %s%d:", coltoa(sr->tlcol), sr->tlrow);
868                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d ", coltoa(sr->brcol), sr->brrow);
869             }
870             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", line);
871             send_to_interp(interp_line);
872             #else
873             sc_error("Color support not compiled in");
874             chg_mode('.');
875             inputline[0] = L'\0';
876             #endif
877 
878         } else if ( ! wcsncmp(inputline, L"color ", 6) ) {
879             #ifdef USECOLORS
880             char line [BUFFERSIZE];
881             wcstombs(line, inputline, BUFFERSIZE);
882             del_range_chars(line, 0, 5);
883             chg_color(line);
884             #else
885             sc_error("Color support not compiled in");
886             chg_mode('.');
887             inputline[0] = '\0';
888             #endif
889 
890         }  else if ( ! wcsncmp(inputline, L"trigger ", 8) ) {
891             interp_line[0]=L'\0';
892             wchar_t line [BUFFERSIZE];
893             wcscpy(line, inputline);
894             del_range_wchars(line, 0, 7);
895             swprintf(interp_line, BUFFERSIZE, L"trigger ");
896             if (p != -1) {
897                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L" %s%d:", coltoa(sr->tlcol), sr->tlrow);
898                 swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d ", coltoa(sr->brcol), sr->brrow);
899             }
900             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%ls", line);
901             send_to_interp(interp_line);
902 
903         }  else if ( ! wcsncmp(inputline, L"untrigger ", 10) ) {
904             wcscpy(interp_line, inputline);
905             send_to_interp(interp_line);
906 
907         }  else if ( ! wcsncmp(inputline, L"set ", 4) ) {
908             wchar_t line [BUFFERSIZE];
909             wcscpy(line, inputline);
910             del_range_wchars(line, 0, 3);
911 
912             wchar_t * l;
913             char oper[BUFFERSIZE];
914             if ((l = wcschr(line, L' ')) != NULL) l[0] = L'\0';
915             if ((l = wcschr(line, L'=')) != NULL) l[0] = L'\0';
916 
917             wcscpy(interp_line, inputline);
918             send_to_interp(interp_line);
919 
920             wcstombs(oper, line, BUFFERSIZE);
921             if (get_conf_value(oper)) {
922                 sc_info("Config value changed: %s", oper);
923             } else if (strlen(oper) > 2 && ! wcsncmp(inputline, L"set no", 6)) {
924                 sc_info("Config value changed: %s", &oper[2]);
925             }
926 
927         } else if ( ! wcsncmp(inputline, L"pad ", 4) ) {
928             int c = curcol, cf = curcol;
929             if (p != -1) { // in case there is a range selected
930                 c = sr->tlcol;
931                 cf = sr->brcol;
932             }
933             wcscpy(interp_line, inputline); // pad 5
934             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L" %s:", coltoa(c)); // pad 5 A:
935             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s", coltoa(cf));  // B
936             send_to_interp(interp_line);
937 
938         } else if ( ! wcsncmp(inputline, L"plot ", 5) ) {
939             int r = currow, c = curcol, rf = currow, cf = curcol;
940             if (p != -1) {
941                 c = sr->tlcol;
942                 r = sr->tlrow;
943                 rf = sr->brrow;
944                 cf = sr->brcol;
945             }
946             wchar_t aux[wcslen(inputline)+1];
947             wcscpy(aux, inputline);
948             del_range_wchars(aux, 0, 4);
949             swprintf(interp_line, BUFFERSIZE, L"plot \"%ls\" %s%d:", aux, coltoa(c), r);
950             swprintf(interp_line + wcslen(interp_line), BUFFERSIZE, L"%s%d", coltoa(cf), rf);
951             send_to_interp(interp_line);
952 
953         } else if ( ! wcsncmp(inputline, L"plotedit ", 9) ) {
954             wchar_t aux[wcslen(inputline)+1];
955             wcscpy(aux, inputline);
956             del_range_wchars(aux, 0, 8);
957             plotedit(aux);
958 
959         } else if ( ! wcscmp(inputline, L"set") ) {
960             char valores[get_dict_buffer_size(user_conf_d) + 1];
961             get_conf_values(valores);
962             ui_show_text(valores);
963 
964         } else if ( ! wcscmp(inputline, L"version") ) {
965             ui_show_text(rev);
966 
967         } else if ( ! wcscmp(inputline, L"showmaps") ) {
968             extern int len_maps;
969             char valores[MAXMAPITEM * len_maps];
970             get_mappings(valores);
971             ui_show_text(valores);
972 
973         } else if ( ! wcsncmp(inputline, L"nmap", 4) ||
974                     ! wcsncmp(inputline, L"imap", 4) ||
975                     ! wcsncmp(inputline, L"vmap", 4) ||
976                     ! wcsncmp(inputline, L"cmap", 4) ||
977                     ! wcsncmp(inputline, L"inoremap", 8) ||
978                     ! wcsncmp(inputline, L"nnoremap", 8) ||
979                     ! wcsncmp(inputline, L"vnoremap", 8) ||
980                     ! wcsncmp(inputline, L"cnoremap", 8) ||
981                     ! wcsncmp(inputline, L"iunmap", 6) ||
982                     ! wcsncmp(inputline, L"vunmap", 6) ||
983                     ! wcsncmp(inputline, L"cunmap", 6) ||
984                     ! wcsncmp(inputline, L"nunmap", 6) ) {
985             send_to_interp(inputline);
986 
987         } else if ( ! wcsncmp(inputline, L"!", 1) ) {
988             char line [BUFFERSIZE];
989             wcstombs(line, inputline, BUFFERSIZE);
990             int found = str_in_str(line, " ");
991             if (found == -1) found++;
992             del_range_chars(line, 0, found);
993             exec_cmd(line);
994 
995         } else if ( ! wcscmp(inputline, L"wq") ) {
996           wcscpy(inputline, L"x");
997           if (savefile() == 0) shall_quit = 1;
998 
999         } else if ( inputline[0] == L'w' ) {
1000           savefile();
1001 
1002         } else if ( ! wcsncmp(inputline, L"file ", 5) ) {
1003 
1004             char name [BUFFERSIZE];
1005             int name_ok = 0;
1006             #ifndef NO_WORDEXP
1007             size_t len;
1008             wordexp_t p;
1009             #endif
1010 
1011             wcstombs(name, inputline, BUFFERSIZE);
1012             del_range_chars(name, 0, 4);
1013 
1014             #ifdef NO_WORDEXP
1015             name_ok = 1;
1016             #else
1017             wordexp(name, &p, 0);
1018             if ( p.we_wordc < 1 ) {
1019                 sc_error("Failed to expand filename");
1020             } else if ( (len = strlen(p.we_wordv[0])) >= sizeof(name) ) {
1021                 sc_error("File path too long");
1022                 wordfree(&p);
1023             } else {
1024                 memcpy(name, p.we_wordv[0], len+1);
1025                 name_ok = 1;
1026                 wordfree(&p);
1027             }
1028             #endif
1029 
1030             if (name_ok) {
1031                 #ifdef AUTOBACKUP
1032                 // check if backup of curfile exists.
1033                 // if it exists, remove it.
1034                 if (strlen(curfile) && backup_exists(curfile)) remove_backup(curfile);
1035                 #endif
1036                 strncpy(curfile, name, PATHLEN - 1);
1037                 sc_info("File name set to \"%s\"", curfile);
1038             }
1039 
1040         } else if ( ! wcscmp(inputline, L"file") ) {
1041 
1042             if( ! *curfile ) {
1043                 sc_info("Current file has no name");
1044             } else {
1045                 sc_info("Current file: \"%s\"", curfile);
1046             }
1047 
1048         } else if ( inputline[0] == L'x' ) {
1049             if (savefile() == 0) shall_quit = 1;
1050 
1051         } else if ( ! wcscmp(inputline, L"fcopy") ) {
1052             fcopy("");
1053 
1054         } else if ( ! wcsncmp(inputline, L"fcopy ", 6)) {
1055 
1056             wchar_t line [BUFFERSIZE];
1057             wcscpy(line, inputline);
1058             del_range_wchars(line, 0, 5);
1059             char action[BUFFERSIZE];
1060             wcstombs(action, line, BUFFERSIZE);
1061             fcopy(action);
1062 
1063         } else if ( ! wcscmp(inputline, L"fsum") ) {
1064             fsum();
1065 
1066         } else if (
1067                 ! wcsncmp(inputline, L"e csv"  , 5) ||
1068                 ! wcsncmp(inputline, L"e! csv" , 6) ||
1069                 ! wcsncmp(inputline, L"e tex"  , 5) ||
1070                 ! wcsncmp(inputline, L"e! tex" , 6) ||
1071                 ! wcsncmp(inputline, L"e tab"  , 5) ||
1072                 ! wcsncmp(inputline, L"e! tab" , 6) ||
1073                 ! wcsncmp(inputline, L"e mkd"  , 4) ||
1074                 ! wcsncmp(inputline, L"e! mkd" , 5) ||
1075                 ! wcsncmp(inputline, L"e txt" , 5) ||
1076                 ! wcsncmp(inputline, L"e! txt" , 6) ) {
1077                 do_export( p == -1 ? 0 : sr->tlrow, p == -1 ? 0 : sr->tlcol,
1078                 p == -1 ? maxrow : sr->brrow, p == -1 ? maxcol : sr->brcol);
1079 
1080         } else if (
1081                 ! wcsncmp(inputline, L"e xlsx"  , 6) ||
1082                 ! wcsncmp(inputline, L"e! xlsx" , 7)) {
1083                 #ifndef XLSX_EXPORT
1084                 sc_error("XLSX export support not compiled in");
1085                 #else
1086                 char linea[BUFFERSIZE];
1087                 char filename[PATHLEN] = "";
1088                 int force_rewrite = 0;
1089                 if (inputline[1] == L'!') force_rewrite = 1;
1090                 wcstombs(linea, inputline, BUFFERSIZE); // Use new variable to keep command history untouched
1091                 del_range_chars(linea, 0, 1 + force_rewrite); // Remove 'e' or 'e!' from inputline
1092 
1093                 // Get path and file name to write.
1094                 // Use parameter if any.
1095                 if (strlen(linea) > 5) {   // ex. 'xlsx '
1096                     del_range_chars(linea, 0, 4); // remove 'xlsx'
1097                     strcpy(filename, linea);
1098                     // Use curfile name and '.xlsx' extension
1099                     // Remove current '.sc' extension if necessary
1100                 } else if (curfile[0]) {
1101                     strcpy(filename, curfile);
1102                     char * ext = strrchr(filename, '.');
1103                     if (ext != NULL) del_range_chars(filename, strlen(filename) - strlen(ext), strlen(filename)-1);
1104                     sprintf(filename + strlen(filename), ".xlsx");
1105                 } else {
1106                     sc_error("No filename specified !");
1107                 }
1108 
1109                 if (strlen(filename) > 0 && ! force_rewrite && file_exists(filename)) {
1110                     sc_error("File %s already exists. Use \"!\" to force rewrite.", filename);
1111 
1112                 #ifdef AUTOBACKUP
1113                     // check if backup of filename exists.
1114                     // if it exists and '!' is set, remove it.
1115                     // if it exists and curfile = fname, remove it.
1116                     // else return.
1117                 } else if (strlen(filename) && backup_exists(filename)
1118                     && !force_rewrite && !(strlen(curfile) && !strcmp(curfile, filename))) {
1119                     sc_error("Backup file of %s exists. Use \"!\" to force the write process.", filename);
1120                 #endif
1121                 } else if (strlen(filename)) {
1122                     #ifdef AUTOBACKUP
1123                     if (backup_exists(filename)) remove_backup(filename);
1124                     #endif
1125                     if (export_xlsx(
1126                     filename, p == -1 ? 0 : sr->tlrow, p == -1 ? 0 : sr->tlcol,
1127                     p == -1 ? maxrow : sr->brrow, p == -1 ? maxcol : sr->brcol) == 0)
1128                     sc_info("File \"%s\" written", filename);
1129                 }
1130                 #endif
1131 
1132         } else {
1133             sc_error("COMMAND NOT FOUND !");
1134         }
1135 
1136 #ifdef HISTORY_FILE
1137         /*
1138          * if exists in history an item with same text to the command typed
1139          * (counting from the second position) it is moved to the beginning of list.
1140          * (first element in list means last command executed)
1141          */
1142         del_item_from_history(commandline_history, 0);
1143         int moved = move_item_from_history_by_str(commandline_history, inputline, -1);
1144         if (! moved) add(commandline_history, inputline);
1145         commandline_history->pos = 0;
1146 #endif
1147 
1148         chg_mode('.');
1149         inputline[0]=L'\0';
1150         inputline_pos = 0; //ADDED 08/10/2018
1151         set_comp(0); // unmark tab completion
1152         ui_update(TRUE);
1153     }
1154     return;
1155 }
1156 
1157 /**
1158  * \brief TODO Document ins_in_line()
1159  *
1160  * \param[in] d
1161  *
1162  * \return none
1163  */
1164 
ins_in_line(wint_t d)1165 void ins_in_line(wint_t d) {
1166     add_wchar(inputline, (wchar_t) d, real_inputline_pos++);
1167     inputline_pos += wcwidth((wchar_t) d);
1168     return;
1169 }
1170