global.c 60.3 KB
Newer Older
Chris Allegretta's avatar
Chris Allegretta committed
1
/**************************************************************************
2
 *   global.c  --  This file is part of GNU nano.                         *
Chris Allegretta's avatar
Chris Allegretta committed
3
 *                                                                        *
4
 *   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,  *
5
 *   2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc.    *
6
7
 *   Copyright (C) 2014, 2015, 2016 Benno Schulenberg                     *
 *                                                                        *
8
9
10
11
 *   GNU nano is free software: you can redistribute it and/or modify     *
 *   it under the terms of the GNU General Public License as published    *
 *   by the Free Software Foundation, either version 3 of the License,    *
 *   or (at your option) any later version.                               *
Chris Allegretta's avatar
Chris Allegretta committed
12
 *                                                                        *
13
14
15
16
 *   GNU nano is distributed in the hope that it will be useful,          *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty          *
 *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.              *
 *   See the GNU General Public License for more details.                 *
Chris Allegretta's avatar
Chris Allegretta committed
17
18
 *                                                                        *
 *   You should have received a copy of the GNU General Public License    *
19
 *   along with this program.  If not, see http://www.gnu.org/licenses/.  *
Chris Allegretta's avatar
Chris Allegretta committed
20
21
22
 *                                                                        *
 **************************************************************************/

23
24
#include "proto.h"

25
#include <ctype.h>
26
#include <string.h>
27
28
#include <strings.h>
#include "assert.h"
Chris Allegretta's avatar
Chris Allegretta committed
29

30
31
/* Global variables. */
#ifndef NANO_TINY
32
33
volatile sig_atomic_t sigwinch_counter = 0;
	/* Is incremented by the handler whenever a SIGWINCH occurs. */
34
35
#endif

36
#ifdef __linux__
37
38
bool console;
	/* Whether we're running on a Linux VC (TRUE) or under X (FALSE). */
39
40
#endif

41
42
bool meta_key;
	/* Whether the current keystroke is a Meta key. */
43
44
bool shift_held;
	/* Whether Shift was being held together with a movement key. */
45
bool focusing = TRUE;
46
	/* Whether an update of the edit window should center the cursor. */
47
48
49

message_type lastmessage = HUSH;
	/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
50

51
int controlleft, controlright, controlup, controldown;
52
#ifndef NANO_TINY
53
54
int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
55
56
#endif

57
#ifndef DISABLE_WRAPJUSTIFY
58
59
ssize_t fill = 0;
	/* The column where we will wrap lines. */
60
ssize_t wrap_at = -CHARS_FROM_EOL;
61
62
63
64
65
66
67
68
	/* The position where we will wrap lines.  fill is equal to this
	 * if it's greater than zero, and equal to (COLS + this) if it
	 * isn't. */
#endif

char *last_search = NULL;
	/* The last string we searched for. */

69
70
71
char *present_path = NULL;
	/* The current browser directory when trying to do tab completion. */

72
unsigned flags[4] = {0, 0, 0, 0};
73
74
75
76
77
78
	/* Our flag containing the states of all global options. */
WINDOW *topwin;
	/* The top portion of the window, where we display the version
	 * number of nano, the name of the current file, and whether the
	 * current file has been modified. */
WINDOW *edit;
79
	/* The middle portion of the window, i.e. the edit window, where
80
81
82
83
84
85
	 * we display the current file we're editing. */
WINDOW *bottomwin;
	/* The bottom portion of the window, where we display statusbar
	 * messages, the statusbar prompt, and a list of shortcuts. */
int editwinrows = 0;
	/* How many rows does the edit window take up? */
86
int maxrows = 0;
87
	/* How many usable lines there are (due to soft wrapping). */
88
89
90

filestruct *cutbuffer = NULL;
	/* The buffer where we store cut text. */
91
filestruct *cutbottom = NULL;
92
	/* The last line in the cutbuffer. */
93
partition *filepart = NULL;
94
	/* The "partition" where we store a portion of the current file. */
95
openfilestruct *openfile = NULL;
96
	/* The list of all open file buffers. */
97

98
99
100
101
#ifndef NANO_TINY
char *matchbrackets = NULL;
	/* The opening and closing brackets that can be found by bracket
	 * searches. */
102
char *whitespace = NULL;
103
	/* The characters used when visibly showing tabs and spaces. */
104
int whitespace_len[2];
105
	/* The length in bytes of these characters. */
106
107
#endif

108
#ifndef DISABLE_JUSTIFY
109
110
111
112
113
114
115
char *punct = NULL;
	/* The closing punctuation that can end sentences. */
char *brackets = NULL;
	/* The closing brackets that can follow closing punctuation and
	 * can end sentences. */
char *quotestr = NULL;
	/* The quoting string.  The default value is set in main(). */
116
#ifdef HAVE_REGEX_H
117
118
119
regex_t quotereg;
	/* The compiled regular expression from the quoting string. */
int quoterc;
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
120
	/* Whether it was compiled successfully. */
121
122
char *quoteerr = NULL;
	/* The error message, if it didn't. */
123
#else
124
125
size_t quotelen;
	/* The length of the quoting string in bytes. */
Chris Allegretta's avatar
Chris Allegretta committed
126
#endif
127
#endif /* !DISABLE_JUSTIFY */
128

129
130
131
char *word_chars = NULL;
	/* Nonalphanumeric characters that also form words. */

132
bool nodelay_mode = FALSE;
133
	/* Are we checking for a cancel wile doing something? */
134

135
char *answer = NULL;
136
	/* The answer string used by the statusbar prompt. */
Chris Allegretta's avatar
Chris Allegretta committed
137

138
ssize_t tabsize = -1;
139
	/* The width of a tab in spaces.  The default is set in main(). */
140

141
142
143
#ifndef NANO_TINY
char *backup_dir = NULL;
	/* The directory where we store backup files. */
144

145
const char *locking_prefix = ".";
146
	/* Prefix of how to store the vim-style lock file. */
147
const char *locking_suffix = ".swp";
148
	/* Suffix of the vim-style lock file. */
149
#endif
150
#ifndef DISABLE_OPERATINGDIR
151
152
153
154
155
char *operating_dir = NULL;
	/* The relative path to the operating directory, which we can't
	 * move outside of. */
char *full_operating_dir = NULL;
	/* The full path to it. */
156
157
#endif

158
#ifndef DISABLE_SPELLER
159
160
char *alt_speller = NULL;
	/* The command to use for the alternate spell checker. */
161
162
#endif

163
#ifndef DISABLE_COLOR
164
syntaxtype *syntaxes = NULL;
165
	/* The global list of color syntaxes. */
166
char *syntaxstr = NULL;
167
	/* The color syntax name specified on the command line. */
168
169
#endif

170
171
172
bool refresh_needed = FALSE;
	/* Did a command mangle enough of the buffer that we should
	 * repaint the screen? */
173

174
175
int currmenu = MMOST;
	/* The currently active menu, initialized to a dummy value. */
176
sc *sclist = NULL;
177
	/* The start of the shortcuts list. */
178
subnfunc *allfuncs = NULL;
179
	/* The start of the functions list. */
180
subnfunc *tailfunc;
181
	/* The last function in the list. */
182
subnfunc *exitfunc;
183
	/* A pointer to the special Exit/Close item. */
184
subnfunc *uncutfunc;
185
	/* A pointer to the special Uncut/Unjustify item. */
186

187
#ifndef DISABLE_HISTORIES
188
filestruct *search_history = NULL;
189
	/* The search string history list. */
190
filestruct *searchage = NULL;
191
	/* The top of the search string history list. */
192
filestruct *searchbot = NULL;
193
	/* The bottom of the search string history list. */
194
filestruct *replace_history = NULL;
195
	/* The replace string history list. */
196
filestruct *replaceage = NULL;
197
	/* The top of the replace string history list. */
198
filestruct *replacebot = NULL;
199
	/* The bottom of the replace string history list. */
200
poshiststruct *position_history = NULL;
201
	/* The cursor position history list. */
202
203
#endif

204
#ifdef HAVE_REGEX_H
205
206
207
208
209
regex_t search_regexp;
	/* The compiled regular expression to use in searches. */
regmatch_t regmatches[10];
	/* The match positions for parenthetical subexpressions, 10
	 * maximum, used in regular expression searches. */
Chris Allegretta's avatar
Chris Allegretta committed
210
#endif
211

212
int hilite_attribute = A_REVERSE;
213
	/* The curses attribute we use to highlight something. */
214
215
216
217
#ifndef DISABLE_COLOR
char* specified_color_combo[] = {};
	/* The color combinations as specified in the rcfile. */
#endif
218
int interface_color_pair[] = {};
219
	/* The processed color pairs for the interface elements. */
220

221
char *homedir = NULL;
222
	/* The user's home directory, from $HOME or /etc/passwd. */
223

224

225
/* Return the number of entries in the shortcut list for a given menu. */
226
size_t length_of_list(int menu)
227
{
228
    subnfunc *f;
229
    size_t i = 0;
230

231
    for (f = allfuncs; f != NULL; f = f->next)
232
	if ((f->menus & menu) && first_sc_for(menu, f->scfunc) != NULL)
233
	    i++;
234

235
236
237
    return i;
}

238
239
240
241
242
243
/* To make the functions and shortcuts lists clearer. */
#define VIEW  TRUE		/* Is allowed in view mode. */
#define NOVIEW  FALSE
#define BLANKAFTER  TRUE	/* A blank line after this one. */
#define TOGETHER  FALSE

244
/* Just throw this here. */
245
246
247
248
249
250
void case_sens_void(void)
{
}
void regexp_void(void)
{
}
251
252
253
void backwards_void(void)
{
}
254
255
256
void gototext_void(void)
{
}
257
#ifndef DISABLE_BROWSER
258
259
260
void to_files_void(void)
{
}
261
262
263
264
void goto_dir_void(void)
{
}
#endif
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
void dos_format_void(void)
{
}
void mac_format_void(void)
{
}
void append_void(void)
{
}
void prepend_void(void)
{
}
void backup_file_void(void)
{
}
280
281
282
void discard_buffer(void)
{
}
283
284
285
void new_buffer_void(void)
{
}
286
void flip_replace_void(void)
287
288
{
}
289
void flip_execute_void(void)
290
291
292
{
}

293
/* Add a function to the function list. */
294
void add_to_funcs(void (*func)(void), int menus, const char *desc, const char *help,
295
296
    bool blank_after, bool viewok)
{
297
    subnfunc *f = (subnfunc *)nmalloc(sizeof(subnfunc));
298
299
300
301
302
303

    if (allfuncs == NULL)
	allfuncs = f;
    else
	tailfunc->next = f;
    tailfunc = f;
304
305
306
307
308
309

    f->next = NULL;
    f->scfunc = func;
    f->menus = menus;
    f->desc = desc;
    f->viewok = viewok;
310
#ifndef DISABLE_HELP
311
312
313
314
315
    f->help = help;
    f->blank_after = blank_after;
#endif

#ifdef DEBUG
316
    fprintf(stderr, "Added func %ld (%s) for menus %x\n", (long)func, f->desc, menus);
317
#endif
318
319
}

