blob: b694192c4f4c9c7cd732e855fa0f10020ff31743 [file] [log] [blame]
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +00001/**************************************************************************
Benno Schulenberg514cd9a2016-08-29 17:10:49 +02002 * help.c -- This file is part of GNU nano. *
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +00003 * *
Chris Allegretta8a07a962009-12-02 03:36:22 +00004 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, *
Benno Schulenberg7a9f4a42014-04-30 20:18:26 +00005 * 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. *
Benno Schulenberg406e5242016-08-29 15:14:18 +02006 * Copyright (C) 2014, 2015, 2016 Benno Schulenberg *
7 * *
Benno Schulenberg514cd9a2016-08-29 17:10:49 +02008 * GNU nano is free software: you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published *
10 * by the Free Software Foundation, either version 3 of the License, *
11 * or (at your option) any later version. *
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +000012 * *
Benno Schulenberg514cd9a2016-08-29 17:10:49 +020013 * GNU nano is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty *
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
16 * See the GNU General Public License for more details. *
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +000017 * *
18 * You should have received a copy of the GNU General Public License *
Benno Schulenberg514cd9a2016-08-29 17:10:49 +020019 * along with this program. If not, see http://www.gnu.org/licenses/. *
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +000020 * *
21 **************************************************************************/
22
David Lawrence Ramsey034b9942005-12-08 02:47:10 +000023#include "proto.h"
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +000024
25#include <stdio.h>
26#include <string.h>
27#include <ctype.h>
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +000028
29#ifndef DISABLE_HELP
30
31static char *help_text = NULL;
32 /* The text displayed in the help window. */
33
Benno Schulenberga9aa0ef2015-08-16 08:43:56 +000034static char *end_of_intro = NULL;
35 /* The point in the help text where the introductory paragraphs end
36 * and the shortcut descriptions begin. */
37
Benno Schulenberg7a1959f2015-08-16 09:28:33 +000038/* Our main help-viewer function. */
39void do_help(void)
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000040{
David Lawrence Ramseya662c552006-06-30 21:13:55 +000041 int kbinput = ERR;
Benno Schulenberg7e5324d2014-06-30 18:04:33 +000042 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramsey6e7d24d2006-05-06 02:26:18 +000043 size_t line = 0;
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000044 /* The line number in help_text of the first displayed help
45 * line. This variable is zero-based. */
David Lawrence Ramseyf629aad2006-05-06 02:42:42 +000046 size_t last_line = 0;
David Lawrence Ramsey6e7d24d2006-05-06 02:26:18 +000047 /* The line number in help_text of the last help line. This
48 * variable is zero-based. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +000049 int oldmenu = currmenu;
Benno Schulenberg8f615112014-04-14 09:57:06 +000050 /* The menu we were called from. */
David Lawrence Ramsey6e7d24d2006-05-06 02:26:18 +000051 const char *ptr;
David Lawrence Ramsey6335fb52007-01-01 05:15:32 +000052 /* The current line of the help text. */
David Lawrence Ramsey60d22f02006-07-05 02:24:23 +000053 size_t old_line = (size_t)-1;
54 /* The line we were on before the current line. */
Benno Schulenberg6418ffa2014-07-02 09:29:05 +000055 functionptrtype func;
56 /* The function of the key the user typed in. */
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000057
Benno Schulenberg568d2a32016-02-13 19:41:12 +000058 /* Don't show a cursor in the help screen. */
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000059 curs_set(0);
60 blank_edit();
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000061 blank_statusbar();
62
63 /* Set help_text as the string to display. */
64 help_init();
65
66 assert(help_text != NULL);
67
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000068 if (ISSET(NO_HELP)) {
69 /* Make sure that the help screen's shortcut list will actually
70 * be displayed. */
71 UNSET(NO_HELP);
72 window_init();
73 }
74
Chris Allegretta79a33bb2008-03-05 07:34:01 +000075 bottombars(MHELP);
David Lawrence Ramsey51b7b0e2006-07-05 06:38:47 +000076 wnoutrefresh(bottomwin);
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +000077
Benno Schulenberg75d64e62015-05-28 13:02:29 +000078 while (TRUE) {
79 size_t i;
80
Benno Schulenberg59187b82015-05-28 13:28:37 +000081 ptr = help_text;
David Lawrence Ramsey6e7d24d2006-05-06 02:26:18 +000082
Benno Schulenberg427eff62015-08-16 09:14:42 +000083 /* Find the line number of the last line of the help text. */
Benno Schulenberg59187b82015-05-28 13:28:37 +000084 for (last_line = 0; *ptr != '\0'; last_line++) {
85 ptr += help_line_len(ptr);
86 if (*ptr == '\n')
87 ptr++;
88 }
89
90 if (last_line > 0)
91 last_line--;
David Lawrence Ramsey6e7d24d2006-05-06 02:26:18 +000092
Benno Schulenberg427eff62015-08-16 09:14:42 +000093 /* Redisplay if the text was scrolled or an invalid key was pressed. */
94 if (line != old_line || kbinput == ERR) {
David Lawrence Ramseyc0ba4bf2006-07-05 01:10:18 +000095 blank_edit();
96
97 ptr = help_text;
98
Benno Schulenberg427eff62015-08-16 09:14:42 +000099 /* Advance in the text to the first line to be displayed. */
David Lawrence Ramseyc0ba4bf2006-07-05 01:10:18 +0000100 for (i = 0; i < line; i++) {
101 ptr += help_line_len(ptr);
102 if (*ptr == '\n')
103 ptr++;
104 }
105
Benno Schulenberg427eff62015-08-16 09:14:42 +0000106 /* Now display as many lines as the window will hold. */
David Lawrence Ramseyc0ba4bf2006-07-05 01:10:18 +0000107 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
108 size_t j = help_line_len(ptr);
109
110 mvwaddnstr(edit, i, 0, ptr, j);
111 ptr += j;
112 if (*ptr == '\n')
113 ptr++;
114 }
115 }
116
117 wnoutrefresh(edit);
118
David Lawrence Ramsey60d22f02006-07-05 02:24:23 +0000119 old_line = line;
120
Benno Schulenbergc8f530a2016-05-19 20:43:08 +0200121 lastmessage = HUSH;
Benno Schulenberg2535f512016-04-30 17:31:43 +0200122
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000123 kbinput = get_kbinput(edit);
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000124
Benno Schulenberg75d64e62015-05-28 13:02:29 +0000125#ifndef NANO_TINY
126 if (kbinput == KEY_WINCH) {
127 kbinput = ERR;
Benno Schulenberg427eff62015-08-16 09:14:42 +0000128 continue; /* Redraw the screen. */
Benno Schulenberg75d64e62015-05-28 13:02:29 +0000129 }
130#endif
131
Chris Allegrettac0b78722008-03-11 04:52:57 +0000132#ifndef DISABLE_MOUSE
Benno Schulenberg8f615112014-04-14 09:57:06 +0000133 if (kbinput == KEY_MOUSE) {
Benno Schulenbergcfa13382014-06-23 20:22:42 +0000134 int mouse_x, mouse_y;
135 get_mouseinput(&mouse_x, &mouse_y, TRUE);
136 continue; /* Redraw the screen. */
Chris Allegrettac0b78722008-03-11 04:52:57 +0000137 }
138#endif
139
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000140 func = parse_help_input(&kbinput);
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000141
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000142 if (func == total_refresh) {
Benno Schulenbergcfa13382014-06-23 20:22:42 +0000143 total_redraw();
Benno Schulenberg8b636de2016-07-01 12:41:35 +0200144 } else if (func == do_up_void) {
145 if (line > 0)
146 line--;
147 } else if (func == do_down_void) {
148 if (line + (editwinrows - 1) < last_line)
149 line++;
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000150 } else if (func == do_page_up) {
Benno Schulenbergcfa13382014-06-23 20:22:42 +0000151 if (line > editwinrows - 2)
152 line -= editwinrows - 2;
153 else
154 line = 0;
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000155 } else if (func == do_page_down) {
Benno Schulenbergcfa13382014-06-23 20:22:42 +0000156 if (line + (editwinrows - 1) < last_line)
157 line += editwinrows - 2;
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000158 } else if (func == do_first_line) {
Benno Schulenberg40ae3942014-06-25 09:17:38 +0000159 line = 0;
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000160 } else if (func == do_last_line) {
Benno Schulenberg40ae3942014-06-25 09:17:38 +0000161 if (line + (editwinrows - 1) < last_line)
162 line = last_line - (editwinrows - 1);
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000163 } else if (func == do_exit) {
Benno Schulenberg427eff62015-08-16 09:14:42 +0000164 /* Exit from the help viewer. */
Benno Schulenberg623b1b62014-04-15 19:32:45 +0000165 break;
Benno Schulenberge0c4f9c2016-04-27 14:37:31 +0200166 } else
167 unbound_key(kbinput);
David Lawrence Ramseya43b1082006-06-30 22:28:37 +0000168 }
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000169
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000170 if (old_no_help) {
171 blank_bottombars();
172 wnoutrefresh(bottomwin);
Benno Schulenbergd8b6dbf2015-04-07 14:16:07 +0000173 currmenu = oldmenu;
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000174 SET(NO_HELP);
175 window_init();
176 } else
Benno Schulenbergd8b6dbf2015-04-07 14:16:07 +0000177 bottombars(oldmenu);
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000178
Benno Schulenberg7a1959f2015-08-16 09:28:33 +0000179#ifndef DISABLE_BROWSER
180 if (oldmenu == MBROWSER || oldmenu == MWHEREISFILE || oldmenu == MGOTODIR)
181 browser_refresh();
182 else
183#endif
184 edit_refresh();
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000185
Benno Schulenberg86bbe502015-08-16 17:53:28 +0000186 /* We're exiting from the help screen. */
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000187 free(help_text);
David Lawrence Ramseyd420b5a2005-11-01 23:00:56 +0000188}
189
Benno Schulenberg86bbe502015-08-16 17:53:28 +0000190/* Allocate space for the help text for the current menu, and concatenate
191 * the different pieces of text into it. */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000192void help_init(void)
193{
Benno Schulenberg427eff62015-08-16 09:14:42 +0000194 size_t allocsize = 0;
195 /* Space needed for help_text. */
196 const char *htx[3];
197 /* Untranslated help introduction. We break it up into three chunks
198 * in case the full string is too long for the compiler to handle. */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000199 char *ptr;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000200 const subnfunc *f;
201 const sc *s;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000202
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000203#ifndef NANO_TINY
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000204 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
205
206 UNSET(WHITESPACE_DISPLAY);
207#endif
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000208
209 /* First, set up the initial help text for the current function. */
Benno Schulenberge167afe2014-04-16 09:26:15 +0000210 if (currmenu == MWHEREIS || currmenu == MREPLACE || currmenu == MREPLACEWITH) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000211 htx[0] = N_("Search Command Help Text\n\n "
212 "Enter the words or characters you would like to "
213 "search for, and then press Enter. If there is a "
214 "match for the text you entered, the screen will be "
215 "updated to the location of the nearest match for the "
216 "search string.\n\n The previous search string will be "
217 "shown in brackets after the search prompt. Hitting "
218 "Enter without entering any text will perform the "
219 "previous search. ");
220 htx[1] = N_("If you have selected text with the mark and then "
221 "search to replace, only matches in the selected text "
222 "will be replaced.\n\n The following function keys are "
223 "available in Search mode:\n\n");
224 htx[2] = NULL;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000225 } else if (currmenu == MGOTOLINE) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000226 htx[0] = N_("Go To Line Help Text\n\n "
227 "Enter the line number that you wish to go to and hit "
228 "Enter. If there are fewer lines of text than the "
229 "number you entered, you will be brought to the last "
230 "line of the file.\n\n The following function keys are "
231 "available in Go To Line mode:\n\n");
232 htx[1] = NULL;
233 htx[2] = NULL;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000234 } else if (currmenu == MINSERTFILE) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000235 htx[0] = N_("Insert File Help Text\n\n "
236 "Type in the name of a file to be inserted into the "
237 "current file buffer at the current cursor "
238 "location.\n\n If you have compiled nano with multiple "
239 "file buffer support, and enable multiple file buffers "
240 "with the -F or --multibuffer command line flags, the "
241 "Meta-F toggle, or a nanorc file, inserting a file "
242 "will cause it to be loaded into a separate buffer "
243 "(use Meta-< and > to switch between file buffers). ");
244 htx[1] = N_("If you need another blank buffer, do not enter "
245 "any filename, or type in a nonexistent filename at "
246 "the prompt and press Enter.\n\n The following "
247 "function keys are available in Insert File mode:\n\n");
248 htx[2] = NULL;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000249 } else if (currmenu == MWRITEFILE) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000250 htx[0] = N_("Write File Help Text\n\n "
251 "Type the name that you wish to save the current file "
252 "as and press Enter to save the file.\n\n If you have "
253 "selected text with the mark, you will be prompted to "
254 "save only the selected portion to a separate file. To "
255 "reduce the chance of overwriting the current file with "
256 "just a portion of it, the current filename is not the "
257 "default in this mode.\n\n The following function keys "
258 "are available in Write File mode:\n\n");
259 htx[1] = NULL;
260 htx[2] = NULL;
261 }
262#ifndef DISABLE_BROWSER
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000263 else if (currmenu == MBROWSER) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000264 htx[0] = N_("File Browser Help Text\n\n "
265 "The file browser is used to visually browse the "
266 "directory structure to select a file for reading "
267 "or writing. You may use the arrow keys or Page Up/"
268 "Down to browse through the files, and S or Enter to "
269 "choose the selected file or enter the selected "
270 "directory. To move up one level, select the "
271 "directory called \"..\" at the top of the file "
272 "list.\n\n The following function keys are available "
273 "in the file browser:\n\n");
274 htx[1] = NULL;
275 htx[2] = NULL;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000276 } else if (currmenu == MWHEREISFILE) {
David Lawrence Ramseye38b8082006-03-30 07:03:04 +0000277 htx[0] = N_("Browser Search Command Help Text\n\n "
278 "Enter the words or characters you would like to "
279 "search for, and then press Enter. If there is a "
280 "match for the text you entered, the screen will be "
281 "updated to the location of the nearest match for the "
282 "search string.\n\n The previous search string will be "
283 "shown in brackets after the search prompt. Hitting "
284 "Enter without entering any text will perform the "
David Lawrence Ramsey9c2f7ab2006-06-09 12:44:34 +0000285 "previous search.\n\n");
286 htx[1] = N_(" The following function keys are available in "
David Lawrence Ramseye38b8082006-03-30 07:03:04 +0000287 "Browser Search mode:\n\n");
288 htx[2] = NULL;
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000289 } else if (currmenu == MGOTODIR) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000290 htx[0] = N_("Browser Go To Directory Help Text\n\n "
291 "Enter the name of the directory you would like to "
292 "browse to.\n\n If tab completion has not been "
293 "disabled, you can use the Tab key to (attempt to) "
294 "automatically complete the directory name.\n\n The "
295 "following function keys are available in Browser Go "
296 "To Directory mode:\n\n");
297 htx[1] = NULL;
298 htx[2] = NULL;
299 }
David Lawrence Ramseye006c512006-03-25 15:23:55 +0000300#endif /* !DISABLE_BROWSER */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000301#ifndef DISABLE_SPELLER
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000302 else if (currmenu == MSPELL) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000303 htx[0] = N_("Spell Check Help Text\n\n "
304 "The spell checker checks the spelling of all text in "
305 "the current file. When an unknown word is "
306 "encountered, it is highlighted and a replacement can "
307 "be edited. It will then prompt to replace every "
308 "instance of the given misspelled word in the current "
309 "file, or, if you have selected text with the mark, in "
David Lawrence Ramseyaf7677e2006-05-19 23:07:02 +0000310 "the selected text.\n\n The following function keys "
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000311 "are available in Spell Check mode:\n\n");
312 htx[1] = NULL;
313 htx[2] = NULL;
314 }
David Lawrence Ramseye006c512006-03-25 15:23:55 +0000315#endif /* !DISABLE_SPELLER */
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000316#ifndef NANO_TINY
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000317 else if (currmenu == MEXTCMD) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000318 htx[0] = N_("Execute Command Help Text\n\n "
David Lawrence Ramsey9e553b22006-06-08 02:16:37 +0000319 "This mode allows you to insert the output of a "
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000320 "command run by the shell into the current buffer (or "
David Lawrence Ramseya7e778e2007-01-29 15:34:45 +0000321 "a new buffer in multiple file buffer mode). If you "
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000322 "need another blank buffer, do not enter any "
David Lawrence Ramseyaf7677e2006-05-19 23:07:02 +0000323 "command.\n\n The following function keys are "
324 "available in Execute Command mode:\n\n");
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000325 htx[1] = NULL;
326 htx[2] = NULL;
327 }
David Lawrence Ramseye006c512006-03-25 15:23:55 +0000328#endif /* !NANO_TINY */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000329 else {
330 /* Default to the main help list. */
David Lawrence Ramsey7b0531a2006-07-31 01:30:31 +0000331 htx[0] = N_("Main nano help text\n\n "
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000332 "The nano editor is designed to emulate the "
333 "functionality and ease-of-use of the UW Pico text "
334 "editor. There are four main sections of the editor. "
335 "The top line shows the program version, the current "
336 "filename being edited, and whether or not the file "
337 "has been modified. Next is the main editor window "
338 "showing the file being edited. The status line is "
339 "the third line from the bottom and shows important "
David Lawrence Ramsey5c55e852006-08-19 11:11:51 +0000340 "messages. ");
341 htx[1] = N_("The bottom two lines show the most commonly used "
Benno Schulenberg4a9b97b2016-04-05 15:42:58 +0200342 "shortcuts in the editor.\n\n Shortcuts are written as "
343 "follows: Control-key sequences are notated with a '^' "
344 "and can be entered either by using the Ctrl key or "
345 "pressing the Esc key twice. Meta-key sequences are "
346 "notated with 'M-' and can be entered using either the "
347 "Alt, Cmd, or Esc key, depending on your keyboard setup. ");
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000348 htx[2] = N_("Also, pressing Esc twice and then typing a "
349 "three-digit decimal number from 000 to 255 will enter "
350 "the character with the corresponding value. The "
351 "following keystrokes are available in the main editor "
352 "window. Alternative keys are shown in "
353 "parentheses:\n\n");
354 }
355
356 htx[0] = _(htx[0]);
357 if (htx[1] != NULL)
358 htx[1] = _(htx[1]);
359 if (htx[2] != NULL)
360 htx[2] = _(htx[2]);
361
362 allocsize += strlen(htx[0]);
363 if (htx[1] != NULL)
364 allocsize += strlen(htx[1]);
365 if (htx[2] != NULL)
366 allocsize += strlen(htx[2]);
367
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000368 /* Calculate the length of the shortcut help text. Each entry has
369 * one or two keys, which fill 16 columns, plus translated text,
370 * plus one or two \n's. */
Benno Schulenberg427eff62015-08-16 09:14:42 +0000371 for (f = allfuncs; f != NULL; f = f->next)
372 if (f->menus & currmenu)
373 allocsize += (16 * mb_cur_max()) + strlen(f->help) + 2;
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000374
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000375#ifndef NANO_TINY
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000376 /* If we're on the main list, we also count the toggle help text.
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000377 * Each entry has "M-%c\t\t", five chars which fill 16 columns,
378 * plus a space, plus translated text, plus one or two '\n's. */
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000379 if (currmenu == MMAIN) {
David Lawrence Ramsey23ed0152006-06-19 16:04:42 +0000380 size_t endis_len = strlen(_("enable/disable"));
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000381
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000382 for (s = sclist; s != NULL; s = s->next)
Benno Schulenberg5bd359d2014-04-15 15:02:43 +0000383 if (s->scfunc == do_toggle_void)
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000384 allocsize += strlen(_(flagtostr(s->toggle))) + endis_len + 8;
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000385 }
386#endif
387
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000388 /* Allocate space for the help text. */
389 help_text = charalloc(allocsize + 1);
390
391 /* Now add the text we want. */
392 strcpy(help_text, htx[0]);
393 if (htx[1] != NULL)
394 strcat(help_text, htx[1]);
395 if (htx[2] != NULL)
396 strcat(help_text, htx[2]);
397
398 ptr = help_text + strlen(help_text);
399
Benno Schulenberga9aa0ef2015-08-16 08:43:56 +0000400 /* Remember this end-of-introduction, start-of-shortcuts. */
401 end_of_intro = ptr;
402
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000403 /* Now add our shortcut info. */
404 for (f = allfuncs; f != NULL; f = f->next) {
Benno Schulenberg54407962015-08-16 08:49:29 +0000405 int scsfound = 0;
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000406
Benno Schulenberg8f615112014-04-14 09:57:06 +0000407 if ((f->menus & currmenu) == 0)
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000408 continue;
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000409
Benno Schulenbergcb7d11b2014-04-22 20:10:43 +0000410 /* Let's simply show the first two shortcuts from the list. */
Benno Schulenberg54407962015-08-16 08:49:29 +0000411 for (s = sclist; s != NULL; s = s->next) {
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000412
Benno Schulenberg1f866c22015-07-15 20:13:05 +0000413 if ((s->menus & currmenu) == 0)
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000414 continue;
415
Benno Schulenberg8f615112014-04-14 09:57:06 +0000416 if (s->scfunc == f->scfunc) {
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000417 scsfound++;
Benno Schulenbergcb7d11b2014-04-22 20:10:43 +0000418 /* Make the first column narrower (6) than the second (10),
419 * but allow it to spill into the second, for "M-Space". */
420 if (scsfound == 1) {
421 sprintf(ptr, "%s ", s->keystr);
Benno Schulenberg7a274d62016-10-12 12:21:44 +0200422 /* Unicode arrows take three bytes instead of one. */
423 if (s->keystr[1] == '\xE2')
424 ptr += 8;
425 else
426 ptr += 6;
Benno Schulenbergcb7d11b2014-04-22 20:10:43 +0000427 } else {
428 ptr += sprintf(ptr, "(%s)\t", s->keystr);
Benno Schulenberg32187712014-05-13 20:34:15 +0000429 break;
Benno Schulenbergcb7d11b2014-04-22 20:10:43 +0000430 }
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000431 }
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000432 }
Benno Schulenbergcb7d11b2014-04-22 20:10:43 +0000433
434 if (scsfound == 0)
435 ptr += sprintf(ptr, "\t\t");
436 else if (scsfound == 1)
437 ptr += 10;
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000438
David Lawrence Ramsey23ed0152006-06-19 16:04:42 +0000439 /* The shortcut's help text. */
Chris Allegrettad3659f82008-03-16 23:57:14 +0000440 ptr += sprintf(ptr, "%s\n", _(f->help));
David Lawrence Ramsey1df3e2d2006-04-22 19:45:26 +0000441
Chris Allegretta79a33bb2008-03-05 07:34:01 +0000442 if (f->blank_after)
David Lawrence Ramsey1df3e2d2006-04-22 19:45:26 +0000443 ptr += sprintf(ptr, "\n");
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000444 }
445
David Lawrence Ramseyebe34252005-11-15 03:17:35 +0000446#ifndef NANO_TINY
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000447 /* And the toggles... */
Benno Schulenberg5ac6a872015-07-06 17:51:17 +0000448 if (currmenu == MMAIN) {
449 int maximum = 0, counter = 0;
450
451 /* First see how many toggles there are. */
Benno Schulenberg6095ff32015-07-06 19:17:27 +0000452 for (s = sclist; s != NULL; s = s->next)
Benno Schulenberg17cf8332016-05-30 09:09:36 +0200453 maximum = (s->toggle && s->ordinal > maximum) ? s->ordinal : maximum;
Benno Schulenberg5ac6a872015-07-06 17:51:17 +0000454
455 /* Now show them in the original order. */
456 while (counter < maximum) {
457 counter++;
Benno Schulenberg6095ff32015-07-06 19:17:27 +0000458 for (s = sclist; s != NULL; s = s->next)
Benno Schulenberg5ac6a872015-07-06 17:51:17 +0000459 if (s->toggle && s->ordinal == counter) {
Benno Schulenberg1f866c22015-07-15 20:13:05 +0000460 ptr += sprintf(ptr, "%s\t\t%s %s\n", (s->menus == MMAIN ? s->keystr : ""),
Benno Schulenberg17cf8332016-05-30 09:09:36 +0200461 _(flagtostr(s->toggle)), _("enable/disable"));
Benno Schulenberg6095ff32015-07-06 19:17:27 +0000462 if (s->toggle == NO_COLOR_SYNTAX || s->toggle == TABS_TO_SPACES)
463 ptr += sprintf(ptr, "\n");
Benno Schulenberg5ac6a872015-07-06 17:51:17 +0000464 break;
Benno Schulenberg6095ff32015-07-06 19:17:27 +0000465 }
Benno Schulenberg5ac6a872015-07-06 17:51:17 +0000466 }
467 }
David Lawrence Ramsey1df3e2d2006-04-22 19:45:26 +0000468
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000469 if (old_whitespace)
470 SET(WHITESPACE_DISPLAY);
Benno Schulenberg71c9a522014-05-13 20:14:01 +0000471#endif /* !NANO_TINY */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000472
Benno Schulenberg86bbe502015-08-16 17:53:28 +0000473 /* If all went well, we didn't overwrite the allocated space. */
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000474 assert(strlen(help_text) <= allocsize + 1);
475}
476
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000477/* Return the function that is bound to the given key, accepting certain
478 * plain characters too, for consistency with the file browser. */
479functionptrtype parse_help_input(int *kbinput)
David Lawrence Ramseybc80cb12006-04-24 23:03:21 +0000480{
Benno Schulenberg7e5324d2014-06-30 18:04:33 +0000481 if (!meta_key) {
David Lawrence Ramseybc80cb12006-04-24 23:03:21 +0000482 switch (*kbinput) {
David Lawrence Ramseycf1879b2006-04-27 23:39:49 +0000483 case ' ':
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000484 return do_page_down;
David Lawrence Ramseycf1879b2006-04-27 23:39:49 +0000485 case '-':
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000486 return do_page_up;
David Lawrence Ramsey1755e282006-10-02 21:25:41 +0000487 case 'E':
488 case 'e':
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000489 return do_exit;
David Lawrence Ramseybc80cb12006-04-24 23:03:21 +0000490 }
491 }
Benno Schulenberg6418ffa2014-07-02 09:29:05 +0000492 return func_from_key(kbinput);
David Lawrence Ramseybc80cb12006-04-24 23:03:21 +0000493}
494
Benno Schulenberg427eff62015-08-16 09:14:42 +0000495/* Calculate the displayable length of the help-text line starting at ptr. */
David Lawrence Ramseyc3593012005-11-01 20:11:55 +0000496size_t help_line_len(const char *ptr)
497{
Benno Schulenberga5b29532015-08-16 12:20:24 +0000498 size_t wrapping_point = (COLS > 24) ? COLS - 1 : 24;
Benno Schulenberga9aa0ef2015-08-16 08:43:56 +0000499 /* The target width for wrapping long lines. */
Benno Schulenberga5b29532015-08-16 12:20:24 +0000500 ssize_t wrap_location;
501 /* Actual position where the line can be wrapped. */
502 size_t length = 0;
503 /* Full length of the line, until the first newline. */
David Lawrence Ramseyc3593012005-11-01 20:11:55 +0000504
Benno Schulenberga9aa0ef2015-08-16 08:43:56 +0000505 /* Avoid overwide paragraphs in the introductory text. */
506 if (ptr < end_of_intro && COLS > 74)
Benno Schulenberga5b29532015-08-16 12:20:24 +0000507 wrapping_point = 74;
Benno Schulenberga9aa0ef2015-08-16 08:43:56 +0000508
Benno Schulenberga5b29532015-08-16 12:20:24 +0000509 wrap_location = break_line(ptr, wrapping_point, TRUE);
Benno Schulenberg9e438cd2015-08-16 12:15:11 +0000510
David Lawrence Ramseyc3593012005-11-01 20:11:55 +0000511 /* Get the length of the entire line up to a null or a newline. */
Benno Schulenberga5b29532015-08-16 12:20:24 +0000512 while (*(ptr + length) != '\0' && *(ptr + length) != '\n')
513 length = move_mbright(ptr, length);
David Lawrence Ramseyc3593012005-11-01 20:11:55 +0000514
Benno Schulenberga5b29532015-08-16 12:20:24 +0000515 /* If the entire line will just fit the screen, don't wrap it. */
516 if (strnlenpt(ptr, length) <= wrapping_point + 1)
517 return length;
518 else if (wrap_location > 0)
519 return wrap_location;
520 else
521 return 0;
David Lawrence Ramseyc3593012005-11-01 20:11:55 +0000522}
523
David Lawrence Ramsey7e2d6732005-11-01 19:32:45 +0000524#endif /* !DISABLE_HELP */
Chris Allegretta1d778232008-08-30 21:00:00 +0000525
Benno Schulenberg7a1959f2015-08-16 09:28:33 +0000526/* Start the help viewer. */
Chris Allegretta1d778232008-08-30 21:00:00 +0000527void do_help_void(void)
528{
Chris Allegretta1d778232008-08-30 21:00:00 +0000529#ifndef DISABLE_HELP
Benno Schulenberg7a1959f2015-08-16 09:28:33 +0000530 do_help();
Chris Allegretta1d778232008-08-30 21:00:00 +0000531#else
532 if (currmenu == MMAIN)
Benno Schulenberg68476162015-07-30 18:10:16 +0000533 say_there_is_no_help();
Chris Allegretta1d778232008-08-30 21:00:00 +0000534 else
535 beep();
Benno Schulenbergbb06fae2014-03-26 19:59:45 +0000536#endif /* !DISABLE_HELP */
Chris Allegretta1d778232008-08-30 21:00:00 +0000537}