blob: 15041d91c8fe34b4be70cfce9e373829a37049ad [file] [log] [blame]
Chris Allegretta11b00112000-08-06 21:13:45 +00001/* $Id$ */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002/**************************************************************************
3 * winio.c *
4 * *
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00005 * Copyright (C) 1999-2005 Chris Allegretta *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00006 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
Chris Allegretta3a24f3f2001-10-24 11:33:54 +00008 * the Free Software Foundation; either version 2, or (at your option) *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00009 * any later version. *
10 * *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000011 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * General Public License for more details. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000015 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
David Lawrence Ramsey6e925cf2005-05-15 19:57:17 +000018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
19 * 02110-1301, USA. *
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000020 * *
21 **************************************************************************/
22
Jordi Mallach55381aa2004-11-17 23:17:05 +000023#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000026
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000027#include <stdarg.h>
28#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000029#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000030#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000031#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000032#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000033#include "proto.h"
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000034
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +000035static int *key_buffer = NULL;
David Lawrence Ramsey74835712004-12-04 17:41:52 +000036 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000045static size_t statusbar_x = (size_t)-1;
46 /* The cursor position in answer. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000047static bool disable_cursorpos = FALSE;
48 /* Should we temporarily disable
49 * constant cursor position display? */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000050static bool resetstatuspos = FALSE;
51 /* Should we reset the cursor position
52 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000053
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000054/* Control character compatibility:
55 *
56 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
57 * VT100, and VT220.
58 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
59 * VT220, and VT320.
60 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
61 * VT220, and VT320.
62 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
63 * VT220, and VT320.
64 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
65 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000066 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000067 * ANSI, VT100, and VT220, and which is Backspace under VT320.
68 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000069 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000070 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
71 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000072 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000073 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000074 * on which the VT320 sequences are translated by the keypad to KEY_DC
75 * and [nothing]. We work around this conflict via the REBIND_DELETE
76 * flag: if it's not set, we assume VT320 compatibility, and if it is,
77 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
78 * Hemel for helping work this conflict out.
79 *
80 * Escape sequence compatibility:
81 *
82 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000083 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000084 * console), xterm, rxvt, and Eterm. Among these, there are several
85 * conflicts and omissions, outlined as follows:
86 *
87 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
88 * (Ctrl-I is also Tab on ANSI, which we already support.)
89 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
90 * NumLock off on Linux console; the latter is omitted. (The editing
91 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000092 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000093 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
94 * latter is omitted. (Mouse input will only work properly if the
95 * extended keypad value KEY_MOUSE is generated on mouse events
96 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000097 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000098 * omitted. (The editing keypad is more important to have working
99 * than the function keys, because the functions of the former are not
100 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000101 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000102 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000103 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000104 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000105 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
106 * omitted. (The arrow keys, with or without modifiers, are more
107 * important to have working than the function keys, because the
108 * functions of the former are not arbitrary and the functions of the
109 * latter are.)
110 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
111 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000112 *
113 * Note that Center (5) on the numeric keypad with NumLock off can also
114 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000115
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000116#ifndef NANO_SMALL
117/* Reset all the input routines that rely on character sequences. */
118void reset_kbinput(void)
119{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000120 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000121 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000122 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000123}
124#endif
125
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000126/* Read in a sequence of keystrokes from win and save them in the
127 * default keystroke buffer. This should only be called when the
128 * default keystroke buffer is empty. */
129void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000130{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000131 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000132
133 /* If the keystroke buffer isn't empty, get out. */
134 if (key_buffer != NULL)
135 return;
136
137 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000138#ifndef NANO_SMALL
139 allow_pending_sigwinch(TRUE);
140#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000141
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000142 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000143
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000144 /* If we get ERR when using blocking input, it means that the input
145 * source that we were using is gone, so die gracefully. */
146 if (input == ERR)
147 handle_hupterm(0);
148
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000149#ifndef NANO_SMALL
150 allow_pending_sigwinch(FALSE);
151#endif
152
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000153 /* Increment the length of the keystroke buffer, save the value of
154 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000155 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000156 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000157 key_buffer = (int *)nmalloc(sizeof(int));
158 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000159
160 /* Read in the remaining characters using non-blocking input. */
161 nodelay(win, TRUE);
162
163 while (TRUE) {
164#ifndef NANO_SMALL
165 allow_pending_sigwinch(TRUE);
166#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000167
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000168 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000169
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000170 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000171 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000172 break;
173
174 /* Otherwise, increment the length of the keystroke buffer, save
175 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000176 * if the keystroke is an extended keypad value or FALSE if it
177 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000178 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000179 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
180 sizeof(int));
181 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000182
183#ifndef NANO_SMALL
184 allow_pending_sigwinch(FALSE);
185#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000186 }
187
188 /* Switch back to non-blocking input. */
189 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000190
191#ifdef DEBUG
192 fprintf(stderr, "get_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
193#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000194}
195
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000196/* Return the length of the default keystroke buffer. */
197size_t get_buffer_len(void)
198{
199 return key_buffer_len;
200}
201
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000202/* Add the contents of the keystroke buffer input to the default
203 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000204void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000205{
206#ifndef NANO_SMALL
207 allow_pending_sigwinch(TRUE);
208 allow_pending_sigwinch(FALSE);
209#endif
210
211 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000212 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000213 return;
214
215 /* If adding input would put the default keystroke buffer beyond
216 * maximum capacity, only add enough of input to put it at maximum
217 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000218 if (key_buffer_len + input_len < key_buffer_len)
219 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000220
221 /* Add the length of input to the length of the default keystroke
222 * buffer, and reallocate the default keystroke buffer so that it
223 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000224 key_buffer_len += input_len;
225 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
226 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000227
228 /* If the default keystroke buffer wasn't empty before, move its
229 * beginning forward far enough so that we can add input to its
230 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000231 if (key_buffer_len > input_len)
232 memmove(key_buffer + input_len, key_buffer,
233 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000234
235 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000236 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000237}
238
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000239/* Put back the character stored in kbinput, putting it in byte range
240 * beforehand. If meta_key is TRUE, put back the Escape character after
241 * putting back kbinput. If func_key is TRUE, put back the function key
242 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000243void unget_kbinput(int kbinput, bool meta_key, bool func_key)
244{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000245 if (!func_key)
246 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000247
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000248 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000249
250 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000251 kbinput = NANO_CONTROL_3;
252 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000253 }
254}
255
256/* Try to read input_len characters from the default keystroke buffer.
257 * If the default keystroke buffer is empty and win isn't NULL, try to
258 * read in more characters from win and add them to the default
259 * keystroke buffer before doing anything else. If the default
260 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000261int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000262{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000263 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000264
265#ifndef NANO_SMALL
266 allow_pending_sigwinch(TRUE);
267 allow_pending_sigwinch(FALSE);
268#endif
269
270 if (key_buffer_len == 0) {
271 if (win != NULL)
272 get_buffer(win);
273
274 if (key_buffer_len == 0)
275 return NULL;
276 }
277
278 /* If input_len is greater than the length of the default keystroke
279 * buffer, only read the number of characters in the default
280 * keystroke buffer. */
281 if (input_len > key_buffer_len)
282 input_len = key_buffer_len;
283
284 /* Subtract input_len from the length of the default keystroke
285 * buffer, and allocate the keystroke buffer input so that it
286 * has enough room for input_len keystrokes. */
287 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000288 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289
290 /* Copy input_len characters from the beginning of the default
291 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000292 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000293
294 /* If the default keystroke buffer is empty, mark it as such. */
295 if (key_buffer_len == 0) {
296 free(key_buffer);
297 key_buffer = NULL;
298 /* If the default keystroke buffer isn't empty, move its
299 * beginning forward far enough back so that the keystrokes in input
300 * are no longer at its beginning. */
301 } else {
302 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000303 sizeof(int));
304 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
305 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000306 }
307
308 return input;
309}
310
311/* Read in a single character. If it's ignored, swallow it and go on.
312 * Otherwise, try to translate it from ASCII, meta key sequences, escape
313 * sequences, and/or extended keypad values. Set meta_key to TRUE when
314 * we get a meta key sequence, and set func_key to TRUE when we get an
315 * extended keypad value. Supported extended keypad values consist of
316 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
317 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
318 * the function keypad (F1-F16), and the numeric keypad with NumLock
319 * off. Assume nodelay(win) is FALSE. */
320int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
321{
322 int kbinput;
323
324 /* Read in a character and interpret it. Continue doing this until
325 * we get a recognized value or sequence. */
326 while ((kbinput = parse_kbinput(win, meta_key, func_key
327#ifndef NANO_SMALL
328 , FALSE
329#endif
330 )) == ERR);
331
332 return kbinput;
333}
334
335/* Translate ASCII characters, extended keypad values, and escape
336 * sequences into their corresponding key values. Set meta_key to TRUE
337 * when we get a meta key sequence, and set func_key to TRUE when we get
338 * a function key. Assume nodelay(win) is FALSE. */
339int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000340#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000341 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000342#endif
343 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000344
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000345{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000346 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000347 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000348
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000349#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000350 if (reset) {
351 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000352 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000353 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000354 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000355#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000356
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000357 *meta_key = FALSE;
358 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000359
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000360 /* Read in a character. */
361 while ((kbinput = get_input(win, 1)) == NULL);
362
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000363 switch (*kbinput) {
364 case ERR:
365 break;
366 case NANO_CONTROL_3:
367 /* Increment the escape counter. */
368 escapes++;
369 switch (escapes) {
370 case 1:
371 /* One escape: wait for more input. */
372 case 2:
373 /* Two escapes: wait for more input. */
374 break;
375 default:
376 /* More than two escapes: reset the escape counter
377 * and wait for more input. */
378 escapes = 0;
379 }
380 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000381#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000382 /* Since we don't change the default SIGWINCH handler when
383 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
384 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
385 case KEY_RESIZE:
386 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000387#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000388#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000389 case KEY_SHIFT_L:
390 case KEY_SHIFT_R:
391 case KEY_CONTROL_L:
392 case KEY_CONTROL_R:
393 case KEY_ALT_L:
394 case KEY_ALT_R:
395 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000396#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000397 default:
398 switch (escapes) {
399 case 0:
400 switch (*kbinput) {
401 case NANO_CONTROL_8:
402 retval = ISSET(REBIND_DELETE) ?
403 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
404 break;
405 case KEY_DOWN:
406 retval = NANO_NEXTLINE_KEY;
407 break;
408 case KEY_UP:
409 retval = NANO_PREVLINE_KEY;
410 break;
411 case KEY_LEFT:
412 retval = NANO_BACK_KEY;
413 break;
414 case KEY_RIGHT:
415 retval = NANO_FORWARD_KEY;
416 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000417#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000418 /* HP-UX 10 and 11 don't support KEY_HOME. */
419 case KEY_HOME:
420 retval = NANO_HOME_KEY;
421 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000422#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000423 case KEY_BACKSPACE:
424 retval = NANO_BACKSPACE_KEY;
425 break;
426 case KEY_DC:
427 retval = ISSET(REBIND_DELETE) ?
428 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
429 break;
430 case KEY_IC:
431 retval = NANO_INSERTFILE_KEY;
432 break;
433 case KEY_NPAGE:
434 retval = NANO_NEXTPAGE_KEY;
435 break;
436 case KEY_PPAGE:
437 retval = NANO_PREVPAGE_KEY;
438 break;
439 case KEY_ENTER:
440 retval = NANO_ENTER_KEY;
441 break;
442 case KEY_A1: /* Home (7) on numeric keypad
443 * with NumLock off. */
444 retval = NANO_HOME_KEY;
445 break;
446 case KEY_A3: /* PageUp (9) on numeric keypad
447 * with NumLock off. */
448 retval = NANO_PREVPAGE_KEY;
449 break;
450 case KEY_B2: /* Center (5) on numeric keypad
451 * with NumLock off. */
452 break;
453 case KEY_C1: /* End (1) on numeric keypad
454 * with NumLock off. */
455 retval = NANO_END_KEY;
456 break;
457 case KEY_C3: /* PageDown (4) on numeric
458 * keypad with NumLock off. */
459 retval = NANO_NEXTPAGE_KEY;
460 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000461#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000462 /* Slang doesn't support KEY_BEG. */
463 case KEY_BEG: /* Center (5) on numeric keypad
464 * with NumLock off. */
465 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000466#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000467#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000468 /* HP-UX 10 and 11 don't support KEY_END. */
469 case KEY_END:
470 retval = NANO_END_KEY;
471 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000472#endif
473#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000474 /* Slang doesn't support KEY_SUSPEND. */
475 case KEY_SUSPEND:
476 retval = NANO_SUSPEND_KEY;
477 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000478#endif
479#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000480 /* Slang doesn't support KEY_SLEFT. */
481 case KEY_SLEFT:
482 retval = NANO_BACK_KEY;
483 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000484#endif
485#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000486 /* Slang doesn't support KEY_SRIGHT. */
487 case KEY_SRIGHT:
488 retval = NANO_FORWARD_KEY;
489 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000490#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000491 default:
492 retval = *kbinput;
493 break;
494 }
495 break;
496 case 1:
497 /* One escape followed by a non-escape: escape
498 * sequence mode. Reset the escape counter. If
499 * there aren't any other keys waiting, we have a
500 * meta key sequence, so set meta_key to TRUE and
501 * save the lowercase version of the non-escape
502 * character as the result. If there are other keys
503 * waiting, we have a true escape sequence, so
504 * interpret it. */
505 escapes = 0;
506 if (get_buffer_len() == 0) {
507 *meta_key = TRUE;
508 retval = tolower(*kbinput);
509 } else {
510 int *seq;
511 size_t seq_len;
512 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000513
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000514 /* Put back the non-escape character, get the
515 * complete escape sequence, translate the
516 * sequence into its corresponding key value,
517 * and save that as the result. */
518 unget_input(kbinput, 1);
519 seq_len = get_buffer_len();
520 seq = get_input(NULL, seq_len);
521 retval = get_escape_seq_kbinput(seq, seq_len,
522 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000523
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000524 /* If the escape sequence is unrecognized and
525 * not ignored, put back all of its characters
526 * except for the initial escape. */
527 if (retval == ERR && !ignore_seq)
528 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000529
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000530 free(seq);
531 }
532 break;
533 case 2:
534 /* Two escapes followed by one or more decimal
535 * digits: byte sequence mode. If the word
536 * sequence's range is limited to 2XX (the first
537 * digit is in the '0' to '2' range and it's the
538 * first digit, or it's in the '0' to '9' range and
539 * it's not the first digit), increment the byte
540 * sequence counter and interpret the digit. If the
541 * byte sequence's range is not limited to 2XX, fall
542 * through. */
543 if (('0' <= *kbinput && *kbinput <= '6' &&
544 byte_digits == 0) || ('0' <= *kbinput &&
545 *kbinput <= '9' && byte_digits > 0)) {
546 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000547
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000548 byte_digits++;
549 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000550#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000551 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000552#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000553 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000554
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000555 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000556 char *byte_mb;
557 int byte_mb_len, *seq, i;
558
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000559 /* If we've read in a complete byte
560 * sequence, reset the byte sequence counter
561 * and the escape counter, and put back the
562 * corresponding byte value. */
563 byte_digits = 0;
564 escapes = 0;
565
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000566 /* Put back the multibyte equivalent of the
567 * byte value. */
568 byte_mb = make_mbchar(byte, &byte_mb_len);
569
570 seq = (int *)nmalloc(byte_mb_len *
571 sizeof(int));
572
573 for (i = 0; i < byte_mb_len; i++)
574 seq[i] = (unsigned char)byte_mb[i];
575
576 unget_input(seq, byte_mb_len);
577
578 free(byte_mb);
579 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000580 }
581 } else {
582 /* Reset the escape counter. */
583 escapes = 0;
584 if (byte_digits == 0)
585 /* Two escapes followed by a non-decimal
586 * digit or a decimal digit that would
587 * create a byte sequence greater than 2XX,
588 * and we're not in the middle of a byte
589 * sequence: control character sequence
590 * mode. Interpret the control sequence and
591 * save the corresponding control character
592 * as the result. */
593 retval = get_control_kbinput(*kbinput);
594 else {
595 /* If we're in the middle of a byte
596 * sequence, reset the byte sequence counter
597 * and save the character we got as the
598 * result. */
599 byte_digits = 0;
600 retval = *kbinput;
601 }
602 }
603 break;
604 }
605 }
606
607 /* If we have a result and it's an extended keypad value (i.e, a
608 * value outside of byte range), set func_key to TRUE. */
609 if (retval != ERR)
610 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000611
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000612#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000613 fprintf(stderr, "parse_kbinput(): kbinput = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", *kbinput, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000614#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000615
616 /* Return the result. */
617 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000618}
619
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000620/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000621 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000622 * are generated when the keypad doesn't support the needed keys. If
623 * the escape sequence is recognized but we want to ignore it, return
624 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
625 * set ignore_seq to FALSE. Assume that Escape has already been read
626 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000627int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000628 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000629{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000630 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000631
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000632 *ignore_seq = FALSE;
633
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000634 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000635 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000636 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000637 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000638 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000639 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000640 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000641 case 'P': /* Esc O 2 P == F13 on
642 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000643 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000644 break;
645 case 'Q': /* Esc O 2 Q == F14 on
646 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000647 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000648 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000649 case 'R': /* Esc O 2 R == F15 on
650 * xterm. */
651 retval = KEY_F(15);
652 break;
653 case 'S': /* Esc O 2 S == F16 on
654 * xterm. */
655 retval = KEY_F(16);
656 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000657 }
658 }
659 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000660 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
661 case 'B': /* Esc O B == Down on
662 * VT100/VT320/xterm. */
663 case 'C': /* Esc O C == Right on
664 * VT100/VT320/xterm. */
665 case 'D': /* Esc O D == Left on
666 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000667 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000668 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000669 case 'E': /* Esc O E == Center (5) on numeric keypad
670 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000671 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000672 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000673 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000674 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000675 break;
676 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000677 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000678 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000679 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000680 * NumLock off on VT100/VT220/VT320/xterm/
681 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000682 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000683 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000684 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000685 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000686 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000687 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000688 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000689 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000690 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000691 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000692 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000693 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000694 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000695 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000696 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000697 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000698 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000699 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000700 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000701 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000702 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000703 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000706 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000707 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000708 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000709 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000710 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000711 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000712 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000713 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000714 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000715 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000716 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000717 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000718 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000719 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000721 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000722 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000723 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000724 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000725 * NumLock off on VT100/VT220/VT320/xterm/
726 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000727 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000728 break;
729 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000730 * NumLock off on VT100/VT220/VT320/xterm/
731 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000732 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000733 break;
734 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000735 * NumLock off on VT100/VT220/VT320/xterm/
736 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000737 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000738 break;
739 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000740 * NumLock off on VT100/VT220/VT320/xterm/
741 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000742 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000743 break;
744 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000745 * with NumLock off on VT100/VT220/VT320/
746 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000747 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000748 break;
749 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000750 * NumLock off on VT100/VT220/VT320/xterm/
751 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000752 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000753 break;
754 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000755 * with NumLock off on VT100/VT220/VT320/
756 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000757 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000758 break;
759 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000760 * with NumLock off on VT100/VT220/VT320/
761 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000762 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000763 break;
764 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000765 * with NumLock off on VT100/VT220/VT320/
766 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000767 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000768 break;
769 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000770 * keypad with NumLock off on VT100/VT220/
771 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000772 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000773 break;
774 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000775 * with NumLock off on VT100/VT220/VT320/
776 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000777 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000778 break;
779 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000780 * with NumLock off on VT100/VT220/VT320/
781 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000782 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000783 break;
784 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000785 * with NumLock off on VT100/VT220/VT320/
786 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000787 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000788 break;
789 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000790 * with NumLock off on VT100/VT220/VT320/
791 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000792 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000793 break;
794 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000795 * with NumLock off on VT100/VT220/VT320/
796 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000797 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000798 break;
799 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000800 * with NumLock off on VT100/VT220/VT320/
801 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000802 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000803 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000804 }
805 break;
806 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000807 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000811 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000812 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000813 break;
814 }
815 break;
816 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000817 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000818 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000819 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000820 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000821 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
822 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000823 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000824 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000825 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
826 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000827 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000828 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000829 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
830 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000831 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000832 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000833 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
834 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000835 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000836 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
838 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000839 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000840 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000841 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000842 * VT220/VT320/Linux console/
843 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000844 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000845 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000846 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000847 * VT220/VT320/Linux console/
848 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000849 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000850 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000851 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000852 * VT220/VT320/Linux console/
853 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000854 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000855 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000856 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000857 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000858 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000859 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000860 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000861 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000862 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
863 * xterm. */
864 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
865 * xterm. */
866 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
867 * xterm. */
868 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
869 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000870 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000871 break;
872 }
873 }
874 break;
875 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000876 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000877 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000878 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
879 * xterm. */
880 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
881 * xterm. */
882 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
883 * xterm. */
884 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
885 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000886 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000887 break;
888 }
889 }
890 break;
891 }
892 }
893 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000894 default: /* Esc [ 1 ~ == Home on
895 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000896 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000897 break;
898 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000899 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000900 break;
901 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000902 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000903 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000904 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000905 * VT220/VT320/Linux console/
906 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000907 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000908 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000909 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000910 * VT220/VT320/Linux console/
911 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000912 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000913 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000914 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000915 * VT220/VT320/Linux console/
916 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000917 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000918 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000919 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000920 * VT220/VT320/Linux console/
921 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000922 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000923 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000924 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000925 * VT220/VT320/Linux console/
926 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000927 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000928 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000929 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000930 * VT220/VT320/Linux console/
931 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000932 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000933 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000934 case '8': /* Esc [ 2 8 ~ == F15 on
935 * VT220/VT320/Linux console/
936 * rxvt/Eterm. */
937 retval = KEY_F(15);
938 break;
939 case '9': /* Esc [ 2 9 ~ == F16 on
940 * VT220/VT320/Linux console/
941 * rxvt/Eterm. */
942 retval = KEY_F(16);
943 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000944 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000945 * VT220/VT320/Linux console/
946 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000947 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000948 break;
949 }
950 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000951 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000952 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
953 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000955 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000956 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000957 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000958 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000959 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000960 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
961 * Linux console/xterm; Esc [ 5 ^ ==
962 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000963 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000964 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000965 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
966 * Linux console/xterm; Esc [ 6 ^ ==
967 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000968 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000969 break;
970 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000971 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000972 break;
973 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000975 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000976 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000977 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000978 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000979 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000980 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000981 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000982 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000983 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000984 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000985 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000986 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000987 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000988 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000989 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000990 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000991 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000992 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000993 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000994 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000995 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000996 case 'E': /* Esc [ E == Center (5) on numeric keypad
997 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000998 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000999 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001000 case 'F': /* Esc [ F == End on FreeBSD
1001 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001002 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001003 break;
1004 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001005 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001007 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001008 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001009 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001010 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001011 break;
1012 case 'I': /* Esc [ I == PageUp on FreeBSD
1013 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001014 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001015 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001016 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001017 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001018 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001019 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001020 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 break;
1023 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001024 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001025 break;
1026 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001027 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001028 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001029 case 'P': /* Esc [ O P == F1 on
1030 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001032 break;
1033 case 'Q': /* Esc [ O Q == F2 on
1034 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001035 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001036 break;
1037 case 'R': /* Esc [ O R == F3 on
1038 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001039 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001040 break;
1041 case 'S': /* Esc [ O S == F4 on
1042 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001044 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001045 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001046 } else {
1047 /* Esc [ O == F3 on FreeBSD console. */
1048 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001049 }
1050 break;
1051 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001055 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001056 break;
1057 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001058 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001059 break;
1060 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001061 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001062 break;
1063 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001064 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001065 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001069 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001070 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001071 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001072 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001074 break;
1075 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001078 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001079 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001080 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001081 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001082 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001083 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001084 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001085 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001086 case 'c': /* Esc [ c == Shift-Right on rxvt/
1087 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001088 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001089 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001090 break;
1091 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001092 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001093 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001094 case 'A': /* Esc [ [ A == F1 on Linux
1095 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001096 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001097 break;
1098 case 'B': /* Esc [ [ B == F2 on Linux
1099 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
1102 case 'C': /* Esc [ [ C == F3 on Linux
1103 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001104 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001105 break;
1106 case 'D': /* Esc [ [ D == F4 on Linux
1107 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001108 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 break;
1110 case 'E': /* Esc [ [ E == F5 on Linux
1111 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001112 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001113 break;
1114 }
1115 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116 break;
1117 }
1118 break;
1119 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001120 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001121
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001122#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001123 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001124#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001125
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001126 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001127}
1128
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001129/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001130 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001131 * to many escape sequences. */
1132int get_escape_seq_abcd(int kbinput)
1133{
1134 switch (tolower(kbinput)) {
1135 case 'a':
1136 return NANO_PREVLINE_KEY;
1137 case 'b':
1138 return NANO_NEXTLINE_KEY;
1139 case 'c':
1140 return NANO_FORWARD_KEY;
1141 case 'd':
1142 return NANO_BACK_KEY;
1143 default:
1144 return ERR;
1145 }
1146}
1147
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001148/* Translate a byte sequence: turn a three-digit decimal number from
1149 * 000 to 255 into its corresponding byte value. */
1150int get_byte_kbinput(int kbinput
1151#ifndef NANO_SMALL
1152 , bool reset
1153#endif
1154 )
1155{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001156 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001157 int retval = ERR;
1158
1159#ifndef NANO_SMALL
1160 if (reset) {
1161 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001162 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001163 return ERR;
1164 }
1165#endif
1166
1167 /* Increment the byte digit counter. */
1168 byte_digits++;
1169
1170 switch (byte_digits) {
1171 case 1:
1172 /* One digit: reset the byte sequence holder and add the
1173 * digit we got to the 100's position of the byte sequence
1174 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001175 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001176 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001177 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001178 else
1179 /* If the character we got isn't a decimal digit, or if
1180 * it is and it would put the byte sequence out of byte
1181 * range, save it as the result. */
1182 retval = kbinput;
1183 break;
1184 case 2:
1185 /* Two digits: add the digit we got to the 10's position of
1186 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001187 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1188 '6' <= kbinput && kbinput <= '9'))
1189 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001190 else
1191 /* If the character we got isn't a decimal digit, or if
1192 * it is and it would put the byte sequence out of byte
1193 * range, save it as the result. */
1194 retval = kbinput;
1195 break;
1196 case 3:
1197 /* Three digits: add the digit we got to the 1's position of
1198 * the byte sequence holder, and save the corresponding word
1199 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001200 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1201 '6' <= kbinput && kbinput <= '9')) {
1202 byte += (kbinput - '0');
1203 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001204 } else
1205 /* If the character we got isn't a decimal digit, or if
1206 * it is and it would put the word sequence out of word
1207 * range, save it as the result. */
1208 retval = kbinput;
1209 break;
1210 default:
1211 /* More than three digits: save the character we got as the
1212 * result. */
1213 retval = kbinput;
1214 break;
1215 }
1216
1217 /* If we have a result, reset the byte digit counter and the byte
1218 * sequence holder. */
1219 if (retval != ERR) {
1220 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001221 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001222 }
1223
1224#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001225 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte = %d, retval = %d\n", kbinput, byte_digits, byte, retval);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001226#endif
1227
1228 return retval;
1229}
1230
1231/* Translate a word sequence: turn a four-digit hexadecimal number from
1232 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001233int get_word_kbinput(int kbinput
1234#ifndef NANO_SMALL
1235 , bool reset
1236#endif
1237 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001238{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001239 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001240 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001241
1242#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001243 if (reset) {
1244 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001245 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001246 return ERR;
1247 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001248#endif
1249
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001250 /* Increment the word digit counter. */
1251 word_digits++;
1252
1253 switch (word_digits) {
1254 case 1:
1255 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001256 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001257 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001258 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001259 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001260 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001261 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001262 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001263 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001264 /* If the character we got isn't a hexadecimal digit, or
1265 * if it is and it would put the word sequence out of
1266 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001267 retval = kbinput;
1268 break;
1269 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001270 /* Two digits: add the digit we got to the 256's position of
1271 * the word sequence holder. */
1272 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001273 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001274 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001275 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001276 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001277 /* If the character we got isn't a hexadecimal digit, or
1278 * if it is and it would put the word sequence out of
1279 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001280 retval = kbinput;
1281 break;
1282 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001283 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001284 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001285 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001286 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001287 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001288 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001289 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001290 /* If the character we got isn't a hexadecimal digit, or
1291 * if it is and it would put the word sequence out of
1292 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001293 retval = kbinput;
1294 break;
1295 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001296 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001297 * the word sequence holder, and save the corresponding word
1298 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001299 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001300 word += (kbinput - '0');
1301 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001302 } else if ('a' <= tolower(kbinput) &&
1303 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001304 word += (tolower(kbinput) + 10 - 'a');
1305 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001306 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001307 /* If the character we got isn't a hexadecimal digit, or
1308 * if it is and it would put the word sequence out of
1309 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001310 retval = kbinput;
1311 break;
1312 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001313 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001314 * result. */
1315 retval = kbinput;
1316 break;
1317 }
1318
1319 /* If we have a result, reset the word digit counter and the word
1320 * sequence holder. */
1321 if (retval != ERR) {
1322 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001323 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001324 }
1325
1326#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001327 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word = %d, retval = %d\n", kbinput, word_digits, word, retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001328#endif
1329
1330 return retval;
1331}
1332
1333/* Translate a control character sequence: turn an ASCII non-control
1334 * character into its corresponding control character. */
1335int get_control_kbinput(int kbinput)
1336{
1337 int retval;
1338
1339 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1340 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1341 kbinput == '`')
1342 retval = NANO_CONTROL_SPACE;
1343 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1344 else if ('3' <= kbinput && kbinput <= '7')
1345 retval = kbinput - 24;
1346 /* Ctrl-8 (Ctrl-?) */
1347 else if (kbinput == '8' || kbinput == '?')
1348 retval = NANO_CONTROL_8;
1349 /* Ctrl-A to Ctrl-_ */
1350 else if ('A' <= kbinput && kbinput <= '_')
1351 retval = kbinput - 64;
1352 /* Ctrl-a to Ctrl-~ */
1353 else if ('a' <= kbinput && kbinput <= '~')
1354 retval = kbinput - 96;
1355 else
1356 retval = kbinput;
1357
1358#ifdef DEBUG
1359 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1360#endif
1361
1362 return retval;
1363}
1364
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001365/* Put the output-formatted characters in output back into the default
1366 * keystroke buffer, so that they can be parsed and displayed as output
1367 * again. */
1368void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001369{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001370 int *input;
1371 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001372
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001373 if (output_len == 0)
1374 return;
1375
1376 input = (int *)nmalloc(output_len * sizeof(int));
1377 for (i = 0; i < output_len; i++)
1378 input[i] = (int)output[i];
1379 unget_input(input, output_len);
1380 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001381}
1382
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001383/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001384 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1385int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1386{
1387 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001388
1389 /* Turn off flow control characters if necessary so that we can type
1390 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001391 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001392 if (ISSET(PRESERVE))
1393 disable_flow_control();
1394 keypad(win, FALSE);
1395
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396 /* Read in a stream of characters and interpret it if possible. */
1397 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001398
1399 /* Turn flow control characters back on if necessary and turn the
1400 * keypad back on now that we're done. */
1401 if (ISSET(PRESERVE))
1402 enable_flow_control();
1403 keypad(win, TRUE);
1404
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001405 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001406}
1407
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001408/* Read in a stream of all available characters, and return the length
1409 * of the string in kbinput_len. Translate the first few characters of
1410 * the input into the corresponding word value if possible. After that,
1411 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001412int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001413{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001414 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001415
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001416 /* Read in the first keystroke. */
1417 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001418
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001419 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001420 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001421#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001422 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001423#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001424 );
1425
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001426 /* If the first keystroke isn't a hexadecimal digit, put back the
1427 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001428 if (word != ERR)
1429 unget_input(kbinput, 1);
1430 /* Otherwise, read in keystrokes until we have a complete word
1431 * sequence, and put back the corresponding word value. */
1432 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001433 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001434 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001435
1436 while (word == ERR) {
1437 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001438
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001439 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001440#ifndef NANO_SMALL
1441 , FALSE
1442#endif
1443 );
1444 }
1445
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001446 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001447 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001448
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001449 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1450
1451 for (i = 0; i < word_mb_len; i++)
1452 seq[i] = (unsigned char)word_mb[i];
1453
1454 unget_input(seq, word_mb_len);
1455
1456 free(seq);
1457 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001458 }
1459
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001460 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001461 * result. */
1462 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001463 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001464
1465 return retval;
1466}
1467
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001468#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001469/* Check for a mouse event, and if one's taken place, save the
1470 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001471 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1472 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001473 * place on it, figure out which shortcut was clicked and put back the
1474 * equivalent keystroke(s). Return FALSE if no keystrokes were
1475 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001476 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001477bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001478{
1479 MEVENT mevent;
1480
1481 *mouse_x = -1;
1482 *mouse_y = -1;
1483
1484 /* First, get the actual mouse event. */
1485 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001486 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001487
1488 /* Save the screen coordinates where the mouse event took place. */
1489 *mouse_x = mevent.x;
1490 *mouse_y = mevent.y;
1491
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001492 /* If we're allowing shortcuts, the current shortcut list is being
1493 * displayed on the last two lines of the screen, and the mouse
1494 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001495 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001496 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1497 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001498 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001499 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001500 /* The number of shortcuts in the current shortcut list. */
1501 const shortcut *s = currshortcut;
1502 /* The actual shortcut we clicked on, starting at the first
1503 * one in the current shortcut list. */
1504
1505 /* Get the shortcut lists' length. */
1506 if (currshortcut == main_list)
1507 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001508 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001509 currslen = length_of_list(currshortcut);
1510
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001511 /* We don't show any more shortcuts than the main list
1512 * does. */
1513 if (currslen > MAIN_VISIBLE)
1514 currslen = MAIN_VISIBLE;
1515 }
1516
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001517 /* Calculate the width of each shortcut in the list. It's the
1518 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001519 if (currslen < 2)
1520 i = COLS / 6;
1521 else
1522 i = COLS / ((currslen / 2) + (currslen % 2));
1523
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001524 /* Calculate the y-coordinate relative to the beginning of
1525 * bottomwin. */
1526 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001527
1528 /* If we're on the statusbar, beyond the end of the shortcut
1529 * list, or beyond the end of a shortcut on the right side of
1530 * the screen, don't do anything. */
1531 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001532 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001533 j = (*mouse_x / i) * 2 + j;
1534 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001535 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001536
1537 /* Go through the shortcut list to determine which shortcut was
1538 * clicked. */
1539 for (; j > 0; j--)
1540 s = s->next;
1541
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001542 /* And put back the equivalent key. Assume that each shortcut
1543 * has, at the very least, an equivalent control key, an
1544 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001545 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001546 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001547 return TRUE;
1548 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001549 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001550 return TRUE;
1551 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001552 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001553 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001554}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001555#endif /* !DISABLE_MOUSE */
1556
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001557const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001558 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001559{
1560 const shortcut *s = s_list;
1561 size_t slen = length_of_list(s_list);
1562
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001563#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001564 fprintf(stderr, "get_shortcut(): kbinput = %d, meta_key = %d, func_key = %d\n", *kbinput, (int)*meta_key, (int)*func_key);
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001565#endif
1566
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001567 /* Check for shortcuts. */
1568 for (; slen > 0; slen--) {
1569 /* We've found a shortcut if:
1570 *
1571 * 1. The key exists.
1572 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001573 * 3. meta_key is TRUE and the key is the primary or
1574 * miscellaneous meta sequence in the shortcut list.
1575 * 4. func_key is TRUE and the key is a function key in the
1576 * shortcut list. */
1577
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001578 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1579 (*meta_key == TRUE && (*kbinput == s->metaval ||
1580 *kbinput == s->miscval)) || (*func_key == TRUE &&
1581 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001582 break;
1583 }
1584
1585 s = s->next;
1586 }
1587
1588 /* Translate the shortcut to either its control key or its meta key
1589 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001590 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001591 if (slen > 0) {
1592 if (s->ctrlval != NANO_NO_KEY) {
1593 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001594 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001595 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001596 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001597 } else if (s->metaval != NANO_NO_KEY) {
1598 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001599 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001600 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001601 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001602 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001603 }
1604
1605 return NULL;
1606}
1607
1608#ifndef NANO_SMALL
1609const toggle *get_toggle(int kbinput, bool meta_key)
1610{
1611 const toggle *t = toggles;
1612
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001613#ifdef DEBUG
1614 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1615#endif
1616
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001617 /* Check for toggles. */
1618 for (; t != NULL; t = t->next) {
1619 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001620 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001621 if (meta_key && kbinput == t->val)
1622 break;
1623 }
1624
1625 return t;
1626}
1627#endif /* !NANO_SMALL */
1628
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001629int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001630 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001631{
1632 int input;
1633 /* The character we read in. */
1634 static int *kbinput = NULL;
1635 /* The input buffer. */
1636 static size_t kbinput_len = 0;
1637 /* The length of the input buffer. */
1638 const shortcut *s;
1639 bool have_shortcut;
1640
1641 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001642 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001643 *finished = FALSE;
1644
1645 /* Read in a character. */
1646 input = get_kbinput(bottomwin, meta_key, func_key);
1647
1648#ifndef DISABLE_MOUSE
1649 /* If we got a mouse click and it was on a shortcut, read in the
1650 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001651 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001652 if (do_mouse())
1653 input = get_kbinput(bottomwin, meta_key, func_key);
1654 else
1655 input = ERR;
1656 }
1657#endif
1658
1659 /* Check for a shortcut in the current list. */
1660 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1661
1662 /* If we got a shortcut from the current list, or a "universal"
1663 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1664 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1665 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1666 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1667 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001668 input == NANO_CUT_KEY ||
1669#ifndef NANO_SMALL
1670 input == NANO_NEXTWORD_KEY ||
1671#endif
1672 (*meta_key == TRUE && (
1673#ifndef NANO_SMALL
1674 input == NANO_PREVWORD_KEY ||
1675#endif
1676 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001677
1678 /* Set s_or_t to TRUE if we got a shortcut. */
1679 *s_or_t = have_shortcut;
1680
1681 if (allow_funcs) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001682 /* If we got a character, and it isn't a shortcut or toggle,
1683 * it's a normal text character. Display the warning if we're
1684 * in view mode, or add the character to the input buffer if
1685 * we're not. */
1686 if (input != ERR && *s_or_t == FALSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001687 /* If we're using restricted mode, the filename isn't blank,
1688 * and we're at the "Write File" prompt, disable text
1689 * input. */
1690 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1691 currshortcut != writefile_list) {
1692 kbinput_len++;
1693 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1694 sizeof(int));
1695 kbinput[kbinput_len - 1] = input;
1696 }
1697 }
1698
1699 /* If we got a shortcut, or if there aren't any other characters
1700 * waiting after the one we read in, we need to display all the
1701 * characters in the input buffer if it isn't empty. */
1702 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1703 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001704
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001705 /* Display all the characters in the input buffer at
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001706 * once, filtering out control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001707 char *output = charalloc(kbinput_len + 1);
1708 size_t i;
1709 bool got_enter;
1710 /* Whether we got the Enter key. */
1711
1712 for (i = 0; i < kbinput_len; i++)
1713 output[i] = (char)kbinput[i];
1714 output[i] = '\0';
1715
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001716 do_statusbar_output(output, kbinput_len, &got_enter,
1717 FALSE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001718
1719 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001720
1721 /* Empty the input buffer. */
1722 kbinput_len = 0;
1723 free(kbinput);
1724 kbinput = NULL;
1725 }
1726 }
1727
1728 if (have_shortcut) {
1729 switch (input) {
1730 /* Handle the "universal" statusbar prompt shortcuts. */
1731 case NANO_REFRESH_KEY:
1732 total_refresh();
1733 break;
1734 case NANO_HOME_KEY:
1735 do_statusbar_home();
1736 break;
1737 case NANO_END_KEY:
1738 do_statusbar_end();
1739 break;
1740 case NANO_FORWARD_KEY:
1741 do_statusbar_right();
1742 break;
1743 case NANO_BACK_KEY:
1744 do_statusbar_left();
1745 break;
1746 case NANO_BACKSPACE_KEY:
1747 /* If we're using restricted mode, the filename
1748 * isn't blank, and we're at the "Write File"
1749 * prompt, disable Backspace. */
1750 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1751 currshortcut != writefile_list)
1752 do_statusbar_backspace();
1753 break;
1754 case NANO_DELETE_KEY:
1755 /* If we're using restricted mode, the filename
1756 * isn't blank, and we're at the "Write File"
1757 * prompt, disable Delete. */
1758 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1759 currshortcut != writefile_list)
1760 do_statusbar_delete();
1761 break;
1762 case NANO_CUT_KEY:
1763 /* If we're using restricted mode, the filename
1764 * isn't blank, and we're at the "Write File"
1765 * prompt, disable Cut. */
1766 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1767 currshortcut != writefile_list)
1768 do_statusbar_cut_text();
1769 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001770#ifndef NANO_SMALL
1771 case NANO_NEXTWORD_KEY:
1772 do_statusbar_next_word();
1773 break;
1774 case NANO_PREVWORD_KEY:
1775 if (*meta_key == TRUE)
1776 do_statusbar_prev_word();
1777 break;
1778#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001779 case NANO_VERBATIM_KEY:
1780 if (*meta_key == TRUE) {
1781 /* If we're using restricted mode, the filename
1782 * isn't blank, and we're at the "Write File"
1783 * prompt, disable verbatim input. */
1784 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001785 currshortcut != writefile_list) {
1786 bool got_enter;
1787 /* Whether we got the Enter key. */
1788
1789 do_statusbar_verbatim_input(&got_enter);
1790
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001791 /* If we got the Enter key, set input to the
1792 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001793 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001794 if (got_enter) {
1795 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001796 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001797 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001798 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001799 break;
1800 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001801 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001802 * ran_func to TRUE if we try to run their associated
1803 * functions and setting finished to TRUE to indicate
1804 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001805 * functions. */
1806 default:
1807 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001808 *ran_func = TRUE;
1809 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001810 s->func();
1811 }
1812 *finished = TRUE;
1813 }
1814 }
1815 }
1816
1817 return input;
1818}
1819
1820#ifndef DISABLE_MOUSE
1821bool do_statusbar_mouse(void)
1822{
1823 /* FIXME: If we clicked on a location in the statusbar, the cursor
1824 * should move to the location we clicked on. This functionality
1825 * should be in this function. */
1826 int mouse_x, mouse_y;
1827 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1828}
1829#endif
1830
1831void do_statusbar_home(void)
1832{
1833#ifndef NANO_SMALL
1834 if (ISSET(SMART_HOME)) {
1835 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001836
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001837 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001838
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001839 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001840 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001841 statusbar_x = 0;
1842 } else
1843#endif
1844 statusbar_x = 0;
1845}
1846
1847void do_statusbar_end(void)
1848{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001849 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001850}
1851
1852void do_statusbar_right(void)
1853{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001854 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001855 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001856}
1857
1858void do_statusbar_left(void)
1859{
1860 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001861 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001862}
1863
1864void do_statusbar_backspace(void)
1865{
1866 if (statusbar_x > 0) {
1867 do_statusbar_left();
1868 do_statusbar_delete();
1869 }
1870}
1871
1872void do_statusbar_delete(void)
1873{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001874 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001875 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1876 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001877 size_t line_len = strlen(answer + statusbar_x);
1878
1879 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001880
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001881 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001882 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001883 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001884
1885 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001886 }
1887}
1888
1889void do_statusbar_cut_text(void)
1890{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001891 assert(answer != NULL);
1892
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001893#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001894 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001895 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001896 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001897#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001898 null_at(&answer, 0);
1899 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001900#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001901 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001902#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001903}
1904
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001905#ifndef NANO_SMALL
1906void do_statusbar_next_word(void)
1907{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001908 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001909 int char_mb_len;
1910
1911 assert(answer != NULL);
1912
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001913 char_mb = charalloc(mb_cur_max());
1914
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001915 /* Move forward until we find the character after the last letter of
1916 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001917 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001918 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1919 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001920
1921 /* If we've found it, stop moving forward through the current
1922 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001923 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001924 break;
1925
1926 statusbar_x += char_mb_len;
1927 }
1928
1929 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001930 if (answer[statusbar_x] != '\0')
1931 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001932
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001933 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001934 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1935 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001936
1937 /* If we've found it, stop moving forward through the current
1938 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001939 if (is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001940 break;
1941
1942 statusbar_x += char_mb_len;
1943 }
1944
1945 free(char_mb);
1946}
1947
1948void do_statusbar_prev_word(void)
1949{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001950 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001951 int char_mb_len;
1952 bool begin_line = FALSE;
1953
1954 assert(answer != NULL);
1955
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001956 char_mb = charalloc(mb_cur_max());
1957
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001958 /* Move backward until we find the character before the first letter
1959 * of the current word. */
1960 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001961 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1962 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001963
1964 /* If we've found it, stop moving backward through the current
1965 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001966 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001967 break;
1968
1969 if (statusbar_x == 0)
1970 begin_line = TRUE;
1971 else
1972 statusbar_x = move_mbleft(answer, statusbar_x);
1973 }
1974
1975 /* Move backward until we find the last letter of the previous
1976 * word. */
1977 if (statusbar_x == 0)
1978 begin_line = TRUE;
1979 else
1980 statusbar_x = move_mbleft(answer, statusbar_x);
1981
1982 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001983 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1984 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001985
1986 /* If we've found it, stop moving backward through the current
1987 * line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00001988 if (is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001989 break;
1990
1991 if (statusbar_x == 0)
1992 begin_line = TRUE;
1993 else
1994 statusbar_x = move_mbleft(answer, statusbar_x);
1995 }
1996
1997 /* If we've found it, move backward until we find the character
1998 * before the first letter of the previous word. */
1999 if (!begin_line) {
2000 if (statusbar_x == 0)
2001 begin_line = TRUE;
2002 else
2003 statusbar_x = move_mbleft(answer, statusbar_x);
2004
2005 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002006 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2007 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002008
2009 /* If we've found it, stop moving backward through the
2010 * current line. */
David Lawrence Ramseye2213112005-06-15 03:03:45 +00002011 if (!is_word_mbchar(char_mb, TRUE))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002012 break;
2013
2014 if (statusbar_x == 0)
2015 begin_line = TRUE;
2016 else
2017 statusbar_x = move_mbleft(answer, statusbar_x);
2018 }
2019
2020 /* If we've found it, move forward to the first letter of the
2021 * previous word. */
2022 if (!begin_line)
2023 statusbar_x += char_mb_len;
2024 }
2025
2026 free(char_mb);
2027}
2028#endif
2029
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002030void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002031{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002032 int *kbinput;
2033 size_t kbinput_len, i;
2034 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002035
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002036 *got_enter = FALSE;
2037
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002038 /* Read in all the verbatim characters. */
2039 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2040
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002041 /* Display all the verbatim characters at once, not filtering out
2042 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002043 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002044
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002045 for (i = 0; i < kbinput_len; i++)
2046 output[i] = (char)kbinput[i];
2047 output[i] = '\0';
2048
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002049 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002050
2051 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002052}
2053
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002054void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002055 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002056{
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002057 size_t answer_len, i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002058 char *char_buf = charalloc(mb_cur_max());
2059 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002060
2061 assert(answer != NULL);
2062
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002063 answer_len = strlen(answer);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002064 *got_enter = FALSE;
2065
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002066 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002067 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2068 * since they're control characters. */
2069 if (allow_cntrls) {
2070 /* Null to newline, if needed. */
2071 if (output[i] == '\0')
2072 output[i] = '\n';
2073 /* Newline to Enter, if needed. */
2074 else if (output[i] == '\n') {
2075 /* Set got_enter to TRUE to indicate that we got the
2076 * Enter key, put back the rest of the characters in
2077 * output so that they can be parsed and output again,
2078 * and get out. */
2079 *got_enter = TRUE;
2080 unparse_kbinput(output + i, output_len - i);
2081 return;
2082 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002083 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002084
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002085 /* Interpret the next multibyte character. If it's an invalid
2086 * multibyte character, interpret it as though it's a byte
2087 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002088 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002089
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002090 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002091
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002092 /* If allow_cntrls is FALSE, filter out a control character. */
2093 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2094 continue;
2095
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002096 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002097 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002098
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002099 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002100
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002101 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002102 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002103 char_buf_len);
2104 charcpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002105 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002106
2107 do_statusbar_right();
2108 }
2109
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002110 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002111}
2112
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002113/* Return the placewewant associated with current_x, i.e, the zero-based
2114 * column position of the cursor. The value will be no smaller than
2115 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002116size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002117{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002118 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002119}
2120
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002121/* actual_x() gives the index in str of the character displayed at
2122 * column xplus. That is, actual_x() is the largest value such that
2123 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2124size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002125{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002126 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002127 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002128 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002129 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002130
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002131 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002132
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002133 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002134 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002135
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002136 if (length > xplus)
2137 break;
2138
2139 i += str_len;
2140 str += str_len;
2141 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002142
Chris Allegretta6df90f52002-07-19 01:08:59 +00002143 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002144}
2145
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002146/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002147 * columns wide are the first size characters of str? */
2148size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002149{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002150 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002151 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002152
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002153 if (size == 0)
2154 return 0;
2155
2156 assert(str != NULL);
2157
2158 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002159 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002160
2161 str += str_len;
2162
2163 if (size <= str_len)
2164 break;
2165
2166 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002167 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002168
Chris Allegretta6df90f52002-07-19 01:08:59 +00002169 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002170}
2171
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002172/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002173size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002174{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002175 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002176}
2177
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002178void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002179{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002180 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002181}
2182
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002183void blank_topbar(void)
2184{
2185 if (!ISSET(MORE_SPACE))
2186 mvwaddstr(topwin, 1, 0, hblank);
2187}
2188
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002189void blank_edit(void)
2190{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002191 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002192 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002193 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002194}
2195
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002196void blank_statusbar(void)
2197{
2198 mvwaddstr(bottomwin, 0, 0, hblank);
2199}
2200
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002201void blank_bottombars(void)
2202{
2203 if (!ISSET(NO_HELP)) {
2204 mvwaddstr(bottomwin, 1, 0, hblank);
2205 mvwaddstr(bottomwin, 2, 0, hblank);
2206 }
2207}
2208
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002209void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002210{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002211 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002212 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002213
2214 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002215 blank_statusbar();
2216 wnoutrefresh(bottomwin);
2217 reset_cursor();
2218 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 }
2220}
2221
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002222/* Convert buf into a string that can be displayed on screen. The
2223 * caller wants to display buf starting with column start_col, and
2224 * extending for at most len columns. start_col is zero-based. len is
2225 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002226 * string is dynamically allocated, and should be freed. If dollars is
2227 * TRUE, the caller might put "$" at the beginning or end of the line if
2228 * it's too long. */
2229char *display_string(const char *buf, size_t start_col, size_t len, bool
2230 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002231{
2232 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002233 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002234 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002235 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002236 size_t alloc_len;
2237 /* The length of memory allocated for converted. */
2238 char *converted;
2239 /* The string we return. */
2240 size_t index;
2241 /* Current position in converted. */
2242
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002243 char *buf_mb = charalloc(mb_cur_max());
2244 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002245 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002246
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002247 /* If dollars is TRUE, make room for the "$" at the end of the
2248 * line. */
2249 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2250 len--;
2251
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002252 if (len == 0)
2253 return mallocstrcpy(NULL, "");
2254
2255 start_index = actual_x(buf, start_col);
2256 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002257
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002258 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002259
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002260 /* Allocate enough space for the entire line, accounting for a
2261 * trailing multibyte character and/or tab. */
2262 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002263
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002264 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002265 index = 0;
2266
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002267 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002268 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002269 /* We don't display all of buf[start_index] since it starts to
2270 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002271 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2272 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002273
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002274 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002275 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002276 char *ctrl_buf_mb = charalloc(mb_cur_max());
2277 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002278
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002279 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2280 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002281
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002282 for (i = 0; i < ctrl_buf_mb_len; i++)
2283 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002284
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002285 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002286
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002287 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002288
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002289 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002290 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002291 }
2292#ifdef NANO_WIDE
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002293 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002294 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002295 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002296
2297 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002298 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002299#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002300 }
2301
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002302 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002303 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2304 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002305
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002306 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002307#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002308 if (ISSET(WHITESPACE_DISPLAY)) {
2309 int i;
2310
2311 for (i = 0; i < whitespace_len[0]; i++)
2312 converted[index++] = whitespace[i];
2313 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002314#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002315 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002317 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002318 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002319 start_col++;
2320 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002321 /* If buf contains a control character, interpret it. If it
2322 * contains an invalid multibyte control character, interpret
2323 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002324 } else if (is_cntrl_mbchar(buf_mb)) {
2325 char *ctrl_buf_mb = charalloc(mb_cur_max());
2326 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002327
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002328 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002329 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2332 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 for (i = 0; i < ctrl_buf_mb_len; i++)
2335 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002336
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002337 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002338
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002339 free(ctrl_buf_mb);
2340 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002341#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002342 if (ISSET(WHITESPACE_DISPLAY)) {
2343 int i;
2344
2345 for (i = whitespace_len[0]; i < whitespace_len[0] +
2346 whitespace_len[1]; i++)
2347 converted[index++] = whitespace[i];
2348 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002349#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002350 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002351 start_col++;
2352 } else {
2353 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002355#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002356 /* If buf contains an invalid multibyte non-control
2357 * character, interpret that character as though it's a
2358 * normal non-control character. */
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002359 if (ISSET(USE_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002360 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002361 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002362
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002363 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002364 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002365
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002366 for (i = 0; i < bad_buf_mb_len; i++)
2367 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002368
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002369 start_col += mbwidth(bad_buf_mb);
2370
2371 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002372 } else {
2373#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002374 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002375 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002376
2377 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002378#ifdef NANO_WIDE
2379 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002380#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002381 }
2382
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002383 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002384 }
2385
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002386 free(buf_mb);
2387
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002388 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002389 converted[index] = '\0';
2390
2391 /* Make sure converted takes up no more than len columns. */
2392 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002393 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002394
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002395 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002396}
2397
Chris Allegretta7662c862003-01-13 01:35:15 +00002398/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002399 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002400 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002401 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002402 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002403void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002404{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002405 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002406 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002407
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002408 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002409
Chris Allegrettab3655b42001-10-22 03:15:31 +00002410 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002411 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002412
Chris Allegretta6df90f52002-07-19 01:08:59 +00002413 mvwaddstr(bottomwin, 0, 0, buf);
2414 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002415
2416 if (COLS > 1)
2417 waddch(bottomwin, x_real < wid ? ' ' : '$');
2418 if (COLS > 2) {
2419 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002420 char *expanded = display_string(inputbuf, page_start, wid,
2421 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002422
2423 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002424 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002425
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002426 waddstr(bottomwin, expanded);
2427 free(expanded);
2428 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2429 } else
2430 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002431
Chris Allegrettab3655b42001-10-22 03:15:31 +00002432 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002433}
2434
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002435/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002436 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002437int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002438#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002439 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002440#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002441 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002442#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002443 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002444#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002445 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002446{
2447 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002448 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002449 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002450#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002451 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002452 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002453#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002454#ifndef NANO_SMALL
2455 char *history = NULL;
2456 /* The current history string. */
2457 char *magichistory = NULL;
2458 /* The temporary string typed at the bottom of the history, if
2459 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002460#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002461 int last_kbinput = ERR;
2462 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002463 size_t complete_len = 0;
2464 /* The length of the original string that we're trying to
2465 * tab complete, if any. */
2466#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002467#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002468
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002469 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002470 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002471
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002472 /* Only put statusbar_x at the end of the string if it's
2473 * uninitialized, if it would be past the end of curranswer, or if
2474 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2475 * the cursor position stays at the same place if a prompt-changing
2476 * toggle is pressed. */
2477 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2478 resetstatuspos)
2479 statusbar_x = curranswer_len;
2480
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002481 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002482
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002483 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002484
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002485 /* Refresh the edit window and the statusbar before getting
2486 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002487 wnoutrefresh(edit);
2488 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002489
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002490 /* If we're using restricted mode, we aren't allowed to change the
2491 * name of a file once it has one because that would allow writing
2492 * to files not specified on the command line. In this case,
2493 * disable all keys that would change the text if the filename isn't
2494 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002495 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002496 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002497 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002498
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002499 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002500
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002501#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002502 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002503 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002504#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002505
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002506 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002507 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002508#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002509#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002510 if (history_list != NULL) {
2511 if (last_kbinput != NANO_TAB_KEY)
2512 complete_len = strlen(answer);
2513
2514 if (complete_len > 0) {
2515 answer = mallocstrcpy(answer,
2516 get_history_completion(history_list,
2517 answer, complete_len));
2518 statusbar_x = strlen(answer);
2519 }
2520 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002521#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002522 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002523 answer = input_tab(answer, &statusbar_x, &tabbed,
2524 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002525#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002526 break;
2527 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002528#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002529 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002530 /* If we're scrolling up at the bottom of the
2531 * history list, answer isn't blank, and
2532 * magichistory isn't set, save answer in
2533 * magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002534 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002535 answer[0] != '\0' && magichistory == NULL)
2536 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002537
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002538 /* Get the older search from the history list and
2539 * save it in answer. If there is no older search,
2540 * don't do anything. */
2541 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002542 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002543 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002544 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002545 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002546
2547 /* This key has a shortcut list entry when it's used
2548 * to move to an older search, which means that
2549 * finished has been set to TRUE. Set it back to
2550 * FALSE here, so that we aren't kicked out of the
2551 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002552 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002553 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002554#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002555 break;
2556 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002557#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002558 if (history_list != NULL) {
2559 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002560 * save it in answer. If there is no newer search,
2561 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002562 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002563 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002564 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002565 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002566 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002567
2568 /* If, after scrolling down, we're at the bottom of
2569 * the history list, answer is blank, and
2570 * magichistory is set, save magichistory in
2571 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002572 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002573 answer[0] == '\0' && magichistory != NULL) {
2574 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002575 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002576 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002577 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002578#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002579 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002580 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002581
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002582 /* If we have a shortcut with an associated function, break out
2583 * if we're finished after running or trying to run the
2584 * function. */
2585 if (finished)
2586 break;
2587
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002588#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002589 last_kbinput = kbinput;
2590#endif
2591
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002592 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002593 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002594 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002595
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002596#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002597 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002598 if (magichistory != NULL)
2599 free(magichistory);
2600#endif
2601
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002602 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002603 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002604 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002605 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002606 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002607
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002608 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002609}
2610
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002611/* Ask a question on the statusbar. Answer will be stored in answer
2612 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002613 * otherwise, the valid shortcut key caught. curranswer is any editable
2614 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002615 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002616 * The allow_tabs parameter indicates whether we should allow tabs to be
2617 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002618int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002619#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002620 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002621#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002622 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002623{
2624 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002625 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002626 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002627#ifndef DISABLE_TABCOMP
2628 bool list = FALSE;
2629#endif
2630
2631 bottombars(s);
2632
2633 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002634 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002635 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002636 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002637
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002638 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002639#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002640 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002641#endif
2642 s
2643#ifndef DISABLE_TABCOMP
2644 , &list
2645#endif
2646 );
2647 free(foo);
2648 resetstatuspos = FALSE;
2649
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002650 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002651 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002652 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002653 resetstatuspos = TRUE;
2654 break;
2655 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002656 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002657 resetstatuspos = TRUE;
2658 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002659 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002660
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002661 blank_statusbar();
David Lawrence Ramseycd0210f2005-06-18 14:05:21 +00002662 wnoutrefresh(bottomwin);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002663
2664#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002665 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002666#endif
2667
2668#ifndef DISABLE_TABCOMP
David Lawrence Ramsey90d505c2005-06-18 22:33:55 +00002669 /* If we've done tab completion, there might be a list of filename
2670 * matches on the edit window at this point. Make sure that they're
2671 * cleared off. */
2672 if (list)
2673 edit_refresh();
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002674#endif
2675
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002676 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002677}
2678
2679void statusq_abort(void)
2680{
2681 resetstatuspos = TRUE;
2682}
2683
Chris Allegrettaf717f982003-02-13 22:25:01 +00002684void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002685{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002686 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002687 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002688 size_t verlen = strlenpt(VERMSG) + 1;
2689 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002690 const char *prefix;
2691 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2692 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002693 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002694 const char *state;
2695 /* "Modified", "View", or spaces the length of "Modified".
2696 * Tells the state of this buffer. */
2697 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002698 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002699 char *exppath = NULL;
2700 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002701 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002702 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002703 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002704 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002705
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002706 assert(path != NULL || filename != NULL);
2707 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002708
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002709 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002710 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002711
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002712 if (COLS <= 5 || COLS - 5 < verlen)
2713 space = 0;
2714 else {
2715 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002716 /* Reserve 2/3 of the screen plus one column for after the
2717 * version message. */
2718 if (space < COLS - (COLS / 3) + 1)
2719 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002720 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002721
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002722 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002723 /* The version message should only take up 1/3 of the screen
2724 * minus one column. */
2725 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002726 waddstr(topwin, " ");
2727 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002728
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002729 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002731 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002732 state = _("View");
2733 else {
2734 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002735 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002736 state = &hblank[COLS - statelen];
2737 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002738 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002739
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002740 /* We need a space before state. */
2741 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2742 statelen++;
2743
2744 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002745
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002746 if (space == 0 || statelen >= space)
2747 goto the_end;
2748
2749#ifndef DISABLE_BROWSER
2750 if (path != NULL)
2751 prefix = _("DIR:");
2752 else
2753#endif
2754 if (filename[0] == '\0') {
2755 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002756 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002757 } else
2758 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002759
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002760 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002761
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002762 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002763
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002764 /* If newfie is FALSE, we need a space after prefix. */
2765 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002766 prefixlen++;
2767
2768 if (path == NULL)
2769 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002770 if (space >= prefixlen + statelen)
2771 space -= prefixlen + statelen;
2772 else
2773 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002774 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002775
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002776 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002777 size_t lenpt = strlenpt(path), start_col;
2778
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002779 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002780
2781 if (dots) {
2782 start_col = lenpt - space + 3;
2783 space -= 3;
2784 } else
2785 start_col = 0;
2786
2787 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002788 }
2789
2790 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002791 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2792 /* The length of the expanded filename. */
2793
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002794 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002795 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002796 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002797 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002798 assert(strlenpt(prefix) + 1 == prefixlen);
2799
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002800 waddch(topwin, ' ');
2801 waddstr(topwin, exppath);
2802 }
2803 } else {
2804 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002805 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002806 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 goto the_end;
2808 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002809 waddnstr(topwin, "...", space + 3);
2810 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002811 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002812 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002813 }
2814
2815 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002816 free(exppath);
2817
2818 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002819 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 else {
2821 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002822
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002823 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002824 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2825 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002827
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002829
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002830 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002831 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002832 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002833}
2834
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002835/* If modified is not already set, set it and update titlebar. */
2836void set_modified(void)
2837{
2838 if (!ISSET(MODIFIED)) {
2839 SET(MODIFIED);
2840 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002841 }
2842}
2843
2844void statusbar(const char *msg, ...)
2845{
2846 va_list ap;
2847
2848 va_start(ap, msg);
2849
2850 /* Curses mode is turned off. If we use wmove() now, it will muck
2851 * up the terminal settings. So we just use vfprintf(). */
2852 if (curses_ended) {
2853 vfprintf(stderr, msg, ap);
2854 va_end(ap);
2855 return;
2856 }
2857
2858 /* Blank out the line. */
2859 blank_statusbar();
2860
2861 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002862 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002863 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002864#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002865 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002866
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002867 UNSET(WHITESPACE_DISPLAY);
2868#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002869 bar = charalloc(mb_cur_max() * (COLS - 3));
2870 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002871 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002872 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002873#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2874 if (old_whitespace)
2875 SET(WHITESPACE_DISPLAY);
2876#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002877 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002878 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002879 start_x = (COLS - foo_len - 4) / 2;
2880
2881 wmove(bottomwin, 0, start_x);
2882 wattron(bottomwin, A_REVERSE);
2883
2884 waddstr(bottomwin, "[ ");
2885 waddstr(bottomwin, foo);
2886 free(foo);
2887 waddstr(bottomwin, " ]");
2888 wattroff(bottomwin, A_REVERSE);
2889 wnoutrefresh(bottomwin);
2890 reset_cursor();
2891 wrefresh(edit);
2892 /* Leave the cursor at its position in the edit window, not
2893 * in the statusbar. */
2894 }
2895
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002896 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002897
2898 /* If we're doing quick statusbar blanking, and constant cursor
2899 * position display is off, blank the statusbar after only one
2900 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2901 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002902 statusblank =
2903#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002904 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002905#endif
2906 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002907}
2908
Chris Allegretta6232d662002-05-12 19:52:15 +00002909void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002911 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002912
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002913 if (ISSET(NO_HELP))
2914 return;
2915
Chris Allegretta6232d662002-05-12 19:52:15 +00002916 if (s == main_list) {
2917 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002918
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002919 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002920 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002921 slen = length_of_list(s);
2922
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002923 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002924 if (slen > MAIN_VISIBLE)
2925 slen = MAIN_VISIBLE;
2926 }
2927
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002928 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002929 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002930 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002931
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002932 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002933
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002934 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002935 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002936 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002937
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002938 /* Yucky sentinel values that we can't handle a better way. */
2939 if (s->ctrlval == NANO_CONTROL_SPACE)
2940 strcpy(foo, "^ ");
2941 else if (s->ctrlval == NANO_CONTROL_8)
2942 strcpy(foo, "^?");
2943 /* Normal values. Assume that the shortcut has an equivalent
2944 * control key, meta key sequence, or both. */
2945 else if (s->ctrlval != NANO_NO_KEY)
2946 sprintf(foo, "^%c", s->ctrlval + 64);
2947 else if (s->metaval != NANO_NO_KEY)
2948 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002949
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002950 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002951
2952 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002953 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002954 }
2955
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002956 wnoutrefresh(bottomwin);
2957 reset_cursor();
2958 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002959}
2960
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002961/* Write a shortcut key to the help area at the bottom of the window.
2962 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2963 * to write at most len characters, even if len is very small and
2964 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2965 * the whole string! We do not bother padding the entry with blanks. */
2966void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002967{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002968 size_t keystroke_len = strlenpt(keystroke) + 1;
2969
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002970 assert(keystroke != NULL && desc != NULL);
2971
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002972 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002973 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002974 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002975
2976 if (len > keystroke_len)
2977 len -= keystroke_len;
2978 else
2979 len = 0;
2980
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002981 if (len > 0) {
2982 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002983 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002984 }
2985}
2986
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002987/* nano scrolls horizontally within a line in chunks. This function
2988 * returns the column number of the first character displayed in the
2989 * window when the cursor is at the given column. Note that
2990 * 0 <= column - get_page_start(column) < COLS. */
2991size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002992{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002993 assert(COLS > 0);
2994 if (column == 0 || column < COLS - 1)
2995 return 0;
2996 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002997 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002998 else if (COLS > 2)
2999 return column - (COLS - 2);
3000 else
3001 return column - (COLS - 1);
3002 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003003}
3004
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003005/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003006 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003007void reset_cursor(void)
3008{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003009 /* If we haven't opened any files yet, put the cursor in the top
3010 * left corner of the edit window and get out. */
3011 if (edittop == NULL || current == NULL) {
3012 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003013 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003014 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003015
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003016 current_y = current->lineno - edittop->lineno;
3017 if (current_y < editwinrows) {
3018 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003019 wmove(edit, current_y, x - get_page_start(x));
3020 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003021}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003022
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003023/* edit_add() takes care of the job of actually painting a line into the
3024 * edit window. fileptr is the line to be painted, at row yval of the
3025 * window. converted is the actual string to be written to the window,
3026 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003027 * characters. start is the column number of the first character of
3028 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003029 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003030void edit_add(const filestruct *fileptr, const char *converted, int
3031 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003032{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003033#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003034 size_t startpos = actual_x(fileptr->data, start);
3035 /* The position in fileptr->data of the leftmost character
3036 * that displays at least partially on the window. */
3037 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3038 /* The position in fileptr->data of the first character that is
3039 * completely off the window to the right.
3040 *
3041 * Note that endpos might be beyond the null terminator of the
3042 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003043#endif
3044
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003045 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003046 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003047
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003048 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003049 * just the text that needs it). */
3050 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003051
Chris Allegretta7dd77682001-12-08 19:52:28 +00003052#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003053 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003054 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003055
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003056 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3057 int x_start;
3058 /* Starting column for mvwaddnstr. Zero-based. */
3059 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003060 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003061 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003062 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003063 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003064 regmatch_t startmatch; /* match position for start_regexp */
3065 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003066
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003067 if (tmpcolor->bright)
3068 wattron(edit, A_BOLD);
3069 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003070 /* Two notes about regexec(). Return value 0 means there is
3071 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003072 * after the match. */
3073
3074 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003075 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003076 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003077
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003078 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003079 * last match. Even though two matches may overlap, we
3080 * want to ignore them, so that we can highlight
3081 * C-strings correctly. */
3082 while (k < endpos) {
3083 /* Note the fifth parameter to regexec(). It says
3084 * not to match the beginning-of-line character
3085 * unless k is 0. If regexec() returns REG_NOMATCH,
3086 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003087 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003088 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003089 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003090 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003091 /* Translate the match to the beginning of the
3092 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003093 startmatch.rm_so += k;
3094 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003095 if (startmatch.rm_so == startmatch.rm_eo) {
3096 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003097 statusbar(
3098 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003099 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003100 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003101 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003102 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003103 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003104 x_start = strnlenpt(fileptr->data,
3105 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003106
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003107 index = actual_x(converted, x_start);
3108
3109 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003110 strnlenpt(fileptr->data,
3111 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003112
3113 assert(0 <= x_start && 0 <= paintlen);
3114
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003116 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003117 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003118 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003119 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003121 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003122 * First, we have to see if the beginning of the line is
3123 * colored by a start on an earlier line, and an end on
3124 * this line or later.
3125 *
3126 * We find the first line before fileptr matching the
3127 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003128 * end, then go to step two. Otherwise, find the next
3129 * line after start_line matching the end. If that line
3130 * is not before fileptr, then paint the beginning of
3131 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003133 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003134 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003135 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003136 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003137
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003138 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003139 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003140 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141 /* If there is an end on this line, there is no need
3142 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003143 if (regexec(tmpcolor->end, start_line->data, 0,
3144 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003145 goto step_two;
3146 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003147 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 /* No start found, so skip to the next step. */
3149 if (start_line == NULL)
3150 goto step_two;
3151 /* Now start_line is the first line before fileptr
3152 * containing a start match. Is there a start on this
3153 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003155 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003156 start_col += startmatch.rm_so;
3157 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003158 if (regexec(tmpcolor->end, start_line->data +
3159 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003160 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003161 REG_NOTBOL) == REG_NOMATCH)
3162 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163 break;
3164 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003165 if (regexec(&tmpcolor->start, start_line->data +
3166 start_col, 1, &startmatch,
3167 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 /* No later start on this line. */
3169 goto step_two;
3170 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 /* Indeed, there is a start not followed on this line by
3172 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003173
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003174 /* We have already checked that there is no end before
3175 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003176 * the start at all? We don't paint unterminated
3177 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003178 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003179 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003180 regexec(tmpcolor->end, end_line->data, 1,
3181 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003182 end_line = end_line->next;
3183
3184 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003185 if (end_line == NULL || (end_line == fileptr &&
3186 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187 goto step_two;
3188
3189 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003190 if (end_line != fileptr)
3191 /* If the start of fileptr is on a different line
3192 * from the end, paintlen is -1, meaning that
3193 * everything on the line gets painted. */
3194 paintlen = -1;
3195 else
3196 /* Otherwise, paintlen is the expanded location of
3197 * the end of the match minus the expanded location
3198 * of the beginning of the page. */
3199 paintlen = actual_x(converted,
3200 strnlenpt(fileptr->data, endmatch.rm_eo) -
3201 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003203 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003204
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003205 step_two:
3206 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003207 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003208
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003209 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003210 if (regexec(&tmpcolor->start,
3211 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003212 (start_col == 0) ? 0 :
3213 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003214 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003215 /* No more starts on this line. */
3216 break;
3217 /* Translate the match to be relative to the
3218 * beginning of the line. */
3219 startmatch.rm_so += start_col;
3220 startmatch.rm_eo += start_col;
3221
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003222 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003223 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003224 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003225 x_start = strnlenpt(fileptr->data,
3226 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003227
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003228 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003229
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003230 if (regexec(tmpcolor->end,
3231 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003232 (startmatch.rm_eo == 0) ? 0 :
3233 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003235 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003236 endmatch.rm_so += startmatch.rm_eo;
3237 endmatch.rm_eo += startmatch.rm_eo;
3238 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003239 * appear on this page, and is the match more
3240 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003241 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003242 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003243 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003244 strnlenpt(fileptr->data,
3245 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003246
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003247 assert(0 <= x_start && x_start < COLS);
3248
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003249 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003250 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003251 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003252 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003253 /* There is no end on this line. But we haven't
3254 * yet looked for one on later lines. */
3255 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003256
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003257 while (end_line != NULL &&
3258 regexec(tmpcolor->end, end_line->data,
3259 0, NULL, 0) == REG_NOMATCH)
3260 end_line = end_line->next;
3261
3262 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003264
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003265 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003266 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003267 /* We painted to the end of the line, so
3268 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003269 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003270 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003271 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003272 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003273 }
3274 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003275
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003276 wattroff(edit, A_BOLD);
3277 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003278 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003279 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003280#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003281
Chris Allegretta7dd77682001-12-08 19:52:28 +00003282#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003283 if (ISSET(MARK_ISSET)
3284 && (fileptr->lineno <= mark_beginbuf->lineno
3285 || fileptr->lineno <= current->lineno)
3286 && (fileptr->lineno >= mark_beginbuf->lineno
3287 || fileptr->lineno >= current->lineno)) {
3288 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003289
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003290 const filestruct *top;
3291 /* Either current or mark_beginbuf, whichever is first. */
3292 size_t top_x;
3293 /* current_x or mark_beginx, corresponding to top. */
3294 const filestruct *bot;
3295 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003296 int x_start;
3297 /* Starting column for mvwaddnstr. Zero-based. */
3298 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003299 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003300 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003301 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003302 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003303
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003304 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003305
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003306 if (top->lineno < fileptr->lineno || top_x < startpos)
3307 top_x = startpos;
3308 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3309 bot_x = endpos;
3310
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003311 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003312 if (top_x < endpos && bot_x > startpos) {
3313 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003314
3315 /* x_start is the expanded location of the beginning of the
3316 * mark minus the beginning of the page. */
3317 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003318
3319 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003320 /* If the end of the mark is off the page, paintlen is
3321 * -1, meaning that everything on the line gets
3322 * painted. */
3323 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003324 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003325 /* Otherwise, paintlen is the expanded location of the
3326 * end of the mark minus the expanded location of the
3327 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003328 paintlen = strnlenpt(fileptr->data, bot_x) -
3329 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003330
3331 /* If x_start is before the beginning of the page, shift
3332 * paintlen x_start characters to compensate, and put
3333 * x_start at the beginning of the page. */
3334 if (x_start < 0) {
3335 paintlen += x_start;
3336 x_start = 0;
3337 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003338
3339 assert(x_start >= 0 && x_start <= strlen(converted));
3340
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003341 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003342
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003343 if (paintlen > 0)
3344 paintlen = actual_x(converted + index, paintlen);
3345
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003346 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003347 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003348 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003349 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003350 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003351 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003352#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003353}
3354
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003355/* Just update one line in the edit buffer. This is basically a wrapper
3356 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003357 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003358 * If fileptr != current, then index is considered 0. The line will be
3359 * displayed starting with fileptr->data[index]. Likely args are
3360 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003361void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003362{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003363 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003364 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003365 char *converted;
3366 /* fileptr->data converted to have tabs and control characters
3367 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003368 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003369
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003370 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003371
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003372 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003373
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003374 /* We assume the line numbers are valid. Is that really true? */
3375 assert(line < 0 || line == check_linenumbers(fileptr));
3376
3377 if (line < 0 || line >= editwinrows)
3378 return;
3379
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003380 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003381 mvwaddstr(edit, line, 0, hblank);
3382
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003383 /* Next, convert variables that index the line to their equivalent
3384 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003385 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003386 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003387
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003388 /* Expand the line, replacing tabs with spaces, and control
3389 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003390 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003391
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003392 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003393 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003394 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003395
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003396 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003397 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003398 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003399 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003400}
3401
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003402/* Return a nonzero value if we need an update after moving
3403 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003404 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003405int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003406{
3407 return
3408#ifndef NANO_SMALL
3409 ISSET(MARK_ISSET) ||
3410#endif
3411 get_page_start(old_pww) != get_page_start(placewewant);
3412}
3413
3414/* Return a nonzero value if we need an update after moving vertically.
3415 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003416 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003417int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003418{
3419 return
3420#ifndef NANO_SMALL
3421 ISSET(MARK_ISSET) ||
3422#endif
3423 get_page_start(old_pww) != get_page_start(placewewant);
3424}
3425
3426/* Scroll the edit window in the given direction and the given number
3427 * of lines, and draw new lines on the blank lines left after the
3428 * scrolling. direction is the direction to scroll, either UP or DOWN,
3429 * and nlines is the number of lines to scroll. Don't redraw the old
3430 * topmost or bottommost line (where we assume current is) before
3431 * scrolling or draw the new topmost or bottommost line after scrolling
3432 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003433 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003434void edit_scroll(updown direction, int nlines)
3435{
3436 filestruct *foo;
3437 int i, scroll_rows = 0;
3438
3439 /* Scrolling less than one line or more than editwinrows lines is
3440 * redundant, so don't allow it. */
3441 if (nlines < 1 || nlines > editwinrows)
3442 return;
3443
3444 /* Move the top line of the edit window up or down (depending on the
3445 * value of direction) nlines lines. If there are fewer lines of
3446 * text than that left, move it to the top or bottom line of the
3447 * file (depending on the value of direction). Keep track of
3448 * how many lines we moved in scroll_rows. */
3449 for (i = nlines; i > 0; i--) {
3450 if (direction == UP) {
3451 if (edittop->prev == NULL)
3452 break;
3453 edittop = edittop->prev;
3454 scroll_rows--;
3455 } else {
3456 if (edittop->next == NULL)
3457 break;
3458 edittop = edittop->next;
3459 scroll_rows++;
3460 }
3461 }
3462
3463 /* Scroll the text on the screen up or down scroll_rows lines,
3464 * depending on the value of direction. */
3465 scrollok(edit, TRUE);
3466 wscrl(edit, scroll_rows);
3467 scrollok(edit, FALSE);
3468
3469 foo = edittop;
3470 if (direction != UP) {
3471 int slines = editwinrows - nlines;
3472 for (; slines > 0 && foo != NULL; slines--)
3473 foo = foo->next;
3474 }
3475
3476 /* And draw new lines on the blank top or bottom lines of the edit
3477 * window, depending on the value of direction. Don't draw the new
3478 * topmost or new bottommost line. */
3479 while (scroll_rows != 0 && foo != NULL) {
3480 if (foo->next != NULL)
3481 update_line(foo, 0);
3482 if (direction == UP)
3483 scroll_rows++;
3484 else
3485 scroll_rows--;
3486 foo = foo->next;
3487 }
3488}
3489
3490/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003491 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003492void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003493{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003494 int do_refresh = need_vertical_update(0) ||
3495 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003496 const filestruct *foo;
3497
3498 /* If either old_current or current is offscreen, refresh the screen
3499 * and get out. */
3500 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3501 edittop->lineno + editwinrows || current->lineno <
3502 edittop->lineno || current->lineno >= edittop->lineno +
3503 editwinrows) {
3504 edit_refresh();
3505 return;
3506 }
3507
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003508 /* Update old_current and current if we're not on the first page
3509 * and/or we're not on the same page as before. If the mark is on,
3510 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003511 foo = old_current;
3512 while (foo != current) {
3513 if (do_refresh)
3514 update_line(foo, 0);
3515#ifndef NANO_SMALL
3516 if (!ISSET(MARK_ISSET))
3517#endif
3518 break;
3519 if (foo->lineno > current->lineno)
3520 foo = foo->prev;
3521 else
3522 foo = foo->next;
3523 }
3524 if (do_refresh)
3525 update_line(current, current_x);
3526}
3527
Chris Allegretta6df90f52002-07-19 01:08:59 +00003528/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003529void edit_refresh(void)
3530{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003531 if (current->lineno < edittop->lineno ||
3532 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003533 /* Note that edit_update() changes edittop so that it's in range
3534 * of current. Thus, when it then calls edit_refresh(), there
3535 * is no danger of getting an infinite loop. */
3536 edit_update(
3537#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003538 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003539#endif
3540 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003541 else {
3542 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003543 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003544
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003545#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003546 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003547#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003548
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003549 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003550 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003551 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003552 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003553 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003554 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003555 }
3556 while (nlines < editwinrows) {
3557 mvwaddstr(edit, nlines, 0, hblank);
3558 nlines++;
3559 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003560 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003561 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003562 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003563}
3564
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003565/* A nice generic routine to update the edit buffer. We keep current in
3566 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003567void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003568{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003569 filestruct *foo = current;
3570
Chris Allegretta6df90f52002-07-19 01:08:59 +00003571 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003572 /* If location is CENTER, we move edittop up (editwinrows / 2)
3573 * lines. This puts current at the center of the screen. If
3574 * location is NONE, we move edittop up current_y lines if
3575 * current_y is in range of the screen, 0 lines if current_y is
3576 * less than 0, or (editwinrows - 1) lines if current_y is
3577 * greater than (editwinrows - 1). This puts current at the
3578 * same place on the screen as before, or at the top or bottom
3579 * of the screen if edittop is beyond either. */
3580 int goal;
3581
3582 if (location == CENTER)
3583 goal = editwinrows / 2;
3584 else {
3585 goal = current_y;
3586
3587 /* Limit goal to (editwinrows - 1) lines maximum. */
3588 if (goal > editwinrows - 1)
3589 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003590 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003591
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003592 for (; goal > 0 && foo->prev != NULL; goal--)
3593 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003594 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003595
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003596 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003597 edit_refresh();
3598}
3599
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003600/* Ask a simple yes/no question, specified in msg, on the statusbar.
3601 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3602 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003603int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003604{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003605 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003606 const char *yesstr; /* String of yes characters accepted. */
3607 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003608 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00003609 char *expmsg; /* Expanded version of msg. */
3610
3611 assert(msg != NULL);
Chris Allegretta235ab192001-04-12 13:24:40 +00003612
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003613 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003614 * consists of all single-byte characters accepted as valid
3615 * characters for that value. The first value will be the one
3616 * displayed in the shortcuts. Translators: if possible, specify
3617 * both the shortcuts for your language and English. For example,
3618 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003619 yesstr = _("Yy");
3620 nostr = _("Nn");
3621 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003622
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003623 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003624 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003625
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003626 if (COLS < 32)
3627 width = COLS / 2;
3628
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003629 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003630 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003631
Chris Allegretta6232d662002-05-12 19:52:15 +00003632 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003633 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003634 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003635
3636 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003637 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003638 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003639 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003640 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003641
Chris Allegrettadb28e962003-01-28 01:23:40 +00003642 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003643 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003644 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003645
Chris Allegrettadb28e962003-01-28 01:23:40 +00003646 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003647 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003648 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003649
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003650 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003651
3652 blank_statusbar();
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00003653
3654 expmsg = display_string(msg, 0, COLS - 1, FALSE);
3655 mvwaddstr(bottomwin, 0, 0, msg);
3656 free(expmsg);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003657
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003658 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003659
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003660 wrefresh(bottomwin);
3661
Chris Allegrettadb28e962003-01-28 01:23:40 +00003662 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003663 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003664 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003665#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003666 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003667#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003668
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003669 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003670
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003671 if (kbinput == NANO_REFRESH_KEY) {
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003672 total_redraw();
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003673 continue;
3674 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003675 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003676#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003677 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003678 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003679
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003680 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003681 wenclose(bottomwin, mouse_y, mouse_x) &&
3682 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003683 int x = mouse_x / width;
3684 /* Did we click in the first column of shortcuts, or
3685 * the second? */
3686 int y = mouse_y - editwinrows - 3;
3687 /* Did we click in the first row of shortcuts? */
3688
3689 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3690
3691 /* x = 0 means they clicked Yes or No.
3692 * y = 0 means Yes or All. */
3693 ok = -2 * x * y + x - y + 1;
3694
3695 if (ok == 2 && !all)
3696 ok = -2;
3697 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003698 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003699#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003700 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003701 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003702 else if (strchr(yesstr, kbinput) != NULL)
3703 ok = 1;
3704 else if (strchr(nostr, kbinput) != NULL)
3705 ok = 0;
3706 else if (all && strchr(allstr, kbinput) != NULL)
3707 ok = 2;
3708 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003709
Chris Allegrettadb28e962003-01-28 01:23:40 +00003710 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003711}
3712
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003713void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003714{
David Lawrence Ramsey7431fe52005-06-18 15:15:48 +00003715#ifdef USE_SLANG
3716 /* Slang curses emulation brain damage, part 3: If we just do what
3717 * curses does here, it'll leave some windows cleared without
3718 * updating them properly. */
3719 SLsmg_touch_screen();
3720 SLsmg_refresh();
3721#else
David Lawrence Ramsey0bfec6e2005-04-25 20:08:29 +00003722 clearok(edit, TRUE);
3723 wrefresh(edit);
David Lawrence Ramsey7431fe52005-06-18 15:15:48 +00003724#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003725}
3726
3727void total_refresh(void)
3728{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003729 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003730 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003731 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003732 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003733}
3734
3735void display_main_list(void)
3736{
3737 bottombars(main_list);
3738}
3739
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003740/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3741 * display the cursor position. Otherwise, we display it only if the
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003742 * character position changed and disable_cursorpos is FALSE.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003743 *
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003744 * If constant is TRUE and disable_cursorpos is TRUE, we set the latter
3745 * to FALSE and update old_i and old_totsize. That way, we leave the
3746 * current statusbar alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003747void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003748{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003749 char c;
3750 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003751 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003752 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003753
Chris Allegrettad26ab912003-01-28 01:16:47 +00003754 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003755
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003756 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003757 old_totsize = totsize;
3758
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003759 c = current->data[current_x];
3760 f = current->next;
3761 current->data[current_x] = '\0';
3762 current->next = NULL;
3763 get_totals(fileage, current, NULL, &i);
3764 current->data[current_x] = c;
3765 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003766
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003767 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003768 * somewhere. */
3769 assert(current != filebot || i == totsize);
3770
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003771 if (constant && disable_cursorpos) {
3772 disable_cursorpos = FALSE;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003773 old_i = i;
3774 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003775 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003776 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003777
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003778 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003779 * unconditionally. Otherwise, only display the position when the
3780 * character values have changed. Finally, if disable_cursorpos is
3781 * TRUE, set it to FALSE. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003782 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003783 size_t xpt = xplustabs() + 1;
3784 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003785 int linepct = 100 * current->lineno / totlines;
3786 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003787 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003788
3789 statusbar(
David Lawrence Ramsey954aba72005-06-17 21:21:10 +00003790 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3791 current->lineno, totlines, linepct, (unsigned long)xpt,
3792 (unsigned long)cur_len, colpct, (unsigned long)i,
3793 (unsigned long)totsize, bytepct);
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003794 disable_cursorpos = FALSE;
Chris Allegretta2084acc2001-11-29 03:43:08 +00003795 }
3796
3797 old_i = i;
3798 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003799}
3800
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003801void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003802{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003803 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003804}
3805
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003806#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003807/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003808size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003809{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003810 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003811
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003812 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003813 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003814 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003815 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003816
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003817 /* Get the length of the entire line up to a null or a newline. */
3818 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3819 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003820
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003821 /* If the entire line doesn't go more than 8 columns beyond where we
3822 * tried to break it, we should display it as-is. Otherwise, we
3823 * should display it only up to the break. */
3824 if (strnlenpt(ptr, retval) > help_cols + 8)
3825 retval = retval_save;
3826
3827 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003828}
3829
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003830/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003831void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003832{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003833 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003834 /* The line number in help_text of the first displayed help
3835 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003836 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003837 /* no_more means the end of the help text is shown, so don't go
3838 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003839 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003840 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003841
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003842 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003843#ifndef DISABLE_MOUSE
3844 const shortcut *oldshortcut = currshortcut;
3845 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003846 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003847#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003848
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003849 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003850 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003851 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003852 blank_statusbar();
3853
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003854 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003855 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003856
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003857 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003858
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003860 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003861 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003862 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003863#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003864
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003865 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003866 /* Make sure that the help screen's shortcut list will actually
3867 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003868 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003869 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003870 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003871
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003872 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003873
3874 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003875 int i;
3876 int old_line = line;
3877 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003878 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003879
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003880 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003881#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003882 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003883 {
3884 int mouse_x, mouse_y;
3885 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3886 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003887 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003888#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003889 case NANO_PREVPAGE_KEY:
3890 case NANO_PREVPAGE_FKEY:
3891 if (line > 0) {
3892 line -= editwinrows - 2;
3893 if (line < 0)
3894 line = 0;
3895 }
3896 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003897 case NANO_NEXTPAGE_KEY:
3898 case NANO_NEXTPAGE_FKEY:
3899 if (!no_more)
3900 line += editwinrows - 2;
3901 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902 case NANO_PREVLINE_KEY:
3903 if (line > 0)
3904 line--;
3905 break;
3906 case NANO_NEXTLINE_KEY:
3907 if (!no_more)
3908 line++;
3909 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003910 }
3911
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003912 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003913 total_redraw();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003914 else {
3915 if (line == old_line && kbinput != ERR)
3916 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003917
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003918 blank_edit();
3919 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003920
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003921 /* Calculate where in the text we should be, based on the
3922 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003923 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003924 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003925 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003926 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003927 }
3928
Chris Allegretta4640fe32003-02-10 03:10:03 +00003929 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003930 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003931
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003932 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003933 ptr += j;
3934 if (*ptr == '\n')
3935 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003936 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003937 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003938
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003939 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003940 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003941 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003942
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003943#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003944 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003945#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003946
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003947 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003948 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003949 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003951 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003952 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003953 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003955 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003956 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003957
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003958 /* The help_init() at the beginning allocated help_text. Since
3959 * help_text has now been written to the screen, we don't need it
3960 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003961 free(help_text);
3962 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003963}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003964#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003965
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003966/* Highlight the current word being replaced or spell checked. We
3967 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003968void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003969{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003970 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003971 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003972
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003973 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003974 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003975 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003976
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003977 assert(y > 0);
3978
3979 if (word_len > y)
3980 y--;
3981
Chris Allegrettafb62f732000-12-05 11:36:41 +00003982 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003983
Chris Allegrettafb62f732000-12-05 11:36:41 +00003984 if (highlight_flag)
3985 wattron(edit, A_REVERSE);
3986
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003987#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003988 /* This is so we can show zero-length regexes. */
3989 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003990 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003991 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003992#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003993 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003994
3995 if (word_len > y)
3996 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003997
3998 if (highlight_flag)
3999 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004000}
4001
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004002#ifndef NDEBUG
4003/* Return what the current line number should be, starting at edittop
4004 * and ending at fileptr. */
4005int check_linenumbers(const filestruct *fileptr)
4006{
4007 int check_line = 0;
4008 const filestruct *filetmp;
4009
4010 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
4011 check_line++;
4012
4013 return check_line;
4014}
4015#endif
4016
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004017#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004018/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004019void dump_buffer(const filestruct *inptr)
4020{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004021 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004022 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004023 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004024 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004025 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004026 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004027
4028 while (inptr != NULL) {
4029 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4030 inptr = inptr->next;
4031 }
4032}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004033
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004034/* Dump the main filestruct to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004035void dump_buffer_reverse(void)
4036{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004037 const filestruct *fileptr = filebot;
4038
4039 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004040 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004041 fileptr = fileptr->prev;
4042 }
4043}
4044#endif /* DEBUG */
4045
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004046#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004047#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004048#define XLCREDIT_LEN 8
4049
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004050/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004051void do_credits(void)
4052{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004053 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004054 const char *credits[CREDIT_LEN] = {
4055 NULL, /* "The nano text editor" */
4056 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004057 VERSION,
4058 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004059 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004060 "Chris Allegretta",
4061 "Jordi Mallach",
4062 "Adam Rogoyski",
4063 "Rob Siemborski",
4064 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004065 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004066 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004067 "Ken Tyler",
4068 "Sven Guckes",
David Lawrence Ramsey7bf86e12005-06-08 19:50:02 +00004069 "Florian K\xF6nig",
Chris Allegretta598106e2002-01-19 01:59:37 +00004070 "Pauli Virtanen",
4071 "Daniele Medri",
4072 "Clement Laforet",
4073 "Tedi Heriyanto",
4074 "Bill Soudan",
4075 "Christian Weisgerber",
4076 "Erik Andersen",
4077 "Big Gaute",
4078 "Joshua Jensen",
4079 "Ryan Krebs",
4080 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004081 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004082 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004083 "Plattsburgh State University",
4084 "Benet Laboratories",
4085 "Amy Allegretta",
4086 "Linda Young",
4087 "Jeremy Robichaud",
4088 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004089 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004090 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004091 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004092 "Thomas Dickey",
4093 "Pavel Curtis",
4094 "Zeyd Ben-Halim",
4095 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004096 NULL, /* "and anyone else we forgot..." */
4097 NULL, /* "Thank you for using nano!" */
4098 "",
4099 "",
4100 "",
4101 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004102 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004103 "",
4104 "",
4105 "",
4106 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004107 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004108 };
4109
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004110 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004111 N_("The nano text editor"),
4112 N_("version"),
4113 N_("Brought to you by:"),
4114 N_("Special thanks to:"),
4115 N_("The Free Software Foundation"),
4116 N_("For ncurses:"),
4117 N_("and anyone else we forgot..."),
4118 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004119 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004120
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004121 curs_set(0);
4122 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004123 scrollok(edit, TRUE);
4124 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004125 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004126 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004127 blank_statusbar();
4128 blank_bottombars();
4129 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004130 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004131 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004132
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004133 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004134 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004135 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004136
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004137 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004138 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004139 size_t start_x;
4140
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004141 /* Make sure every credit is a valid multibyte string, since
4142 * we can't dynamically set the credits to their multibyte
4143 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004144 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004145 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004146
4147 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004148 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004149 } else
David Lawrence Ramsey30d0a812005-06-13 14:50:32 +00004150 what = make_valid_mbstring(credits[crpos]);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004151
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004152 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004153 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4154 start_x, what);
4155
4156 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004157 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004158
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004159 napms(700);
4160 scroll(edit);
4161 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004162 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004163 break;
4164 napms(700);
4165 scroll(edit);
4166 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004167 }
4168
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004169 if (kbinput != ERR)
4170 ungetch(kbinput);
4171
4172 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004173 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004174 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004175 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004176}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004177#endif