320
/* Add a key combo to the shortcut list. */
321
void add_to_sclist(int menus, const char *scstring, void (*func)(void), int toggle)
Chris Allegretta's avatar
Chris Allegretta committed
322
{
323
    static sc *tailsc;
324
#ifndef NANO_TINY
325
    static int counter = 0;
326
#endif
327
    sc *s = (sc *)nmalloc(sizeof(sc));
328

329
330
331
332
333
334
335
336
337
    /* Start the list, or tack on the next item. */
    if (sclist == NULL)
	sclist = s;
    else
	tailsc->next = s;
    tailsc = s;
    s->next = NULL;

    /* Fill in the data. */
338
    s->menus = menus;
339
    s->scfunc = func;
340
#ifndef NANO_TINY
341
    s->toggle = toggle;
342
343
    if (toggle)
	s->ordinal = ++counter;
344
#endif
345
    assign_keyinfo(s, scstring);
346
347

#ifdef DEBUG
348
    fprintf(stderr, "Setting keycode to %d for shortcut \"%s\" in menus %x\n", s->keycode, scstring, s->menus);
349
#endif
Chris Allegretta's avatar
Chris Allegretta committed
350
351
}

352
/* Assign one function's shortcuts to another function. */
353
354
355
356
void replace_scs_for(void (*oldfunc)(void), void (*newfunc)(void))
{
    sc *s;

357
    for (s = sclist; s != NULL; s = s->next)
358
	if (s->scfunc == oldfunc)
359
360
361
	    s->scfunc = newfunc;
}

362
363
364
365
366
367
368
/* Return the first shortcut in the list of shortcuts that
 * matches the given func in the given menu. */
const sc *first_sc_for(int menu, void (*func)(void))
{
    const sc *s;

    for (s = sclist; s != NULL; s = s->next)
369
	if ((s->menus & menu) && s->scfunc == func)
370
371
372
373
374
375
376
377
378
	    return s;

#ifdef DEBUG
    fprintf(stderr, "Whoops, returning null given func %ld in menu %x\n", (long)func, menu);
#endif
    /* Otherwise... */
    return NULL;
}

Chris Allegretta's avatar
Chris Allegretta committed
379
/* Return the given menu's first shortcut sequence, or the default value
380
 * (2nd arg).  Assumes currmenu for the menu to check. */
381
int sc_seq_or(void (*func)(void), int defaultval)
Chris Allegretta's avatar
Chris Allegretta committed
382
383
384
{
    const sc *s = first_sc_for(currmenu, func);

385
    if (s) {
386
	meta_key = s->meta;
387
	return s->keycode;
388
    }
Chris Allegretta's avatar
Chris Allegretta committed
389
390
391
392
    /* else */
    return defaultval;
}

393
394
395
396
397
398
399
400
401
402
403
/* Return a pointer to the function that is bound to the given key. */
functionptrtype func_from_key(int *kbinput)
{
    const sc *s = get_shortcut(kbinput);

    if (s)
	return s->scfunc;
    else
	return NULL;
}

404
405
/* Set the string and its corresponding keycode for the given shortcut s. */
void assign_keyinfo(sc *s, const char *keystring)
406
{
407
    s->keystr = keystring;
408
    s->meta = (keystring[0] == 'M');
409

410
411
    assert(strlen(keystring) > 1 && (!s->meta || strlen(keystring) > 2));

412
413
414
    if (keystring[0] == '^') {
	if (strcasecmp(keystring, "^Space") == 0)
	    s->keycode = 0;
415
	else if (strcasecmp(keystring, "^Left") == 0 ||
416
		strcasecmp(keystring, "^\xE2\x86\x90") == 0)
417
	    s->keycode = CONTROL_LEFT;
418
	else if (strcasecmp(keystring, "^Right") == 0 ||
419
		strcasecmp(keystring, "^\xE2\x86\x92") == 0)
420
	    s->keycode = CONTROL_RIGHT;
421
	else if (strcasecmp(keystring, "^Up") == 0 ||
422
		strcasecmp(keystring, "^\xE2\x86\x91") == 0)
423
	    s->keycode = CONTROL_UP;
424
	else if (strcasecmp(keystring, "^Down") == 0 ||
425
		strcasecmp(keystring, "^\xE2\x86\x93") == 0)
426
427
428
	    s->keycode = CONTROL_DOWN;
	else
	    s->keycode = keystring[1] - 64;
429
    } else if (s->meta) {
430
	s->keycode = tolower((int)keystring[2]);
431
432
433
	if (strcasecmp(keystring, "M-Space") == 0)
	    s->keycode = (int)' ';
    } else if (keystring[0] == 'F')
434
	s->keycode = KEY_F0 + atoi(&keystring[1]);
435
    /* Catch the strings that don't bind as easily as we'd like. */
436
    else if (!strcasecmp(keystring, "Up"))
437
	s->keycode = KEY_UP;
438
    else if (!strcasecmp(keystring, "Down"))
439
	s->keycode = KEY_DOWN;
440
    else if (!strcasecmp(keystring, "Left"))
441
	s->keycode = KEY_LEFT;
442
    else if (!strcasecmp(keystring, "Right"))
443
	s->keycode = KEY_RIGHT;
444
    else if (!strcasecmp(keystring, "Ins"))
445
	s->keycode = KEY_IC;
446
    else if (!strcasecmp(keystring, "Del"))
447
	s->keycode = KEY_DC;
448
    else if (!strcasecmp(keystring, "Bsp"))
449
450
451
452
	s->keycode = KEY_BACKSPACE;
    /* The Tab and Enter keys don't actually produce special codes
     * but the exact integer values of ^I and ^M.  Rebinding the
     * latter therefore also rebinds Tab and Enter. */
453
    else if (!strcasecmp(keystring, "Tab"))
454
	s->keycode = TAB_CODE;
455
    else if (!strcasecmp(keystring, "Enter"))
456
	s->keycode = KEY_ENTER;
457
    else if (!strcasecmp(keystring, "PgUp"))
458
	s->keycode = KEY_PPAGE;
459
    else if (!strcasecmp(keystring, "PgDn"))
460
	s->keycode = KEY_NPAGE;
461
    else if (!strcasecmp(keystring, "Home"))
462
	s->keycode = KEY_HOME;
463
    else if (!strcasecmp(keystring, "End"))
464
	s->keycode = KEY_END;
465
466
467
468
469
470
471
472
}

#ifdef DEBUG
void print_sclist(void)
{
    sc *s;
    const subnfunc *f;

473
    for (s = sclist; s != NULL; s = s->next) {
474
	f = sctofunc(s);
475
	if (f)
476
	    fprintf(stderr, "Shortcut \"%s\", function: %s, menus %x\n", s->keystr, f->desc, f->menus);
477
	else
478
	    fprintf(stderr, "Hmm, didn't find a func for \"%s\"\n", s->keystr);
479
480
481
482
    }
}
#endif

483
484
/* These four tags are used elsewhere too, so they are global. */
/* TRANSLATORS: Try to keep the next fifteen strings at most 10 characters. */
485
486
const char *exit_tag = N_("Exit");
const char *close_tag = N_("Close");
487
const char *uncut_tag = N_("Uncut Text");
488
#ifndef DISABLE_JUSTIFY
489
490
const char *unjust_tag = N_("Unjustify");
#endif
491

