1 /**************************************************************************
2  *   global.c  --  This file is part of GNU nano.                         *
3  *                                                                        *
4  *   Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.    *
5  *   Copyright (C) 2014-2020 Benno Schulenberg                            *
6  *                                                                        *
7  *   GNU nano is free software: you can redistribute it and/or modify     *
8  *   it under the terms of the GNU General Public License as published    *
9  *   by the Free Software Foundation, either version 3 of the License,    *
10  *   or (at your option) any later version.                               *
11  *                                                                        *
12  *   GNU nano is distributed in the hope that it will be useful,          *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty          *
14  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.              *
15  *   See the GNU General Public License for more details.                 *
16  *                                                                        *
17  *   You should have received a copy of the GNU General Public License    *
18  *   along with this program.  If not, see http://www.gnu.org/licenses/.  *
19  *                                                                        *
20  **************************************************************************/
21 
22 #include "prototypes.h"
23 
24 #include <ctype.h>
25 #include <string.h>
26 #include <strings.h>
27 
28 /* Global variables. */
29 #ifndef NANO_TINY
30 volatile sig_atomic_t the_window_resized = FALSE;
31 		/* Set to TRUE by the handler whenever a SIGWINCH occurs. */
32 #endif
33 
34 bool on_a_vt = FALSE;
35 		/* Whether we're running on a Linux console (a VT). */
36 bool shifted_metas = FALSE;
37 		/* Whether any Sh-M-<letter> combo has been bound. */
38 
39 bool meta_key;
40 		/* Whether the current keystroke is a Meta key. */
41 bool shift_held;
42 		/* Whether Shift was being held together with a movement key. */
43 bool mute_modifiers = FALSE;
44 		/* Whether to ignore modifier keys while running a macro or string bind. */
45 bool bracketed_paste = FALSE;
46 		/* Whether text is being pasted into nano from outside. */
47 
48 bool we_are_running = FALSE;
49 		/* Becomes TRUE as soon as all options and files have been read. */
50 bool more_than_one = FALSE;
51 		/* Whether more than one buffer is or has been open. */
52 bool report_size = TRUE;
53 		/* Whether to show the number of lines when the minibar is used. */
54 bool ran_a_tool = FALSE;
55 		/* Whether a tool has been run at the Execute-Command prompt. */
56 
57 bool inhelp = FALSE;
58 		/* Whether we are in the help viewer. */
59 char *title = NULL;
60 		/* When not NULL: the title of the current help text. */
61 
62 bool refresh_needed = FALSE;
63 		/* Did a command mangle enough of the buffer that we should
64 		 * repaint the screen? */
65 bool focusing = TRUE;
66 		/* Whether an update of the edit window should center the cursor. */
67 
68 bool as_an_at = TRUE;
69 		/* Whether a 0x0A byte should be shown as a ^@ instead of a ^J. */
70 
71 bool control_C_was_pressed = FALSE;
72 		/* Whether Ctrl+C was pressed (when a keyboard interrupt is enabled). */
73 
74 message_type lastmessage = VACUUM;
75 		/* Messages of type HUSH should not overwrite type MILD nor ALERT. */
76 
77 linestruct *pletion_line = NULL;
78 		/* The line where the last completion was found, if any. */
79 
80 bool also_the_last = FALSE;
81 		/* Whether indenting/commenting should include the last line of
82 		 * the marked region. */
83 bool hide_cursor = FALSE;
84 		/* Whether to suppress the cursor when highlighting a search match. */
85 
86 char *answer = NULL;
87 		/* The answer string used by the status-bar prompt. */
88 
89 char *last_search = NULL;
90 		/* The last string we searched for. */
91 int didfind = 0;
92 		/* Whether the last search found something. */
93 
94 char *present_path = NULL;
95 		/* The current browser directory when trying to do tab completion. */
96 
97 unsigned flags[4] = {0, 0, 0, 0};
98 		/* Our flags array, containing the states of all global options. */
99 
100 int controlleft, controlright, controlup, controldown;
101 int controlhome, controlend;
102 #ifndef NANO_TINY
103 int controldelete, controlshiftdelete;
104 int shiftleft, shiftright, shiftup, shiftdown;
105 int shiftcontrolleft, shiftcontrolright, shiftcontrolup, shiftcontroldown;
106 int shiftcontrolhome, shiftcontrolend;
107 int altleft, altright, altup, altdown;
108 int altpageup, altpagedown;
109 int altinsert, altdelete;
110 int shiftaltleft, shiftaltright, shiftaltup, shiftaltdown;
111 #endif
112 
113 #ifdef ENABLED_WRAPORJUSTIFY
114 ssize_t fill = -COLUMNS_FROM_EOL;
115 		/* The relative column where we will wrap lines. */
116 size_t wrap_at = 0;
117 		/* The actual column where we will wrap lines, based on fill. */
118 #endif
119 
120 WINDOW *topwin = NULL;
121 		/* The top portion of the screen, showing the version number of nano,
122 		 * the name of the file, and whether the buffer was modified. */
123 WINDOW *edit = NULL;
124 		/* The middle portion of the screen: the edit window, showing the
125 		 * contents of the current buffer, the file we are editing. */
126 WINDOW *bottomwin = NULL;
127 		/* The bottom portion of the screen, where we display statusbar
128 		 * messages, the status-bar prompt, and a list of shortcuts. */
129 int editwinrows = 0;
130 		/* How many rows does the edit window take up? */
131 int editwincols = -1;
132 		/* The number of usable columns in the edit window: COLS - margin. */
133 int margin = 0;
134 		/* The amount of space reserved at the left for line numbers. */
135 int thebar = 0;
136 		/* Becomes 1 when a scrollbar is shown. */
137 #ifndef NANO_TINY
138 int *bardata = NULL;
139 		/* An array of characters that together depict the scrollbar. */
140 ssize_t stripe_column = 0;
141 		/* The column at which a vertical bar will be drawn. */
142 #endif
143 
144 linestruct *cutbuffer = NULL;
145 		/* The buffer where we store cut text. */
146 linestruct *cutbottom = NULL;
147 		/* The last line in the cutbuffer. */
148 bool keep_cutbuffer = FALSE;
149 		/* Whether to add to the cutbuffer instead of clearing it first. */
150 
151 openfilestruct *openfile = NULL;
152 		/* The list of all open file buffers. */
153 #ifdef ENABLE_MULTIBUFFER
154 openfilestruct *startfile = NULL;
155 		/* The first open buffer. */
156 #endif
157 
158 #ifndef NANO_TINY
159 char *matchbrackets = NULL;
160 		/* The opening and closing brackets that bracket searches can find. */
161 char *whitespace = NULL;
162 		/* The characters used when visibly showing tabs and spaces. */
163 int whitelen[2];
164 		/* The length in bytes of these characters. */
165 #endif
166 
167 #ifdef ENABLE_JUSTIFY
168 char *punct = NULL;
169 		/* The closing punctuation that can end sentences. */
170 char *brackets = NULL;
171 		/* The closing brackets that can follow closing punctuation and
172 		 * can end sentences. */
173 char *quotestr = NULL;
174 		/* The quoting string.  The default value is set in main(). */
175 regex_t quotereg;
176 		/* The compiled regular expression from the quoting string. */
177 #endif
178 
179 char *word_chars = NULL;
180 		/* Nonalphanumeric characters that also form words. */
181 
182 ssize_t tabsize = -1;
183 		/* The width of a tab in spaces.  The default is set in main(). */
184 
185 #ifndef NANO_TINY
186 char *backup_dir = NULL;
187 		/* The directory where we store backup files. */
188 #endif
189 #ifdef ENABLE_OPERATINGDIR
190 char *operating_dir = NULL;
191 		/* The path to our confining "operating" directory, when given. */
192 #endif
193 
194 #ifdef ENABLE_SPELLER
195 char *alt_speller = NULL;
196 		/* The command to use for the alternate spell checker. */
197 #endif
198 
199 #ifdef ENABLE_COLOR
200 syntaxtype *syntaxes = NULL;
201 		/* The global list of color syntaxes. */
202 char *syntaxstr = NULL;
203 		/* The color syntax name specified on the command line. */
204 bool have_palette = FALSE;
205 		/* Whether the colors for the current syntax have been initialized. */
206 #endif
207 
208 int currmenu = MMOST;
209 		/* The currently active menu, initialized to a dummy value. */
210 keystruct *sclist = NULL;
211 		/* The start of the shortcuts list. */
212 funcstruct *allfuncs = NULL;
213 		/* The start of the functions list. */
214 funcstruct *tailfunc;
215 		/* The last function in the list. */
216 funcstruct *exitfunc;
217 		/* A pointer to the special Exit/Close item. */
218 
219 linestruct *search_history = NULL;
220 		/* The current item in the list of strings that were searched for. */
221 linestruct *execute_history = NULL;
222 		/* The current item in the list of commands that were run with ^R ^X. */
223 linestruct *replace_history = NULL;
224 		/* The current item in the list of replace strings. */
225 #ifdef ENABLE_HISTORIES
226 linestruct *searchtop = NULL;
227 		/* The oldest item in the list of search strings. */
228 linestruct *searchbot = NULL;
229 		/* The newest item in the list of search strings. */
230 
231 linestruct *replacetop = NULL;
232 linestruct *replacebot = NULL;
233 
234 linestruct *executetop = NULL;
235 linestruct *executebot = NULL;
236 #endif
237 
238 regex_t search_regexp;
239 		/* The compiled regular expression to use in searches. */
240 regmatch_t regmatches[10];
241 		/* The match positions for parenthetical subexpressions, 10
242 		 * maximum, used in regular expression searches. */
243 
244 int hilite_attribute = A_REVERSE;
245 		/* The curses attribute we use to highlight something. */
246 #ifdef ENABLE_COLOR
247 colortype* color_combo[NUMBER_OF_ELEMENTS] = {NULL};
248 		/* The color combinations for interface elements given in the rcfile. */
249 #endif
250 int interface_color_pair[NUMBER_OF_ELEMENTS] = {0};
251 		/* The processed color pairs for the interface elements. */
252 
253 char *homedir = NULL;
254 		/* The user's home directory, from $HOME or /etc/passwd. */
255 char *statedir = NULL;
256 		/* The directory for nano's history files. */
257 
258 #if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
259 char *startup_problem = NULL;
260 		/* An error message (if any) about nanorc files or history files. */
261 #endif
262 #ifdef ENABLE_NANORC
263 char *custom_nanorc = NULL;
264 #endif
265 
266 bool spotlighted = FALSE;
267 	/* Whether any text is spotlighted. */
268 size_t light_from_col = 0;
269 	/* Where the spotlighted text starts. */
270 size_t light_to_col = 0;
271 	/* Where the spotlighted text ends. */
272 
273 /* To make the functions and shortcuts lists clearer. */
274 #define VIEW  TRUE    /* Is allowed in view mode. */
275 #define NOVIEW  FALSE
276 #define BLANKAFTER  TRUE    /* A blank line after this one. */
277 #define TOGETHER  FALSE
278 #ifdef ENABLE_MULTIBUFFER
279 #define CAN_OPEN_OTHER_BUFFER  TRUE
280 #else
281 #define CAN_OPEN_OTHER_BUFFER  FALSE
282 #endif
283 
284 /* Empty functions, for the most part corresponding to toggles. */
case_sens_void(void)285 void case_sens_void(void)
286 {
287 }
regexp_void(void)288 void regexp_void(void)
289 {
290 }
backwards_void(void)291 void backwards_void(void)
292 {
293 }
flip_replace(void)294 void flip_replace(void)
295 {
296 }
flip_goto(void)297 void flip_goto(void)
298 {
299 }
300 #ifdef ENABLE_BROWSER
to_files(void)301 void to_files(void)
302 {
303 }
goto_dir(void)304 void goto_dir(void)
305 {
306 }
307 #endif
308 #ifndef NANO_TINY
do_nothing(void)309 void do_nothing(void)
310 {
311 }
do_toggle_void(void)312 void do_toggle_void(void)
313 {
314 }
dos_format_void(void)315 void dos_format_void(void)
316 {
317 }
mac_format_void(void)318 void mac_format_void(void)
319 {
320 }
append_void(void)321 void append_void(void)
322 {
323 }
prepend_void(void)324 void prepend_void(void)
325 {
326 }
backup_file_void(void)327 void backup_file_void(void)
328 {
329 }
flip_execute(void)330 void flip_execute(void)
331 {
332 }
flip_pipe(void)333 void flip_pipe(void)
334 {
335 }
flip_convert(void)336 void flip_convert(void)
337 {
338 }
339 #endif
340 #ifdef ENABLE_MULTIBUFFER
flip_newbuffer(void)341 void flip_newbuffer(void)
342 {
343 }
344 #endif
discard_buffer(void)345 void discard_buffer(void)
346 {
347 }
do_cancel(void)348 void do_cancel(void)
349 {
350 }
351 
352 /* Add a function to the linked list of functions. */
add_to_funcs(void (* func)(void),int menus,const char * desc,const char * help,bool blank_after,bool viewok)353 void add_to_funcs(void (*func)(void), int menus, const char *desc,
354 					const char *help, bool blank_after, bool viewok)
355 {
356 	funcstruct *f = nmalloc(sizeof(funcstruct));
357 
358 	if (allfuncs == NULL)
359 		allfuncs = f;
360 	else
361 		tailfunc->next = f;
362 	tailfunc = f;
363 
364 	f->next = NULL;
365 	f->func = func;
366 	f->menus = menus;
367 	f->desc = desc;
368 	f->viewok = viewok;
369 #ifdef ENABLE_HELP
370 	f->help = help;
371 	f->blank_after = blank_after;
372 #endif
373 }
374 
375 /* Parse the given keystring and return the corresponding keycode,
376  * or return -1 when the string is invalid. */
keycode_from_string(const char * keystring)377 int keycode_from_string(const char *keystring)
378 {
379 	if (keystring[0] == '^') {
380 		if (keystring[2] == '\0') {
381 			if (keystring[1] == '/' || keystring[1] == '-')
382 				return 31;
383 			if (keystring[1] <= '_')
384 				return keystring[1] - 64;
385 			if (keystring[1] == '`')
386 				return 0;
387 			else
388 				return -1;
389 		} else if (strcasecmp(keystring, "^Space") == 0)
390 			return 0;
391 		else
392 			return -1;
393 	} else if (keystring[0] == 'M') {
394 		if (keystring[1] == '-' && keystring[3] == '\0')
395 			return tolower((unsigned char)keystring[2]);
396 		if (strcasecmp(keystring, "M-Space") == 0)
397 			return (int)' ';
398 		else
399 			return -1;
400 #ifdef ENABLE_NANORC
401 	} else if (strncasecmp(keystring, "Sh-M-", 5) == 0 &&
402 				'a' <= (keystring[5] | 0x20) && (keystring[5] | 0x20) <= 'z' &&
403 				keystring[6] == '\0') {
404 		shifted_metas = TRUE;
405 		return (keystring[5] & 0x5F);
406 #endif
407 	} else if (keystring[0] == 'F') {
408 		int fn = atoi(&keystring[1]);
409 		if (fn < 1 || fn > 24)
410 			return -1;
411 		return KEY_F0 + fn;
412 	} else if (strcasecmp(keystring, "Ins") == 0)
413 		return KEY_IC;
414 	else if (strcasecmp(keystring, "Del") == 0)
415 		return KEY_DC;
416 	else
417 		return -1;
418 }
419 
420 /* Add a key combo to the linked list of shortcuts. */
add_to_sclist(int menus,const char * scstring,const int keycode,void (* func)(void),int toggle)421 void add_to_sclist(int menus, const char *scstring, const int keycode,
422 						void (*func)(void), int toggle)
423 {
424 	static keystruct *tailsc;
425 #ifndef NANO_TINY
426 	static int counter = 0;
427 #endif
428 	keystruct *sc = nmalloc(sizeof(keystruct));
429 
430 	/* Start the list, or tack on the next item. */
431 	if (sclist == NULL)
432 		sclist = sc;
433 	else
434 		tailsc->next = sc;
435 	sc->next = NULL;
436 
437 	/* Fill in the data. */
438 	sc->menus = menus;
439 	sc->func = func;
440 #ifndef NANO_TINY
441 	sc->toggle = toggle;
442 	/* When not the same toggle as the previous one, increment the ID. */
443 	if (toggle)
444 		sc->ordinal = (tailsc->toggle == toggle) ? counter : ++counter;
445 #endif
446 	sc->keystr = scstring;
447 	sc->keycode = (keycode ? keycode : keycode_from_string(scstring));
448 
449 	tailsc = sc;
450 }
451 
452 /* Return the first shortcut in the list of shortcuts that
453  * matches the given func in the given menu. */
first_sc_for(int menu,void (* func)(void))454 const keystruct *first_sc_for(int menu, void (*func)(void))
455 {
456 	for (keystruct *sc = sclist; sc != NULL; sc = sc->next)
457 		if ((sc->menus & menu) && sc->func == func && sc->keystr[0])
458 			return sc;
459 
460 	return NULL;
461 }
462 
463 /* Return the number of entries that can be shown in the given menu. */
shown_entries_for(int menu)464 size_t shown_entries_for(int menu)
465 {
466 	funcstruct *item = allfuncs;
467 	size_t maximum = ((COLS + 40) / 20) * 2;
468 	size_t count = 0;
469 
470 	while (count < maximum && item != NULL) {
471 		if (item->menus & menu)
472 			count++;
473 		item = item->next;
474 	}
475 
476 	/* When --saveonexit is not used, widen the grid of the WriteOut menu. */
477 	if (menu == MWRITEFILE && item == NULL &&
478 						first_sc_for(menu, discard_buffer) == NULL)
479 		count--;
480 
481 	return count;
482 }
483 
484 /* Return the first shortcut in the current menu that matches the given input. */
get_shortcut(int * keycode)485 const keystruct *get_shortcut(int *keycode)
486 {
487 	/* Plain characters and upper control codes cannot be shortcuts. */
488 	if (!meta_key && 0x20 <= *keycode && *keycode <= 0xFF)
489 		return NULL;
490 
491 	/* Lower control codes with Meta cannot be shortcuts either. */
492 	if (meta_key && *keycode < 0x20)
493 		return NULL;
494 
495 #ifndef NANO_TINY
496 	/* During a paste at a prompt, ignore all command keycodes. */
497 	if (bracketed_paste && *keycode != BRACKETED_PASTE_MARKER)
498 		return NULL;
499 #endif
500 
501 	for (keystruct *sc = sclist; sc != NULL; sc = sc->next) {
502 		if ((sc->menus & currmenu) && *keycode == sc->keycode)
503 			return sc;
504 	}
505 
506 	return NULL;
507 }
508 
509 /* Return a pointer to the function that is bound to the given key. */
func_from_key(int * keycode)510 functionptrtype func_from_key(int *keycode)
511 {
512 	const keystruct *sc = get_shortcut(keycode);
513 
514 	return (sc) ? sc->func : NULL;
515 }
516 
517 #if defined(ENABLE_BROWSER) || defined(ENABLE_HELP)
518 /* Return the function that is bound to the given key in the file browser or
519  * the help viewer.  Accept also certain plain characters, for compatibility
520  * with Pico or to mimic 'less' and similar text viewers. */
interpret(int * keycode)521 functionptrtype interpret(int *keycode)
522 {
523 	if (!meta_key) {
524 		if (*keycode == 'N')
525 			return do_findprevious;
526 		if (*keycode == 'n')
527 			return do_findnext;
528 
529 		switch (tolower(*keycode)) {
530 			case 'b':
531 			case '-':
532 				return do_page_up;
533 			case ' ':
534 				return do_page_down;
535 			case 'w':
536 			case '/':
537 				return do_search_forward;
538 #ifdef ENABLE_BROWSER
539 			case 'g':
540 				return goto_dir;
541 #endif
542 			case '?':
543 				return do_help;
544 			case 's':
545 				return do_enter;
546 			case 'e':
547 			case 'q':
548 			case 'x':
549 				return do_exit;
550 		}
551 	}
552 
553 	return func_from_key(keycode);
554 }
555 #endif /* ENABLE_BROWSER || ENABLE_HELP */
556 
557 /* These two tags are used elsewhere too, so they are global. */
558 /* TRANSLATORS: Try to keep the next two strings at most 10 characters. */
559 const char *exit_tag = N_("Exit");
560 const char *close_tag = N_("Close");
561 
562 /* Initialize the list of functions and the list of shortcuts. */
shortcut_init(void)563 void shortcut_init(void)
564 {
565 #ifdef ENABLE_HELP
566 	/* TRANSLATORS: The next long series of strings are shortcut descriptions;
567 	 * they are best kept shorter than 56 characters, but may be longer. */
568 	const char *cancel_gist = N_("Cancel the current function");
569 	const char *help_gist = N_("Display this help text");
570 	const char *exit_gist = N_("Close the current buffer / Exit from nano");
571 	const char *writeout_gist =
572 		N_("Write the current buffer (or the marked region) to disk");
573 	const char *readfile_gist =
574 		N_("Insert another file into current buffer (or into new buffer)");
575 	const char *whereis_gist =
576 		N_("Search forward for a string or a regular expression");
577 	const char *wherewas_gist =
578 		N_("Search backward for a string or a regular expression");
579 	const char *cut_gist =
580 		N_("Cut current line (or marked region) and store it in cutbuffer");
581 	const char *paste_gist =
582 		N_("Paste the contents of cutbuffer at current cursor position");
583 	const char *cursorpos_gist = N_("Display the position of the cursor");
584 #ifdef ENABLE_SPELLER
585 	const char *spell_gist = N_("Invoke the spell checker, if available");
586 #endif
587 	const char *replace_gist = N_("Replace a string or a regular expression");
588 	const char *gotoline_gist = N_("Go to line and column number");
589 #ifndef NANO_TINY
590 	const char *mark_gist = N_("Mark text starting from the cursor position");
591 	const char *copy_gist =
592 		N_("Copy current line (or marked region) and store it in cutbuffer");
593 	const char *zap_gist = N_("Throw away the current line (or marked region)");
594 	const char *indent_gist = N_("Indent the current line (or marked lines)");
595 	const char *unindent_gist = N_("Unindent the current line (or marked lines)");
596 	const char *undo_gist = N_("Undo the last operation");
597 	const char *redo_gist = N_("Redo the last undone operation");
598 #endif
599 	const char *back_gist = N_("Go back one character");
600 	const char *forward_gist = N_("Go forward one character");
601 	const char *prevword_gist = N_("Go back one word");
602 	const char *nextword_gist = N_("Go forward one word");
603 	const char *prevline_gist = N_("Go to previous line");
604 	const char *nextline_gist = N_("Go to next line");
605 	const char *home_gist = N_("Go to beginning of current line");
606 	const char *end_gist = N_("Go to end of current line");
607 	const char *prevblock_gist = N_("Go to previous block of text");
608 	const char *nextblock_gist = N_("Go to next block of text");
609 #ifdef ENABLE_JUSTIFY
610 	const char *parabegin_gist =
611 		N_("Go to beginning of paragraph; then of previous paragraph");
612 	const char *paraend_gist =
613 		N_("Go just beyond end of paragraph; then of next paragraph");
614 #endif
615 	const char *prevpage_gist = N_("Go one screenful up");
616 	const char *nextpage_gist = N_("Go one screenful down");
617 	const char *firstline_gist = N_("Go to the first line of the file");
618 	const char *lastline_gist = N_("Go to the last line of the file");
619 #ifndef NANO_TINY
620 	const char *bracket_gist = N_("Go to the matching bracket");
621 #endif
622 #if !defined(NANO_TINY) || defined(ENABLE_HELP)
623 	const char *scrollup_gist =
624 		N_("Scroll up one line without moving the cursor textually");
625 	const char *scrolldown_gist =
626 		N_("Scroll down one line without moving the cursor textually");
627 	const char *center_gist = N_("Center the line where the cursor is");
628 #endif
629 #ifdef ENABLE_MULTIBUFFER
630 	const char *prevfile_gist = N_("Switch to the previous file buffer");
631 	const char *nextfile_gist = N_("Switch to the next file buffer");
632 #endif
633 	const char *verbatim_gist = N_("Insert the next keystroke verbatim");
634 	const char *tab_gist = N_("Insert a tab at the cursor position");
635 	const char *enter_gist = N_("Insert a newline at the cursor position");
636 	const char *delete_gist = N_("Delete the character under the cursor");
637 	const char *backspace_gist =
638 		N_("Delete the character to the left of the cursor");
639 #ifndef NANO_TINY
640 	const char *chopwordleft_gist =
641 		N_("Delete backward from cursor to word start");
642 	const char *chopwordright_gist =
643 		N_("Delete forward from cursor to next word start");
644 	const char *cuttilleof_gist =
645 		N_("Cut from the cursor position to the end of the file");
646 #endif
647 #ifdef ENABLE_JUSTIFY
648 	const char *justify_gist = N_("Justify the current paragraph");
649 	const char *fulljustify_gist = N_("Justify the entire file");
650 #endif
651 #ifndef NANO_TINY
652 	const char *wordcount_gist =
653 		N_("Count the number of words, lines, and characters");
654 #endif
655 	const char *refresh_gist = N_("Refresh (redraw) the current screen");
656 	const char *suspend_gist = N_("Suspend the editor (if suspension is enabled)");
657 #ifdef ENABLE_WORDCOMPLETION
658 	const char *completion_gist = N_("Try and complete the current word");
659 #endif
660 #ifdef ENABLE_COMMENT
661 	const char *comment_gist =
662 		N_("Comment/uncomment the current line (or marked lines)");
663 #endif
664 	const char *savefile_gist = N_("Save file without prompting");
665 	const char *findprev_gist = N_("Search next occurrence backward");
666 	const char *findnext_gist = N_("Search next occurrence forward");
667 #ifndef NANO_TINY
668 	const char *recordmacro_gist = N_("Start/stop recording a macro");
669 	const char *runmacro_gist = N_("Run the last recorded macro");
670 	const char *anchor_gist = N_("Place or remove an anchor at the current line");
671 	const char *prevanchor_gist = N_("Jump backward to the nearest anchor");
672 	const char *nextanchor_gist = N_("Jump forward to the nearest anchor");
673 #endif
674 	const char *case_gist = N_("Toggle the case sensitivity of the search");
675 	const char *reverse_gist = N_("Reverse the direction of the search");
676 	const char *regexp_gist = N_("Toggle the use of regular expressions");
677 #ifdef ENABLE_HISTORIES
678 	const char *older_gist = N_("Recall the previous search/replace string");
679 	const char *newer_gist = N_("Recall the next search/replace string");
680 #endif
681 #ifndef NANO_TINY
682 	const char *dos_gist = N_("Toggle the use of DOS format");
683 	const char *mac_gist = N_("Toggle the use of Mac format");
684 	const char *append_gist = N_("Toggle appending");
685 	const char *prepend_gist = N_("Toggle prepending");
686 	const char *backup_gist = N_("Toggle backing up of the original file");
687 	const char *execute_gist = N_("Execute a function or an external command");
688 	const char *pipe_gist =
689 		N_("Pipe the current buffer (or marked region) to the command");
690 	const char *convert_gist = N_("Do not convert from DOS/Mac format");
691 #endif
692 #ifdef ENABLE_MULTIBUFFER
693 	const char *newbuffer_gist = N_("Toggle the use of a new buffer");
694 #endif
695 	const char *discardbuffer_gist = N_("Close buffer without saving it");
696 #ifdef ENABLE_BROWSER
697 	const char *tofiles_gist = N_("Go to file browser");
698 	const char *exitbrowser_gist = N_("Exit from the file browser");
699 	const char *firstfile_gist = N_("Go to the first file in the list");
700 	const char *lastfile_gist = N_("Go to the last file in the list");
701 	const char *backfile_gist = N_("Go to the previous file in the list");
702 	const char *forwardfile_gist = N_("Go to the next file in the list");
703 #ifndef NANO_TINY
704 	const char *browserlefthand_gist = N_("Go to lefthand column");
705 	const char *browserrighthand_gist = N_("Go to righthand column");
706 	const char *browsertoprow_gist = N_("Go to first row in this column");
707 	const char *browserbottomrow_gist = N_("Go to last row in this column");
708 #endif
709 	const char *browserwhereis_gist = N_("Search forward for a string");
710 	const char *browserwherewas_gist = N_("Search backward for a string");
711 	const char *browserrefresh_gist = N_("Refresh the file list");
712 	const char *gotodir_gist = N_("Go to directory");
713 #endif
714 #ifdef ENABLE_COLOR
715 	const char *lint_gist = N_("Invoke the linter, if available");
716 	const char *prevlint_gist = N_("Go to previous linter msg");
717 	const char *nextlint_gist = N_("Go to next linter msg");
718 	const char *formatter_gist =
719 		N_("Invoke a program to format/arrange/manipulate the buffer");
720 #endif
721 #endif /* ENABLE_HELP */
722 
723 #ifdef ENABLE_HELP
724 #define WITHORSANS(help)  help
725 #else
726 #define WITHORSANS(help)  ""
727 #endif
728 
729 	/* Start populating the different menus with functions. */
730 #ifdef ENABLE_HELP
731 	add_to_funcs(do_help, (MMOST | MBROWSER) & ~MFINDINHELP,
732 		/* TRANSLATORS: Try to keep the next thirteen strings at most 10 characters. */
733 		N_("Help"), WITHORSANS(help_gist), TOGETHER, VIEW);
734 #endif
735 
736 	add_to_funcs(do_cancel, ((MMOST & ~MMAIN) | MYESNO),
737 		N_("Cancel"), WITHORSANS(cancel_gist), BLANKAFTER, VIEW);
738 
739 	add_to_funcs(do_exit, MMAIN,
740 		exit_tag, WITHORSANS(exit_gist), TOGETHER, VIEW);
741 	/* Remember the entry for Exit, to be able to replace it with Close. */
742 	exitfunc = tailfunc;
743 
744 #ifdef ENABLE_BROWSER
745 	add_to_funcs(do_exit, MBROWSER,
746 		close_tag, WITHORSANS(exitbrowser_gist), TOGETHER, VIEW);
747 #endif
748 
749 #ifndef ENABLE_HELP
750 	add_to_funcs(full_refresh, MMAIN|MREPLACE, "Refresh", "x", 0, VIEW);
751 #ifndef NANO_TINY
752 	add_to_funcs(full_refresh, MINSERTFILE|MEXECUTE, "Refresh", "x", 0, VIEW);
753 #endif
754 	add_to_funcs(flip_goto, MWHEREIS, "Go To Line", "x", 0, VIEW);
755 	add_to_funcs(flip_goto, MGOTOLINE, "Go To Text", "x", 0, VIEW);
756 #endif
757 
758 	add_to_funcs(do_writeout_void, MMAIN,
759 		N_("Write Out"), WITHORSANS(writeout_gist), TOGETHER, NOVIEW);
760 
761 #ifdef ENABLE_JUSTIFY
762 	/* In restricted mode, replace Insert with Justify, when possible;
763 	 * otherwise, show Insert anyway, to keep the help items paired. */
764 	if (!ISSET(RESTRICTED))
765 #endif
766 		add_to_funcs(do_insertfile_void, MMAIN,
767 				N_("Read File"), WITHORSANS(readfile_gist), BLANKAFTER,
768 				/* We allow inserting files in view mode if multibuffer mode
769 				 * is available, so that the user can view multiple files. */
770 				CAN_OPEN_OTHER_BUFFER);
771 #ifdef ENABLE_JUSTIFY
772 	else
773 		add_to_funcs(do_justify, MMAIN,
774 				N_("Justify"), WITHORSANS(justify_gist), BLANKAFTER, NOVIEW);
775 #endif
776 
777 #ifdef ENABLE_HELP
778 	/* The description ("x") and blank_after (0) are irrelevant,
779 	 * because the help viewer does not have a help text. */
780 	add_to_funcs(full_refresh, MHELP, N_("Refresh"), "x", 0, VIEW);
781 	add_to_funcs(do_exit, MHELP, close_tag, "x", 0, VIEW);
782 #endif
783 
784 	add_to_funcs(do_search_forward, MMAIN|MHELP,
785 		N_("Where Is"), WITHORSANS(whereis_gist), TOGETHER, VIEW);
786 
787 	add_to_funcs(do_replace, MMAIN,
788 		N_("Replace"), WITHORSANS(replace_gist), TOGETHER, NOVIEW);
789 
790 #ifdef NANO_TINY
791 	add_to_funcs(do_search_backward, MHELP,
792 		N_("Where Was"), WITHORSANS(wherewas_gist), TOGETHER, VIEW);
793 
794 	add_to_funcs(do_findprevious, MMAIN|MHELP,
795 		N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
796 	add_to_funcs(do_findnext, MMAIN|MHELP,
797 		N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
798 #endif
799 
800 	add_to_funcs(cut_text, MMAIN,
801 		N_("Cut"), WITHORSANS(cut_gist), TOGETHER, NOVIEW);
802 
803 	add_to_funcs(paste_text, MMAIN,
804 		N_("Paste"), WITHORSANS(paste_gist), BLANKAFTER, NOVIEW);
805 
806 	if (!ISSET(RESTRICTED)) {
807 #ifndef NANO_TINY
808 		add_to_funcs(do_execute, MMAIN,
809 				N_("Execute"), WITHORSANS(execute_gist), TOGETHER, NOVIEW);
810 #endif
811 #ifdef ENABLE_JUSTIFY
812 		add_to_funcs(do_justify, MMAIN,
813 				N_("Justify"), WITHORSANS(justify_gist), BLANKAFTER, NOVIEW);
814 #endif
815 	}
816 
817 	add_to_funcs(report_cursor_position, MMAIN,
818 		/* TRANSLATORS: This refers to the position of the cursor. */
819 		N_("Location"), WITHORSANS(cursorpos_gist), TOGETHER, VIEW);
820 
821 #if defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
822 	/* Conditionally placing this one here or further on, to keep the
823 	 * help items nicely paired in most conditions. */
824 	add_to_funcs(do_gotolinecolumn_void, MMAIN,
825 		N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
826 #endif
827 
828 #ifndef NANO_TINY
829 	add_to_funcs(do_undo, MMAIN,
830 		/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
831 		N_("Undo"), WITHORSANS(undo_gist), TOGETHER, NOVIEW);
832 	add_to_funcs(do_redo, MMAIN,
833 		N_("Redo"), WITHORSANS(redo_gist), BLANKAFTER, NOVIEW);
834 
835 	add_to_funcs(do_mark, MMAIN,
836 		N_("Set Mark"), WITHORSANS(mark_gist), TOGETHER, VIEW);
837 	add_to_funcs(copy_text, MMAIN,
838 		N_("Copy"), WITHORSANS(copy_gist), BLANKAFTER, VIEW);
839 #endif
840 
841 	add_to_funcs(case_sens_void, MWHEREIS|MREPLACE,
842 		N_("Case Sens"), WITHORSANS(case_gist), TOGETHER, VIEW);
843 	add_to_funcs(regexp_void, MWHEREIS|MREPLACE,
844 		N_("Reg.exp."), WITHORSANS(regexp_gist), TOGETHER, VIEW);
845 	add_to_funcs(backwards_void, MWHEREIS|MREPLACE,
846 		N_("Backwards"), WITHORSANS(reverse_gist), BLANKAFTER, VIEW);
847 
848 	add_to_funcs(flip_replace, MWHEREIS,
849 		N_("Replace"), WITHORSANS(replace_gist), BLANKAFTER, VIEW);
850 	add_to_funcs(flip_replace, MREPLACE,
851 		N_("No Replace"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW);
852 
853 #ifdef ENABLE_HISTORIES
854 	add_to_funcs(get_history_older_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
855 		N_("Older"), WITHORSANS(older_gist), TOGETHER, VIEW);
856 	add_to_funcs(get_history_newer_void, MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE,
857 		N_("Newer"), WITHORSANS(newer_gist), BLANKAFTER, VIEW);
858 #endif
859 
860 #ifdef ENABLE_HELP
861 	add_to_funcs(flip_goto, MWHEREIS,
862 		N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
863 #endif
864 
865 #ifdef ENABLE_BROWSER
866 	add_to_funcs(goto_dir, MBROWSER,
867 		/* TRANSLATORS: Try to keep the next seven strings at most 10 characters. */
868 		N_("Go To Dir"), WITHORSANS(gotodir_gist), TOGETHER, VIEW);
869 #ifdef ENABLE_HELP
870 	add_to_funcs(full_refresh, MBROWSER,
871 		N_("Refresh"), WITHORSANS(browserrefresh_gist), BLANKAFTER, VIEW);
872 #endif
873 	add_to_funcs(do_search_forward, MBROWSER,
874 		N_("Where Is"), WITHORSANS(browserwhereis_gist), TOGETHER, VIEW);
875 	add_to_funcs(do_search_backward, MBROWSER,
876 		N_("Where Was"), WITHORSANS(browserwherewas_gist), TOGETHER, VIEW);
877 
878 	add_to_funcs(do_findprevious, MBROWSER,
879 		N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
880 	add_to_funcs(do_findnext, MBROWSER,
881 		N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
882 #endif
883 
884 #ifdef NANO_TINY
885 	add_to_funcs(to_prev_word, MMAIN,
886 		"Prev Word", WITHORSANS(prevword_gist), TOGETHER, VIEW);
887 	add_to_funcs(to_next_word, MMAIN,
888 		"Next Word", WITHORSANS(nextword_gist), BLANKAFTER, VIEW);
889 #else
890 	add_to_funcs(do_find_bracket, MMAIN,
891 		N_("To Bracket"), WITHORSANS(bracket_gist), BLANKAFTER, VIEW);
892 
893 	add_to_funcs(do_search_backward, MMAIN|MHELP,
894 		/* TRANSLATORS: This starts a backward search. */
895 		N_("Where Was"), WITHORSANS(wherewas_gist), TOGETHER, VIEW);
896 
897 	add_to_funcs(do_findprevious, MMAIN|MHELP,
898 		/* TRANSLATORS: This refers to searching the preceding occurrence. */
899 		N_("Previous"), WITHORSANS(findprev_gist), TOGETHER, VIEW);
900 	add_to_funcs(do_findnext, MMAIN|MHELP,
901 		N_("Next"), WITHORSANS(findnext_gist), BLANKAFTER, VIEW);
902 #endif
903 
904 	add_to_funcs(do_left, MMAIN,
905 		/* TRANSLATORS: This means move the cursor one character back. */
906 		N_("Back"), WITHORSANS(back_gist), TOGETHER, VIEW);
907 	add_to_funcs(do_right, MMAIN,
908 		N_("Forward"), WITHORSANS(forward_gist), TOGETHER, VIEW);
909 #ifdef ENABLE_BROWSER
910 	add_to_funcs(do_left, MBROWSER,
911 		N_("Back"), WITHORSANS(backfile_gist), TOGETHER, VIEW);
912 	add_to_funcs(do_right, MBROWSER,
913 		N_("Forward"), WITHORSANS(forwardfile_gist), TOGETHER, VIEW);
914 #endif
915 
916 #ifndef NANO_TINY
917 	add_to_funcs(to_prev_word, MMAIN,
918 		/* TRANSLATORS: Try to keep the next ten strings at most 12 characters. */
919 		N_("Prev Word"), WITHORSANS(prevword_gist), TOGETHER, VIEW);
920 	add_to_funcs(to_next_word, MMAIN,
921 		N_("Next Word"), WITHORSANS(nextword_gist), TOGETHER, VIEW);
922 #endif
923 
924 	add_to_funcs(do_home, MMAIN,
925 		N_("Home"), WITHORSANS(home_gist), TOGETHER, VIEW);
926 	add_to_funcs(do_end, MMAIN,
927 		N_("End"), WITHORSANS(end_gist), BLANKAFTER, VIEW);
928 
929 	add_to_funcs(do_up, MMAIN|MBROWSER|MHELP,
930 		N_("Prev Line"), WITHORSANS(prevline_gist), TOGETHER, VIEW);
931 	add_to_funcs(do_down, MMAIN|MBROWSER|MHELP,
932 		N_("Next Line"), WITHORSANS(nextline_gist), TOGETHER, VIEW);
933 #if !defined(NANO_TINY) || defined(ENABLE_HELP)
934 	add_to_funcs(do_scroll_up, MMAIN,
935 		N_("Scroll Up"), WITHORSANS(scrollup_gist), TOGETHER, VIEW);
936 	add_to_funcs(do_scroll_down, MMAIN,
937 		N_("Scroll Down"), WITHORSANS(scrolldown_gist), BLANKAFTER, VIEW);
938 #endif
939 
940 	add_to_funcs(to_prev_block, MMAIN,
941 		N_("Prev Block"), WITHORSANS(prevblock_gist), TOGETHER, VIEW);
942 	add_to_funcs(to_next_block, MMAIN,
943 		N_("Next Block"), WITHORSANS(nextblock_gist), TOGETHER, VIEW);
944 #ifdef ENABLE_JUSTIFY
945 	add_to_funcs(to_para_begin, MMAIN|MGOTOLINE,
946 		/* TRANSLATORS: Try to keep these two strings at most 16 characters. */
947 		N_("Begin of Paragr."), WITHORSANS(parabegin_gist), TOGETHER, VIEW);
948 	add_to_funcs(to_para_end, MMAIN|MGOTOLINE,
949 		N_("End of Paragraph"), WITHORSANS(paraend_gist), BLANKAFTER, VIEW);
950 #endif
951 
952 	add_to_funcs(do_page_up, MMAIN|MHELP,
953 		/* TRANSLATORS: Try to keep the next six strings at most 12 characters. */
954 		N_("Prev Page"), WITHORSANS(prevpage_gist), TOGETHER, VIEW);
955 	add_to_funcs(do_page_down, MMAIN|MHELP,
956 		N_("Next Page"), WITHORSANS(nextpage_gist), TOGETHER, VIEW);
957 
958 	add_to_funcs(to_first_line, MMAIN|MHELP|MGOTOLINE,
959 		N_("First Line"), WITHORSANS(firstline_gist), TOGETHER, VIEW);
960 	add_to_funcs(to_last_line, MMAIN|MHELP|MGOTOLINE,
961 		N_("Last Line"), WITHORSANS(lastline_gist), BLANKAFTER, VIEW);
962 
963 #ifdef ENABLE_MULTIBUFFER
964 	add_to_funcs(switch_to_prev_buffer, MMAIN,
965 		N_("Prev File"), WITHORSANS(prevfile_gist), TOGETHER, VIEW);
966 	add_to_funcs(switch_to_next_buffer, MMAIN,
967 		N_("Next File"), WITHORSANS(nextfile_gist), BLANKAFTER, VIEW);
968 #endif
969 
970 #if !defined(NANO_TINY) && !defined(ENABLE_JUSTIFY)
971 	add_to_funcs(do_gotolinecolumn_void, MMAIN,
972 		N_("Go To Line"), WITHORSANS(gotoline_gist), BLANKAFTER, VIEW);
973 #endif
974 
975 	add_to_funcs(do_tab, MMAIN,
976 		/* TRANSLATORS: The next four strings are names of keyboard keys. */
977 		N_("Tab"), WITHORSANS(tab_gist), TOGETHER, NOVIEW);
978 	add_to_funcs(do_enter, MMAIN,
979 		N_("Enter"), WITHORSANS(enter_gist), BLANKAFTER, NOVIEW);
980 
981 	add_to_funcs(do_backspace, MMAIN,
982 		N_("Backspace"), WITHORSANS(backspace_gist), TOGETHER, NOVIEW);
983 	add_to_funcs(do_delete, MMAIN,
984 		N_("Delete"), WITHORSANS(delete_gist),
985 #ifndef NANO_TINY
986 		TOGETHER,
987 #else
988 		BLANKAFTER,
989 #endif
990 		NOVIEW);
991 
992 #ifndef NANO_TINY
993 	add_to_funcs(chop_previous_word, MMAIN,
994 		/* TRANSLATORS: The next two strings refer to deleting words. */
995 		N_("Chop Left"), WITHORSANS(chopwordleft_gist), TOGETHER, NOVIEW);
996 	add_to_funcs(chop_next_word, MMAIN,
997 		N_("Chop Right"), WITHORSANS(chopwordright_gist), TOGETHER, NOVIEW);
998 	add_to_funcs(cut_till_eof, MMAIN,
999 		N_("Cut Till End"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW);
1000 #endif
1001 
1002 #ifdef ENABLE_JUSTIFY
1003 	add_to_funcs(do_full_justify, MMAIN,
1004 		N_("Full Justify"), WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW);
1005 #endif
1006 
1007 #ifndef NANO_TINY
1008 	add_to_funcs(do_wordlinechar_count, MMAIN,
1009 		N_("Word Count"), WITHORSANS(wordcount_gist), TOGETHER, VIEW);
1010 #endif
1011 
1012 	add_to_funcs(do_verbatim_input, MMAIN,
1013 		N_("Verbatim"), WITHORSANS(verbatim_gist), BLANKAFTER, NOVIEW);
1014 
1015 #ifdef ENABLE_HELP
1016 	add_to_funcs(full_refresh, MMAIN,
1017 		N_("Refresh"), WITHORSANS(refresh_gist), TOGETHER, VIEW);
1018 #endif
1019 
1020 	add_to_funcs(do_suspend_void, MMAIN,
1021 		N_("Suspend"), WITHORSANS(suspend_gist), BLANKAFTER, VIEW);
1022 
1023 #ifndef NANO_TINY
1024 	add_to_funcs(do_indent, MMAIN,
1025 		N_("Indent"), WITHORSANS(indent_gist), TOGETHER, NOVIEW);
1026 	add_to_funcs(do_unindent, MMAIN,
1027 		N_("Unindent"), WITHORSANS(unindent_gist), BLANKAFTER, NOVIEW);
1028 #endif
1029 #ifdef ENABLE_COMMENT
1030 	add_to_funcs(do_comment, MMAIN,
1031 		N_("Comment Lines"), WITHORSANS(comment_gist), TOGETHER, NOVIEW);
1032 #endif
1033 #ifdef ENABLE_WORDCOMPLETION
1034 	add_to_funcs(complete_a_word, MMAIN,
1035 		N_("Complete"), WITHORSANS(completion_gist), BLANKAFTER, NOVIEW);
1036 #endif
1037 
1038 #ifndef NANO_TINY
1039 	add_to_funcs(record_macro, MMAIN,
1040 		N_("Record"), WITHORSANS(recordmacro_gist), TOGETHER, VIEW);
1041 	add_to_funcs(run_macro, MMAIN,
1042 		N_("Run Macro"), WITHORSANS(runmacro_gist), BLANKAFTER, VIEW);
1043 
1044 	add_to_funcs(put_or_lift_anchor, MMAIN,
1045 		N_("Anchor"), WITHORSANS(anchor_gist), TOGETHER, VIEW);
1046 	add_to_funcs(to_prev_anchor, MMAIN,
1047 		N_("Up to anchor"), WITHORSANS(prevanchor_gist), TOGETHER, VIEW);
1048 	add_to_funcs(to_next_anchor, MMAIN,
1049 		N_("Down to anchor"), WITHORSANS(nextanchor_gist), BLANKAFTER, VIEW);
1050 
1051 	add_to_funcs(zap_text, MMAIN,
1052 		/* TRANSLATORS: This *deletes* a line or marked region. */
1053 		N_("Zap"), WITHORSANS(zap_gist), BLANKAFTER, NOVIEW);
1054 
1055 	if (!ISSET(RESTRICTED)) {
1056 #ifdef ENABLE_SPELLER
1057 		add_to_funcs(do_spell, MMAIN,
1058 				N_("Spell Check"), WITHORSANS(spell_gist), TOGETHER, NOVIEW);
1059 #endif
1060 #ifdef ENABLE_COLOR
1061 		add_to_funcs(do_linter, MMAIN,
1062 				N_("Linter"), WITHORSANS(lint_gist), TOGETHER, NOVIEW);
1063 		add_to_funcs(do_formatter, MMAIN,
1064 				N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW);
1065 #endif
1066 	}
1067 #endif /* !NANO_TINY */
1068 
1069 #ifdef NANO_TINY
1070 	add_to_funcs(do_search_backward, MMAIN,
1071 		N_("Where Was"), WITHORSANS(wherewas_gist), BLANKAFTER, VIEW);
1072 #endif
1073 
1074 #if !defined(NANO_TINY) || defined(ENABLE_HELP)
1075 	add_to_funcs(do_center, MMAIN,
1076 		N_("Center"), WITHORSANS(center_gist), BLANKAFTER, VIEW);
1077 #endif
1078 	add_to_funcs(do_savefile, MMAIN,
1079 		N_("Save"), WITHORSANS(savefile_gist), BLANKAFTER, NOVIEW);
1080 
1081 #ifdef ENABLE_MULTIBUFFER
1082 	/* Multiple buffers are only available when not in restricted mode. */
1083 	if (!ISSET(RESTRICTED))
1084 		add_to_funcs(flip_newbuffer, MINSERTFILE|MEXECUTE,
1085 			N_("New Buffer"), WITHORSANS(newbuffer_gist), TOGETHER, NOVIEW);
1086 #endif
1087 #ifndef NANO_TINY
1088 	add_to_funcs(flip_pipe, MEXECUTE,
1089 			N_("Pipe Text"), WITHORSANS(pipe_gist), BLANKAFTER, NOVIEW);
1090 #endif
1091 #ifdef ENABLE_SPELLER
1092 	add_to_funcs(do_spell, MEXECUTE,
1093 			N_("Spell Check"), WITHORSANS(spell_gist), TOGETHER, NOVIEW);
1094 #endif
1095 #ifdef ENABLE_COLOR
1096 	add_to_funcs(do_linter, MEXECUTE,
1097 			N_("Linter"), WITHORSANS(lint_gist), BLANKAFTER, NOVIEW);
1098 #endif
1099 #ifdef ENABLE_JUSTIFY
1100 	add_to_funcs(do_full_justify, MEXECUTE,
1101 		N_("Full Justify"), WITHORSANS(fulljustify_gist), TOGETHER, NOVIEW);
1102 #endif
1103 #ifdef ENABLE_COLOR
1104 	add_to_funcs(do_formatter, MEXECUTE,
1105 			N_("Formatter"), WITHORSANS(formatter_gist), BLANKAFTER, NOVIEW);
1106 #endif
1107 
1108 #ifdef ENABLE_HELP
1109 	add_to_funcs(flip_goto, MGOTOLINE,
1110 		N_("Go To Text"), WITHORSANS(whereis_gist), BLANKAFTER, VIEW);
1111 #endif
1112 
1113 #ifndef NANO_TINY
1114 	add_to_funcs(dos_format_void, MWRITEFILE,
1115 		N_("DOS Format"), WITHORSANS(dos_gist), TOGETHER, NOVIEW);
1116 	add_to_funcs(mac_format_void, MWRITEFILE,
1117 		N_("Mac Format"), WITHORSANS(mac_gist), TOGETHER, NOVIEW);
1118 
1119 	/* If we're using restricted mode, the Append, Prepend, and Backup toggles
1120 	 * are disabled.  The first and second are not useful as they only allow
1121 	 * reduplicating the current file, and the third is not allowed as it
1122 	 * would write to a file not specified on the command line. */
1123 	if (!ISSET(RESTRICTED)) {
1124 		add_to_funcs(append_void, MWRITEFILE,
1125 			N_("Append"), WITHORSANS(append_gist), TOGETHER, NOVIEW);
1126 		add_to_funcs(prepend_void, MWRITEFILE,
1127 			N_("Prepend"), WITHORSANS(prepend_gist), TOGETHER, NOVIEW);
1128 
1129 		add_to_funcs(backup_file_void, MWRITEFILE,
1130 			N_("Backup File"), WITHORSANS(backup_gist), BLANKAFTER, NOVIEW);
1131 	}
1132 
1133 	add_to_funcs(flip_convert, MINSERTFILE,
1134 		N_("No Conversion"), WITHORSANS(convert_gist), BLANKAFTER, NOVIEW);
1135 
1136 	/* Command execution is only available when not in restricted mode. */
1137 	if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE)) {
1138 		add_to_funcs(flip_execute, MINSERTFILE,
1139 			N_("Execute Command"), WITHORSANS(execute_gist), BLANKAFTER, NOVIEW);
1140 
1141 		add_to_funcs(cut_till_eof, MEXECUTE,
1142 			N_("Cut Till End"), WITHORSANS(cuttilleof_gist), BLANKAFTER, NOVIEW);
1143 
1144 		add_to_funcs(do_suspend_void, MEXECUTE,
1145 			N_("Suspend"), WITHORSANS(suspend_gist), BLANKAFTER, VIEW);
1146 	}
1147 #endif /* !NANO_TINY */
1148 
1149 #ifdef ENABLE_BROWSER
1150 	/* The file browser is only available when not in restricted mode. */
1151 	if (!ISSET(RESTRICTED))
1152 		add_to_funcs(to_files, MWRITEFILE|MINSERTFILE,
1153 			/* TRANSLATORS: This invokes the file browser. */
1154 			N_("Browse"), WITHORSANS(tofiles_gist), BLANKAFTER, VIEW);
1155 
1156 	add_to_funcs(do_page_up, MBROWSER,
1157 		N_("Prev Page"), WITHORSANS(prevpage_gist), TOGETHER, VIEW);
1158 	add_to_funcs(do_page_down, MBROWSER,
1159 		N_("Next Page"), WITHORSANS(nextpage_gist), TOGETHER, VIEW);
1160 
1161 	add_to_funcs(to_first_file, MBROWSER|MWHEREISFILE,
1162 		N_("First File"), WITHORSANS(firstfile_gist), TOGETHER, VIEW);
1163 	add_to_funcs(to_last_file, MBROWSER|MWHEREISFILE,
1164 		N_("Last File"), WITHORSANS(lastfile_gist), BLANKAFTER, VIEW);
1165 
1166 #ifndef NANO_TINY
1167 	add_to_funcs(to_prev_word, MBROWSER,
1168 		N_("Left Column"), WITHORSANS(browserlefthand_gist), TOGETHER, VIEW);
1169 	add_to_funcs(to_next_word, MBROWSER,
1170 		N_("Right Column"), WITHORSANS(browserrighthand_gist), TOGETHER, VIEW);
1171 	add_to_funcs(to_prev_block, MBROWSER,
1172 		N_("Top Row"), WITHORSANS(browsertoprow_gist), TOGETHER, VIEW);
1173 	add_to_funcs(to_next_block, MBROWSER,
1174 		N_("Bottom Row"), WITHORSANS(browserbottomrow_gist), BLANKAFTER, VIEW);
1175 #endif
1176 #endif /* ENABLE_BROWSER */
1177 
1178 	add_to_funcs(discard_buffer, MWRITEFILE,
1179 		N_("Discard buffer"), WITHORSANS(discardbuffer_gist), BLANKAFTER, NOVIEW);
1180 
1181 #ifdef ENABLE_COLOR
1182 	add_to_funcs(do_page_up, MLINTER,
1183 		/* TRANSLATORS: The next two strings may be up to 37 characters each. */
1184 		N_("Previous Linter message"), WITHORSANS(prevlint_gist), TOGETHER, VIEW);
1185 	add_to_funcs(do_page_down, MLINTER,
1186 		N_("Next Linter message"), WITHORSANS(nextlint_gist), TOGETHER, VIEW);
1187 #endif
1188 
1189 #ifdef __linux__
1190 #define SLASH_OR_DASH  (on_a_vt) ? "^-" : "^/"
1191 #else
1192 #define SLASH_OR_DASH  "^/"
1193 #endif
1194 
1195 	/* Link key combos to functions in certain menus. */
1196 	add_to_sclist(MMOST|MBROWSER, "^M", '\r', do_enter, 0);
1197 	add_to_sclist(MMOST|MBROWSER, "Enter", KEY_ENTER, do_enter, 0);
1198 	add_to_sclist(MMOST, "^H", '\b', do_backspace, 0);
1199 	add_to_sclist(MMOST, "Bsp", KEY_BACKSPACE, do_backspace, 0);
1200 	add_to_sclist(MMOST, "Sh-Del", SHIFT_DELETE, do_backspace, 0);
1201 	add_to_sclist(MMOST, "^D", 0, do_delete, 0);
1202 	add_to_sclist(MMOST, "Del", KEY_DC, do_delete, 0);
1203 	add_to_sclist(MMOST, "^I", '\t', do_tab, 0);
1204 	add_to_sclist(MMOST, "Tab", '\t', do_tab, 0);
1205 	add_to_sclist((MMOST|MBROWSER) & ~MFINDINHELP, "^G", 0, do_help, 0);
1206 	add_to_sclist(MMAIN|MBROWSER|MHELP, "^X", 0, do_exit, 0);
1207 	if (!ISSET(PRESERVE))
1208 		add_to_sclist(MMAIN, "^S", 0, do_savefile, 0);
1209 	add_to_sclist(MMAIN, "^O", 0, do_writeout_void, 0);
1210 	add_to_sclist(MMAIN, "^R", 0, do_insertfile_void, 0);
1211 	add_to_sclist(MMAIN, "Ins", KEY_IC, do_insertfile_void, 0);
1212 	if (!ISSET(PRESERVE))
1213 		add_to_sclist(MMAIN|MBROWSER|MHELP, "^Q", 0, do_search_backward, 0);
1214 	add_to_sclist(MMAIN|MBROWSER|MHELP, "^W", 0, do_search_forward, 0);
1215 	add_to_sclist(MMAIN, "^\\", 0, do_replace, 0);
1216 	add_to_sclist(MMAIN, "M-R", 0, do_replace, 0);
1217 	add_to_sclist(MMOST, "^K", 0, cut_text, 0);
1218 	add_to_sclist(MMOST, "^U", 0, paste_text, 0);
1219 #ifndef NANO_TINY
1220 	add_to_sclist(MMAIN, "^T", 0, do_execute, 0);
1221 #endif
1222 #ifdef ENABLE_JUSTIFY
1223 	add_to_sclist(MMAIN, "^J", '\n', do_justify, 0);
1224 #endif
1225 #ifdef ENABLE_SPELLER
1226 	add_to_sclist(MEXECUTE, "^S", 0, do_spell, 0);
1227 	add_to_sclist(MEXECUTE, "^T", 0, do_spell, 0);
1228 #endif
1229 #ifdef ENABLE_COLOR
1230 	add_to_sclist(MMAIN, "M-B", 0, do_linter, 0);
1231 	add_to_sclist(MEXECUTE, "^Y", 0, do_linter, 0);
1232 	add_to_sclist(MMAIN, "M-F", 0, do_formatter, 0);
1233 	add_to_sclist(MEXECUTE, "^O", 0, do_formatter, 0);
1234 #endif
1235 	add_to_sclist(MMAIN, "^C", 0, report_cursor_position, 0);
1236 	add_to_sclist(MMAIN, SLASH_OR_DASH, 0, do_gotolinecolumn_void, 0);
1237 	add_to_sclist(MMAIN, "M-G", 0, do_gotolinecolumn_void, 0);
1238 	add_to_sclist(MMAIN, "^_", 0, do_gotolinecolumn_void, 0);
1239 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "^Y", 0, do_page_up, 0);
1240 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "PgUp", KEY_PPAGE, do_page_up, 0);
1241 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "^V", 0, do_page_down, 0);
1242 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "PgDn", KEY_NPAGE, do_page_down, 0);
1243 	add_to_sclist(MBROWSER|MHELP, "Bsp", KEY_BACKSPACE, do_page_up, 0);
1244 	add_to_sclist(MBROWSER|MHELP, "Sh-Del", SHIFT_DELETE, do_page_up, 0);
1245 	add_to_sclist(MBROWSER|MHELP, "Space", 0x20, do_page_down, 0);
1246 	add_to_sclist(MMAIN|MHELP, "M-\\", 0, to_first_line, 0);
1247 	add_to_sclist(MMAIN|MHELP, "^Home", CONTROL_HOME, to_first_line, 0);
1248 	add_to_sclist(MMAIN|MHELP, "M-/", 0, to_last_line, 0);
1249 	add_to_sclist(MMAIN|MHELP, "^End", CONTROL_END, to_last_line, 0);
1250 	add_to_sclist(MMAIN|MBROWSER|MHELP, "M-W", 0, do_findnext, 0);
1251 	add_to_sclist(MMAIN|MBROWSER|MHELP, "M-Q", 0, do_findprevious, 0);
1252 #ifdef NANO_TINY
1253 	add_to_sclist(MMAIN, "M-B", 0, to_prev_word, 0);
1254 	add_to_sclist(MMAIN, "M-D", 0, to_prev_word, 0);
1255 	add_to_sclist(MMAIN, "M-N", 0, to_next_word, 0);
1256 	add_to_sclist(MMAIN, "M-F", 0, to_next_word, 0);
1257 #else
1258 	add_to_sclist(MMAIN, "M-]", 0, do_find_bracket, 0);
1259 	add_to_sclist(MMAIN, "M-A", 0, do_mark, 0);
1260 	add_to_sclist(MMAIN, "^6", 0, do_mark, 0);
1261 	add_to_sclist(MMAIN, "^^", 0, do_mark, 0);
1262 	add_to_sclist(MMAIN, "M-6", 0, copy_text, 0);
1263 	add_to_sclist(MMAIN, "M-^", 0, copy_text, 0);
1264 	add_to_sclist(MMAIN, "M-}", 0, do_indent, 0);
1265 	add_to_sclist(MMAIN, "Tab", INDENT_KEY, do_indent, 0);
1266 	add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0);
1267 	add_to_sclist(MMAIN, "Sh-Tab", SHIFT_TAB, do_unindent, 0);
1268 	add_to_sclist(MMAIN, "M-:", 0, record_macro, 0);
1269 	add_to_sclist(MMAIN, "M-;", 0, run_macro, 0);
1270 	add_to_sclist(MMAIN, "M-U", 0, do_undo, 0);
1271 	add_to_sclist(MMAIN, "M-E", 0, do_redo, 0);
1272 	add_to_sclist(MMAIN, "M-Bsp", CONTROL_SHIFT_DELETE, chop_previous_word, 0);
1273 	add_to_sclist(MMAIN, "Sh-^Del", CONTROL_SHIFT_DELETE, chop_previous_word, 0);
1274 	add_to_sclist(MMAIN, "^Del", CONTROL_DELETE, chop_next_word, 0);
1275 	add_to_sclist(MMAIN, "M-Del", ALT_DELETE, zap_text, 0);
1276 	add_to_sclist(MMAIN, "M-Ins", ALT_INSERT, put_or_lift_anchor, 0);
1277 	add_to_sclist(MMAIN, "M-PgUp", ALT_PAGEUP, to_prev_anchor, 0);
1278 	add_to_sclist(MMAIN, "M-PgDn", ALT_PAGEDOWN, to_next_anchor, 0);
1279 #endif
1280 #ifdef ENABLE_WORDCOMPLETION
1281 	add_to_sclist(MMAIN, "^]", 0, complete_a_word, 0);
1282 #endif
1283 #ifdef ENABLE_COMMENT
1284 	add_to_sclist(MMAIN, "M-3", 0, do_comment, 0);
1285 #endif
1286 	add_to_sclist(MMOST|MBROWSER, "^B", 0, do_left, 0);
1287 	add_to_sclist(MMOST|MBROWSER, "^F", 0, do_right, 0);
1288 #ifdef ENABLE_UTF8
1289 	if (using_utf8()) {
1290 		add_to_sclist(MMOST|MBROWSER|MHELP, "\xE2\x97\x82", KEY_LEFT, do_left, 0);
1291 		add_to_sclist(MMOST|MBROWSER|MHELP, "\xE2\x96\xb8", KEY_RIGHT, do_right, 0);
1292 		add_to_sclist(MSOME, "^\xE2\x97\x82", CONTROL_LEFT, to_prev_word, 0);
1293 		add_to_sclist(MSOME, "^\xE2\x96\xb8", CONTROL_RIGHT, to_next_word, 0);
1294 #if !defined(NANO_TINY) && defined(ENABLE_MULTIBUFFER)
1295 		if (!on_a_vt) {
1296 			add_to_sclist(MMAIN, "M-\xE2\x97\x82", ALT_LEFT, switch_to_prev_buffer, 0);
1297 			add_to_sclist(MMAIN, "M-\xE2\x96\xb8", ALT_RIGHT, switch_to_next_buffer, 0);
1298 		}
1299 #endif
1300 	} else
1301 #endif
1302 	{
1303 		add_to_sclist(MMOST|MBROWSER|MHELP, "Left", KEY_LEFT, do_left, 0);
1304 		add_to_sclist(MMOST|MBROWSER|MHELP, "Right", KEY_RIGHT, do_right, 0);
1305 		add_to_sclist(MSOME, "^Left", CONTROL_LEFT, to_prev_word, 0);
1306 		add_to_sclist(MSOME, "^Right", CONTROL_RIGHT, to_next_word, 0);
1307 #ifdef ENABLE_MULTIBUFFER
1308 		if (!on_a_vt) {
1309 			add_to_sclist(MMAIN, "M-Left", ALT_LEFT, switch_to_prev_buffer, 0);
1310 			add_to_sclist(MMAIN, "M-Right", ALT_RIGHT, switch_to_next_buffer, 0);
1311 		}
1312 #endif
1313 	}
1314 	add_to_sclist(MMOST, "M-Space", 0, to_prev_word, 0);
1315 	add_to_sclist(MMOST, "^Space", 0, to_next_word, 0);
1316 	add_to_sclist(MMOST, "^A", 0, do_home, 0);
1317 	add_to_sclist(MMOST, "Home", KEY_HOME, do_home, 0);
1318 	add_to_sclist(MMOST, "^E", 0, do_end, 0);
1319 	add_to_sclist(MMOST, "End", KEY_END, do_end, 0);
1320 	add_to_sclist(MMAIN|MBROWSER|MHELP, "^P", 0, do_up, 0);
1321 	add_to_sclist(MMAIN|MBROWSER|MHELP, "^N", 0, do_down, 0);
1322 #ifdef ENABLE_UTF8
1323 	if (using_utf8()) {
1324 		add_to_sclist(MMAIN|MBROWSER|MHELP, "\xE2\x96\xb4", KEY_UP, do_up, 0);
1325 		add_to_sclist(MMAIN|MBROWSER|MHELP, "\xE2\x96\xbe", KEY_DOWN, do_down, 0);
1326 		add_to_sclist(MMAIN|MBROWSER|MLINTER, "^\xE2\x96\xb4", CONTROL_UP, to_prev_block, 0);
1327 		add_to_sclist(MMAIN|MBROWSER|MLINTER, "^\xE2\x96\xbe", CONTROL_DOWN, to_next_block, 0);
1328 	} else
1329 #endif
1330 	{
1331 		add_to_sclist(MMAIN|MBROWSER|MHELP, "Up", KEY_UP, do_up, 0);
1332 		add_to_sclist(MMAIN|MBROWSER|MHELP, "Down", KEY_DOWN, do_down, 0);
1333 		add_to_sclist(MMAIN|MBROWSER|MLINTER, "^Up", CONTROL_UP, to_prev_block, 0);
1334 		add_to_sclist(MMAIN|MBROWSER|MLINTER, "^Down", CONTROL_DOWN, to_next_block, 0);
1335 	}
1336 	add_to_sclist(MMAIN, "M-7", 0, to_prev_block, 0);
1337 	add_to_sclist(MMAIN, "M-8", 0, to_next_block, 0);
1338 #ifdef ENABLE_JUSTIFY
1339 	add_to_sclist(MMAIN, "M-(", 0, to_para_begin, 0);
1340 	add_to_sclist(MMAIN, "M-9", 0, to_para_begin, 0);
1341 	add_to_sclist(MMAIN, "M-)", 0, to_para_end, 0);
1342 	add_to_sclist(MMAIN, "M-0", 0, to_para_end, 0);
1343 #endif
1344 #ifndef NANO_TINY
1345 #ifdef ENABLE_UTF8
1346 	if (using_utf8()) {
1347 		add_to_sclist(MMAIN|MHELP, "M-\xE2\x96\xb4", ALT_UP, do_scroll_up, 0);
1348 		add_to_sclist(MMAIN|MHELP, "M-\xE2\x96\xbe", ALT_DOWN, do_scroll_down, 0);
1349 	} else
1350 #endif
1351 	{
1352 		add_to_sclist(MMAIN|MHELP, "M-Up", ALT_UP, do_scroll_up, 0);
1353 		add_to_sclist(MMAIN|MHELP, "M-Down", ALT_DOWN, do_scroll_down, 0);
1354 	}
1355 #endif
1356 #if !defined(NANO_TINY) || defined(ENABLE_HELP)
1357 	add_to_sclist(MMAIN|MHELP, "M--", 0, do_scroll_up, 0);
1358 	add_to_sclist(MMAIN|MHELP, "M-_", 0, do_scroll_up, 0);
1359 	add_to_sclist(MMAIN|MHELP, "M-+", 0, do_scroll_down, 0);
1360 	add_to_sclist(MMAIN|MHELP, "M-=", 0, do_scroll_down, 0);
1361 #endif
1362 #ifdef ENABLE_MULTIBUFFER
1363 	add_to_sclist(MMAIN, "M-<", 0, switch_to_prev_buffer, 0);
1364 	add_to_sclist(MMAIN, "M-,", 0, switch_to_prev_buffer, 0);
1365 	add_to_sclist(MMAIN, "M->", 0, switch_to_next_buffer, 0);
1366 	add_to_sclist(MMAIN, "M-.", 0, switch_to_next_buffer, 0);
1367 #endif
1368 	add_to_sclist(MMOST, "M-V", 0, do_verbatim_input, 0);
1369 #ifndef NANO_TINY
1370 	add_to_sclist(MMAIN, "M-T", 0, cut_till_eof, 0);
1371 	add_to_sclist(MEXECUTE, "^V", 0, cut_till_eof, 0);
1372 	add_to_sclist(MMAIN, "M-D", 0, do_wordlinechar_count, 0);
1373 #else
1374 	add_to_sclist(MMAIN, "M-H", 0, do_help, 0);
1375 #endif
1376 #ifdef ENABLE_JUSTIFY
1377 	add_to_sclist(MMAIN, "M-J", 0, do_full_justify, 0);
1378 	add_to_sclist(MEXECUTE, "^J", 0, do_full_justify, 0);
1379 #endif
1380 #if !defined(NANO_TINY) || defined(ENABLE_HELP)
1381 	add_to_sclist(MMAIN, "^L", 0, do_center, 0);
1382 #endif
1383 	if (!ISSET(PRESERVE))
1384 		add_to_sclist(MMOST|MBROWSER|MHELP|MYESNO, "^L", 0, full_refresh, 0);
1385 	else
1386 		add_to_sclist(MMOST|MBROWSER|MYESNO, "^L", 0, full_refresh, 0);
1387 	add_to_sclist(MMAIN|MEXECUTE, "^Z", 0, do_suspend_void, 0);
1388 
1389 #ifndef NANO_TINY
1390 	/* Group of "Appearance" toggles. */
1391 	add_to_sclist((MMOST|MBROWSER|MYESNO) & ~MFINDINHELP, "M-X", 0, do_toggle_void, NO_HELP);
1392 	add_to_sclist(MMAIN, "M-C", 0, do_toggle_void, CONSTANT_SHOW);
1393 	add_to_sclist(MMAIN, "M-S", 0, do_toggle_void, SOFTWRAP);
1394 	add_to_sclist(MMAIN, "M-$", 0, do_toggle_void, SOFTWRAP);
1395 #ifdef ENABLE_LINENUMBERS
1396 	add_to_sclist(MMAIN, "M-N", 0, do_toggle_void, LINE_NUMBERS);
1397 	add_to_sclist(MMAIN, "M-#", 0, do_toggle_void, LINE_NUMBERS);
1398 #endif
1399 	add_to_sclist(MMAIN, "M-P", 0, do_toggle_void, WHITESPACE_DISPLAY);
1400 #ifdef ENABLE_COLOR
1401 	add_to_sclist(MMAIN, "M-Y", 0, do_toggle_void, NO_SYNTAX);
1402 #endif
1403 
1404 	/* Group of "Editing-behavior" toggles. */
1405 	add_to_sclist(MMAIN, "M-H", 0, do_toggle_void, SMART_HOME);
1406 	add_to_sclist(MMAIN, "M-I", 0, do_toggle_void, AUTOINDENT);
1407 	add_to_sclist(MMAIN, "M-K", 0, do_toggle_void, CUT_FROM_CURSOR);
1408 #ifdef ENABLE_WRAPPING
1409 	add_to_sclist(MMAIN, "M-L", 0, do_toggle_void, BREAK_LONG_LINES);
1410 #endif
1411 	add_to_sclist(MMAIN, "M-O", 0, do_toggle_void, TABS_TO_SPACES);
1412 
1413 	/* Group of "Peripheral-feature" toggles. */
1414 #ifdef ENABLE_MOUSE
1415 	add_to_sclist(MMAIN, "M-M", 0, do_toggle_void, USE_MOUSE);
1416 #endif
1417 	add_to_sclist(MMAIN, "M-Z", 0, do_toggle_void, SUSPENDABLE);
1418 #endif /* !NANO_TINY */
1419 
1420 	add_to_sclist(((MMOST & ~MMAIN) | MYESNO), "^C", 0, do_cancel, 0);
1421 
1422 	add_to_sclist(MWHEREIS|MREPLACE, "M-C", 0, case_sens_void, 0);
1423 	add_to_sclist(MWHEREIS|MREPLACE, "M-R", 0, regexp_void, 0);
1424 	add_to_sclist(MWHEREIS|MREPLACE, "M-B", 0, backwards_void, 0);
1425 	add_to_sclist(MWHEREIS|MREPLACE, "^R", 0, flip_replace, 0);
1426 	add_to_sclist(MWHEREIS|MGOTOLINE, "^T", 0, flip_goto, 0);
1427 #ifdef ENABLE_HISTORIES
1428 	add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^P", 0, get_history_older_void, 0);
1429 	add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "^N", 0, get_history_newer_void, 0);
1430 #ifdef ENABLE_UTF8
1431 	if (using_utf8()) {
1432 		add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "\xE2\x96\xb4", KEY_UP, get_history_older_void, 0);
1433 		add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "\xE2\x96\xbe", KEY_DOWN, get_history_newer_void, 0);
1434 	} else
1435 #endif
1436 	{
1437 		add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "Up", KEY_UP, get_history_older_void, 0);
1438 		add_to_sclist(MWHEREIS|MREPLACE|MREPLACEWITH|MWHEREISFILE|MFINDINHELP|MEXECUTE, "Down", KEY_DOWN, get_history_newer_void, 0);
1439 	}
1440 #endif
1441 #ifdef ENABLE_JUSTIFY
1442 	add_to_sclist(MGOTOLINE, "^W", 0, to_para_begin, 0);
1443 	add_to_sclist(MGOTOLINE, "^O", 0, to_para_end, 0);
1444 #endif
1445 	/* Some people are used to having these keystrokes in the Search menu. */
1446 	add_to_sclist(MGOTOLINE|MWHEREIS|MFINDINHELP, "^Y", 0, to_first_line, 0);
1447 	add_to_sclist(MGOTOLINE|MWHEREIS|MFINDINHELP, "^V", 0, to_last_line, 0);
1448 #ifdef ENABLE_BROWSER
1449 	add_to_sclist(MWHEREISFILE, "^Y", 0, to_first_file, 0);
1450 	add_to_sclist(MWHEREISFILE, "^V", 0, to_last_file, 0);
1451 	add_to_sclist(MBROWSER|MWHEREISFILE, "M-\\", 0, to_first_file, 0);
1452 	add_to_sclist(MBROWSER|MWHEREISFILE, "M-/", 0, to_last_file, 0);
1453 	add_to_sclist(MBROWSER, "Home", KEY_HOME, to_first_file, 0);
1454 	add_to_sclist(MBROWSER, "End", KEY_END, to_last_file, 0);
1455 	add_to_sclist(MBROWSER, "^Home", CONTROL_HOME, to_first_file, 0);
1456 	add_to_sclist(MBROWSER, "^End", CONTROL_END, to_last_file, 0);
1457 	add_to_sclist(MBROWSER, SLASH_OR_DASH, 0, goto_dir, 0);
1458 	add_to_sclist(MBROWSER, "M-G", 0, goto_dir, 0);
1459 	add_to_sclist(MBROWSER, "^_", 0, goto_dir, 0);
1460 #endif
1461 	if (ISSET(SAVE_ON_EXIT) && !ISSET(PRESERVE))
1462 		add_to_sclist(MWRITEFILE, "^Q", 0, discard_buffer, 0);
1463 #ifndef NANO_TINY
1464 	add_to_sclist(MWRITEFILE, "M-D", 0, dos_format_void, 0);
1465 	add_to_sclist(MWRITEFILE, "M-M", 0, mac_format_void, 0);
1466 	/* Only when not in restricted mode, allow Appending, Prepending,
1467 	 * making backups, and executing a command. */
1468 	if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE)) {
1469 		add_to_sclist(MWRITEFILE, "M-A", 0, append_void, 0);
1470 		add_to_sclist(MWRITEFILE, "M-P", 0, prepend_void, 0);
1471 		add_to_sclist(MWRITEFILE, "M-B", 0, backup_file_void, 0);
1472 		add_to_sclist(MINSERTFILE|MEXECUTE, "^X", 0, flip_execute, 0);
1473 	}
1474 	add_to_sclist(MINSERTFILE, "M-N", 0, flip_convert, 0);
1475 #endif
1476 #ifdef ENABLE_MULTIBUFFER
1477 	/* Only when not in restricted mode, allow multiple buffers. */
1478 	if (!ISSET(RESTRICTED)) {
1479 		add_to_sclist(MINSERTFILE|MEXECUTE, "M-F", 0, flip_newbuffer, 0);
1480 #ifndef NANO_TINY
1481 		add_to_sclist(MEXECUTE, "M-\\", 0, flip_pipe, 0);
1482 #endif
1483 	}
1484 #endif
1485 #ifdef ENABLE_BROWSER
1486 	/* Only when not in restricted mode, allow entering the file browser. */
1487 	if (!ISSET(RESTRICTED))
1488 		add_to_sclist(MWRITEFILE|MINSERTFILE, "^T", 0, to_files, 0);
1489 #endif
1490 	add_to_sclist(MBROWSER|MHELP, "^C", 0, do_exit, 0);
1491 	/* Allow exiting from the file browser and the help viewer with
1492 	 * the same key as they were entered. */
1493 #ifdef ENABLE_BROWSER
1494 	add_to_sclist(MBROWSER, "^T", 0, do_exit, 0);
1495 #endif
1496 #ifdef ENABLE_HELP
1497 	add_to_sclist(MHELP, "^G", 0, do_exit, 0);
1498 	add_to_sclist(MHELP, "F1", KEY_F(1), do_exit, 0);
1499 	add_to_sclist(MHELP, "Home", KEY_HOME, to_first_line, 0);
1500 	add_to_sclist(MHELP, "End", KEY_END, to_last_line, 0);
1501 #endif
1502 #ifdef ENABLE_COLOR
1503 	add_to_sclist(MLINTER, "^X", 0, do_cancel, 0);
1504 #endif
1505 	add_to_sclist(MMOST & ~MFINDINHELP, "F1", KEY_F(1), do_help, 0);
1506 	add_to_sclist(MMAIN|MBROWSER|MHELP, "F2", KEY_F(2), do_exit, 0);
1507 	add_to_sclist(MMAIN, "F3", KEY_F(3), do_writeout_void, 0);
1508 #ifdef ENABLE_JUSTIFY
1509 	add_to_sclist(MMAIN, "F4", KEY_F(4), do_justify, 0);
1510 #endif
1511 	add_to_sclist(MMAIN, "F5", KEY_F(5), do_insertfile_void, 0);
1512 	add_to_sclist(MMAIN|MBROWSER|MHELP, "F6", KEY_F(6), do_search_forward, 0);
1513 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "F7", KEY_F(7), do_page_up, 0);
1514 	add_to_sclist(MMAIN|MBROWSER|MHELP|MLINTER, "F8", KEY_F(8), do_page_down, 0);
1515 	add_to_sclist(MMOST, "F9", KEY_F(9), cut_text, 0);
1516 	add_to_sclist(MMOST, "F10", KEY_F(10), paste_text, 0);
1517 	add_to_sclist(MMAIN, "F11", KEY_F(11), report_cursor_position, 0);
1518 #ifdef ENABLE_SPELLER
1519 	add_to_sclist(MMAIN, "F12", KEY_F(12), do_spell, 0);
1520 #endif
1521 #if defined(KEY_CANCEL) && defined(KEY_SUSPEND) && defined(KEY_SIC)
1522 	add_to_sclist((MMOST & ~MMAIN) | MYESNO, "", KEY_CANCEL, do_cancel, 0);
1523 	add_to_sclist(MMAIN|MEXECUTE, "", KEY_SUSPEND, do_suspend_void, 0);
1524 	add_to_sclist(MMAIN, "", KEY_SIC, do_insertfile_void, 0);
1525 #endif
1526 #ifndef NANO_TINY
1527 	/* Catch and ignore bracketed paste marker keys. */
1528 	add_to_sclist(MMOST|MBROWSER|MHELP|MYESNO, "", BRACKETED_PASTE_MARKER, do_nothing, 0);
1529 #endif
1530 }
1531 
1532 #ifndef NANO_TINY
1533 /* Return the textual description that corresponds to the given flag. */
flagtostr(int flag)1534 const char *flagtostr(int flag)
1535 {
1536 	switch (flag) {
1537 		case NO_HELP:
1538 			/* TRANSLATORS: The next thirteen strings are toggle descriptions;
1539 			 * they are best kept shorter than 40 characters, but may be longer. */
1540 			return N_("Help mode");
1541 		case CONSTANT_SHOW:
1542 			return N_("Constant cursor position display");
1543 		case SOFTWRAP:
1544 			return N_("Soft wrapping of overlong lines");
1545 		case WHITESPACE_DISPLAY:
1546 			return N_("Whitespace display");
1547 		case NO_SYNTAX:
1548 			return N_("Color syntax highlighting");
1549 		case SMART_HOME:
1550 			return N_("Smart home key");
1551 		case AUTOINDENT:
1552 			return N_("Auto indent");
1553 		case CUT_FROM_CURSOR:
1554 			return N_("Cut to end");
1555 		case BREAK_LONG_LINES:
1556 			return N_("Hard wrapping of overlong lines");
1557 		case TABS_TO_SPACES:
1558 			return N_("Conversion of typed tabs to spaces");
1559 		case USE_MOUSE:
1560 			return N_("Mouse support");
1561 		case SUSPENDABLE:
1562 			return N_("Suspension");
1563 		case LINE_NUMBERS:
1564 			return N_("Line numbering");
1565 		default:
1566 			die("Bad toggle -- please report a bug\n");
1567 			return "";
1568 	}
1569 }
1570 #endif /* !NANO_TINY */
1571