blob: bb35635522b478e8efe056b081ce0b0ad5d6ec3a [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);
2663 reset_cursor();
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002664
2665#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002666 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002667#endif
2668
2669#ifndef DISABLE_TABCOMP
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002670 /* If we've done tab completion, there might be a list of
2671 * filename matches on the edit window at this point. Make sure
2672 * that they're cleared off. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002673 if (list)
2674 edit_refresh();
2675#endif
2676
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002677 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002678}
2679
2680void statusq_abort(void)
2681{
2682 resetstatuspos = TRUE;
2683}
2684
Chris Allegrettaf717f982003-02-13 22:25:01 +00002685void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002686{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002687 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002688 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002689 size_t verlen = strlenpt(VERMSG) + 1;
2690 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002691 const char *prefix;
2692 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2693 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002694 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002695 const char *state;
2696 /* "Modified", "View", or spaces the length of "Modified".
2697 * Tells the state of this buffer. */
2698 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002699 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002700 char *exppath = NULL;
2701 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002702 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002703 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002704 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002705 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002706
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002707 assert(path != NULL || filename != NULL);
2708 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002709
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002710 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002711 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002712
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002713 if (COLS <= 5 || COLS - 5 < verlen)
2714 space = 0;
2715 else {
2716 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002717 /* Reserve 2/3 of the screen plus one column for after the
2718 * version message. */
2719 if (space < COLS - (COLS / 3) + 1)
2720 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002721 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002722
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002723 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002724 /* The version message should only take up 1/3 of the screen
2725 * minus one column. */
2726 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002727 waddstr(topwin, " ");
2728 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002729
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002730 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002731 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002732 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002733 state = _("View");
2734 else {
2735 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002736 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002737 state = &hblank[COLS - statelen];
2738 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002739 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002740
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002741 /* We need a space before state. */
2742 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2743 statelen++;
2744
2745 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002746
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002747 if (space == 0 || statelen >= space)
2748 goto the_end;
2749
2750#ifndef DISABLE_BROWSER
2751 if (path != NULL)
2752 prefix = _("DIR:");
2753 else
2754#endif
2755 if (filename[0] == '\0') {
2756 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002757 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002758 } else
2759 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002760
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002761 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002762
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002763 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002764
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002765 /* If newfie is FALSE, we need a space after prefix. */
2766 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002767 prefixlen++;
2768
2769 if (path == NULL)
2770 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002771 if (space >= prefixlen + statelen)
2772 space -= prefixlen + statelen;
2773 else
2774 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002775 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002776
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002777 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002778 size_t lenpt = strlenpt(path), start_col;
2779
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002780 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002781
2782 if (dots) {
2783 start_col = lenpt - space + 3;
2784 space -= 3;
2785 } else
2786 start_col = 0;
2787
2788 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002789 }
2790
2791 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002792 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2793 /* The length of the expanded filename. */
2794
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002795 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002796 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002797 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002798 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002799 assert(strlenpt(prefix) + 1 == prefixlen);
2800
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 waddch(topwin, ' ');
2802 waddstr(topwin, exppath);
2803 }
2804 } else {
2805 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002806 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002807 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002808 goto the_end;
2809 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002810 waddnstr(topwin, "...", space + 3);
2811 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002812 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002813 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002814 }
2815
2816 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002817 free(exppath);
2818
2819 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002820 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002821 else {
2822 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002823
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002824 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002825 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2826 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002827 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002828
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002830
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002831 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002832 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002833 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002834}
2835
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002836/* If modified is not already set, set it and update titlebar. */
2837void set_modified(void)
2838{
2839 if (!ISSET(MODIFIED)) {
2840 SET(MODIFIED);
2841 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002842 }
2843}
2844
2845void statusbar(const char *msg, ...)
2846{
2847 va_list ap;
2848
2849 va_start(ap, msg);
2850
2851 /* Curses mode is turned off. If we use wmove() now, it will muck
2852 * up the terminal settings. So we just use vfprintf(). */
2853 if (curses_ended) {
2854 vfprintf(stderr, msg, ap);
2855 va_end(ap);
2856 return;
2857 }
2858
2859 /* Blank out the line. */
2860 blank_statusbar();
2861
2862 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002863 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002864 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002865#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002866 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002867
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002868 UNSET(WHITESPACE_DISPLAY);
2869#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002870 bar = charalloc(mb_cur_max() * (COLS - 3));
2871 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002872 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002873 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002874#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2875 if (old_whitespace)
2876 SET(WHITESPACE_DISPLAY);
2877#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002878 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002879 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002880 start_x = (COLS - foo_len - 4) / 2;
2881
2882 wmove(bottomwin, 0, start_x);
2883 wattron(bottomwin, A_REVERSE);
2884
2885 waddstr(bottomwin, "[ ");
2886 waddstr(bottomwin, foo);
2887 free(foo);
2888 waddstr(bottomwin, " ]");
2889 wattroff(bottomwin, A_REVERSE);
2890 wnoutrefresh(bottomwin);
2891 reset_cursor();
2892 wrefresh(edit);
2893 /* Leave the cursor at its position in the edit window, not
2894 * in the statusbar. */
2895 }
2896
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002897 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002898
2899 /* If we're doing quick statusbar blanking, and constant cursor
2900 * position display is off, blank the statusbar after only one
2901 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2902 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002903 statusblank =
2904#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002905 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002906#endif
2907 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002908}
2909
Chris Allegretta6232d662002-05-12 19:52:15 +00002910void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002911{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002912 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002913
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002914 if (ISSET(NO_HELP))
2915 return;
2916
Chris Allegretta6232d662002-05-12 19:52:15 +00002917 if (s == main_list) {
2918 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002919
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002920 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002921 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002922 slen = length_of_list(s);
2923
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002924 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002925 if (slen > MAIN_VISIBLE)
2926 slen = MAIN_VISIBLE;
2927 }
2928
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002929 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002930 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002931 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002932
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002933 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002934
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002935 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002936 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002937 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002938
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002939 /* Yucky sentinel values that we can't handle a better way. */
2940 if (s->ctrlval == NANO_CONTROL_SPACE)
2941 strcpy(foo, "^ ");
2942 else if (s->ctrlval == NANO_CONTROL_8)
2943 strcpy(foo, "^?");
2944 /* Normal values. Assume that the shortcut has an equivalent
2945 * control key, meta key sequence, or both. */
2946 else if (s->ctrlval != NANO_NO_KEY)
2947 sprintf(foo, "^%c", s->ctrlval + 64);
2948 else if (s->metaval != NANO_NO_KEY)
2949 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002950
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002951 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002952
2953 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002954 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002955 }
2956
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002957 wnoutrefresh(bottomwin);
2958 reset_cursor();
2959 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002960}
2961
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002962/* Write a shortcut key to the help area at the bottom of the window.
2963 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2964 * to write at most len characters, even if len is very small and
2965 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2966 * the whole string! We do not bother padding the entry with blanks. */
2967void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002968{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002969 size_t keystroke_len = strlenpt(keystroke) + 1;
2970
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002971 assert(keystroke != NULL && desc != NULL);
2972
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002973 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002974 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002975 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002976
2977 if (len > keystroke_len)
2978 len -= keystroke_len;
2979 else
2980 len = 0;
2981
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002982 if (len > 0) {
2983 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002984 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002985 }
2986}
2987
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002988/* nano scrolls horizontally within a line in chunks. This function
2989 * returns the column number of the first character displayed in the
2990 * window when the cursor is at the given column. Note that
2991 * 0 <= column - get_page_start(column) < COLS. */
2992size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002993{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002994 assert(COLS > 0);
2995 if (column == 0 || column < COLS - 1)
2996 return 0;
2997 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002998 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002999 else if (COLS > 2)
3000 return column - (COLS - 2);
3001 else
3002 return column - (COLS - 1);
3003 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003004}
3005
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003006/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003007 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003008void reset_cursor(void)
3009{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003010 /* If we haven't opened any files yet, put the cursor in the top
3011 * left corner of the edit window and get out. */
3012 if (edittop == NULL || current == NULL) {
3013 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003014 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003015 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003016
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003017 current_y = current->lineno - edittop->lineno;
3018 if (current_y < editwinrows) {
3019 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003020 wmove(edit, current_y, x - get_page_start(x));
3021 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003022}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003023
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003024/* edit_add() takes care of the job of actually painting a line into the
3025 * edit window. fileptr is the line to be painted, at row yval of the
3026 * window. converted is the actual string to be written to the window,
3027 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003028 * characters. start is the column number of the first character of
3029 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003030 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003031void edit_add(const filestruct *fileptr, const char *converted, int
3032 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003033{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003034#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003035 size_t startpos = actual_x(fileptr->data, start);
3036 /* The position in fileptr->data of the leftmost character
3037 * that displays at least partially on the window. */
3038 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3039 /* The position in fileptr->data of the first character that is
3040 * completely off the window to the right.
3041 *
3042 * Note that endpos might be beyond the null terminator of the
3043 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003044#endif
3045
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003046 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003047 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003048
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003049 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003050 * just the text that needs it). */
3051 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003052
Chris Allegretta7dd77682001-12-08 19:52:28 +00003053#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003054 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003055 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003056
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003057 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3058 int x_start;
3059 /* Starting column for mvwaddnstr. Zero-based. */
3060 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003061 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003062 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003063 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003064 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003065 regmatch_t startmatch; /* match position for start_regexp */
3066 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003067
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003068 if (tmpcolor->bright)
3069 wattron(edit, A_BOLD);
3070 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003071 /* Two notes about regexec(). Return value 0 means there is
3072 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003073 * after the match. */
3074
3075 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003076 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003077 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003078
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003079 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003080 * last match. Even though two matches may overlap, we
3081 * want to ignore them, so that we can highlight
3082 * C-strings correctly. */
3083 while (k < endpos) {
3084 /* Note the fifth parameter to regexec(). It says
3085 * not to match the beginning-of-line character
3086 * unless k is 0. If regexec() returns REG_NOMATCH,
3087 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003088 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003089 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003090 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003091 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003092 /* Translate the match to the beginning of the
3093 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003094 startmatch.rm_so += k;
3095 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003096 if (startmatch.rm_so == startmatch.rm_eo) {
3097 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003098 statusbar(
3099 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003100 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003101 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003102 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003103 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003104 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003105 x_start = strnlenpt(fileptr->data,
3106 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003107
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003108 index = actual_x(converted, x_start);
3109
3110 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003111 strnlenpt(fileptr->data,
3112 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003113
3114 assert(0 <= x_start && 0 <= paintlen);
3115
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003116 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003117 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003119 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003120 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003121 } else {
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003122 /* This is a multi-line regexp. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003123 * First, we have to see if the beginning of the line is
3124 * colored by a start on an earlier line, and an end on
3125 * this line or later.
3126 *
3127 * We find the first line before fileptr matching the
3128 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003129 * end, then go to step two. Otherwise, find the next
3130 * line after start_line matching the end. If that line
3131 * is not before fileptr, then paint the beginning of
3132 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003133 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003134 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003135 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003136 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003137 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003138
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003139 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003140 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003141 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 /* If there is an end on this line, there is no need
3143 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003144 if (regexec(tmpcolor->end, start_line->data, 0,
3145 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003146 goto step_two;
3147 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003148 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003149 /* No start found, so skip to the next step. */
3150 if (start_line == NULL)
3151 goto step_two;
3152 /* Now start_line is the first line before fileptr
3153 * containing a start match. Is there a start on this
3154 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003155 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003156 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003157 start_col += startmatch.rm_so;
3158 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003159 if (regexec(tmpcolor->end, start_line->data +
3160 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003161 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003162 REG_NOTBOL) == REG_NOMATCH)
3163 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003164 break;
3165 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003166 if (regexec(&tmpcolor->start, start_line->data +
3167 start_col, 1, &startmatch,
3168 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003169 /* No later start on this line. */
3170 goto step_two;
3171 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003172 /* Indeed, there is a start not followed on this line by
3173 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003174
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003175 /* We have already checked that there is no end before
3176 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003177 * the start at all? We don't paint unterminated
3178 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003179 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003180 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003181 regexec(tmpcolor->end, end_line->data, 1,
3182 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003183 end_line = end_line->next;
3184
3185 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003186 if (end_line == NULL || (end_line == fileptr &&
3187 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003188 goto step_two;
3189
3190 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003191 if (end_line != fileptr)
3192 /* If the start of fileptr is on a different line
3193 * from the end, paintlen is -1, meaning that
3194 * everything on the line gets painted. */
3195 paintlen = -1;
3196 else
3197 /* Otherwise, paintlen is the expanded location of
3198 * the end of the match minus the expanded location
3199 * of the beginning of the page. */
3200 paintlen = actual_x(converted,
3201 strnlenpt(fileptr->data, endmatch.rm_eo) -
3202 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003203
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003204 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003205
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003206 step_two:
3207 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003208 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003209
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003210 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003211 if (regexec(&tmpcolor->start,
3212 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003213 (start_col == 0) ? 0 :
3214 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003215 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003216 /* No more starts on this line. */
3217 break;
3218 /* Translate the match to be relative to the
3219 * beginning of the line. */
3220 startmatch.rm_so += start_col;
3221 startmatch.rm_eo += start_col;
3222
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003223 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003224 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003225 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003226 x_start = strnlenpt(fileptr->data,
3227 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003228
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003229 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003230
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003231 if (regexec(tmpcolor->end,
3232 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003233 (startmatch.rm_eo == 0) ? 0 :
3234 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003235 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003236 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003237 endmatch.rm_so += startmatch.rm_eo;
3238 endmatch.rm_eo += startmatch.rm_eo;
3239 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003240 * appear on this page, and is the match more
3241 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003242 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003244 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003245 strnlenpt(fileptr->data,
3246 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003247
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003248 assert(0 <= x_start && x_start < COLS);
3249
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003250 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003251 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003252 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003253 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003254 /* There is no end on this line. But we haven't
3255 * yet looked for one on later lines. */
3256 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003257
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003258 while (end_line != NULL &&
3259 regexec(tmpcolor->end, end_line->data,
3260 0, NULL, 0) == REG_NOMATCH)
3261 end_line = end_line->next;
3262
3263 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003265
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003267 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003268 /* We painted to the end of the line, so
3269 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003270 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003271 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003272 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003273 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003274 }
3275 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003276
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003277 wattroff(edit, A_BOLD);
3278 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003279 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003280 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003281#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003282
Chris Allegretta7dd77682001-12-08 19:52:28 +00003283#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003284 if (ISSET(MARK_ISSET)
3285 && (fileptr->lineno <= mark_beginbuf->lineno
3286 || fileptr->lineno <= current->lineno)
3287 && (fileptr->lineno >= mark_beginbuf->lineno
3288 || fileptr->lineno >= current->lineno)) {
3289 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003290
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003291 const filestruct *top;
3292 /* Either current or mark_beginbuf, whichever is first. */
3293 size_t top_x;
3294 /* current_x or mark_beginx, corresponding to top. */
3295 const filestruct *bot;
3296 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297 int x_start;
3298 /* Starting column for mvwaddnstr. Zero-based. */
3299 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003300 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003301 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003302 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003303 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003304
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003305 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003306
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003307 if (top->lineno < fileptr->lineno || top_x < startpos)
3308 top_x = startpos;
3309 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3310 bot_x = endpos;
3311
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003312 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003313 if (top_x < endpos && bot_x > startpos) {
3314 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003315
3316 /* x_start is the expanded location of the beginning of the
3317 * mark minus the beginning of the page. */
3318 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003319
3320 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003321 /* If the end of the mark is off the page, paintlen is
3322 * -1, meaning that everything on the line gets
3323 * painted. */
3324 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003325 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003326 /* Otherwise, paintlen is the expanded location of the
3327 * end of the mark minus the expanded location of the
3328 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003329 paintlen = strnlenpt(fileptr->data, bot_x) -
3330 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003331
3332 /* If x_start is before the beginning of the page, shift
3333 * paintlen x_start characters to compensate, and put
3334 * x_start at the beginning of the page. */
3335 if (x_start < 0) {
3336 paintlen += x_start;
3337 x_start = 0;
3338 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003339
3340 assert(x_start >= 0 && x_start <= strlen(converted));
3341
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003342 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003343
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003344 if (paintlen > 0)
3345 paintlen = actual_x(converted + index, paintlen);
3346
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003347 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003348 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003349 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003350 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003351 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003352 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003354}
3355
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003356/* Just update one line in the edit buffer. This is basically a wrapper
3357 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003358 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003359 * If fileptr != current, then index is considered 0. The line will be
3360 * displayed starting with fileptr->data[index]. Likely args are
3361 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003362void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003363{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003364 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003365 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003366 char *converted;
3367 /* fileptr->data converted to have tabs and control characters
3368 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003369 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003370
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003371 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003372
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003373 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003374
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003375 /* We assume the line numbers are valid. Is that really true? */
3376 assert(line < 0 || line == check_linenumbers(fileptr));
3377
3378 if (line < 0 || line >= editwinrows)
3379 return;
3380
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003381 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003382 mvwaddstr(edit, line, 0, hblank);
3383
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003384 /* Next, convert variables that index the line to their equivalent
3385 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003386 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003387 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003388
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003389 /* Expand the line, replacing tabs with spaces, and control
3390 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003391 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003392
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003393 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003394 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003395 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003396
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003397 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003398 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003399 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003400 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003401}
3402
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003403/* Return a nonzero value if we need an update after moving
3404 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003405 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003406int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003407{
3408 return
3409#ifndef NANO_SMALL
3410 ISSET(MARK_ISSET) ||
3411#endif
3412 get_page_start(old_pww) != get_page_start(placewewant);
3413}
3414
3415/* Return a nonzero value if we need an update after moving vertically.
3416 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003417 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003418int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003419{
3420 return
3421#ifndef NANO_SMALL
3422 ISSET(MARK_ISSET) ||
3423#endif
3424 get_page_start(old_pww) != get_page_start(placewewant);
3425}
3426
3427/* Scroll the edit window in the given direction and the given number
3428 * of lines, and draw new lines on the blank lines left after the
3429 * scrolling. direction is the direction to scroll, either UP or DOWN,
3430 * and nlines is the number of lines to scroll. Don't redraw the old
3431 * topmost or bottommost line (where we assume current is) before
3432 * scrolling or draw the new topmost or bottommost line after scrolling
3433 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003434 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003435void edit_scroll(updown direction, int nlines)
3436{
3437 filestruct *foo;
3438 int i, scroll_rows = 0;
3439
3440 /* Scrolling less than one line or more than editwinrows lines is
3441 * redundant, so don't allow it. */
3442 if (nlines < 1 || nlines > editwinrows)
3443 return;
3444
3445 /* Move the top line of the edit window up or down (depending on the
3446 * value of direction) nlines lines. If there are fewer lines of
3447 * text than that left, move it to the top or bottom line of the
3448 * file (depending on the value of direction). Keep track of
3449 * how many lines we moved in scroll_rows. */
3450 for (i = nlines; i > 0; i--) {
3451 if (direction == UP) {
3452 if (edittop->prev == NULL)
3453 break;
3454 edittop = edittop->prev;
3455 scroll_rows--;
3456 } else {
3457 if (edittop->next == NULL)
3458 break;
3459 edittop = edittop->next;
3460 scroll_rows++;
3461 }
3462 }
3463
3464 /* Scroll the text on the screen up or down scroll_rows lines,
3465 * depending on the value of direction. */
3466 scrollok(edit, TRUE);
3467 wscrl(edit, scroll_rows);
3468 scrollok(edit, FALSE);
3469
3470 foo = edittop;
3471 if (direction != UP) {
3472 int slines = editwinrows - nlines;
3473 for (; slines > 0 && foo != NULL; slines--)
3474 foo = foo->next;
3475 }
3476
3477 /* And draw new lines on the blank top or bottom lines of the edit
3478 * window, depending on the value of direction. Don't draw the new
3479 * topmost or new bottommost line. */
3480 while (scroll_rows != 0 && foo != NULL) {
3481 if (foo->next != NULL)
3482 update_line(foo, 0);
3483 if (direction == UP)
3484 scroll_rows++;
3485 else
3486 scroll_rows--;
3487 foo = foo->next;
3488 }
3489}
3490
3491/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003492 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003493void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003494{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003495 int do_refresh = need_vertical_update(0) ||
3496 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003497 const filestruct *foo;
3498
3499 /* If either old_current or current is offscreen, refresh the screen
3500 * and get out. */
3501 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3502 edittop->lineno + editwinrows || current->lineno <
3503 edittop->lineno || current->lineno >= edittop->lineno +
3504 editwinrows) {
3505 edit_refresh();
3506 return;
3507 }
3508
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003509 /* Update old_current and current if we're not on the first page
3510 * and/or we're not on the same page as before. If the mark is on,
3511 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003512 foo = old_current;
3513 while (foo != current) {
3514 if (do_refresh)
3515 update_line(foo, 0);
3516#ifndef NANO_SMALL
3517 if (!ISSET(MARK_ISSET))
3518#endif
3519 break;
3520 if (foo->lineno > current->lineno)
3521 foo = foo->prev;
3522 else
3523 foo = foo->next;
3524 }
3525 if (do_refresh)
3526 update_line(current, current_x);
3527}
3528
Chris Allegretta6df90f52002-07-19 01:08:59 +00003529/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003530void edit_refresh(void)
3531{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003532 if (current->lineno < edittop->lineno ||
3533 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003534 /* Note that edit_update() changes edittop so that it's in range
3535 * of current. Thus, when it then calls edit_refresh(), there
3536 * is no danger of getting an infinite loop. */
3537 edit_update(
3538#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003539 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003540#endif
3541 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003542 else {
3543 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003544 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003545
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003546#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003547 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003548#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003549
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003550 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003551 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003552 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003553 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003554 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003555 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003556 }
3557 while (nlines < editwinrows) {
3558 mvwaddstr(edit, nlines, 0, hblank);
3559 nlines++;
3560 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003561 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003562 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003563 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003564}
3565
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003566/* A nice generic routine to update the edit buffer. We keep current in
3567 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003568void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003569{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003570 filestruct *foo = current;
3571
Chris Allegretta6df90f52002-07-19 01:08:59 +00003572 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003573 /* If location is CENTER, we move edittop up (editwinrows / 2)
3574 * lines. This puts current at the center of the screen. If
3575 * location is NONE, we move edittop up current_y lines if
3576 * current_y is in range of the screen, 0 lines if current_y is
3577 * less than 0, or (editwinrows - 1) lines if current_y is
3578 * greater than (editwinrows - 1). This puts current at the
3579 * same place on the screen as before, or at the top or bottom
3580 * of the screen if edittop is beyond either. */
3581 int goal;
3582
3583 if (location == CENTER)
3584 goal = editwinrows / 2;
3585 else {
3586 goal = current_y;
3587
3588 /* Limit goal to (editwinrows - 1) lines maximum. */
3589 if (goal > editwinrows - 1)
3590 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003591 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003592
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003593 for (; goal > 0 && foo->prev != NULL; goal--)
3594 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003595 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003596
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003597 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003598 edit_refresh();
3599}
3600
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003601/* Ask a simple yes/no question, specified in msg, on the statusbar.
3602 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3603 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003604int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003605{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003606 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003607 const char *yesstr; /* String of yes characters accepted. */
3608 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003609 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003610
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003611 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003612 * consists of all single-byte characters accepted as valid
3613 * characters for that value. The first value will be the one
3614 * displayed in the shortcuts. Translators: if possible, specify
3615 * both the shortcuts for your language and English. For example,
3616 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003617 yesstr = _("Yy");
3618 nostr = _("Nn");
3619 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003620
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003621 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003622 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003623
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003624 if (COLS < 32)
3625 width = COLS / 2;
3626
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003627 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003628 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003629
Chris Allegretta6232d662002-05-12 19:52:15 +00003630 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003631 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003632 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003633
3634 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003635 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003636 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003637 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003638 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003639
Chris Allegrettadb28e962003-01-28 01:23:40 +00003640 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003641 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003642 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003643
Chris Allegrettadb28e962003-01-28 01:23:40 +00003644 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003645 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003646 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003647
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003648 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003649
3650 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003651 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003652
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003653 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003654
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003655 wrefresh(bottomwin);
3656
Chris Allegrettadb28e962003-01-28 01:23:40 +00003657 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003658 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003659 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003660#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003661 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003662#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003663
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003664 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003665
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003666 if (kbinput == NANO_REFRESH_KEY) {
3667 total_update();
3668 continue;
3669 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003670 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003671#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003672 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003673 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003674
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003675 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003676 wenclose(bottomwin, mouse_y, mouse_x) &&
3677 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003678 int x = mouse_x / width;
3679 /* Did we click in the first column of shortcuts, or
3680 * the second? */
3681 int y = mouse_y - editwinrows - 3;
3682 /* Did we click in the first row of shortcuts? */
3683
3684 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3685
3686 /* x = 0 means they clicked Yes or No.
3687 * y = 0 means Yes or All. */
3688 ok = -2 * x * y + x - y + 1;
3689
3690 if (ok == 2 && !all)
3691 ok = -2;
3692 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003693 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003694#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003695 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003696 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003697 else if (strchr(yesstr, kbinput) != NULL)
3698 ok = 1;
3699 else if (strchr(nostr, kbinput) != NULL)
3700 ok = 0;
3701 else if (all && strchr(allstr, kbinput) != NULL)
3702 ok = 2;
3703 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003704
Chris Allegrettadb28e962003-01-28 01:23:40 +00003705 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003706}
3707
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003708void total_update(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003709{
David Lawrence Ramsey0bfec6e2005-04-25 20:08:29 +00003710 clearok(edit, TRUE);
3711 wrefresh(edit);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003712}
3713
3714void total_refresh(void)
3715{
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003716 total_update();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003717 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003718 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003719 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003720}
3721
3722void display_main_list(void)
3723{
3724 bottombars(main_list);
3725}
3726
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003727/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3728 * display the cursor position. Otherwise, we display it only if the
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003729 * character position changed and disable_cursorpos is FALSE.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003730 *
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003731 * If constant is TRUE and disable_cursorpos is TRUE, we set the latter
3732 * to FALSE and update old_i and old_totsize. That way, we leave the
3733 * current statusbar alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003734void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003735{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003736 char c;
3737 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003738 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003739 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003740
Chris Allegrettad26ab912003-01-28 01:16:47 +00003741 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003742
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003743 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003744 old_totsize = totsize;
3745
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003746 c = current->data[current_x];
3747 f = current->next;
3748 current->data[current_x] = '\0';
3749 current->next = NULL;
3750 get_totals(fileage, current, NULL, &i);
3751 current->data[current_x] = c;
3752 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003753
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003754 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003755 * somewhere. */
3756 assert(current != filebot || i == totsize);
3757
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003758 if (constant && disable_cursorpos) {
3759 disable_cursorpos = FALSE;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003760 old_i = i;
3761 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003762 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003763 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003764
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003765 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003766 * unconditionally. Otherwise, only display the position when the
3767 * character values have changed. Finally, if disable_cursorpos is
3768 * TRUE, set it to FALSE. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003769 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003770 size_t xpt = xplustabs() + 1;
3771 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003772 int linepct = 100 * current->lineno / totlines;
3773 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003774 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003775
3776 statusbar(
David Lawrence Ramsey954aba72005-06-17 21:21:10 +00003777 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3778 current->lineno, totlines, linepct, (unsigned long)xpt,
3779 (unsigned long)cur_len, colpct, (unsigned long)i,
3780 (unsigned long)totsize, bytepct);
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003781 disable_cursorpos = FALSE;
Chris Allegretta2084acc2001-11-29 03:43:08 +00003782 }
3783
3784 old_i = i;
3785 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003786}
3787
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003788void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003789{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003790 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003791}
3792
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003793#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003794/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003795size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003796{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003797 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003798
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003799 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003800 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003801 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003802 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003803
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003804 /* Get the length of the entire line up to a null or a newline. */
3805 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3806 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003807
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003808 /* If the entire line doesn't go more than 8 columns beyond where we
3809 * tried to break it, we should display it as-is. Otherwise, we
3810 * should display it only up to the break. */
3811 if (strnlenpt(ptr, retval) > help_cols + 8)
3812 retval = retval_save;
3813
3814 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003815}
3816
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003817/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003818void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003819{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003820 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003821 /* The line number in help_text of the first displayed help
3822 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003823 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003824 /* no_more means the end of the help text is shown, so don't go
3825 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003826 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003827 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003828
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003829 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003830#ifndef DISABLE_MOUSE
3831 const shortcut *oldshortcut = currshortcut;
3832 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003833 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003834#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003835
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003836 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003837 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003838 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003839 blank_statusbar();
3840
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003841 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003842 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003843
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003844 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003845
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003846#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003847 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003848 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003849 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003850#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003851
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003852 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003853 /* Make sure that the help screen's shortcut list will actually
3854 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003855 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003856 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003857 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003858
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003859 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003860
3861 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003862 int i;
3863 int old_line = line;
3864 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003865 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003866
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003867 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003868#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003869 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003870 {
3871 int mouse_x, mouse_y;
3872 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3873 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003874 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003875#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003876 case NANO_PREVPAGE_KEY:
3877 case NANO_PREVPAGE_FKEY:
3878 if (line > 0) {
3879 line -= editwinrows - 2;
3880 if (line < 0)
3881 line = 0;
3882 }
3883 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003884 case NANO_NEXTPAGE_KEY:
3885 case NANO_NEXTPAGE_FKEY:
3886 if (!no_more)
3887 line += editwinrows - 2;
3888 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003889 case NANO_PREVLINE_KEY:
3890 if (line > 0)
3891 line--;
3892 break;
3893 case NANO_NEXTLINE_KEY:
3894 if (!no_more)
3895 line++;
3896 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003897 }
3898
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003899 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003900 total_update();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003901 else {
3902 if (line == old_line && kbinput != ERR)
3903 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003904
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003905 blank_edit();
3906 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003907
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003908 /* Calculate where in the text we should be, based on the
3909 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003910 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003911 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003912 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003913 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003914 }
3915
Chris Allegretta4640fe32003-02-10 03:10:03 +00003916 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003917 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003918
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003919 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003920 ptr += j;
3921 if (*ptr == '\n')
3922 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003923 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003924 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003925
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003926 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003927 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003928 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003929
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003930#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003931 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003932#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003933
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003934 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003935 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003936 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003937 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003938 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003939 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003940 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003941
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003942 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003943 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003944
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003945 /* The help_init() at the beginning allocated help_text. Since
3946 * help_text has now been written to the screen, we don't need it
3947 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003948 free(help_text);
3949 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003951#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003952
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003953/* Highlight the current word being replaced or spell checked. We
3954 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003955void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003956{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003957 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003958 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003959
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003960 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003961 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003962 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003963
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003964 assert(y > 0);
3965
3966 if (word_len > y)
3967 y--;
3968
Chris Allegrettafb62f732000-12-05 11:36:41 +00003969 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003970
Chris Allegrettafb62f732000-12-05 11:36:41 +00003971 if (highlight_flag)
3972 wattron(edit, A_REVERSE);
3973
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003974#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003975 /* This is so we can show zero-length regexes. */
3976 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00003977 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003978 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003979#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003980 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003981
3982 if (word_len > y)
3983 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00003984
3985 if (highlight_flag)
3986 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003987}
3988
David Lawrence Ramseycc814362005-06-05 19:08:59 +00003989#ifndef NDEBUG
3990/* Return what the current line number should be, starting at edittop
3991 * and ending at fileptr. */
3992int check_linenumbers(const filestruct *fileptr)
3993{
3994 int check_line = 0;
3995 const filestruct *filetmp;
3996
3997 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3998 check_line++;
3999
4000 return check_line;
4001}
4002#endif
4003
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004004#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004005/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004006void dump_buffer(const filestruct *inptr)
4007{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004008 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004009 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004010 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004011 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004012 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004013 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004014
4015 while (inptr != NULL) {
4016 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4017 inptr = inptr->next;
4018 }
4019}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004020
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004021/* Dump the main filestruct to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004022void dump_buffer_reverse(void)
4023{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004024 const filestruct *fileptr = filebot;
4025
4026 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004027 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004028 fileptr = fileptr->prev;
4029 }
4030}
4031#endif /* DEBUG */
4032
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004033#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004034#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004035#define XLCREDIT_LEN 8
4036
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004037/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004038void do_credits(void)
4039{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004040 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004041 const char *credits[CREDIT_LEN] = {
4042 NULL, /* "The nano text editor" */
4043 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004044 VERSION,
4045 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004046 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004047 "Chris Allegretta",
4048 "Jordi Mallach",
4049 "Adam Rogoyski",
4050 "Rob Siemborski",
4051 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004052 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004053 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004054 "Ken Tyler",
4055 "Sven Guckes",
David Lawrence Ramsey7bf86e12005-06-08 19:50:02 +00004056 "Florian K\xF6nig",
Chris Allegretta598106e2002-01-19 01:59:37 +00004057 "Pauli Virtanen",
4058 "Daniele Medri",
4059 "Clement Laforet",
4060 "Tedi Heriyanto",
4061 "Bill Soudan",
4062 "Christian Weisgerber",
4063 "Erik Andersen",
4064 "Big Gaute",
4065 "Joshua Jensen",
4066 "Ryan Krebs",
4067 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004068 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004069 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004070 "Plattsburgh State University",
4071 "Benet Laboratories",
4072 "Amy Allegretta",
4073 "Linda Young",
4074 "Jeremy Robichaud",
4075 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004076 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004077 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004078 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004079 "Thomas Dickey",
4080 "Pavel Curtis",
4081 "Zeyd Ben-Halim",
4082 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004083 NULL, /* "and anyone else we forgot..." */
4084 NULL, /* "Thank you for using nano!" */
4085 "",
4086 "",
4087 "",
4088 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004089 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004090 "",
4091 "",
4092 "",
4093 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004094 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004095 };
4096
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004097 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004098 N_("The nano text editor"),
4099 N_("version"),
4100 N_("Brought to you by:"),
4101 N_("Special thanks to:"),
4102 N_("The Free Software Foundation"),
4103 N_("For ncurses:"),
4104 N_("and anyone else we forgot..."),
4105 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004106 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004107
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004108 curs_set(0);
4109 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004110 scrollok(edit, TRUE);
4111 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004112 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004113 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004114 blank_statusbar();
4115 blank_bottombars();
4116 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004117 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004118 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004119
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004120 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004121 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004122 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004123
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004124 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004125 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004126 size_t start_x;
4127
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004128 /* Make sure every credit is a valid multibyte string, since
4129 * we can't dynamically set the credits to their multibyte
4130 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004131 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004132 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004133
4134 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004135 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004136 } else
David Lawrence Ramsey30d0a812005-06-13 14:50:32 +00004137 what = make_valid_mbstring(credits[crpos]);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004138
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004139 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004140 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4141 start_x, what);
4142
4143 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004144 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004145
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004146 napms(700);
4147 scroll(edit);
4148 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004149 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004150 break;
4151 napms(700);
4152 scroll(edit);
4153 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004154 }
4155
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004156 if (kbinput != ERR)
4157 ungetch(kbinput);
4158
4159 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004160 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004161 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004162 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004163}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004164#endif