492
493
/* Initialize the list of functions and the list of shortcuts. */
void shortcut_init(void)
494
{
495
    const char *read_file_tag = N_("Read File");
496
    const char *whereis_tag = N_("Where Is");
497
498
    const char *replace_tag = N_("Replace");
    const char *gotoline_tag = N_("Go To Line");
499
500
    const char *prev_line_tag = N_("Prev Line");
    const char *next_line_tag = N_("Next Line");
501
502
    const char *prev_page_tag = N_("Prev Page");
    const char *next_page_tag = N_("Next Page");
503
#ifndef DISABLE_JUSTIFY
504
    const char *justify_tag = N_("Justify");
505
    const char *fulljustify_tag = N_("FullJstify");
506
#endif
507
    const char *refresh_tag = N_("Refresh");
508
509
    /* TRANSLATORS: Try to keep this string at most 12 characters. */
    const char *whereis_next_tag = N_("WhereIs Next");
510

511
#ifndef DISABLE_HELP
512
#ifndef DISABLE_JUSTIFY
513
514
    /* TRANSLATORS: The next long series of strings are shortcut descriptions;
     * they are best kept shorter than 56 characters, but may be longer. */
515
516
    const char *nano_justify_msg = N_("Justify the current paragraph");
#endif
517
    const char *nano_cancel_msg = N_("Cancel the current function");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
518
    const char *nano_help_msg = N_("Display this help text");
519
    const char *nano_exit_msg =
520
#ifndef DISABLE_MULTIBUFFER
521
	N_("Close the current file buffer / Exit from nano")
522
#else
523
	N_("Exit from nano")
524
525
#endif
	;
526
527
    const char *nano_writeout_msg =
	N_("Write the current file to disk");
528
529
    const char *nano_insert_msg =
	N_("Insert another file into the current one");
530
    const char *nano_whereis_msg =
531
	N_("Search for a string or a regular expression");
532
#ifndef DISABLE_BROWSER
533
534
    const char *nano_browser_whereis_msg = N_("Search for a string");
    const char *nano_browser_refresh_msg = N_("Refresh the file list");
535
536
    const char *nano_browser_lefthand_msg = N_("Go to lefthand column");
    const char *nano_browser_righthand_msg = N_("Go to righthand column");
537
#endif
538
539
    const char *nano_prevpage_msg = N_("Go one screenful up");
    const char *nano_nextpage_msg = N_("Go one screenful down");
540
541
542
543
    const char *nano_cut_msg =
	N_("Cut the current line and store it in the cutbuffer");
    const char *nano_uncut_msg =
	N_("Uncut from the cutbuffer into the current line");
544
    const char *nano_cursorpos_msg = N_("Display the position of the cursor");
545
#ifndef DISABLE_SPELLER
546
    const char *nano_spell_msg = N_("Invoke the spell checker, if available");
547
#endif
548
    const char *nano_replace_msg = N_("Replace a string or a regular expression");
Benno Schulenberg's avatar
Benno Schulenberg committed
549
    const char *nano_gotoline_msg = N_("Go to line and column number");
550
#ifndef NANO_TINY
551
552
    const char *nano_mark_msg = N_("Mark text starting from the cursor position");
    const char *nano_whereis_next_msg = N_("Repeat the last search");
553
554
    const char *nano_copy_msg =
	N_("Copy the current line and store it in the cutbuffer");
555
556
    const char *nano_indent_msg = N_("Indent the current line");
    const char *nano_unindent_msg = N_("Unindent the current line");
557
558
559
#ifdef ENABLE_COMMENT
    const char *nano_comment_msg = N_("Comment/uncomment the current line or marked lines");
#endif
560
561
    const char *nano_undo_msg = N_("Undo the last operation");
    const char *nano_redo_msg = N_("Redo the last undone operation");
562
#endif
563
    const char *nano_back_msg = N_("Go back one character");
564
    const char *nano_forward_msg = N_("Go forward one character");
565
    const char *nano_prevword_msg = N_("Go back one word");
566
    const char *nano_nextword_msg = N_("Go forward one word");
567
568
569
570
    const char *nano_prevline_msg = N_("Go to previous line");
    const char *nano_nextline_msg = N_("Go to next line");
    const char *nano_home_msg = N_("Go to beginning of current line");
    const char *nano_end_msg = N_("Go to end of current line");
571
572
    const char *nano_prevblock_msg = N_("Go to previous block of text");
    const char *nano_nextblock_msg = N_("Go to next block of text");
573
574
#ifndef DISABLE_JUSTIFY
    const char *nano_parabegin_msg =
575
	N_("Go to beginning of paragraph; then of previous paragraph");
576
    const char *nano_paraend_msg =
577
	N_("Go just beyond end of paragraph; then of next paragraph");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
578
#endif
579
580
    const char *nano_firstline_msg = N_("Go to the first line of the file");
    const char *nano_lastline_msg = N_("Go to the last line of the file");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
581
#ifndef NANO_TINY
582
    const char *nano_bracket_msg = N_("Go to the matching bracket");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
583
584
585
586
    const char *nano_scrollup_msg =
	N_("Scroll up one line without scrolling the cursor");
    const char *nano_scrolldown_msg =
	N_("Scroll down one line without scrolling the cursor");
587
#endif
588
#ifndef DISABLE_MULTIBUFFER
589
590
591
592
593
594
595
    const char *nano_prevfile_msg = N_("Switch to the previous file buffer");
    const char *nano_nextfile_msg = N_("Switch to the next file buffer");
#endif
    const char *nano_verbatim_msg = N_("Insert the next keystroke verbatim");
    const char *nano_tab_msg = N_("Insert a tab at the cursor position");
    const char *nano_enter_msg = N_("Insert a newline at the cursor position");
    const char *nano_delete_msg = N_("Delete the character under the cursor");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
596
597
    const char *nano_backspace_msg =
	N_("Delete the character to the left of the cursor");
598
#ifndef NANO_TINY
599
600
601
602
    const char *nano_cut_word_left_msg =
	N_("Cut backward from cursor to word start");
    const char *nano_cut_word_right_msg =
	N_("Cut forward from cursor to next word start");
603
    const char *nano_cut_till_eof_msg =
604
605
	N_("Cut from the cursor position to the end of the file");
#endif
606
607
#ifndef DISABLE_JUSTIFY
    const char *nano_fulljustify_msg = N_("Justify the entire file");
608
#endif
609
#ifndef NANO_TINY
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
610
611
    const char *nano_wordcount_msg =
	N_("Count the number of words, lines, and characters");
612
#endif
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
613
614
    const char *nano_refresh_msg =
	N_("Refresh (redraw) the current screen");
615
    const char *nano_suspend_msg =
616
	N_("Suspend the editor (if suspension is enabled)");
617
#ifndef NANO_TINY
618
    const char *nano_savefile_msg = N_("Save file without prompting");
619
620
    const char *nano_findprev_msg = N_("Search next occurrence backward");
    const char *nano_findnext_msg = N_("Search next occurrence forward");
621
    const char *nano_case_msg =
622
	N_("Toggle the case sensitivity of the search");
623
    const char *nano_reverse_msg =
624
	N_("Reverse the direction of the search");
625
#endif
626
#ifdef HAVE_REGEX_H
627
628
    const char *nano_regexp_msg =
	N_("Toggle the use of regular expressions");
629
#endif
630
#ifndef DISABLE_HISTORIES
631
    const char *nano_prev_history_msg =
632
	N_("Recall the previous search/replace string");
633
    const char *nano_next_history_msg =
634
	N_("Recall the next search/replace string");
635
#endif
636
637
#ifndef DISABLE_BROWSER
    const char *nano_tofiles_msg = N_("Go to file browser");
Chris Allegretta's avatar
Chris Allegretta committed
638
#endif
639
#ifndef NANO_TINY
640
641
642
643
    const char *nano_dos_msg = N_("Toggle the use of DOS format");
    const char *nano_mac_msg = N_("Toggle the use of Mac format");
    const char *nano_append_msg = N_("Toggle appending");
    const char *nano_prepend_msg = N_("Toggle prepending");
644
    const char *nano_backup_msg = N_("Toggle backing up of the original file");
645
    const char *nano_execute_msg = N_("Execute external command");
646
#endif
647
    const char *nano_discard_buffer_msg = N_("Close buffer without saving it");
648
#ifndef DISABLE_MULTIBUFFER
649
    const char *nano_multibuffer_msg = N_("Toggle the use of a new buffer");
650
651
#endif
#ifndef DISABLE_BROWSER
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
652
    const char *nano_exitbrowser_msg = N_("Exit from the file browser");
653
654
    const char *nano_firstfile_msg = N_("Go to the first file in the list");
    const char *nano_lastfile_msg = N_("Go to the last file in the list");
655
    const char *nano_backfile_msg = N_("Go to the previous file in the list");
656
    const char *nano_forwardfile_msg = N_("Go to the next file in the list");
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
657
    const char *nano_gotodir_msg = N_("Go to directory");
Chris Allegretta's avatar
Chris Allegretta committed
658
#endif
659
#ifndef DISABLE_COLOR
660
    const char *nano_lint_msg = N_("Invoke the linter, if available");
661
662
    const char *nano_prevlint_msg = N_("Go to previous linter msg");
    const char *nano_nextlint_msg = N_("Go to next linter msg");
663
#ifndef DISABLE_SPELLER
664
    const char *nano_formatter_msg = N_("Invoke formatter, if available");
665
#endif
666
#endif
667
#endif /* !DISABLE_HELP */
Chris Allegretta's avatar
Chris Allegretta committed
668

David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
669
#ifndef DISABLE_HELP
670
#define IFSCHELP(help) help
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
671
#else
672
#define IFSCHELP(help) ""
673
#endif
674

Benno Schulenberg's avatar
Benno Schulenberg committed
675
676
    /* Start populating the different menus with functions. */

677
    add_to_funcs(do_help_void, MMOST,
678
	/* TRANSLATORS: Try to keep the following strings at most 10 characters. */
679
	N_("Get Help"), IFSCHELP(nano_help_msg), TOGETHER, VIEW);
Chris Allegretta's avatar
Chris Allegretta committed
680

681
    add_to_funcs(do_cancel, ((MMOST & ~MMAIN & ~MBROWSER) | MYESNO),
682
	N_("Cancel"), IFSCHELP(nano_cancel_msg), BLANKAFTER, VIEW);
683

684
    add_to_funcs(do_exit, MMAIN,
685
	exit_tag, IFSCHELP(nano_exit_msg), TOGETHER, VIEW);
686
687
    /* Remember the entry for Exit, to be able to replace it with Close. */
    exitfunc = tailfunc;
Chris Allegretta's avatar
Chris Allegretta committed
688

689
#ifndef DISABLE_BROWSER
690
    add_to_funcs(do_exit, MBROWSER,
691
	exit_tag, IFSCHELP(nano_exitbrowser_msg), TOGETHER, VIEW);
692
#endif
Chris Allegretta's avatar
Chris Allegretta committed
693

694
    add_to_funcs(do_writeout_void, MMAIN,
695
	N_("Write Out"), IFSCHELP(nano_writeout_msg), TOGETHER, NOVIEW);
696

697
698
699
700
701
702
703
#ifndef DISABLE_JUSTIFY
    if (!ISSET(RESTRICTED)) {
#else
    /* If we can't replace Insert with Justify, show Insert anyway, to
     * keep the help items nicely paired also in restricted mode.  */
    if (TRUE) {
#endif
704
705
	add_to_funcs(do_insertfile_void, MMAIN,
		read_file_tag, IFSCHELP(nano_insert_msg), BLANKAFTER,
706
707
		/* We allow inserting files in view mode if multibuffer mode
		 * is switched on, so that we can view multiple files. */
708
#ifndef DISABLE_MULTIBUFFER
709
		VIEW);
710
#else
711
		NOVIEW);
712
#endif
713
714
    } else {
#ifndef DISABLE_JUSTIFY
715
	add_to_funcs(do_justify_void, MMAIN,
716
		justify_tag, IFSCHELP(nano_justify_msg), BLANKAFTER, NOVIEW);
717
718
#endif
    }
Chris Allegretta's avatar
Chris Allegretta committed
719

720
    add_to_funcs(do_search, MMAIN,
721
	whereis_tag, IFSCHELP(nano_whereis_msg), TOGETHER, VIEW);
Chris Allegretta's avatar
Chris Allegretta committed
722

723
    add_to_funcs(do_replace, MMAIN,
724
	replace_tag, IFSCHELP(nano_replace_msg), TOGETHER, NOVIEW);
725
726

#ifndef DISABLE_BROWSER
727
    add_to_funcs(do_search, MBROWSER,
728
	whereis_tag, IFSCHELP(nano_browser_whereis_msg), TOGETHER, VIEW);
729

730
    add_to_funcs(goto_dir_void, MBROWSER,
731
	N_("Go To Dir"), IFSCHELP(nano_gotodir_msg), BLANKAFTER, VIEW);
732
733
#endif

734
#ifndef DISABLE_HELP
735
736
    /* The description ("x") and blank_after (0) are irrelevant,
     * because the help viewer does not have a help text. */
737
    add_to_funcs(do_exit, MHELP, exit_tag, "x", 0, VIEW);
738

739
    add_to_funcs(total_refresh, MHELP, refresh_tag, "x", 0, VIEW);
740
741
742

    add_to_funcs(do_up_void, MHELP, prev_line_tag, "x", 0, VIEW);
    add_to_funcs(do_down_void, MHELP, next_line_tag, "x" , 0, VIEW);
743
744
#endif

745
    add_to_funcs(do_cut_text_void, MMAIN,
746
	N_("Cut Text"), IFSCHELP(nano_cut_msg), TOGETHER, NOVIEW);
Chris Allegretta's avatar
Chris Allegretta committed
747

748
    add_to_funcs(do_uncut_text, MMAIN,
749
	uncut_tag, IFSCHELP(nano_uncut_msg), BLANKAFTER, NOVIEW);
750
    /* Remember the entry for Uncut, to be able to replace it with Unjustify. */
751
    uncutfunc = tailfunc;
Chris Allegretta's avatar
Chris Allegretta committed
752

753
    if (!ISSET(RESTRICTED)) {
754
#ifndef DISABLE_JUSTIFY
755
	add_to_funcs(do_justify_void, MMAIN,
756
		justify_tag, IFSCHELP(nano_justify_msg), TOGETHER, NOVIEW);
Chris Allegretta's avatar
Chris Allegretta committed
757
#endif
Chris Allegretta's avatar
Chris Allegretta committed
758

759
#ifndef DISABLE_SPELLER
760
761
	add_to_funcs(do_spell, MMAIN,
		N_("To Spell"), IFSCHELP(nano_spell_msg), TOGETHER, NOVIEW);
762
#endif
763
#ifndef DISABLE_COLOR
764
765
	add_to_funcs(do_linter, MMAIN,
		N_("To Linter"), IFSCHELP(nano_lint_msg), TOGETHER, NOVIEW);
766
#ifndef DISABLE_SPELLER
767
768
	add_to_funcs(do_formatter, MMAIN,
		N_("Formatter"), IFSCHELP(nano_formatter_msg), BLANKAFTER, NOVIEW);
769
#endif
770
#endif
771
    }
772

773
774
775
776
777
778
779
780
781
782
783
    add_to_funcs(do_cursorpos_void, MMAIN,
	N_("Cur Pos"), IFSCHELP(nano_cursorpos_msg), TOGETHER, VIEW);

#if (!defined(DISABLE_JUSTIFY) && (!defined(DISABLE_SPELLER) || !defined(DISABLE_COLOR)) || \
	defined(DISABLE_JUSTIFY) && defined(DISABLE_SPELLER) && defined(DISABLE_COLOR))
    /* Conditionally placing this one here or further on, to keep the
     * help items nicely paired in most conditions. */
    add_to_funcs(do_gotolinecolumn_void, MMAIN,
	gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
#endif

784
    add_to_funcs(case_sens_void, MWHEREIS|MREPLACE,
785
	N_("Case Sens"), IFSCHELP(nano_case_msg), TOGETHER, VIEW);
786
#ifdef HAVE_REGEX_H
787
    add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
788
	N_("Regexp"), IFSCHELP(nano_regexp_msg), TOGETHER, VIEW);
789
#endif
790
    add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
791
	N_("Backwards"), IFSCHELP(nano_reverse_msg), TOGETHER, VIEW);
792

793
    add_to_funcs(flip_replace_void, MWHEREIS,
794
	replace_tag, IFSCHELP(nano_replace_msg), BLANKAFTER, VIEW);
795

796
    add_to_funcs(flip_replace_void, MREPLACE,
797
	N_("No Replace"), IFSCHELP(nano_whereis_msg), BLANKAFTER, VIEW);
798
799

#ifndef DISABLE_JUSTIFY
800
    add_to_funcs(do_full_justify, MWHEREIS,
801
	fulljustify_tag, IFSCHELP(nano_fulljustify_msg), TOGETHER, NOVIEW);
802

803
    add_to_funcs(do_gotolinecolumn_void, MWHEREIS,
804
	gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
805
#endif
806

807
808
809
810
    add_to_funcs(do_page_up, MMAIN|MHELP,
	prev_page_tag, IFSCHELP(nano_prevpage_msg), TOGETHER, VIEW);
    add_to_funcs(do_page_down, MMAIN|MHELP,
	next_page_tag, IFSCHELP(nano_nextpage_msg), TOGETHER, VIEW);
811

812
    add_to_funcs(do_first_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE,
813
	N_("First Line"), IFSCHELP(nano_firstline_msg), TOGETHER, VIEW);
814
    add_to_funcs(do_last_line, MMAIN|MHELP|MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE,
815
	N_("Last Line"), IFSCHELP(nano_lastline_msg), BLANKAFTER, VIEW);
816

817
#ifndef NANO_TINY
818
    add_to_funcs(do_research, MMAIN,
819
	whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
820

821
    add_to_funcs(do_find_bracket, MMAIN,
822
	N_("To Bracket"), IFSCHELP(nano_bracket_msg), TOGETHER, VIEW);
823

824
    add_to_funcs(do_mark, MMAIN,
825
	N_("Mark Text"), IFSCHELP(nano_mark_msg), TOGETHER, VIEW);
826

827
    add_to_funcs(do_copy_text, MMAIN,
828
	N_("Copy Text"), IFSCHELP(nano_copy_msg), BLANKAFTER, NOVIEW);
829

830
    add_to_funcs(do_indent_void, MMAIN,
831
	N_("Indent Text"), IFSCHELP(nano_indent_msg), TOGETHER, NOVIEW);
832
    add_to_funcs(do_unindent, MMAIN,
833
	N_("Unindent Text"), IFSCHELP(nano_unindent_msg), BLANKAFTER, NOVIEW);
834

835
    add_to_funcs(do_undo, MMAIN,
836
	N_("Undo"), IFSCHELP(nano_undo_msg), TOGETHER, NOVIEW);
837
    add_to_funcs(do_redo, MMAIN,
838
	N_("Redo"), IFSCHELP(nano_redo_msg), BLANKAFTER, NOVIEW);
839
#endif /* !NANO_TINY */
840

841
    add_to_funcs(do_left, MMAIN,
842
	N_("Back"), IFSCHELP(nano_back_msg), TOGETHER, VIEW);
843
    add_to_funcs(do_right, MMAIN,
844
	N_("Forward"), IFSCHELP(nano_forward_msg), TOGETHER, VIEW);
845
846

#ifndef DISABLE_BROWSER
847
    add_to_funcs(do_left, MBROWSER,
848
	N_("Back"), IFSCHELP(nano_backfile_msg), TOGETHER, VIEW);
849
    add_to_funcs(do_right, MBROWSER,
850
	N_("Forward"), IFSCHELP(nano_forwardfile_msg), TOGETHER, VIEW);
851
852
#endif

853
    add_to_funcs(do_prev_word_void, MMAIN,
854
	N_("Prev Word"), IFSCHELP(nano_prevword_msg), TOGETHER, VIEW);
855
    add_to_funcs(do_next_word_void, MMAIN,
856
	N_("Next Word"), IFSCHELP(nano_nextword_msg), TOGETHER, VIEW);
857

858
    add_to_funcs(do_home, MMAIN,
859
	N_("Home"), IFSCHELP(nano_home_msg), TOGETHER, VIEW);
860
    add_to_funcs(do_end, MMAIN,
861
	N_("End"), IFSCHELP(nano_end_msg), TOGETHER, VIEW);
862

863
    add_to_funcs(do_up_void, MMAIN|MBROWSER,
864
	prev_line_tag, IFSCHELP(nano_prevline_msg), TOGETHER, VIEW);
865
    add_to_funcs(do_down_void, MMAIN|MBROWSER,
866
	next_line_tag, IFSCHELP(nano_nextline_msg), BLANKAFTER, VIEW);
867

868
869
870
871
872
    add_to_funcs(do_prev_block, MMAIN,
	N_("Prev Block"), IFSCHELP(nano_prevblock_msg), TOGETHER, VIEW);
    add_to_funcs(do_next_block, MMAIN,
	N_("Next Block"), IFSCHELP(nano_nextblock_msg), TOGETHER, VIEW);

873
#ifndef DISABLE_JUSTIFY
874
    add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS,
875
	N_("Beg of Par"), IFSCHELP(nano_parabegin_msg), TOGETHER, VIEW);
876
    add_to_funcs(do_para_end_void, MMAIN|MWHEREIS,
877
	N_("End of Par"), IFSCHELP(nano_paraend_msg), TOGETHER, VIEW);
878
#endif
879

880
#ifndef NANO_TINY
881
    add_to_funcs(do_scroll_up, MMAIN,
882
	N_("Scroll Up"), IFSCHELP(nano_scrollup_msg), TOGETHER, VIEW);
883
    add_to_funcs(do_scroll_down, MMAIN,
884
	N_("Scroll Down"), IFSCHELP(nano_scrolldown_msg), BLANKAFTER, VIEW);
885
886
#endif

887
#ifndef DISABLE_MULTIBUFFER
888
    add_to_funcs(switch_to_prev_buffer_void, MMAIN,
889
	N_("Prev File"), IFSCHELP(nano_prevfile_msg), TOGETHER, VIEW);
890
    add_to_funcs(switch_to_next_buffer_void, MMAIN,
891
	N_("Next File"), IFSCHELP(nano_nextfile_msg), BLANKAFTER, VIEW);
892
893
#endif

894
895
#if (defined(DISABLE_JUSTIFY) && (!defined(DISABLE_SPELLER) || !defined(DISABLE_COLOR)) || \
	!defined(DISABLE_JUSTIFY) && defined(DISABLE_SPELLER) && defined(DISABLE_COLOR))
896
    add_to_funcs(do_gotolinecolumn_void, MMAIN,
897
	gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
898
899
#endif

900
901
902
903
904
905
#ifdef NANO_TINY
    /* Place this one here only in the tiny version; otherwise further up. */
    add_to_funcs(do_research, MMAIN,
	whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
#endif

906
    add_to_funcs(do_verbatim_input, MMAIN,
907
	N_("Verbatim"), IFSCHELP(nano_verbatim_msg), TOGETHER, NOVIEW);
908

909
    add_to_funcs(do_tab, MMAIN,
910
	N_("Tab"), IFSCHELP(nano_tab_msg), TOGETHER, NOVIEW);
911
    add_to_funcs(do_enter, MMAIN,
912
913
	N_("Enter"), IFSCHELP(nano_enter_msg), BLANKAFTER, NOVIEW);

914
    add_to_funcs(do_delete, MMAIN,
915
	N_("Delete"), IFSCHELP(nano_delete_msg), TOGETHER, NOVIEW);
916
917
    add_to_funcs(do_backspace, MMAIN,
	N_("Backspace"), IFSCHELP(nano_backspace_msg),
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
918
#ifndef NANO_TINY
919
	TOGETHER,
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
920
#else
921
	BLANKAFTER,
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
922
#endif
923
924
	NOVIEW);

925
#ifndef NANO_TINY
926
    add_to_funcs(do_cut_prev_word, MMAIN,
927
	/* TRANSLATORS: The next two strings refer to cutting words. */
928
929
930
	N_("Cut Left"), IFSCHELP(nano_cut_word_left_msg), TOGETHER, NOVIEW);
    add_to_funcs(do_cut_next_word, MMAIN,
	N_("Cut Right"), IFSCHELP(nano_cut_word_right_msg), TOGETHER, NOVIEW);
931
    add_to_funcs(do_cut_till_eof, MMAIN,
932
	N_("CutTillEnd"), IFSCHELP(nano_cut_till_eof_msg), BLANKAFTER, NOVIEW);
933
#endif
Chris Allegretta's avatar
Chris Allegretta committed
934

935
#ifndef DISABLE_JUSTIFY
936
    add_to_funcs(do_full_justify, MMAIN,
937
	fulljustify_tag, IFSCHELP(nano_fulljustify_msg), TOGETHER, NOVIEW);
938
939
#endif

940
#ifndef NANO_TINY
941
    add_to_funcs(do_wordlinechar_count, MMAIN,
942
	N_("Word Count"), IFSCHELP(nano_wordcount_msg), TOGETHER, VIEW);
943
#endif
944

945
    add_to_funcs(total_refresh, MMAIN,
946
	refresh_tag, IFSCHELP(nano_refresh_msg), TOGETHER, VIEW);
947

948
    add_to_funcs(do_suspend_void, MMAIN,
949
	N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW);
Chris Allegretta's avatar
Chris Allegretta committed
950

951
952
953
954
#ifdef ENABLE_COMMENT
    add_to_funcs(do_comment, MMAIN,
	N_("Comment Lines"), IFSCHELP(nano_comment_msg), BLANKAFTER, NOVIEW);
#endif
955
956
957
#ifndef NANO_TINY
    add_to_funcs(do_savefile, MMAIN,
	N_("Save"), IFSCHELP(nano_savefile_msg), BLANKAFTER, NOVIEW);
958
959
960
961
962

    add_to_funcs(do_findprevious, MMAIN,
	N_("Previous"), IFSCHELP(nano_findprev_msg), TOGETHER, VIEW);
    add_to_funcs(do_findnext, MMAIN,
	N_("Next"), IFSCHELP(nano_findnext_msg), BLANKAFTER, VIEW);
963
964
#endif

965
#ifndef DISABLE_HISTORIES
966
    add_to_funcs(get_history_older_void,
967
	(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE),
968
	N_("PrevHstory"), IFSCHELP(nano_prev_history_msg), TOGETHER, VIEW);
969
    add_to_funcs(get_history_newer_void,
970
	(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE),
971
972
973
	N_("NextHstory"), IFSCHELP(nano_next_history_msg), BLANKAFTER, VIEW);
#endif

974
#ifdef DISABLE_JUSTIFY
975
976
    add_to_funcs(do_gotolinecolumn_void, MWHEREIS,
	gotoline_tag, IFSCHELP(nano_gotoline_msg), BLANKAFTER, VIEW);
977
#endif
978

979
    add_to_funcs(gototext_void, MGOTOLINE,
980
	N_("Go To Text"), IFSCHELP(nano_whereis_msg), BLANKAFTER, VIEW);
981

982
#ifndef NANO_TINY
983
    add_to_funcs(dos_format_void, MWRITEFILE,
984
	N_("DOS Format"), IFSCHELP(nano_dos_msg), TOGETHER, NOVIEW);
985
    add_to_funcs(mac_format_void, MWRITEFILE,
986
987
988
989
990
991
	N_("Mac Format"), IFSCHELP(nano_mac_msg), TOGETHER, NOVIEW);

    /* If we're using restricted mode, the Append, Prepend, and Backup toggles
     * are disabled.  The first and second are not useful as they only allow
     * reduplicating the current file, and the third is not allowed as it
     * would write to a file not specified on the command line. */
992
    if (!ISSET(RESTRICTED)) {
993
994
995
996
	add_to_funcs(append_void, MWRITEFILE,
	    N_("Append"), IFSCHELP(nano_append_msg), TOGETHER, NOVIEW);
	add_to_funcs(prepend_void, MWRITEFILE,
	    N_("Prepend"), IFSCHELP(nano_prepend_msg), TOGETHER, NOVIEW);
997

998
	add_to_funcs(backup_file_void, MWRITEFILE,
999
	    N_("Backup File"), IFSCHELP(nano_backup_msg), BLANKAFTER, NOVIEW);
1000
    }
1001

1002
1003
1004
    /* If we're using restricted mode, file insertion is disabled, and
     * thus command execution and the multibuffer toggle have no place. */
    if (!ISSET(RESTRICTED)) {
1005
	add_to_funcs(flip_execute_void, MINSERTFILE,
1006
	    N_("Execute Command"), IFSCHELP(nano_execute_msg), TOGETHER, NOVIEW);
1007

1008
	add_to_funcs(flip_execute_void, MEXTCMD,
1009
	    read_file_tag, IFSCHELP(nano_insert_msg), TOGETHER, NOVIEW);
1010

1011
#ifndef DISABLE_MULTIBUFFER
1012
	add_to_funcs(new_buffer_void, MINSERTFILE|MEXTCMD,
1013
	    N_("New Buffer"), IFSCHELP(nano_multibuffer_msg), TOGETHER, NOVIEW);
1014
#endif
1015
    }
1016
#endif /* !NANO_TINY */
1017

1018
#ifndef DISABLE_BROWSER
1019
1020
    if (!ISSET(RESTRICTED))
	add_to_funcs(to_files_void, MWRITEFILE|MINSERTFILE,
1021
	    N_("To Files"), IFSCHELP(nano_tofiles_msg), TOGETHER, VIEW);
1022

1023
1024
1025
1026
1027
    add_to_funcs(do_page_up, MBROWSER,
	prev_page_tag, IFSCHELP(nano_prevpage_msg), TOGETHER, VIEW);
    add_to_funcs(do_page_down, MBROWSER,
	next_page_tag, IFSCHELP(nano_nextpage_msg), TOGETHER, VIEW);

Benno Schulenberg's avatar
Benno Schulenberg committed
1028
    add_to_funcs(do_first_file, (MBROWSER|MWHEREISFILE),
1029
	N_("First File"), IFSCHELP(nano_firstfile_msg), TOGETHER, VIEW);
Benno Schulenberg's avatar
Benno Schulenberg committed
1030
    add_to_funcs(do_last_file, (MBROWSER|MWHEREISFILE),
1031
	N_("Last File"), IFSCHELP(nano_lastfile_msg), BLANKAFTER, VIEW);
1032
#endif
Chris Allegretta's avatar
Chris Allegretta committed
1033

1034
1035
1036
    add_to_funcs(discard_buffer, MWRITEFILE,
	N_("Discard buffer"), IFSCHELP(nano_discard_buffer_msg), BLANKAFTER, NOVIEW);

1037
#if !defined(NANO_TINY) && !defined(DISABLE_BROWSER)
1038
    add_to_funcs(do_research, MBROWSER,
1039
	whereis_next_tag, IFSCHELP(nano_whereis_next_msg), TOGETHER, VIEW);
1040
#endif
1041
1042
1043
#ifndef DISABLE_BROWSER
    add_to_funcs(total_refresh, MBROWSER,
	refresh_tag, IFSCHELP(nano_browser_refresh_msg), BLANKAFTER, VIEW);
1044
#ifndef NANO_TINY
1045
1046
1047
1048
    add_to_funcs(do_prev_word_void, MBROWSER,
	N_("Left Column"), IFSCHELP(nano_browser_lefthand_msg), TOGETHER, VIEW);
    add_to_funcs(do_next_word_void, MBROWSER,
	N_("Right Column"), IFSCHELP(nano_browser_righthand_msg), BLANKAFTER, VIEW);
1049
#endif
1050
#endif
1051
1052
1053

#ifndef DISABLE_COLOR
    add_to_funcs(do_page_up, MLINTER,
1054
	/* TRANSLATORS: Try to keep the next two strings at most 20 characters. */
1055
	N_("Prev Lint Msg"), IFSCHELP(nano_prevlint_msg), TOGETHER, VIEW);
1056
    add_to_funcs(do_page_down, MLINTER,
1057
	N_("Next Lint Msg"), IFSCHELP(nano_nextlint_msg), TOGETHER, VIEW);
1058
1059
#endif

Benno Schulenberg's avatar
Benno Schulenberg committed
1060
1061
    /* Start associating key combos with functions in specific menus. */

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
    add_to_sclist(MMOST, "^G", do_help_void, 0);
    add_to_sclist(MMOST, "F1", do_help_void, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER, "^X", do_exit, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER, "F2", do_exit, 0);
    add_to_sclist(MMAIN, "^O", do_writeout_void, 0);
    add_to_sclist(MMAIN, "F3", do_writeout_void, 0);
    add_to_sclist(MMAIN, "^R", do_insertfile_void, 0);
    add_to_sclist(MMAIN, "F5", do_insertfile_void, 0);
    add_to_sclist(MMAIN, "Ins", do_insertfile_void, 0);
    add_to_sclist(MMAIN|MBROWSER, "^W", do_search, 0);
    add_to_sclist(MMAIN|MBROWSER, "F6", do_search, 0);
    add_to_sclist(MMAIN, "^\\", do_replace, 0);
    add_to_sclist(MMAIN, "M-R", do_replace, 0);
    add_to_sclist(MMAIN, "F14", do_replace, 0);
    add_to_sclist(MMOST, "^K", do_cut_text_void, 0);
    add_to_sclist(MMOST, "F9", do_cut_text_void, 0);
    add_to_sclist(MMAIN, "^U", do_uncut_text, 0);
    add_to_sclist(MMAIN, "F10", do_uncut_text, 0);
1080
#ifndef DISABLE_JUSTIFY
1081
1082
    add_to_sclist(MMAIN, "^J", do_justify_void, 0);
    add_to_sclist(MMAIN, "F4", do_justify_void, 0);
1083
#endif
1084
#ifndef DISABLE_SPELLER
1085
1086
    add_to_sclist(MMAIN, "^T", do_spell, 0);
    add_to_sclist(MMAIN, "F12", do_spell, 0);
1087
1088
#else
#ifndef DISABLE_COLOR
1089
1090
1091
1092
1093
1094
1095
1096
1097
    add_to_sclist(MMAIN, "^T", do_linter, 0);
    add_to_sclist(MMAIN, "F12", do_linter, 0);
#endif
#endif
    add_to_sclist(MMAIN, "^C", do_cursorpos_void, 0);
    add_to_sclist(MMAIN, "F11", do_cursorpos_void, 0);
    add_to_sclist(MMAIN, "^_", do_gotolinecolumn_void, 0);
    add_to_sclist(MMAIN, "M-G", do_gotolinecolumn_void, 0);
    add_to_sclist(MMAIN, "F13", do_gotolinecolumn_void, 0);
1098
1099
1100
1101
1102
1103
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^Y", do_page_up, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F7", do_page_up, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgUp", do_page_up, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "^V", do_page_down, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "F8", do_page_down, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER|MLINTER, "PgDn", do_page_down, 0);
1104
1105
1106
1107
1108
1109
    add_to_sclist(MMAIN|MHELP, "M-\\", do_first_line, 0);
    add_to_sclist(MMAIN|MHELP, "M-|", do_first_line, 0);
    add_to_sclist(MMAIN|MHELP, "M-/", do_last_line, 0);
    add_to_sclist(MMAIN|MHELP, "M-?", do_last_line, 0);
    add_to_sclist(MMAIN|MBROWSER, "M-W", do_research, 0);
    add_to_sclist(MMAIN|MBROWSER, "F16", do_research, 0);
1110
#ifndef NANO_TINY
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
    add_to_sclist(MMAIN, "M-]", do_find_bracket, 0);
    add_to_sclist(MMAIN, "^^", do_mark, 0);
    add_to_sclist(MMAIN, "M-A", do_mark, 0);
    add_to_sclist(MMAIN, "F15", do_mark, 0);
    add_to_sclist(MMAIN, "M-^", do_copy_text, 0);
    add_to_sclist(MMAIN, "M-6", do_copy_text, 0);
    add_to_sclist(MMAIN, "M-}", do_indent_void, 0);
    add_to_sclist(MMAIN, "M-{", do_unindent, 0);
    add_to_sclist(MMAIN, "M-U", do_undo, 0);
    add_to_sclist(MMAIN, "M-E", do_redo, 0);
1121
1122
1123
#endif
#ifdef ENABLE_COMMENT
    add_to_sclist(MMAIN, "M-3", do_comment, 0);
1124
1125
1126
1127
1128
#endif
    add_to_sclist(MMOST, "^B", do_left, 0);
    add_to_sclist(MMOST, "Left", do_left, 0);
    add_to_sclist(MMOST, "^F", do_right, 0);
    add_to_sclist(MMOST, "Right", do_right, 0);
1129
    if (using_utf8()) {
1130
1131
	add_to_sclist(MMOST, "^\xE2\x86\x90", do_prev_word_void, 0);
	add_to_sclist(MMOST, "^\xE2\x86\x92", do_next_word_void, 0);
1132
1133
1134
1135
    } else {
	add_to_sclist(MMOST, "^Left", do_prev_word_void, 0);
	add_to_sclist(MMOST, "^Right", do_next_word_void, 0);
    }
1136
1137
    add_to_sclist(MMOST, "M-Space", do_prev_word_void, 0);
    add_to_sclist(MMOST, "^Space", do_next_word_void, 0);
1138
1139
1140
1141
    add_to_sclist((MMOST & ~MBROWSER), "^A", do_home, 0);
    add_to_sclist((MMOST & ~MBROWSER), "Home", do_home, 0);
    add_to_sclist((MMOST & ~MBROWSER), "^E", do_end, 0);
    add_to_sclist((MMOST & ~MBROWSER), "End", do_end, 0);
1142
1143
1144
1145
    add_to_sclist(MMAIN|MHELP|MBROWSER, "^P", do_up_void, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", do_up_void, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER, "^N", do_down_void, 0);
    add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", do_down_void, 0);
1146
1147
1148
1149
1150
1151
1152
    if (using_utf8()) {
	add_to_sclist(MMAIN, "^\xE2\x86\x91", do_prev_block, 0);
	add_to_sclist(MMAIN, "^\xE2\x86\x93", do_next_block, 0);
    } else {
	add_to_sclist(MMAIN, "^Up", do_prev_block, 0);
	add_to_sclist(MMAIN, "^Down", do_next_block, 0);
    }
1153
1154
    add_to_sclist(MMAIN, "M-7", do_prev_block, 0);
    add_to_sclist(MMAIN, "M-8", do_next_block, 0);
1155
#ifndef DISABLE_JUSTIFY
1156
1157
1158
1159
    add_to_sclist(MMAIN, "M-(", do_para_begin_void, 0);
    add_to_sclist(MMAIN, "M-9", do_para_begin_void, 0);
    add_to_sclist(MMAIN, "M-)", do_para_end_void, 0);
    add_to_sclist(MMAIN, "M-0", do_para_end_void, 0);
Benno Schulenberg's avatar
Benno Schulenberg committed
1160
#endif
1161
#ifndef NANO_TINY
1162
1163
1164
1165
    add_to_sclist(MMAIN, "M--", do_scroll_up, 0);
    add_to_sclist(MMAIN, "M-_", do_scroll_up, 0);
    add_to_sclist(MMAIN, "M-+", do_scroll_down, 0);
    add_to_sclist(MMAIN, "M-=", do_scroll_down, 0);
1166
#endif
1167
#ifndef DISABLE_MULTIBUFFER
1168
1169
1170
1171
    add_to_sclist(MMAIN, "M-<", switch_to_prev_buffer_void, 0);
    add_to_sclist(MMAIN, "M-,", switch_to_prev_buffer_void, 0);
    add_to_sclist(MMAIN, "M->", switch_to_next_buffer_void, 0);
    add_to_sclist(MMAIN, "M-.", switch_to_next_buffer_void, 0);
1172
#endif
1173
    add_to_sclist(MMOST, "M-V", do_verbatim_input, 0);
1174
#ifndef NANO_TINY
1175
    add_to_sclist(MMAIN, "M-T", do_cut_till_eof, 0);
1176
    add_to_sclist(MMAIN, "M-D", do_wordlinechar_count, 0);
1177
#endif
1178
#ifndef DISABLE_JUSTIFY
1179
    add_to_sclist(MMAIN|MWHEREIS, "M-J", do_full_justify, 0);
1180
#endif
1181
1182
    add_to_sclist(MMAIN|MHELP, "^L", total_refresh, 0);
    add_to_sclist(MMAIN, "^Z", do_suspend_void, 0);
1183

1184
#ifndef NANO_TINY
1185
    /* Group of "Appearance" toggles. */
1186
1187
1188
1189
1190
1191
    add_to_sclist(MMAIN, "M-X", do_toggle_void, NO_HELP);
    add_to_sclist(MMAIN, "M-C", do_toggle_void, CONST_UPDATE);
    add_to_sclist(MMAIN, "M-O", do_toggle_void, MORE_SPACE);
    add_to_sclist(MMAIN, "M-S", do_toggle_void, SMOOTH_SCROLL);
    add_to_sclist(MMAIN, "M-$", do_toggle_void, SOFTWRAP);
    add_to_sclist(MMAIN, "M-P", do_toggle_void, WHITESPACE_DISPLAY);
1192
#ifndef DISABLE_COLOR
1193
    add_to_sclist(MMAIN, "M-Y", do_toggle_void, NO_COLOR_SYNTAX);
1194
#endif
1195

1196
    /* Group of "Editing-behavior" toggles. */
1197
1198
1199
    add_to_sclist(MMAIN, "M-H", do_toggle_void, SMART_HOME);
    add_to_sclist(MMAIN, "M-I", do_toggle_void, AUTOINDENT);
    add_to_sclist(MMAIN, "M-K", do_toggle_void, CUT_TO_END);
1200
#ifndef DISABLE_WRAPPING
1201
    add_to_sclist(MMAIN, "M-L", do_toggle_void, NO_WRAP);
1202
#endif
1203
    add_to_sclist(MMAIN, "M-Q", do_toggle_void, TABS_TO_SPACES);
1204

1205
    /* Group of "Peripheral-feature" toggles. */
1206
    add_to_sclist(MMAIN, "M-B", do_toggle_void, BACKUP_FILE);
1207
#ifndef DISABLE_MULTIBUFFER
1208
    add_to_sclist(MMAIN, "M-F", do_toggle_void, MULTIBUFFER);
1209
1210
#endif
#ifndef DISABLE_MOUSE
1211
    add_to_sclist(MMAIN, "M-M", do_toggle_void, USE_MOUSE);
1212
#endif
1213
1214
    add_to_sclist(MMAIN, "M-N", do_toggle_void, NO_CONVERT);
    add_to_sclist(MMAIN, "M-Z", do_toggle_void, SUSPEND);
1215
#endif /* !NANO_TINY */
Benno Schulenberg's avatar
Benno Schulenberg committed
1216

1217
1218
    add_to_sclist(MMAIN, "^Q", xon_complaint, 0);
    add_to_sclist(MMAIN, "^S", xoff_complaint, 0);
1219

1220
    add_to_sclist(((MMOST & ~MMAIN & ~MBROWSER) | MYESNO), "^C", do_cancel, 0);
1221

1222
1223
    add_to_sclist(MWHEREIS|MREPLACE, "M-C", case_sens_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE, "M-R", regexp_void, 0);
1224
    add_to_sclist(MWHEREIS|MREPLACE, "M-B", backwards_void, 0);
1225
1226
1227
    add_to_sclist(MWHEREIS|MREPLACE, "^R", flip_replace_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^Y", do_first_line, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MGOTOLINE, "^V", do_last_line, 0);
1228
#ifndef DISABLE_JUSTIFY
1229
1230
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^W", do_para_begin_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH, "^O", do_para_end_void, 0);
1231
#endif
1232
1233
    add_to_sclist(MWHEREIS, "^T", do_gotolinecolumn_void, 0);
    add_to_sclist(MGOTOLINE, "^T", gototext_void, 0);
1234
#ifndef DISABLE_HISTORIES
1235
1236
1237
1238
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^P", get_history_older_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Up", get_history_older_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "^N", get_history_newer_void, 0);
    add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE, "Down", get_history_newer_void, 0);
1239
1240
#endif
#ifndef DISABLE_BROWSER
1241
1242
    add_to_sclist(MWHEREISFILE, "^Y", do_first_file, 0);
    add_to_sclist(MWHEREISFILE, "^V", do_last_file, 0);
1243
1244
1245
1246
    add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", do_first_file, 0);
    add_to_sclist(MBROWSER|MWHEREISFILE, "M-|", do_first_file, 0);
    add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", do_last_file, 0);
    add_to_sclist(MBROWSER|MWHEREISFILE, "M-?", do_last_file, 0);
1247
1248
    add_to_sclist(MBROWSER, "Home", do_first_file, 0);
    add_to_sclist(MBROWSER, "End", do_last_file, 0);
1249
1250
1251
    add_to_sclist(MBROWSER, "^_", goto_dir_void, 0);
    add_to_sclist(MBROWSER, "M-G", goto_dir_void, 0);
    add_to_sclist(MBROWSER, "F13", goto_dir_void, 0);
1252
    add_to_sclist(MBROWSER, "^L", total_refresh, 0);
1253
#endif
1254
1255
    if (ISSET(TEMP_FILE))
	add_to_sclist(MWRITEFILE, "^Q", discard_buffer, 0);
1256
1257
    add_to_sclist(MWRITEFILE, "M-D", dos_format_void, 0);
    add_to_sclist(MWRITEFILE, "M-M", mac_format_void, 0);
1258
1259
1260
1261
1262
    if (!ISSET(RESTRICTED)) {
	/* Don't allow Appending, Prepending, nor Backups in restricted mode. */
	add_to_sclist(MWRITEFILE, "M-A", append_void, 0);
	add_to_sclist(MWRITEFILE, "M-P", prepend_void, 0);
	add_to_sclist(MWRITEFILE, "M-B", backup_file_void, 0);
1263
#ifndef DISABLE_BROWSER
1264
	add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", to_files_void, 0);
1265
#endif
1266
1267
1268
	add_to_sclist(MINSERTFILE|MEXTCMD, "^X", flip_execute_void, 0);
	add_to_sclist(MINSERTFILE|MEXTCMD, "M-F", new_buffer_void, 0);
    }
1269
    add_to_sclist(MHELP|MBROWSER, "^C", do_exit, 0);
1270
1271
1272
1273
1274
    /* Allow exiting from the file browser and the help viewer with
     * the same key as they were entered. */
#ifndef DISABLE_BROWSER
    add_to_sclist(MBROWSER, "^T", do_exit, 0);
#endif
1275
#ifndef DISABLE_HELP
1276
    add_to_sclist(MHELP, "^G", do_exit, 0);
1277
1278
    add_to_sclist(MHELP, "Home", do_first_line, 0);
    add_to_sclist(MHELP, "End", do_last_line, 0);
1279
#endif
1280
    add_to_sclist(MMOST, "^I", do_tab, 0);
1281
    add_to_sclist(MMOST, "Tab", do_tab, 0);
1282
1283
    add_to_sclist(MMOST, "^M", do_enter, 0);
    add_to_sclist(MMOST, "Enter", do_enter, 0);
1284
1285
1286
1287
    add_to_sclist(MMOST, "^D", do_delete, 0);
    add_to_sclist(MMOST, "Del", do_delete, 0);
    add_to_sclist(MMOST, "^H", do_backspace, 0);
    add_to_sclist(MMOST, "Bsp", do_backspace, 0);
Chris Allegretta's avatar
Chris Allegretta committed
1288

1289
1290
#ifdef DEBUG
    print_sclist();
Chris Allegretta's avatar
Chris Allegretta committed
1291
#endif
1292
}
1293

1294
#ifndef DISABLE_COLOR
1295
void set_lint_or_format_shortcuts(void)
1296
1297
{
#ifndef DISABLE_SPELLER
1298
1299
1300
1301
1302
1303
1304
    if (openfile->syntax->formatter) {
	replace_scs_for(do_spell, do_formatter);
	replace_scs_for(do_linter, do_formatter);
    } else {
	replace_scs_for(do_spell, do_linter);
	replace_scs_for(do_formatter, do_linter);
    }
1305
1306
1307
1308
1309
1310
#endif
}

void set_spell_shortcuts(void)
{
#ifndef DISABLE_SPELLER
1311
1312
	replace_scs_for(do_formatter, do_spell);
	replace_scs_for(do_linter, do_spell);
1313
1314
#endif
}
1315
#endif /* !DISABLE_COLOR */
1316

1317
const subnfunc *sctofunc(const sc *s)
1318
{
1319
    subnfunc *f = allfuncs;
1320

1321
1322
    while (f != NULL && f->scfunc != s->scfunc)
	f = f->next;
1323

1324
    return f;
1325
1326
}

1327
#ifndef NANO_TINY
1328
1329
/* Now let's come up with a single (hopefully) function to get a string
 * for each flag. */
1330
const char *flagtostr(int flag)
1331
{
1332
    switch (flag) {
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
	case NO_HELP:
	    /* TRANSLATORS: The next seventeen strings are toggle descriptions;
	     * they are best kept shorter than 40 characters, but may be longer. */
	    return N_("Help mode");
	case CONST_UPDATE:
	    return N_("Constant cursor position display");
	case MORE_SPACE:
	    return N_("Use of one more line for editing");
	case SMOOTH_SCROLL:
	    return N_("Smooth scrolling");
	case SOFTWRAP:
	    return N_("Soft wrapping of overlong lines");
	case WHITESPACE_DISPLAY:
	    return N_("Whitespace display");
	case NO_COLOR_SYNTAX:
	    return N_("Color syntax highlighting");
	case SMART_HOME:
	    return N_("Smart home key");
	case AUTOINDENT:
	    return N_("Auto indent");
	case CUT_TO_END:
	    return N_("Cut to end");
	case NO_WRAP:
	    return N_("Hard wrapping of overlong lines");
	case TABS_TO_SPACES:
	    return N_("Conversion of typed tabs to spaces");
	case BACKUP_FILE:
	    return N_("Backup files");
	case MULTIBUFFER:
1362
	    return N_("Reading file into separate buffer");
1363
1364
1365
1366
1367
1368
1369
1370
	case USE_MOUSE:
	    return N_("Mouse support");
	case NO_CONVERT:
	    return N_("No conversion from DOS/Mac format");
	case SUSPEND:
	    return N_("Suspension");
	default:
	    return "?????";
1371
1372
    }
}
1373
#endif /* !NANO_TINY */
1374

1375
#ifndef DISABLE_NANORC
1376
/* Interpret a function string given in the rc file, and return a
1377
 * shortcut struct with the corresponding function filled in. */
1378
sc *strtosc(const char *input)
1379
{
1380
    sc *s = nmalloc(sizeof(sc));
1381

1382
#ifndef NANO_TINY
1383
    s->toggle = 0;
1384
#endif
1385

Chris Allegretta's avatar
Chris Allegretta committed
1386
#ifndef DISABLE_HELP
1387
    if (!strcasecmp(input, "help"))
1388
1389
	s->scfunc = do_help_void;
    else
Chris Allegretta's avatar
Chris Allegretta committed
1390
#endif
1391
    if (!strcasecmp(input, "cancel"))
1392
	s->scfunc = do_cancel;
1393
    else if (!strcasecmp(input, "exit"))
1394
	s->scfunc = do_exit;
1395
1396
    else if (!strcasecmp(input, "discardbuffer"))
	s->scfunc = discard_buffer;
1397
    else if (!strcasecmp(input, "writeout"))
1398
	s->scfunc = do_writeout_void;
1399
1400
1401
1402
#ifndef NANO_TINY
    else if (!strcasecmp(input, "savefile"))
	s->scfunc = do_savefile;
#endif
1403
    else if (!strcasecmp(input, "insert"))
1404
	s->scfunc = do_insertfile_void;
1405
    else if (!strcasecmp(input, "whereis"))
1406
	s->scfunc = do_search;
1407
    else if (!strcasecmp(input, "searchagain") ||
1408
	     !strcasecmp(input, "research"))  /* Deprecated.  Remove in 2018. */
1409
	s->scfunc = do_research;
1410
#ifndef NANO_TINY
1411
1412
1413
1414
    else if (!strcasecmp(input, "findprevious"))
	s->scfunc = do_findprevious;
    else if (!strcasecmp(input, "findnext"))
	s->scfunc = do_findnext;
1415
#endif
1416
1417
    else if (!strcasecmp(input, "replace"))
	s->scfunc = do_replace;
1418
    else if (!strcasecmp(input, "cut"))
1419
	s->scfunc = do_cut_text_void;
1420
    else if (!strcasecmp(input, "uncut"))
1421
	s->scfunc = do_uncut_text;
1422
#ifndef NANO_TINY
1423
    else if (!strcasecmp(input, "cutrestoffile"))
1424
	s->scfunc = do_cut_till_eof;
1425
1426
    else if (!strcasecmp(input, "copytext"))
	s->scfunc = do_copy_text;
1427
1428
    else if (!strcasecmp(input, "mark"))
	s->scfunc = do_mark;
1429
1430
#endif
#ifndef DISABLE_SPELLER
1431
1432
1433
    else if (!strcasecmp(input, "tospell") ||
	     !strcasecmp(input, "speller"))
	s->scfunc = do_spell;
1434
#endif
1435
#ifndef DISABLE_COLOR
1436
1437
    else if (!strcasecmp(input, "linter"))
	s->scfunc = do_linter;
1438
#endif
1439
    else if (!strcasecmp(input, "curpos") ||
1440
	     !strcasecmp(input, "cursorpos"))  /* Deprecated.  Remove in 2018. */
1441
	s->scfunc = do_cursorpos_void;
1442
    else if (!strcasecmp(input, "gotoline"))
1443
	s->scfunc = do_gotolinecolumn_void;
1444
#ifndef DISABLE_JUSTIFY
Chris Allegretta's avatar
Chris Allegretta committed
1445
    else if (!strcasecmp(input, "justify"))
1446
	s->scfunc = do_justify_void;
1447
1448
    else if (!strcasecmp(input, "fulljustify"))
	s->scfunc = do_full_justify;
1449
    else if (!strcasecmp(input, "beginpara"))
1450
	s->scfunc = do_para_begin_void;
1451
    else if (!strcasecmp(input, "endpara"))
1452
	s->scfunc = do_para_end_void;
1453
#endif
1454
1455
1456
1457
#ifdef ENABLE_COMMENT
    else if (!strcasecmp(input, "comment"))
	s->scfunc = do_comment;
#endif
1458
#ifndef NANO_TINY
1459
    else if (!strcasecmp(input, "indent"))
1460
	s->scfunc = do_indent_void;
1461
    else if (!strcasecmp(input, "unindent"))
1462
	s->scfunc = do_unindent;
Chris Allegretta's avatar
Chris Allegretta committed
1463
    else if (!strcasecmp(input, "scrollup"))
1464
	s->scfunc = do_scroll_up;
Chris Allegretta's avatar
Chris Allegretta committed
1465
    else if (!strcasecmp(input, "scrolldown"))
1466
	s->scfunc = do_scroll_down;
1467
    else if (!strcasecmp(input, "prevword"))
1468
	s->scfunc = do_prev_word_void;
1469
1470
    else if (!strcasecmp(input, "nextword"))
	s->scfunc = do_next_word_void;
1471
1472
1473
1474
    else if (!strcasecmp(input, "cutwordleft"))
	s->scfunc = do_cut_prev_word;
    else if (!strcasecmp(input, "cutwordright"))
	s->scfunc = do_cut_next_word;
1475
1476
1477
1478
    else if (!strcasecmp(input, "prevblock"))
	s->scfunc = do_prev_block;
    else if (!strcasecmp(input, "nextblock"))
	s->scfunc = do_next_block;
1479
    else if (!strcasecmp(input, "findbracket"))
1480
	s->scfunc = do_find_bracket;
1481
    else if (!strcasecmp(input, "wordcount"))
1482
	s->scfunc = do_wordlinechar_count;
1483
    else if (!strcasecmp(input, "undo"))
1484
	s->scfunc = do_undo;
1485
    else if (!strcasecmp(input, "redo"))
1486
	s->scfunc = do_redo;
1487
#endif
Chris Allegretta's avatar
Chris Allegretta committed
1488
    else if (!strcasecmp(input, "left") ||
1489
	     !strcasecmp(input, "back"))
1490
	s->scfunc = do_left;
1491
1492
1493
    else if (!strcasecmp(input, "right") ||
	     !strcasecmp(input, "forward"))
	s->scfunc = do_right;
Chris Allegretta's avatar
Chris Allegretta committed
1494
    else if (!strcasecmp(input, "up") ||
1495
	     !strcasecmp(input, "prevline"))
1496
	s->scfunc = do_up_void;
Chris Allegretta's avatar
Chris Allegretta committed
1497
    else if (!strcasecmp(input, "down") ||
1498
	     !strcasecmp(input, "nextline"))
1499
	s->scfunc = do_down_void;
Chris Allegretta's avatar
Chris Allegretta committed
1500
    else if (!strcasecmp(input, "home"))
1501
	s->scfunc = do_home;
Chris Allegretta's avatar
Chris Allegretta committed
1502
    else if (!strcasecmp(input, "end"))
1503
	s->scfunc = do_end;
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
    else if (!strcasecmp(input, "pageup") ||
	     !strcasecmp(input, "prevpage"))
	s->scfunc = do_page_up;
    else if (!strcasecmp(input, "pagedown") ||
	     !strcasecmp(input, "nextpage"))
	s->scfunc = do_page_down;
    else if (!strcasecmp(input, "firstline"))
	s->scfunc = do_first_line;
    else if (!strcasecmp(input, "lastline"))
	s->scfunc = do_last_line;
1514
#ifndef DISABLE_MULTIBUFFER
Chris Allegretta's avatar
Chris Allegretta committed
1515
    else if (!strcasecmp(input, "prevbuf"))
1516
	s->scfunc = switch_to_prev_buffer_void;
Chris Allegretta's avatar
Chris Allegretta committed
1517
    else if (!strcasecmp(input, "nextbuf"))
1518
	s->scfunc = switch_to_next_buffer_void;
Chris Allegretta's avatar
Chris Allegretta committed
1519
1520
#endif
    else if (!strcasecmp(input, "verbatim"))
1521
	s->scfunc = do_verbatim_input;
Chris Allegretta's avatar
Chris Allegretta committed
1522
    else if (!strcasecmp(input, "tab"))
1523
	s->scfunc = do_tab;
Chris Allegretta's avatar
Chris Allegretta committed
1524
    else if (!strcasecmp(input, "enter"))
1525
	s->scfunc = do_enter;
Chris Allegretta's avatar
Chris Allegretta committed
1526
    else if (!strcasecmp(input, "delete"))
1527
	s->scfunc = do_delete;
1528
    else if (!strcasecmp(input, "backspace"))
1529
	s->scfunc = do_backspace;
Chris Allegretta's avatar
Chris Allegretta committed
1530
    else if (!strcasecmp(input, "refresh"))
1531
	s->scfunc = total_refresh;
1532
1533
    else if (!strcasecmp(input, "suspend"))
	s->scfunc = do_suspend_void;
1534
    else if (!strcasecmp(input, "casesens"))
1535
	s->scfunc = case_sens_void;
1536
    else if (!strcasecmp(input, "regexp") ||
1537
	     !strcasecmp(input, "regex"))  /* Deprecated.  Remove in 2018. */
1538
	s->scfunc = regexp_void;
1539
    else if (!strcasecmp(input, "backwards"))
1540
	s->scfunc = backwards_void;
1541
    else if (!strcasecmp(input, "flipreplace") ||
1542
	     !strcasecmp(input, "dontreplace"))  /* Deprecated.  Remove in 2018. */
1543
	s->scfunc = flip_replace_void;
1544
    else if (!strcasecmp(input, "gototext"))
1545
	s->scfunc = gototext_void;
1546
1547
1548
1549
1550
1551
1552
#ifndef DISABLE_HISTORIES
    else if (!strcasecmp(input, "prevhistory"))
	s->scfunc = get_history_older_void;
    else if (!strcasecmp(input, "nexthistory"))
	s->scfunc = get_history_newer_void;
#endif
    else if (!strcasecmp(input, "dosformat"))
1553
	s->scfunc = dos_format_void;
1554
    else if (!strcasecmp(input, "macformat"))
1555
	s->scfunc = mac_format_void;
1556
    else if (!strcasecmp(input, "append"))
1557
	s->scfunc = append_void;
1558
    else if (!strcasecmp(input, "prepend"))
1559
	s->scfunc = prepend_void;
1560
    else if (!strcasecmp(input, "backup"))
1561
	s->scfunc = backup_file_void;
1562
#ifndef ENABLE_TINY
1563
    else if (!strcasecmp(input, "flipexecute"))
1564
1565
	s->scfunc = flip_execute_void;
#endif
1566
#ifndef DISABLE_MULTIBUFFER
1567
    else if (!strcasecmp(input, "flipnewbuffer") ||
1568
	     !strcasecmp(input, "newbuffer"))  /* Deprecated.  Remove in 2018. */
1569
	s->scfunc = new_buffer_void;
Chris Allegretta's avatar
Chris Allegretta committed
1570
#endif
1571
#ifndef DISABLE_BROWSER
1572
1573
    else if (!strcasecmp(input, "tofiles") ||
	     !strcasecmp(input, "browser"))
1574
	s->scfunc = to_files_void;
1575
    else if (!strcasecmp(input, "gotodir"))
1576
	s->scfunc = goto_dir_void;
1577
    else if (!strcasecmp(input, "firstfile"))
1578
	s->scfunc = do_first_file;
1579
    else if (!strcasecmp(input, "lastfile"))
1580
1581
	s->scfunc = do_last_file;
#endif
1582
    else {
1583
#ifndef NANO_TINY
1584
	s->scfunc = do_toggle_void;
1585
	if (!strcasecmp(input, "nohelp"))
1586
	    s->toggle = NO_HELP;
1587
	else if (!strcasecmp(input, "constupdate"))
1588
	    s->toggle = CONST_UPDATE;
1589
	else if (!strcasecmp(input, "morespace"))
1590
	    s->toggle = MORE_SPACE;
1591
	else if (!strcasecmp(input, "smoothscroll"))
1592
	    s->toggle = SMOOTH_SCROLL;
1593
	else if (!strcasecmp(input, "softwrap"))
1594
	    s->toggle = SOFTWRAP;
1595
	else if (!strcasecmp(input, "whitespacedisplay"))
1596
	    s->toggle = WHITESPACE_DISPLAY;
1597
#ifndef DISABLE_COLOR
1598
	else if (!strcasecmp(input, "nosyntax"))
1599
1600
	    s->toggle = NO_COLOR_SYNTAX;
#endif
1601
	else if (!strcasecmp(input, "smarthome"))
1602
	    s->toggle = SMART_HOME;
1603
	else if (!strcasecmp(input, "autoindent"))
1604
	    s->toggle = AUTOINDENT;
1605
	else if (!strcasecmp(input, "cuttoend"))
1606
	    s->toggle = CUT_TO_END;
1607
#ifndef DISABLE_WRAPPING
1608
	else if (!strcasecmp(input, "nowrap"))
1609
	    s->toggle = NO_WRAP;
1610
#endif
1611
	else if (!strcasecmp(input, "tabstospaces"))
1612
	    s->toggle = TABS_TO_SPACES;
1613
	else if (!strcasecmp(input, "backupfile"))
1614
	    s->toggle = BACKUP_FILE;
1615
#ifndef DISABLE_MULTIBUFFER
1616
	else if (!strcasecmp(input, "multibuffer"))
1617
	    s->toggle = MULTIBUFFER;
1618
1619
#endif
#ifndef DISABLE_MOUSE
1620
	else if (!strcasecmp(input, "mouse"))
1621
	    s->toggle = USE_MOUSE;
1622
#endif
1623
	else if (!strcasecmp(input, "noconvert"))
1624
	    s->toggle = NO_CONVERT;
1625
	else if (!strcasecmp(input, "suspendenable"))
1626
	    s->toggle = SUSPEND;
1627
	else
1628
#endif /* !NANO_TINY */
1629
	{
1630
1631
1632
	    free(s);
	    return NULL;
	}
1633
1634
1635
    }
    return s;
}
1636

1637
/* Interpret a menu name and return the corresponding menu flag. */
1638
int strtomenu(const char *input)
1639
1640
{
    if (!strcasecmp(input, "all"))
1641
	return (MMOST|MHELP|MYESNO);
1642
1643
1644
1645
1646
1647
    else if (!strcasecmp(input, "main"))
	return MMAIN;
    else if (!strcasecmp(input, "search"))
	return MWHEREIS;
    else if (!strcasecmp(input, "replace"))
	return MREPLACE;
1648
    else if (!strcasecmp(input, "replace2") ||  /* Deprecated.  Remove in 2018. */
Benno Schulenberg's avatar
Benno Schulenberg committed
1649
	     !strcasecmp(input, "replacewith"))
1650
	return MREPLACEWITH;
1651
1652
1653
1654
1655
1656
1657
    else if (!strcasecmp(input, "gotoline"))
	return MGOTOLINE;
    else if (!strcasecmp(input, "writeout"))
	return MWRITEFILE;
    else if (!strcasecmp(input, "insert"))
	return MINSERTFILE;
    else if (!strcasecmp(input, "externalcmd") ||
Benno Schulenberg's avatar
Benno Schulenberg committed
1658
	     !strcasecmp(input, "extcmd"))
1659
	return MEXTCMD;
1660
#ifndef DISABLE_HELP
1661
1662
    else if (!strcasecmp(input, "help"))
	return MHELP;
1663
1664
#endif
#ifndef DISABLE_SPELLER
1665
    else if (!strcasecmp(input, "spell"))
1666
	return MSPELL;
1667
#endif
1668
1669
    else if (!strcasecmp(input, "linter"))
	return MLINTER;
1670
#ifndef DISABLE_BROWSER
1671
1672
1673
1674
1675
1676
    else if (!strcasecmp(input, "browser"))
	return MBROWSER;
    else if (!strcasecmp(input, "whereisfile"))
	return MWHEREISFILE;
    else if (!strcasecmp(input, "gotodir"))
	return MGOTODIR;
1677
#endif
1678
1679
    return -1;
}
1680
#endif /* !DISABLE_NANORC */
1681

Chris Allegretta's avatar
Chris Allegretta committed
1682

1683
1684
1685
#ifdef DEBUG
/* This function is used to gracefully return all the memory we've used.
 * It should be called just before calling exit().  Practically, the
1686
1687
 * only effect is to cause a segmentation fault if the various data
 * structures got bolloxed earlier.  Thus, we don't bother having this
Chris Allegretta's avatar
Chris Allegretta committed
1688
1689
 * function unless debugging is turned on. */
void thanks_for_all_the_fish(void)
1690
{
1691
1692
1693
1694
    delwin(topwin);
    delwin(edit);
    delwin(bottomwin);

1695
    free(word_chars);
Chris Allegretta's avatar
Chris Allegretta committed
1696
#ifndef DISABLE_JUSTIFY
1697
    free(quotestr);
1698
1699
#ifdef HAVE_REGEX_H
    regfree(&quotereg);
1700
    free(quoteerr);
1701
#endif
Chris Allegretta's avatar
Chris Allegretta committed
1702
#endif
1703
#ifndef NANO_TINY
1704
    free(backup_dir);
1705
#endif
Chris Allegretta's avatar
Chris Allegretta committed
1706
#ifndef DISABLE_OPERATINGDIR
1707
1708
    free(operating_dir);
    free(full_operating_dir);
1709
#endif
1710
    free(answer);
1711
    free(last_search);
1712
    free(present_path);
1713
#ifndef DISABLE_SPELLER
1714
    free(alt_speller);
1715
#endif
1716
    free_filestruct(cutbuffer);
David Lawrence Ramsey's avatar
David Lawrence Ramsey committed
1717
    /* Free the memory associated with each open file buffer. */
1718
1719
1720
1721
1722
    while (openfile != openfile->next) {
	openfile = openfile->next;
	delete_opennode(openfile->prev);
    }
    delete_opennode(openfile);
1723
#ifndef DISABLE_COLOR
1724
    free(syntaxstr);
Chris Allegretta's avatar
Chris Allegretta committed
1725
    while (syntaxes != NULL) {
1726
1727
	syntaxtype *sint = syntaxes;
	syntaxes = syntaxes->next;
Chris Allegretta's avatar
Chris Allegretta committed
1728

1729
1730
1731
	free(sint->name);
	free(sint->linter);
	free(sint->formatter);
1732

1733
1734
1735
1736
1737
	while (sint->extensions != NULL) {
	    regexlisttype *item = sint->extensions;
	    sint->extensions = sint->extensions->next;
	    free(item->full_regex);
	    free(item);
Chris Allegretta's avatar
Chris Allegretta committed
1738
	}
1739
1740
1741
1742
1743
	while (sint->headers != NULL) {
	    regexlisttype *item = sint->headers;
	    sint->headers = sint->headers->next;
	    free(item->full_regex);
	    free(item);
1744
	}
1745
1746
1747
1748
1749
	while (sint->magics != NULL) {
	    regexlisttype *item = sint->magics;
	    sint->magics = sint->magics->next;
	    free(item->full_regex);
	    free(item);
1750
	}
1751

1752
1753
1754
1755
1756
1757
1758
	while (sint->color != NULL) {
	    colortype *ink = sint->color;
	    sint->color = sint->color->next;
	    free(ink->start_regex);
	    if (ink->start != NULL) {
		regfree(ink->start);
		free(ink->start);
1759
	    }
1760
1761
1762
1763
	    free(ink->end_regex);
	    if (ink->end != NULL) {
		regfree(ink->end);
		free(ink->end);
1764
	    }
1765
	    free(ink);
Chris Allegretta's avatar
Chris Allegretta committed
1766
	}
1767
1768

	free(sint);
Chris Allegretta's avatar
Chris Allegretta committed
1769
    }
1770
#endif /* !DISABLE_COLOR */
1771
#ifndef DISABLE_HISTORIES
1772
    /* Free the search and replace history lists. */
1773
1774
    free_filestruct(searchage);
    free_filestruct(replaceage);
1775
#endif
1776
    /* Free the list of functions. */
1777
    while (allfuncs != NULL) {
1778
1779
1780
	subnfunc *f = allfuncs;
	allfuncs = allfuncs->next;
	free(f);
1781
    }
1782
    /* Free the list of shortcuts. */
1783
    while (sclist != NULL) {
1784
1785
1786
	sc *s = sclist;
	sclist = sclist->next;
	free(s);
1787
    }
1788
#ifndef DISABLE_NANORC
1789
    free(homedir);
1790
#endif
1791
}
1792
#endif /* DEBUG */