blob: 8fce798b788938e70c40193fe40a59dc60c95a6e [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. */
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +000042static int statusblank = 0;
43 /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000044 * we call statusbar(), before we
45 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000046static size_t statusbar_x = (size_t)-1;
47 /* The cursor position in answer. */
David Lawrence Ramseyea014742005-06-17 18:27:00 +000048static bool disable_cursorpos = FALSE;
49 /* Should we temporarily disable
50 * constant cursor position display? */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000051static bool resetstatuspos = FALSE;
52 /* Should we reset the cursor position
53 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000054
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000055/* Control character compatibility:
56 *
57 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
58 * VT100, and VT220.
59 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
60 * VT220, and VT320.
61 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
64 * VT220, and VT320.
65 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
66 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000067 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000068 * ANSI, VT100, and VT220, and which is Backspace under VT320.
69 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000070 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000071 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
72 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000073 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000074 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000075 * on which the VT320 sequences are translated by the keypad to KEY_DC
76 * and [nothing]. We work around this conflict via the REBIND_DELETE
77 * flag: if it's not set, we assume VT320 compatibility, and if it is,
78 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
79 * Hemel for helping work this conflict out.
80 *
81 * Escape sequence compatibility:
82 *
83 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000084 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000085 * console), xterm, rxvt, and Eterm. Among these, there are several
86 * conflicts and omissions, outlined as follows:
87 *
88 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
89 * (Ctrl-I is also Tab on ANSI, which we already support.)
90 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
91 * NumLock off on Linux console; the latter is omitted. (The editing
92 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000093 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000094 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
95 * latter is omitted. (Mouse input will only work properly if the
96 * extended keypad value KEY_MOUSE is generated on mouse events
97 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (The editing keypad is more important to have working
100 * than the function keys, because the functions of the former are not
101 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000102 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000103 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000104 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000105 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000106 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
107 * omitted. (The arrow keys, with or without modifiers, are more
108 * important to have working than the function keys, because the
109 * functions of the former are not arbitrary and the functions of the
110 * latter are.)
111 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
112 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000113 *
114 * Note that Center (5) on the numeric keypad with NumLock off can also
115 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000116
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000117#ifndef NANO_SMALL
118/* Reset all the input routines that rely on character sequences. */
119void reset_kbinput(void)
120{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000121 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000122 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000124}
125#endif
126
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000127/* Read in a sequence of keystrokes from win and save them in the
128 * default keystroke buffer. This should only be called when the
129 * default keystroke buffer is empty. */
130void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000131{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000132 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000133
134 /* If the keystroke buffer isn't empty, get out. */
135 if (key_buffer != NULL)
136 return;
137
138 /* Read in the first character using blocking input. */
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000139#ifndef NANO_SMALL
140 allow_pending_sigwinch(TRUE);
141#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000142
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000143 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000144
David Lawrence Ramseyc275dc52005-03-08 17:45:36 +0000145 /* If we get ERR when using blocking input, it means that the input
146 * source that we were using is gone, so die gracefully. */
147 if (input == ERR)
148 handle_hupterm(0);
149
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000150#ifndef NANO_SMALL
151 allow_pending_sigwinch(FALSE);
152#endif
153
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000154 /* Increment the length of the keystroke buffer, save the value of
155 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000156 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000157 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000158 key_buffer = (int *)nmalloc(sizeof(int));
159 key_buffer[0] = input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000160
161 /* Read in the remaining characters using non-blocking input. */
162 nodelay(win, TRUE);
163
164 while (TRUE) {
165#ifndef NANO_SMALL
166 allow_pending_sigwinch(TRUE);
167#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000168
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000169 input = wgetch(win);
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000170
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000171 /* If there aren't any more characters, stop reading. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000172 if (input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000173 break;
174
175 /* Otherwise, increment the length of the keystroke buffer, save
176 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000177 * if the keystroke is an extended keypad value or FALSE if it
178 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000179 key_buffer_len++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000180 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
181 sizeof(int));
182 key_buffer[key_buffer_len - 1] = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000183
184#ifndef NANO_SMALL
185 allow_pending_sigwinch(FALSE);
186#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000187 }
188
189 /* Switch back to non-blocking input. */
190 nodelay(win, FALSE);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000191
192#ifdef DEBUG
193 fprintf(stderr, "get_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
194#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000195}
196
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000197/* Return the length of the default keystroke buffer. */
198size_t get_buffer_len(void)
199{
200 return key_buffer_len;
201}
202
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000203/* Add the contents of the keystroke buffer input to the default
204 * keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000205void unget_input(int *input, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206{
207#ifndef NANO_SMALL
208 allow_pending_sigwinch(TRUE);
209 allow_pending_sigwinch(FALSE);
210#endif
211
212 /* If input is empty, get out. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000213 if (input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000214 return;
215
216 /* If adding input would put the default keystroke buffer beyond
217 * maximum capacity, only add enough of input to put it at maximum
218 * capacity. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000219 if (key_buffer_len + input_len < key_buffer_len)
220 input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000221
222 /* Add the length of input to the length of the default keystroke
223 * buffer, and reallocate the default keystroke buffer so that it
224 * has enough room for input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000225 key_buffer_len += input_len;
226 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
227 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000228
229 /* If the default keystroke buffer wasn't empty before, move its
230 * beginning forward far enough so that we can add input to its
231 * beginning. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000232 if (key_buffer_len > input_len)
233 memmove(key_buffer + input_len, key_buffer,
234 (key_buffer_len - input_len) * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000235
236 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000237 memcpy(key_buffer, input, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000238}
239
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000240/* Put back the character stored in kbinput, putting it in byte range
241 * beforehand. If meta_key is TRUE, put back the Escape character after
242 * putting back kbinput. If func_key is TRUE, put back the function key
243 * (a value outside byte range) without putting it in byte range. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000244void unget_kbinput(int kbinput, bool meta_key, bool func_key)
245{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000246 if (!func_key)
247 kbinput = (char)kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000248
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000249 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000250
251 if (meta_key) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000252 kbinput = NANO_CONTROL_3;
253 unget_input(&kbinput, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000254 }
255}
256
257/* Try to read input_len characters from the default keystroke buffer.
258 * If the default keystroke buffer is empty and win isn't NULL, try to
259 * read in more characters from win and add them to the default
260 * keystroke buffer before doing anything else. If the default
261 * keystroke buffer is empty and win is NULL, return NULL. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000262int *get_input(WINDOW *win, size_t input_len)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000263{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000264 int *input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000265
266#ifndef NANO_SMALL
267 allow_pending_sigwinch(TRUE);
268 allow_pending_sigwinch(FALSE);
269#endif
270
271 if (key_buffer_len == 0) {
272 if (win != NULL)
273 get_buffer(win);
274
275 if (key_buffer_len == 0)
276 return NULL;
277 }
278
279 /* If input_len is greater than the length of the default keystroke
280 * buffer, only read the number of characters in the default
281 * keystroke buffer. */
282 if (input_len > key_buffer_len)
283 input_len = key_buffer_len;
284
285 /* Subtract input_len from the length of the default keystroke
286 * buffer, and allocate the keystroke buffer input so that it
287 * has enough room for input_len keystrokes. */
288 key_buffer_len -= input_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000289 input = (int *)nmalloc(input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000290
291 /* Copy input_len characters from the beginning of the default
292 * keystroke buffer into input. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000293 memcpy(input, key_buffer, input_len * sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000294
295 /* If the default keystroke buffer is empty, mark it as such. */
296 if (key_buffer_len == 0) {
297 free(key_buffer);
298 key_buffer = NULL;
299 /* If the default keystroke buffer isn't empty, move its
300 * beginning forward far enough back so that the keystrokes in input
301 * are no longer at its beginning. */
302 } else {
303 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000304 sizeof(int));
305 key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
306 sizeof(int));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000307 }
308
309 return input;
310}
311
312/* Read in a single character. If it's ignored, swallow it and go on.
313 * Otherwise, try to translate it from ASCII, meta key sequences, escape
314 * sequences, and/or extended keypad values. Set meta_key to TRUE when
315 * we get a meta key sequence, and set func_key to TRUE when we get an
316 * extended keypad value. Supported extended keypad values consist of
317 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
318 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
319 * the function keypad (F1-F16), and the numeric keypad with NumLock
320 * off. Assume nodelay(win) is FALSE. */
321int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
322{
323 int kbinput;
324
325 /* Read in a character and interpret it. Continue doing this until
326 * we get a recognized value or sequence. */
327 while ((kbinput = parse_kbinput(win, meta_key, func_key
328#ifndef NANO_SMALL
329 , FALSE
330#endif
331 )) == ERR);
332
333 return kbinput;
334}
335
336/* Translate ASCII characters, extended keypad values, and escape
337 * sequences into their corresponding key values. Set meta_key to TRUE
338 * when we get a meta key sequence, and set func_key to TRUE when we get
339 * a function key. Assume nodelay(win) is FALSE. */
340int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000341#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000342 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000343#endif
344 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000345
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000346{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000347 static int escapes = 0, byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000348 int *kbinput, retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000349
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000350#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000351 if (reset) {
352 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000353 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000354 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000355 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000356#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000357
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000358 *meta_key = FALSE;
359 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000360
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000361 /* Read in a character. */
362 while ((kbinput = get_input(win, 1)) == NULL);
363
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000364 switch (*kbinput) {
365 case ERR:
366 break;
367 case NANO_CONTROL_3:
368 /* Increment the escape counter. */
369 escapes++;
370 switch (escapes) {
371 case 1:
372 /* One escape: wait for more input. */
373 case 2:
374 /* Two escapes: wait for more input. */
375 break;
376 default:
377 /* More than two escapes: reset the escape counter
378 * and wait for more input. */
379 escapes = 0;
380 }
381 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000382#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000383 /* Since we don't change the default SIGWINCH handler when
384 * NANO_SMALL is defined, KEY_RESIZE is never generated. Also,
385 * Slang and SunOS 5.7-5.9 don't support KEY_RESIZE. */
386 case KEY_RESIZE:
387 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000388#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000389#ifdef PDCURSES
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000390 case KEY_SHIFT_L:
391 case KEY_SHIFT_R:
392 case KEY_CONTROL_L:
393 case KEY_CONTROL_R:
394 case KEY_ALT_L:
395 case KEY_ALT_R:
396 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000397#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000398 default:
399 switch (escapes) {
400 case 0:
401 switch (*kbinput) {
402 case NANO_CONTROL_8:
403 retval = ISSET(REBIND_DELETE) ?
404 NANO_DELETE_KEY : NANO_BACKSPACE_KEY;
405 break;
406 case KEY_DOWN:
407 retval = NANO_NEXTLINE_KEY;
408 break;
409 case KEY_UP:
410 retval = NANO_PREVLINE_KEY;
411 break;
412 case KEY_LEFT:
413 retval = NANO_BACK_KEY;
414 break;
415 case KEY_RIGHT:
416 retval = NANO_FORWARD_KEY;
417 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000418#ifdef KEY_HOME
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000419 /* HP-UX 10 and 11 don't support KEY_HOME. */
420 case KEY_HOME:
421 retval = NANO_HOME_KEY;
422 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000423#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000424 case KEY_BACKSPACE:
425 retval = NANO_BACKSPACE_KEY;
426 break;
427 case KEY_DC:
428 retval = ISSET(REBIND_DELETE) ?
429 NANO_BACKSPACE_KEY : NANO_DELETE_KEY;
430 break;
431 case KEY_IC:
432 retval = NANO_INSERTFILE_KEY;
433 break;
434 case KEY_NPAGE:
435 retval = NANO_NEXTPAGE_KEY;
436 break;
437 case KEY_PPAGE:
438 retval = NANO_PREVPAGE_KEY;
439 break;
440 case KEY_ENTER:
441 retval = NANO_ENTER_KEY;
442 break;
443 case KEY_A1: /* Home (7) on numeric keypad
444 * with NumLock off. */
445 retval = NANO_HOME_KEY;
446 break;
447 case KEY_A3: /* PageUp (9) on numeric keypad
448 * with NumLock off. */
449 retval = NANO_PREVPAGE_KEY;
450 break;
451 case KEY_B2: /* Center (5) on numeric keypad
452 * with NumLock off. */
453 break;
454 case KEY_C1: /* End (1) on numeric keypad
455 * with NumLock off. */
456 retval = NANO_END_KEY;
457 break;
458 case KEY_C3: /* PageDown (4) on numeric
459 * keypad with NumLock off. */
460 retval = NANO_NEXTPAGE_KEY;
461 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000462#ifdef KEY_BEG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000463 /* Slang doesn't support KEY_BEG. */
464 case KEY_BEG: /* Center (5) on numeric keypad
465 * with NumLock off. */
466 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000467#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000468#ifdef KEY_END
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000469 /* HP-UX 10 and 11 don't support KEY_END. */
470 case KEY_END:
471 retval = NANO_END_KEY;
472 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000473#endif
474#ifdef KEY_SUSPEND
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000475 /* Slang doesn't support KEY_SUSPEND. */
476 case KEY_SUSPEND:
477 retval = NANO_SUSPEND_KEY;
478 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000479#endif
480#ifdef KEY_SLEFT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000481 /* Slang doesn't support KEY_SLEFT. */
482 case KEY_SLEFT:
483 retval = NANO_BACK_KEY;
484 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000485#endif
486#ifdef KEY_SRIGHT
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000487 /* Slang doesn't support KEY_SRIGHT. */
488 case KEY_SRIGHT:
489 retval = NANO_FORWARD_KEY;
490 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000491#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000492 default:
493 retval = *kbinput;
494 break;
495 }
496 break;
497 case 1:
498 /* One escape followed by a non-escape: escape
499 * sequence mode. Reset the escape counter. If
500 * there aren't any other keys waiting, we have a
501 * meta key sequence, so set meta_key to TRUE and
502 * save the lowercase version of the non-escape
503 * character as the result. If there are other keys
504 * waiting, we have a true escape sequence, so
505 * interpret it. */
506 escapes = 0;
507 if (get_buffer_len() == 0) {
508 *meta_key = TRUE;
509 retval = tolower(*kbinput);
510 } else {
511 int *seq;
512 size_t seq_len;
513 bool ignore_seq;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000514
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000515 /* Put back the non-escape character, get the
516 * complete escape sequence, translate the
517 * sequence into its corresponding key value,
518 * and save that as the result. */
519 unget_input(kbinput, 1);
520 seq_len = get_buffer_len();
521 seq = get_input(NULL, seq_len);
522 retval = get_escape_seq_kbinput(seq, seq_len,
523 &ignore_seq);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000524
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000525 /* If the escape sequence is unrecognized and
526 * not ignored, put back all of its characters
527 * except for the initial escape. */
528 if (retval == ERR && !ignore_seq)
529 unget_input(seq, seq_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000530
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000531 free(seq);
532 }
533 break;
534 case 2:
535 /* Two escapes followed by one or more decimal
536 * digits: byte sequence mode. If the word
537 * sequence's range is limited to 2XX (the first
538 * digit is in the '0' to '2' range and it's the
539 * first digit, or it's in the '0' to '9' range and
540 * it's not the first digit), increment the byte
541 * sequence counter and interpret the digit. If the
542 * byte sequence's range is not limited to 2XX, fall
543 * through. */
544 if (('0' <= *kbinput && *kbinput <= '6' &&
545 byte_digits == 0) || ('0' <= *kbinput &&
546 *kbinput <= '9' && byte_digits > 0)) {
547 int byte;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000548
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000549 byte_digits++;
550 byte = get_byte_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000551#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000552 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000553#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000554 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000555
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000556 if (byte != ERR) {
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000557 char *byte_mb;
558 int byte_mb_len, *seq, i;
559
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000560 /* If we've read in a complete byte
561 * sequence, reset the byte sequence counter
562 * and the escape counter, and put back the
563 * corresponding byte value. */
564 byte_digits = 0;
565 escapes = 0;
566
David Lawrence Ramseyce9d2992005-06-14 23:38:08 +0000567 /* Put back the multibyte equivalent of the
568 * byte value. */
569 byte_mb = make_mbchar(byte, &byte_mb_len);
570
571 seq = (int *)nmalloc(byte_mb_len *
572 sizeof(int));
573
574 for (i = 0; i < byte_mb_len; i++)
575 seq[i] = (unsigned char)byte_mb[i];
576
577 unget_input(seq, byte_mb_len);
578
579 free(byte_mb);
580 free(seq);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000581 }
582 } else {
583 /* Reset the escape counter. */
584 escapes = 0;
585 if (byte_digits == 0)
586 /* Two escapes followed by a non-decimal
587 * digit or a decimal digit that would
588 * create a byte sequence greater than 2XX,
589 * and we're not in the middle of a byte
590 * sequence: control character sequence
591 * mode. Interpret the control sequence and
592 * save the corresponding control character
593 * as the result. */
594 retval = get_control_kbinput(*kbinput);
595 else {
596 /* If we're in the middle of a byte
597 * sequence, reset the byte sequence counter
598 * and save the character we got as the
599 * result. */
600 byte_digits = 0;
601 retval = *kbinput;
602 }
603 }
604 break;
605 }
606 }
607
608 /* If we have a result and it's an extended keypad value (i.e, a
609 * value outside of byte range), set func_key to TRUE. */
610 if (retval != ERR)
611 *func_key = !is_byte(retval);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000612
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000613#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000614 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 +0000615#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000616
617 /* Return the result. */
618 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000619}
620
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000621/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000622 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000623 * are generated when the keypad doesn't support the needed keys. If
624 * the escape sequence is recognized but we want to ignore it, return
625 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
626 * set ignore_seq to FALSE. Assume that Escape has already been read
627 * in. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000628int get_escape_seq_kbinput(const int *seq, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000629 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000630{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000631 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000632
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000633 *ignore_seq = FALSE;
634
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000635 if (seq_len > 1) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000636 switch (seq[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000637 case 'O':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000638 switch (seq[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000639 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000640 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000641 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000642 case 'P': /* Esc O 2 P == F13 on
643 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000644 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000645 break;
646 case 'Q': /* Esc O 2 Q == F14 on
647 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000648 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000649 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000650 case 'R': /* Esc O 2 R == F15 on
651 * xterm. */
652 retval = KEY_F(15);
653 break;
654 case 'S': /* Esc O 2 S == F16 on
655 * xterm. */
656 retval = KEY_F(16);
657 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000658 }
659 }
660 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000661 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
662 case 'B': /* Esc O B == Down on
663 * VT100/VT320/xterm. */
664 case 'C': /* Esc O C == Right on
665 * VT100/VT320/xterm. */
666 case 'D': /* Esc O D == Left on
667 * VT100/VT320/xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000668 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000669 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000670 case 'E': /* Esc O E == Center (5) on numeric keypad
671 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000672 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000673 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000674 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000675 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000676 break;
677 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000678 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000679 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000680 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000681 * NumLock off on VT100/VT220/VT320/xterm/
682 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000683 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000684 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000685 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000686 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000687 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000688 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000689 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000690 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000691 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000692 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000693 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000694 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000695 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000696 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000697 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000698 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000699 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000700 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000701 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000702 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000703 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000704 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000705 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000706 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000707 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000708 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000709 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000710 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000711 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000712 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000713 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000714 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000715 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000716 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000717 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000718 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000719 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000721 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000722 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000723 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000724 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000725 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000726 * NumLock off on VT100/VT220/VT320/xterm/
727 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000728 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
730 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000731 * NumLock off on VT100/VT220/VT320/xterm/
732 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000733 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000734 break;
735 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000736 * NumLock off on VT100/VT220/VT320/xterm/
737 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000738 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000739 break;
740 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000741 * NumLock off on VT100/VT220/VT320/xterm/
742 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000744 break;
745 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000746 * with NumLock off on VT100/VT220/VT320/
747 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000749 break;
750 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000751 * NumLock off on VT100/VT220/VT320/xterm/
752 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000753 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000754 break;
755 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000756 * with NumLock off on VT100/VT220/VT320/
757 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000759 break;
760 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000761 * with NumLock off on VT100/VT220/VT320/
762 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000764 break;
765 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000766 * with NumLock off on VT100/VT220/VT320/
767 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000768 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000769 break;
770 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000771 * keypad with NumLock off on VT100/VT220/
772 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 break;
775 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000776 * with NumLock off on VT100/VT220/VT320/
777 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000778 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000779 break;
780 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000781 * with NumLock off on VT100/VT220/VT320/
782 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000783 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 break;
785 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000786 * with NumLock off on VT100/VT220/VT320/
787 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000788 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000789 break;
790 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000791 * with NumLock off on VT100/VT220/VT320/
792 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000794 break;
795 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000796 * with NumLock off on VT100/VT220/VT320/
797 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000798 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000799 break;
800 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000801 * with NumLock off on VT100/VT220/VT320/
802 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000804 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000805 }
806 break;
807 case 'o':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000808 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000811 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000812 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000813 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000814 break;
815 }
816 break;
817 case '[':
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000818 switch (seq[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000819 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000820 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000821 switch (seq[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
823 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000825 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000826 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
827 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000828 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000829 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000830 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
831 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000832 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000833 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000834 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
835 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000836 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000837 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000838 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
839 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000840 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000841 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000842 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000843 * VT220/VT320/Linux console/
844 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000845 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000846 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000847 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000848 * VT220/VT320/Linux console/
849 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000850 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000851 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000852 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000853 * VT220/VT320/Linux console/
854 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000855 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000856 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000857 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000858 if (seq_len >= 4) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000859 switch (seq[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000860 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000861 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000862 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000863 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
864 * xterm. */
865 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
866 * xterm. */
867 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
868 * xterm. */
869 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
870 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000871 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000872 break;
873 }
874 }
875 break;
876 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000877 if (seq_len >= 5) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000878 switch (seq[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000879 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
880 * xterm. */
881 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
882 * xterm. */
883 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
884 * xterm. */
885 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
886 * xterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000887 retval = get_escape_seq_abcd(seq[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000888 break;
889 }
890 }
891 break;
892 }
893 }
894 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000895 default: /* Esc [ 1 ~ == Home on
896 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000897 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000898 break;
899 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000901 break;
902 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000903 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000904 switch (seq[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000905 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000906 * VT220/VT320/Linux console/
907 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000908 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000909 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000910 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000911 * VT220/VT320/Linux console/
912 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000913 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000914 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000915 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000916 * VT220/VT320/Linux console/
917 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000918 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000919 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000920 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000921 * VT220/VT320/Linux console/
922 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000923 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000924 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000925 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 * VT220/VT320/Linux console/
927 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000930 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000931 * VT220/VT320/Linux console/
932 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000933 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000934 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000935 case '8': /* Esc [ 2 8 ~ == F15 on
936 * VT220/VT320/Linux console/
937 * rxvt/Eterm. */
938 retval = KEY_F(15);
939 break;
940 case '9': /* Esc [ 2 9 ~ == F16 on
941 * VT220/VT320/Linux console/
942 * rxvt/Eterm. */
943 retval = KEY_F(16);
944 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000945 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000946 * VT220/VT320/Linux console/
947 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000948 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000949 break;
950 }
951 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000952 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000953 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
954 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000955 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000956 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000957 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000958 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000960 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000961 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
962 * Linux console/xterm; Esc [ 5 ^ ==
963 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000965 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000966 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
967 * Linux console/xterm; Esc [ 6 ^ ==
968 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000969 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000970 break;
971 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000972 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000973 break;
974 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000975 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000976 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000977 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000978 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000979 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000980 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000981 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000982 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000983 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000984 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000985 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000986 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000987 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000988 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000989 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000990 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000991 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000992 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000993 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000994 * rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000995 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000996 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000997 case 'E': /* Esc [ E == Center (5) on numeric keypad
998 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000999 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001000 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001001 case 'F': /* Esc [ F == End on FreeBSD
1002 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001003 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001004 break;
1005 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001006 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001007 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001009 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001010 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
1013 case 'I': /* Esc [ I == PageUp on FreeBSD
1014 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001016 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001017 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001018 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001019 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001020 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001021 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
1024 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001025 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001026 break;
1027 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001028 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001029 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001030 case 'P': /* Esc [ O P == F1 on
1031 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001032 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001033 break;
1034 case 'Q': /* Esc [ O Q == F2 on
1035 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
1038 case 'R': /* Esc [ O R == F3 on
1039 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001040 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001041 break;
1042 case 'S': /* Esc [ O S == F4 on
1043 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001044 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001045 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001046 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001047 } else {
1048 /* Esc [ O == F3 on FreeBSD console. */
1049 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001050 }
1051 break;
1052 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001053 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001054 break;
1055 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001056 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001057 break;
1058 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001059 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001060 break;
1061 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001062 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001063 break;
1064 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001065 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001066 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001067 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001068 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001069 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001070 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001071 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001072 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001073 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001074 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001075 break;
1076 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001077 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001078 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001079 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001080 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001081 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001082 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001083 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001084 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001085 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001086 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001087 case 'c': /* Esc [ c == Shift-Right on rxvt/
1088 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001089 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001090 retval = get_escape_seq_abcd(seq[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001091 break;
1092 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001093 if (seq_len >= 3) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001094 switch (seq[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001095 case 'A': /* Esc [ [ A == F1 on Linux
1096 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001097 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001098 break;
1099 case 'B': /* Esc [ [ B == F2 on Linux
1100 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001101 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 break;
1103 case 'C': /* Esc [ [ C == F3 on Linux
1104 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001105 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 break;
1107 case 'D': /* Esc [ [ D == F4 on Linux
1108 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 case 'E': /* Esc [ [ E == F5 on Linux
1112 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001114 break;
1115 }
1116 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001117 break;
1118 }
1119 break;
1120 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001121 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001124 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001125#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001126
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001128}
1129
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001130/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001131 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001132 * to many escape sequences. */
1133int get_escape_seq_abcd(int kbinput)
1134{
1135 switch (tolower(kbinput)) {
1136 case 'a':
1137 return NANO_PREVLINE_KEY;
1138 case 'b':
1139 return NANO_NEXTLINE_KEY;
1140 case 'c':
1141 return NANO_FORWARD_KEY;
1142 case 'd':
1143 return NANO_BACK_KEY;
1144 default:
1145 return ERR;
1146 }
1147}
1148
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001149/* Translate a byte sequence: turn a three-digit decimal number from
1150 * 000 to 255 into its corresponding byte value. */
1151int get_byte_kbinput(int kbinput
1152#ifndef NANO_SMALL
1153 , bool reset
1154#endif
1155 )
1156{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001157 static int byte_digits = 0, byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001158 int retval = ERR;
1159
1160#ifndef NANO_SMALL
1161 if (reset) {
1162 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001163 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001164 return ERR;
1165 }
1166#endif
1167
1168 /* Increment the byte digit counter. */
1169 byte_digits++;
1170
1171 switch (byte_digits) {
1172 case 1:
1173 /* One digit: reset the byte sequence holder and add the
1174 * digit we got to the 100's position of the byte sequence
1175 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001176 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001177 if ('0' <= kbinput && kbinput <= '2')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001178 byte += (kbinput - '0') * 100;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001179 else
1180 /* If the character we got isn't a decimal digit, or if
1181 * it is and it would put the byte sequence out of byte
1182 * range, save it as the result. */
1183 retval = kbinput;
1184 break;
1185 case 2:
1186 /* Two digits: add the digit we got to the 10's position of
1187 * the byte sequence holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001188 if (('0' <= kbinput && kbinput <= '5') || (byte < 200 &&
1189 '6' <= kbinput && kbinput <= '9'))
1190 byte += (kbinput - '0') * 10;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001191 else
1192 /* If the character we got isn't a decimal digit, or if
1193 * it is and it would put the byte sequence out of byte
1194 * range, save it as the result. */
1195 retval = kbinput;
1196 break;
1197 case 3:
1198 /* Three digits: add the digit we got to the 1's position of
1199 * the byte sequence holder, and save the corresponding word
1200 * value as the result. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001201 if (('0' <= kbinput && kbinput <= '5') || (byte < 250 &&
1202 '6' <= kbinput && kbinput <= '9')) {
1203 byte += (kbinput - '0');
1204 retval = byte;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001205 } else
1206 /* If the character we got isn't a decimal digit, or if
1207 * it is and it would put the word sequence out of word
1208 * range, save it as the result. */
1209 retval = kbinput;
1210 break;
1211 default:
1212 /* More than three digits: save the character we got as the
1213 * result. */
1214 retval = kbinput;
1215 break;
1216 }
1217
1218 /* If we have a result, reset the byte digit counter and the byte
1219 * sequence holder. */
1220 if (retval != ERR) {
1221 byte_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001222 byte = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001223 }
1224
1225#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001226 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 +00001227#endif
1228
1229 return retval;
1230}
1231
1232/* Translate a word sequence: turn a four-digit hexadecimal number from
1233 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001234int get_word_kbinput(int kbinput
1235#ifndef NANO_SMALL
1236 , bool reset
1237#endif
1238 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001239{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001240 static int word_digits = 0, word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001241 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001242
1243#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001244 if (reset) {
1245 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001246 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001247 return ERR;
1248 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001249#endif
1250
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001251 /* Increment the word digit counter. */
1252 word_digits++;
1253
1254 switch (word_digits) {
1255 case 1:
1256 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001257 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001258 * holder. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001259 word = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001260 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001261 word += (kbinput - '0') * 4096;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001262 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001263 word += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001264 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001265 /* If the character we got isn't a hexadecimal digit, or
1266 * if it is and it would put the word sequence out of
1267 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001268 retval = kbinput;
1269 break;
1270 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001271 /* Two digits: add the digit we got to the 256's position of
1272 * the word sequence holder. */
1273 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001274 word += (kbinput - '0') * 256;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001275 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001276 word += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001277 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001278 /* If the character we got isn't a hexadecimal digit, or
1279 * if it is and it would put the word sequence out of
1280 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001281 retval = kbinput;
1282 break;
1283 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001284 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001285 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001286 if ('0' <= kbinput && kbinput <= '9')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001287 word += (kbinput - '0') * 16;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001288 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001289 word += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001290 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001291 /* If the character we got isn't a hexadecimal digit, or
1292 * if it is and it would put the word sequence out of
1293 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001294 retval = kbinput;
1295 break;
1296 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001297 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001298 * the word sequence holder, and save the corresponding word
1299 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001300 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001301 word += (kbinput - '0');
1302 retval = word;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001303 } else if ('a' <= tolower(kbinput) &&
1304 tolower(kbinput) <= 'f') {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001305 word += (tolower(kbinput) + 10 - 'a');
1306 retval = word;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001307 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001308 /* If the character we got isn't a hexadecimal digit, or
1309 * if it is and it would put the word sequence out of
1310 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001311 retval = kbinput;
1312 break;
1313 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001314 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001315 * result. */
1316 retval = kbinput;
1317 break;
1318 }
1319
1320 /* If we have a result, reset the word digit counter and the word
1321 * sequence holder. */
1322 if (retval != ERR) {
1323 word_digits = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001324 word = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001325 }
1326
1327#ifdef DEBUG
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001328 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 +00001329#endif
1330
1331 return retval;
1332}
1333
1334/* Translate a control character sequence: turn an ASCII non-control
1335 * character into its corresponding control character. */
1336int get_control_kbinput(int kbinput)
1337{
1338 int retval;
1339
1340 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1341 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1342 kbinput == '`')
1343 retval = NANO_CONTROL_SPACE;
1344 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1345 else if ('3' <= kbinput && kbinput <= '7')
1346 retval = kbinput - 24;
1347 /* Ctrl-8 (Ctrl-?) */
1348 else if (kbinput == '8' || kbinput == '?')
1349 retval = NANO_CONTROL_8;
1350 /* Ctrl-A to Ctrl-_ */
1351 else if ('A' <= kbinput && kbinput <= '_')
1352 retval = kbinput - 64;
1353 /* Ctrl-a to Ctrl-~ */
1354 else if ('a' <= kbinput && kbinput <= '~')
1355 retval = kbinput - 96;
1356 else
1357 retval = kbinput;
1358
1359#ifdef DEBUG
1360 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1361#endif
1362
1363 return retval;
1364}
1365
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001366/* Put the output-formatted characters in output back into the default
1367 * keystroke buffer, so that they can be parsed and displayed as output
1368 * again. */
1369void unparse_kbinput(char *output, size_t output_len)
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001370{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001371 int *input;
1372 size_t i;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001373
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001374 if (output_len == 0)
1375 return;
1376
1377 input = (int *)nmalloc(output_len * sizeof(int));
1378 for (i = 0; i < output_len; i++)
1379 input[i] = (int)output[i];
1380 unget_input(input, output_len);
1381 free(input);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001382}
1383
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001384/* Read in a stream of characters verbatim, and return the length of the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001385 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1386int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1387{
1388 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389
1390 /* Turn off flow control characters if necessary so that we can type
1391 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001392 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001393 if (ISSET(PRESERVE))
1394 disable_flow_control();
1395 keypad(win, FALSE);
1396
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001397 /* Read in a stream of characters and interpret it if possible. */
1398 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001399
1400 /* Turn flow control characters back on if necessary and turn the
1401 * keypad back on now that we're done. */
1402 if (ISSET(PRESERVE))
1403 enable_flow_control();
1404 keypad(win, TRUE);
1405
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001406 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001407}
1408
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001409/* Read in a stream of all available characters, and return the length
1410 * of the string in kbinput_len. Translate the first few characters of
1411 * the input into the corresponding word value if possible. After that,
1412 * leave the input as-is. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001415 int *kbinput, word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001416
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001417 /* Read in the first keystroke. */
1418 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001419
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001420 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001421 word = get_word_kbinput(*kbinput
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001422#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001423 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001424#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001425 );
1426
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001427 /* If the first keystroke isn't a hexadecimal digit, put back the
1428 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001429 if (word != ERR)
1430 unget_input(kbinput, 1);
1431 /* Otherwise, read in keystrokes until we have a complete word
1432 * sequence, and put back the corresponding word value. */
1433 else {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001434 char *word_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001435 int word_mb_len, *seq, i;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001436
1437 while (word == ERR) {
1438 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001439
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001440 word = get_word_kbinput(*kbinput
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001441#ifndef NANO_SMALL
1442 , FALSE
1443#endif
1444 );
1445 }
1446
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001447 /* Put back the multibyte equivalent of the word value. */
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00001448 word_mb = make_mbchar(word, &word_mb_len);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001449
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001450 seq = (int *)nmalloc(word_mb_len * sizeof(int));
1451
1452 for (i = 0; i < word_mb_len; i++)
1453 seq[i] = (unsigned char)word_mb[i];
1454
1455 unget_input(seq, word_mb_len);
1456
1457 free(seq);
1458 free(word_mb);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001459 }
1460
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001461 /* Get the complete sequence, and save the characters in it as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001462 * result. */
1463 *kbinput_len = get_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001464 retval = get_input(NULL, *kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001465
1466 return retval;
1467}
1468
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001469#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001470/* Check for a mouse event, and if one's taken place, save the
1471 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001472 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1473 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001474 * place on it, figure out which shortcut was clicked and put back the
1475 * equivalent keystroke(s). Return FALSE if no keystrokes were
1476 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001477 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001478bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001479{
1480 MEVENT mevent;
1481
1482 *mouse_x = -1;
1483 *mouse_y = -1;
1484
1485 /* First, get the actual mouse event. */
1486 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001487 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001488
1489 /* Save the screen coordinates where the mouse event took place. */
1490 *mouse_x = mevent.x;
1491 *mouse_y = mevent.y;
1492
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001493 /* If we're allowing shortcuts, the current shortcut list is being
1494 * displayed on the last two lines of the screen, and the mouse
1495 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001496 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001497 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1498 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001499 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001500 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001501 /* The number of shortcuts in the current shortcut list. */
1502 const shortcut *s = currshortcut;
1503 /* The actual shortcut we clicked on, starting at the first
1504 * one in the current shortcut list. */
1505
1506 /* Get the shortcut lists' length. */
1507 if (currshortcut == main_list)
1508 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001509 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001510 currslen = length_of_list(currshortcut);
1511
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001512 /* We don't show any more shortcuts than the main list
1513 * does. */
1514 if (currslen > MAIN_VISIBLE)
1515 currslen = MAIN_VISIBLE;
1516 }
1517
David Lawrence Ramsey0df61f12005-06-08 20:23:06 +00001518 /* Calculate the width of each shortcut in the list. It's the
1519 * same for all of them. */
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001520 if (currslen < 2)
1521 i = COLS / 6;
1522 else
1523 i = COLS / ((currslen / 2) + (currslen % 2));
1524
David Lawrence Ramsey798e67e2005-01-28 19:11:51 +00001525 /* Calculate the y-coordinate relative to the beginning of
1526 * bottomwin. */
1527 j = *mouse_y - ((2 - no_more_space()) + 1) - editwinrows;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001528
1529 /* If we're on the statusbar, beyond the end of the shortcut
1530 * list, or beyond the end of a shortcut on the right side of
1531 * the screen, don't do anything. */
1532 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001533 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001534 j = (*mouse_x / i) * 2 + j;
1535 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001536 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001537
1538 /* Go through the shortcut list to determine which shortcut was
1539 * clicked. */
1540 for (; j > 0; j--)
1541 s = s->next;
1542
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001543 /* And put back the equivalent key. Assume that each shortcut
1544 * has, at the very least, an equivalent control key, an
1545 * equivalent primary meta key sequence, or both. */
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001546 if (s->ctrlval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001547 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001548 return TRUE;
1549 } else if (s->metaval != NANO_NO_KEY) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001550 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001551 return TRUE;
1552 }
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001553 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001554 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001555}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001556#endif /* !DISABLE_MOUSE */
1557
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001558const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001559 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001560{
1561 const shortcut *s = s_list;
1562 size_t slen = length_of_list(s_list);
1563
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001564#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001565 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 +00001566#endif
1567
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001568 /* Check for shortcuts. */
1569 for (; slen > 0; slen--) {
1570 /* We've found a shortcut if:
1571 *
1572 * 1. The key exists.
1573 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001574 * 3. meta_key is TRUE and the key is the primary or
1575 * miscellaneous meta sequence in the shortcut list.
1576 * 4. func_key is TRUE and the key is a function key in the
1577 * shortcut list. */
1578
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001579 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1580 (*meta_key == TRUE && (*kbinput == s->metaval ||
1581 *kbinput == s->miscval)) || (*func_key == TRUE &&
1582 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001583 break;
1584 }
1585
1586 s = s->next;
1587 }
1588
1589 /* Translate the shortcut to either its control key or its meta key
1590 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001591 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001592 if (slen > 0) {
1593 if (s->ctrlval != NANO_NO_KEY) {
1594 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001595 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001596 *kbinput = s->ctrlval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001597 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001598 } else if (s->metaval != NANO_NO_KEY) {
1599 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001600 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001601 *kbinput = s->metaval;
David Lawrence Ramseyf4a799a2005-01-08 06:16:19 +00001602 return s;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001603 }
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001604 }
1605
1606 return NULL;
1607}
1608
1609#ifndef NANO_SMALL
1610const toggle *get_toggle(int kbinput, bool meta_key)
1611{
1612 const toggle *t = toggles;
1613
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001614#ifdef DEBUG
1615 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1616#endif
1617
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001618 /* Check for toggles. */
1619 for (; t != NULL; t = t->next) {
1620 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001621 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001622 if (meta_key && kbinput == t->val)
1623 break;
1624 }
1625
1626 return t;
1627}
1628#endif /* !NANO_SMALL */
1629
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001630int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001631 bool *ran_func, bool *finished, bool allow_funcs)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001632{
1633 int input;
1634 /* The character we read in. */
1635 static int *kbinput = NULL;
1636 /* The input buffer. */
1637 static size_t kbinput_len = 0;
1638 /* The length of the input buffer. */
1639 const shortcut *s;
1640 bool have_shortcut;
1641
1642 *s_or_t = FALSE;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001643 *ran_func = FALSE;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001644 *finished = FALSE;
1645
1646 /* Read in a character. */
1647 input = get_kbinput(bottomwin, meta_key, func_key);
1648
1649#ifndef DISABLE_MOUSE
1650 /* If we got a mouse click and it was on a shortcut, read in the
1651 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001652 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001653 if (do_mouse())
1654 input = get_kbinput(bottomwin, meta_key, func_key);
1655 else
1656 input = ERR;
1657 }
1658#endif
1659
1660 /* Check for a shortcut in the current list. */
1661 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1662
1663 /* If we got a shortcut from the current list, or a "universal"
1664 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1665 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1666 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1667 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1668 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001669 input == NANO_CUT_KEY ||
1670#ifndef NANO_SMALL
1671 input == NANO_NEXTWORD_KEY ||
1672#endif
1673 (*meta_key == TRUE && (
1674#ifndef NANO_SMALL
1675 input == NANO_PREVWORD_KEY ||
1676#endif
1677 input == NANO_VERBATIM_KEY)));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001678
1679 /* Set s_or_t to TRUE if we got a shortcut. */
1680 *s_or_t = have_shortcut;
1681
1682 if (allow_funcs) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001683 /* If we got a character, and it isn't a shortcut or toggle,
1684 * it's a normal text character. Display the warning if we're
1685 * in view mode, or add the character to the input buffer if
1686 * we're not. */
1687 if (input != ERR && *s_or_t == FALSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001688 /* If we're using restricted mode, the filename isn't blank,
1689 * and we're at the "Write File" prompt, disable text
1690 * input. */
1691 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1692 currshortcut != writefile_list) {
1693 kbinput_len++;
1694 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1695 sizeof(int));
1696 kbinput[kbinput_len - 1] = input;
1697 }
1698 }
1699
1700 /* If we got a shortcut, or if there aren't any other characters
1701 * waiting after the one we read in, we need to display all the
1702 * characters in the input buffer if it isn't empty. */
1703 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1704 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001705
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001706 /* Display all the characters in the input buffer at
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001707 * once, filtering out control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001708 char *output = charalloc(kbinput_len + 1);
1709 size_t i;
1710 bool got_enter;
1711 /* Whether we got the Enter key. */
1712
1713 for (i = 0; i < kbinput_len; i++)
1714 output[i] = (char)kbinput[i];
1715 output[i] = '\0';
1716
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00001717 do_statusbar_output(output, kbinput_len, &got_enter,
1718 FALSE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001719
1720 free(output);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001721
1722 /* Empty the input buffer. */
1723 kbinput_len = 0;
1724 free(kbinput);
1725 kbinput = NULL;
1726 }
1727 }
1728
1729 if (have_shortcut) {
1730 switch (input) {
1731 /* Handle the "universal" statusbar prompt shortcuts. */
1732 case NANO_REFRESH_KEY:
1733 total_refresh();
1734 break;
1735 case NANO_HOME_KEY:
1736 do_statusbar_home();
1737 break;
1738 case NANO_END_KEY:
1739 do_statusbar_end();
1740 break;
1741 case NANO_FORWARD_KEY:
1742 do_statusbar_right();
1743 break;
1744 case NANO_BACK_KEY:
1745 do_statusbar_left();
1746 break;
1747 case NANO_BACKSPACE_KEY:
1748 /* If we're using restricted mode, the filename
1749 * isn't blank, and we're at the "Write File"
1750 * prompt, disable Backspace. */
1751 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1752 currshortcut != writefile_list)
1753 do_statusbar_backspace();
1754 break;
1755 case NANO_DELETE_KEY:
1756 /* If we're using restricted mode, the filename
1757 * isn't blank, and we're at the "Write File"
1758 * prompt, disable Delete. */
1759 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1760 currshortcut != writefile_list)
1761 do_statusbar_delete();
1762 break;
1763 case NANO_CUT_KEY:
1764 /* If we're using restricted mode, the filename
1765 * isn't blank, and we're at the "Write File"
1766 * prompt, disable Cut. */
1767 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1768 currshortcut != writefile_list)
1769 do_statusbar_cut_text();
1770 break;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001771#ifndef NANO_SMALL
1772 case NANO_NEXTWORD_KEY:
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001773 do_statusbar_next_word(FALSE);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001774 break;
1775 case NANO_PREVWORD_KEY:
1776 if (*meta_key == TRUE)
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001777 do_statusbar_prev_word(FALSE);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001778 break;
1779#endif
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001780 case NANO_VERBATIM_KEY:
1781 if (*meta_key == TRUE) {
1782 /* If we're using restricted mode, the filename
1783 * isn't blank, and we're at the "Write File"
1784 * prompt, disable verbatim input. */
1785 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001786 currshortcut != writefile_list) {
1787 bool got_enter;
1788 /* Whether we got the Enter key. */
1789
1790 do_statusbar_verbatim_input(&got_enter);
1791
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001792 /* If we got the Enter key, set input to the
1793 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001794 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001795 if (got_enter) {
1796 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001797 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001798 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001799 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001800 break;
1801 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001802 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001803 * ran_func to TRUE if we try to run their associated
1804 * functions and setting finished to TRUE to indicate
1805 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001806 * functions. */
1807 default:
1808 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001809 *ran_func = TRUE;
1810 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001811 s->func();
1812 }
1813 *finished = TRUE;
1814 }
1815 }
1816 }
1817
1818 return input;
1819}
1820
1821#ifndef DISABLE_MOUSE
1822bool do_statusbar_mouse(void)
1823{
1824 /* FIXME: If we clicked on a location in the statusbar, the cursor
1825 * should move to the location we clicked on. This functionality
1826 * should be in this function. */
1827 int mouse_x, mouse_y;
1828 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1829}
1830#endif
1831
1832void do_statusbar_home(void)
1833{
1834#ifndef NANO_SMALL
1835 if (ISSET(SMART_HOME)) {
1836 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001837
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001838 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001839
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001840 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001841 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001842 statusbar_x = 0;
1843 } else
1844#endif
1845 statusbar_x = 0;
1846}
1847
1848void do_statusbar_end(void)
1849{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001850 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001851}
1852
1853void do_statusbar_right(void)
1854{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001855 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001856 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001857}
1858
1859void do_statusbar_left(void)
1860{
1861 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001862 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001863}
1864
1865void do_statusbar_backspace(void)
1866{
1867 if (statusbar_x > 0) {
1868 do_statusbar_left();
1869 do_statusbar_delete();
1870 }
1871}
1872
1873void do_statusbar_delete(void)
1874{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001875 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001876 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1877 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001878 size_t line_len = strlen(answer + statusbar_x);
1879
1880 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001881
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001882 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001883 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001884 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001885
1886 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001887 }
1888}
1889
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +00001890/* Move text from the statusbar prompt into oblivion. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001891void do_statusbar_cut_text(void)
1892{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001893 assert(answer != NULL);
1894
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001895#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001896 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001897 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001898 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001899#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001900 null_at(&answer, 0);
1901 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001902#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001903 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001904#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001905}
1906
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001907#ifndef NANO_SMALL
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001908/* Move to the next word at the statusbar prompt. If allow_punct is
1909 * TRUE, treat punctuation as part of a word. Return TRUE if we started
1910 * on a word, and FALSE otherwise. */
1911bool do_statusbar_next_word(bool allow_punct)
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001912{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001913 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001914 int char_mb_len;
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001915 bool started_on_word = FALSE;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001916
1917 assert(answer != NULL);
1918
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001919 char_mb = charalloc(mb_cur_max());
1920
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001921 /* Move forward until we find the character after the last letter of
1922 * the current word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001923 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001924 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1925 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001926
1927 /* If we've found it, stop moving forward through the current
1928 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001929 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001930 break;
1931
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001932 /* If we haven't found it, then we've started on a word, so set
1933 * started_on_word to TRUE. */
1934 started_on_word = TRUE;
1935
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001936 statusbar_x += char_mb_len;
1937 }
1938
1939 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001940 if (answer[statusbar_x] != '\0')
1941 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001942
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001943 while (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001944 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1945 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001946
1947 /* If we've found it, stop moving forward through the current
1948 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001949 if (is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001950 break;
1951
1952 statusbar_x += char_mb_len;
1953 }
1954
1955 free(char_mb);
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001956
1957 /* Return whether we started on a word. */
1958 return started_on_word;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001959}
1960
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001961/* Move to the previous word at the statusbar prompt. If allow_punct is
1962 * TRUE, treat punctuation as part of a word. Return TRUE if we started
1963 * on a word, and FALSE otherwise. */
1964bool do_statusbar_prev_word(bool allow_punct)
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001965{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001966 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001967 int char_mb_len;
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001968 bool begin_line = FALSE, started_on_word = FALSE;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001969
1970 assert(answer != NULL);
1971
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001972 char_mb = charalloc(mb_cur_max());
1973
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001974 /* Move backward until we find the character before the first letter
1975 * of the current word. */
1976 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001977 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1978 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001979
1980 /* If we've found it, stop moving backward through the current
1981 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001982 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001983 break;
1984
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001985 /* If we haven't found it, then we've started on a word, so set
1986 * started_on_word to TRUE. */
1987 started_on_word = TRUE;
1988
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001989 if (statusbar_x == 0)
1990 begin_line = TRUE;
1991 else
1992 statusbar_x = move_mbleft(answer, statusbar_x);
1993 }
1994
1995 /* Move backward until we find the last letter of the previous
1996 * word. */
1997 if (statusbar_x == 0)
1998 begin_line = TRUE;
1999 else
2000 statusbar_x = move_mbleft(answer, statusbar_x);
2001
2002 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002003 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
2004 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002005
2006 /* If we've found it, stop moving backward through the current
2007 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002008 if (is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002009 break;
2010
2011 if (statusbar_x == 0)
2012 begin_line = TRUE;
2013 else
2014 statusbar_x = move_mbleft(answer, statusbar_x);
2015 }
2016
2017 /* If we've found it, move backward until we find the character
2018 * before the first letter of the previous word. */
2019 if (!begin_line) {
2020 if (statusbar_x == 0)
2021 begin_line = TRUE;
2022 else
2023 statusbar_x = move_mbleft(answer, statusbar_x);
2024
2025 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002026 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2027 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002028
2029 /* If we've found it, stop moving backward through the
2030 * current line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002031 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002032 break;
2033
2034 if (statusbar_x == 0)
2035 begin_line = TRUE;
2036 else
2037 statusbar_x = move_mbleft(answer, statusbar_x);
2038 }
2039
2040 /* If we've found it, move forward to the first letter of the
2041 * previous word. */
2042 if (!begin_line)
2043 statusbar_x += char_mb_len;
2044 }
2045
2046 free(char_mb);
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002047
2048 /* Return whether we started on a word. */
2049 return started_on_word;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002050}
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002051#endif /* !NANO_SMALL */
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002052
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002053void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002054{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002055 int *kbinput;
2056 size_t kbinput_len, i;
2057 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002058
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002059 *got_enter = FALSE;
2060
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002061 /* Read in all the verbatim characters. */
2062 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2063
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002064 /* Display all the verbatim characters at once, not filtering out
2065 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002066 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002067
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002068 for (i = 0; i < kbinput_len; i++)
2069 output[i] = (char)kbinput[i];
2070 output[i] = '\0';
2071
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002072 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002073
2074 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002075}
2076
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +00002077/* The user typed ouuput_len multibyte characters. Add them to the
2078 * statusbar prompt, setting got_enter to TRUE if we get a newline, and
2079 * filtering out all control characters if allow_cntrls is TRUE. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002080void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002081 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002082{
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002083 size_t answer_len, i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002084 char *char_buf = charalloc(mb_cur_max());
2085 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002086
2087 assert(answer != NULL);
2088
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002089 answer_len = strlen(answer);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002090 *got_enter = FALSE;
2091
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002092 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002093 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2094 * since they're control characters. */
2095 if (allow_cntrls) {
2096 /* Null to newline, if needed. */
2097 if (output[i] == '\0')
2098 output[i] = '\n';
2099 /* Newline to Enter, if needed. */
2100 else if (output[i] == '\n') {
2101 /* Set got_enter to TRUE to indicate that we got the
2102 * Enter key, put back the rest of the characters in
2103 * output so that they can be parsed and output again,
2104 * and get out. */
2105 *got_enter = TRUE;
2106 unparse_kbinput(output + i, output_len - i);
2107 return;
2108 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002109 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002110
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002111 /* Interpret the next multibyte character. If it's an invalid
2112 * multibyte character, interpret it as though it's a byte
2113 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002114 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002115
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002116 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002117
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002118 /* If allow_cntrls is FALSE, filter out a control character. */
2119 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2120 continue;
2121
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002122 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002123 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002124
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002125 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002126
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002127 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002128 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002129 char_buf_len);
David Lawrence Ramsey7a3f49c2005-06-22 00:24:11 +00002130 strncpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002131 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002132
2133 do_statusbar_right();
2134 }
2135
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002136 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002137}
2138
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002139/* Return the placewewant associated with current_x, i.e, the zero-based
2140 * column position of the cursor. The value will be no smaller than
2141 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002142size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002143{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002144 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002145}
2146
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002147/* actual_x() gives the index in str of the character displayed at
2148 * column xplus. That is, actual_x() is the largest value such that
2149 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2150size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002151{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002152 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002153 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002154 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002155 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002156
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002157 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002158
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002159 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002160 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002161
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002162 if (length > xplus)
2163 break;
2164
2165 i += str_len;
2166 str += str_len;
2167 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002168
Chris Allegretta6df90f52002-07-19 01:08:59 +00002169 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002170}
2171
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002172/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002173 * columns wide are the first size characters of str? */
2174size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002175{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002176 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002177 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002178
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002179 if (size == 0)
2180 return 0;
2181
2182 assert(str != NULL);
2183
2184 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002185 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002186
2187 str += str_len;
2188
2189 if (size <= str_len)
2190 break;
2191
2192 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002193 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002194
Chris Allegretta6df90f52002-07-19 01:08:59 +00002195 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002196}
2197
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002198/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002199size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002200{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002201 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002202}
2203
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002204void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002206 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002207}
2208
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002209void blank_topbar(void)
2210{
2211 if (!ISSET(MORE_SPACE))
2212 mvwaddstr(topwin, 1, 0, hblank);
2213}
2214
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002215void blank_edit(void)
2216{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002217 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002218 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002219 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002220}
2221
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002222void blank_statusbar(void)
2223{
2224 mvwaddstr(bottomwin, 0, 0, hblank);
2225}
2226
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002227void blank_bottombars(void)
2228{
2229 if (!ISSET(NO_HELP)) {
2230 mvwaddstr(bottomwin, 1, 0, hblank);
2231 mvwaddstr(bottomwin, 2, 0, hblank);
2232 }
2233}
2234
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002235void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002236{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002237 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002238 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002239
2240 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002241 blank_statusbar();
2242 wnoutrefresh(bottomwin);
2243 reset_cursor();
2244 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002245 }
2246}
2247
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002248/* Convert buf into a string that can be displayed on screen. The
2249 * caller wants to display buf starting with column start_col, and
2250 * extending for at most len columns. start_col is zero-based. len is
2251 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002252 * string is dynamically allocated, and should be freed. If dollars is
2253 * TRUE, the caller might put "$" at the beginning or end of the line if
2254 * it's too long. */
2255char *display_string(const char *buf, size_t start_col, size_t len, bool
2256 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002257{
2258 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002259 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002260 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002261 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002262 size_t alloc_len;
2263 /* The length of memory allocated for converted. */
2264 char *converted;
2265 /* The string we return. */
2266 size_t index;
2267 /* Current position in converted. */
2268
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002269 char *buf_mb = charalloc(mb_cur_max());
2270 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002271 bool bad_char;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002272
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002273 /* If dollars is TRUE, make room for the "$" at the end of the
2274 * line. */
2275 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2276 len--;
2277
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002278 if (len == 0)
2279 return mallocstrcpy(NULL, "");
2280
2281 start_index = actual_x(buf, start_col);
2282 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002283
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002284 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002285
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002286 /* Allocate enough space for the entire line, accounting for a
2287 * trailing multibyte character and/or tab. */
2288 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002289
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002290 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002291 index = 0;
2292
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002293 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002294 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002295 /* We don't display all of buf[start_index] since it starts to
2296 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002297 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2298 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002299
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002300 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002301 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002302 char *ctrl_buf_mb = charalloc(mb_cur_max());
2303 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002304
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002305 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2306 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002307
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002308 for (i = 0; i < ctrl_buf_mb_len; i++)
2309 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002310
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002311 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002312
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002313 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002314
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002315 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002316 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002317 }
2318#ifdef NANO_WIDE
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002319 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002320 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002321 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002322
2323 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002324 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002325#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002326 }
2327
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002328 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002329 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2330 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002331
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002332 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002333#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002334 if (ISSET(WHITESPACE_DISPLAY)) {
2335 int i;
2336
2337 for (i = 0; i < whitespace_len[0]; i++)
2338 converted[index++] = whitespace[i];
2339 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002340#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002341 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002342 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002343 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002344 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345 start_col++;
2346 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002347 /* If buf contains a control character, interpret it. If it
2348 * contains an invalid multibyte control character, interpret
2349 * that character as though it's a normal control character. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002350 } else if (is_cntrl_mbchar(buf_mb)) {
2351 char *ctrl_buf_mb = charalloc(mb_cur_max());
2352 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002353
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002354 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002355 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002356
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002357 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2358 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002359
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002360 for (i = 0; i < ctrl_buf_mb_len; i++)
2361 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002362
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002363 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002364
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002365 free(ctrl_buf_mb);
2366 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002367#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002368 if (ISSET(WHITESPACE_DISPLAY)) {
2369 int i;
2370
2371 for (i = whitespace_len[0]; i < whitespace_len[0] +
2372 whitespace_len[1]; i++)
2373 converted[index++] = whitespace[i];
2374 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002375#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002376 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002377 start_col++;
2378 } else {
2379 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002380
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002381#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002382 /* If buf contains an invalid multibyte non-control
2383 * character, interpret that character as though it's a
2384 * normal non-control character. */
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002385 if (ISSET(USE_UTF8) && bad_char) {
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002386 char *bad_buf_mb;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002387 int bad_buf_mb_len;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002388
David Lawrence Ramsey4c6956b2005-01-12 04:32:43 +00002389 bad_buf_mb = make_mbchar((unsigned char)*buf_mb,
David Lawrence Ramseyf0195a82005-03-14 18:47:21 +00002390 &bad_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002391
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002392 for (i = 0; i < bad_buf_mb_len; i++)
2393 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002394
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002395 start_col += mbwidth(bad_buf_mb);
2396
2397 free(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002398 } else {
2399#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002400 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002401 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002402
2403 start_col += mbwidth(buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002404#ifdef NANO_WIDE
2405 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002406#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002407 }
2408
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002409 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002410 }
2411
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002412 free(buf_mb);
2413
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002414 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002415 converted[index] = '\0';
2416
2417 /* Make sure converted takes up no more than len columns. */
2418 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002419 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002420
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002421 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002422}
2423
Chris Allegretta7662c862003-01-13 01:35:15 +00002424/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002425 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002426 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002427 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002428 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002429void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002430{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002431 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002432 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002433
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002434 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002435
Chris Allegrettab3655b42001-10-22 03:15:31 +00002436 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002437 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002438
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00002439 mvwaddnstr(bottomwin, 0, 0, buf, actual_x(buf, COLS - 2));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002440 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002441
2442 if (COLS > 1)
2443 waddch(bottomwin, x_real < wid ? ' ' : '$');
2444 if (COLS > 2) {
2445 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002446 char *expanded = display_string(inputbuf, page_start, wid,
2447 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002448
2449 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002450 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002451
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002452 waddstr(bottomwin, expanded);
2453 free(expanded);
2454 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2455 } else
2456 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002457
Chris Allegrettab3655b42001-10-22 03:15:31 +00002458 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002459}
2460
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002461/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002462 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002463int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002464#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002465 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002466#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002467 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002468#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002469 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002470#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002471 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002472{
2473 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002474 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002475 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002476#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002477 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002478 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002479#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002480#ifndef NANO_SMALL
2481 char *history = NULL;
2482 /* The current history string. */
2483 char *magichistory = NULL;
2484 /* The temporary string typed at the bottom of the history, if
2485 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002486#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002487 int last_kbinput = ERR;
2488 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002489 size_t complete_len = 0;
2490 /* The length of the original string that we're trying to
2491 * tab complete, if any. */
2492#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002493#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002494
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002495 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002496 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002497
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002498 /* Only put statusbar_x at the end of the string if it's
2499 * uninitialized, if it would be past the end of curranswer, or if
2500 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2501 * the cursor position stays at the same place if a prompt-changing
2502 * toggle is pressed. */
2503 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2504 resetstatuspos)
2505 statusbar_x = curranswer_len;
2506
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002507 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002508
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002509 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002510
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002511 /* Refresh the edit window and the statusbar before getting
2512 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002513 wnoutrefresh(edit);
2514 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002515
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002516 /* If we're using restricted mode, we aren't allowed to change the
2517 * name of a file once it has one because that would allow writing
2518 * to files not specified on the command line. In this case,
2519 * disable all keys that would change the text if the filename isn't
2520 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002521 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002522 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002523 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002524
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002525 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002526
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002527#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002528 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002529 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002530#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002531
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002532 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002533 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002534#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002535#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002536 if (history_list != NULL) {
2537 if (last_kbinput != NANO_TAB_KEY)
2538 complete_len = strlen(answer);
2539
2540 if (complete_len > 0) {
2541 answer = mallocstrcpy(answer,
2542 get_history_completion(history_list,
2543 answer, complete_len));
2544 statusbar_x = strlen(answer);
2545 }
2546 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002547#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002548 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002549 answer = input_tab(answer, &statusbar_x, &tabbed,
2550 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002551#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002552 break;
2553 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002554#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002555 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002556 /* If we're scrolling up at the bottom of the
2557 * history list, answer isn't blank, and
2558 * magichistory isn't set, save answer in
2559 * magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002560 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002561 answer[0] != '\0' && magichistory == NULL)
2562 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002563
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002564 /* Get the older search from the history list and
2565 * save it in answer. If there is no older search,
2566 * don't do anything. */
2567 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002568 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002569 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002570 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002571 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002572
2573 /* This key has a shortcut list entry when it's used
2574 * to move to an older search, which means that
2575 * finished has been set to TRUE. Set it back to
2576 * FALSE here, so that we aren't kicked out of the
2577 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002578 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002579 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002580#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002581 break;
2582 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002583#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002584 if (history_list != NULL) {
2585 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002586 * save it in answer. If there is no newer search,
2587 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002588 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002589 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002590 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002591 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002592 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002593
2594 /* If, after scrolling down, we're at the bottom of
2595 * the history list, answer is blank, and
2596 * magichistory is set, save magichistory in
2597 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002598 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002599 answer[0] == '\0' && magichistory != NULL) {
2600 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002601 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002602 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002603 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002604#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002605 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002606 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002607
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002608 /* If we have a shortcut with an associated function, break out
2609 * if we're finished after running or trying to run the
2610 * function. */
2611 if (finished)
2612 break;
2613
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002614#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002615 last_kbinput = kbinput;
2616#endif
2617
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002618 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002619 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002620 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002621
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002622#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002623 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002624 if (magichistory != NULL)
2625 free(magichistory);
2626#endif
2627
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002628 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002629 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002630 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002631 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002632 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002633
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002634 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002635}
2636
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002637/* Ask a question on the statusbar. Answer will be stored in answer
2638 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002639 * otherwise, the valid shortcut key caught. curranswer is any editable
2640 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002641 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002642 * The allow_tabs parameter indicates whether we should allow tabs to be
2643 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002644int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002645#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002646 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002647#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002648 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002649{
2650 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002651 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002652 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002653#ifndef DISABLE_TABCOMP
2654 bool list = FALSE;
2655#endif
2656
2657 bottombars(s);
2658
2659 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002660 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002661 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002662 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002663
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002664 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002665#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002666 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002667#endif
2668 s
2669#ifndef DISABLE_TABCOMP
2670 , &list
2671#endif
2672 );
2673 free(foo);
2674 resetstatuspos = FALSE;
2675
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002676 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002677 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002678 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002679 resetstatuspos = TRUE;
2680 break;
2681 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002682 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002683 resetstatuspos = TRUE;
2684 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002685 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002686
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002687 blank_statusbar();
David Lawrence Ramseycd0210f2005-06-18 14:05:21 +00002688 wnoutrefresh(bottomwin);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002689
2690#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002691 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002692#endif
2693
2694#ifndef DISABLE_TABCOMP
David Lawrence Ramsey90d505c2005-06-18 22:33:55 +00002695 /* If we've done tab completion, there might be a list of filename
2696 * matches on the edit window at this point. Make sure that they're
2697 * cleared off. */
2698 if (list)
2699 edit_refresh();
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002700#endif
2701
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002702 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002703}
2704
2705void statusq_abort(void)
2706{
2707 resetstatuspos = TRUE;
2708}
2709
Chris Allegrettaf717f982003-02-13 22:25:01 +00002710void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002711{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002712 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002713 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002714 size_t verlen = strlenpt(VERMSG) + 1;
2715 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002716 const char *prefix;
2717 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2718 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002719 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002720 const char *state;
2721 /* "Modified", "View", or spaces the length of "Modified".
2722 * Tells the state of this buffer. */
2723 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002724 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002725 char *exppath = NULL;
2726 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002727 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002728 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002729 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002730 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002731
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002732 assert(path != NULL || filename != NULL);
2733 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002734
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002735 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002736 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002737
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002738 if (COLS <= 5 || COLS - 5 < verlen)
2739 space = 0;
2740 else {
2741 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002742 /* Reserve 2/3 of the screen plus one column for after the
2743 * version message. */
2744 if (space < COLS - (COLS / 3) + 1)
2745 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002746 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002747
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002748 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002749 /* The version message should only take up 1/3 of the screen
2750 * minus one column. */
David Lawrence Ramsey8d5beb52005-06-21 20:37:04 +00002751 mvwaddnstr(topwin, 0, 2, VERMSG, actual_x(VERMSG,
2752 (COLS / 3) - 3));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002753 waddstr(topwin, " ");
2754 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002756 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002757 state = _("Modified");
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002758 else if (ISSET(VIEW_MODE))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002759 state = _("View");
2760 else {
2761 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002762 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002763 state = &hblank[COLS - statelen];
2764 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002765 statelen = strnlenpt(state, COLS);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002766
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002767 /* We need a space before state. */
2768 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2769 statelen++;
2770
2771 assert(space >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002772
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002773 if (space == 0 || statelen >= space)
2774 goto the_end;
2775
2776#ifndef DISABLE_BROWSER
2777 if (path != NULL)
2778 prefix = _("DIR:");
2779 else
2780#endif
2781 if (filename[0] == '\0') {
2782 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002783 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002784 } else
2785 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002786
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002787 assert(statelen < space);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002788
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002789 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002790
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002791 /* If newfie is FALSE, we need a space after prefix. */
2792 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 prefixlen++;
2794
2795 if (path == NULL)
2796 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002797 if (space >= prefixlen + statelen)
2798 space -= prefixlen + statelen;
2799 else
2800 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 /* space is now the room we have for the file name. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002802
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002803 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002804 size_t lenpt = strlenpt(path), start_col;
2805
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002807
2808 if (dots) {
2809 start_col = lenpt - space + 3;
2810 space -= 3;
2811 } else
2812 start_col = 0;
2813
2814 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002815 }
2816
2817 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002818 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2819 /* The length of the expanded filename. */
2820
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002821 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002822 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002823 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002824 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002825 assert(strlenpt(prefix) + 1 == prefixlen);
2826
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002827 waddch(topwin, ' ');
2828 waddstr(topwin, exppath);
2829 }
2830 } else {
2831 /* We will say something like "File: ...ename". */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002832 waddnstr(topwin, prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002833 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002834 goto the_end;
2835 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002836 waddnstr(topwin, "...", space + 3);
2837 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002838 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002839 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002840 }
2841
2842 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002843 free(exppath);
2844
2845 if (COLS <= 1 || statelen >= COLS - 1)
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002846 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002847 else {
2848 assert(COLS - statelen - 2 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002849
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002850 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002851 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
2852 actual_x(state, statelen));
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002853 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002854
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002855 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002856
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002857 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002858 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002859 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002860}
2861
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002862/* If modified is not already set, set it and update titlebar. */
2863void set_modified(void)
2864{
2865 if (!ISSET(MODIFIED)) {
2866 SET(MODIFIED);
2867 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002868 }
2869}
2870
2871void statusbar(const char *msg, ...)
2872{
2873 va_list ap;
2874
2875 va_start(ap, msg);
2876
2877 /* Curses mode is turned off. If we use wmove() now, it will muck
2878 * up the terminal settings. So we just use vfprintf(). */
2879 if (curses_ended) {
2880 vfprintf(stderr, msg, ap);
2881 va_end(ap);
2882 return;
2883 }
2884
2885 /* Blank out the line. */
2886 blank_statusbar();
2887
2888 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002889 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002890 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002891#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002892 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002893
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002894 UNSET(WHITESPACE_DISPLAY);
2895#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002896 bar = charalloc(mb_cur_max() * (COLS - 3));
2897 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002898 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002899 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002900#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2901 if (old_whitespace)
2902 SET(WHITESPACE_DISPLAY);
2903#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002904 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002905 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002906 start_x = (COLS - foo_len - 4) / 2;
2907
2908 wmove(bottomwin, 0, start_x);
2909 wattron(bottomwin, A_REVERSE);
2910
2911 waddstr(bottomwin, "[ ");
2912 waddstr(bottomwin, foo);
2913 free(foo);
2914 waddstr(bottomwin, " ]");
2915 wattroff(bottomwin, A_REVERSE);
2916 wnoutrefresh(bottomwin);
2917 reset_cursor();
2918 wrefresh(edit);
2919 /* Leave the cursor at its position in the edit window, not
2920 * in the statusbar. */
2921 }
2922
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002923 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002924
2925 /* If we're doing quick statusbar blanking, and constant cursor
2926 * position display is off, blank the statusbar after only one
2927 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2928 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002929 statusblank =
2930#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002931 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002932#endif
2933 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002934}
2935
Chris Allegretta6232d662002-05-12 19:52:15 +00002936void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002937{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002938 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002939
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002940 if (ISSET(NO_HELP))
2941 return;
2942
Chris Allegretta6232d662002-05-12 19:52:15 +00002943 if (s == main_list) {
2944 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002945
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002946 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002947 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002948 slen = length_of_list(s);
2949
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002950 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002951 if (slen > MAIN_VISIBLE)
2952 slen = MAIN_VISIBLE;
2953 }
2954
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002955 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002956 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002957 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002958
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002959 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002960
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002961 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002962 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002963 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002964
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002965 /* Yucky sentinel values that we can't handle a better way. */
2966 if (s->ctrlval == NANO_CONTROL_SPACE)
2967 strcpy(foo, "^ ");
2968 else if (s->ctrlval == NANO_CONTROL_8)
2969 strcpy(foo, "^?");
2970 /* Normal values. Assume that the shortcut has an equivalent
2971 * control key, meta key sequence, or both. */
2972 else if (s->ctrlval != NANO_NO_KEY)
2973 sprintf(foo, "^%c", s->ctrlval + 64);
2974 else if (s->metaval != NANO_NO_KEY)
2975 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00002976
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002977 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002978
2979 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002980 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002981 }
2982
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002983 wnoutrefresh(bottomwin);
2984 reset_cursor();
2985 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002986}
2987
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002988/* Write a shortcut key to the help area at the bottom of the window.
2989 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2990 * to write at most len characters, even if len is very small and
2991 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2992 * the whole string! We do not bother padding the entry with blanks. */
2993void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002994{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002995 size_t keystroke_len = strlenpt(keystroke) + 1;
2996
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00002997 assert(keystroke != NULL && desc != NULL);
2998
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002999 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003000 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003001 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003002
3003 if (len > keystroke_len)
3004 len -= keystroke_len;
3005 else
3006 len = 0;
3007
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003008 if (len > 0) {
3009 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003010 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003011 }
3012}
3013
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003014/* nano scrolls horizontally within a line in chunks. This function
3015 * returns the column number of the first character displayed in the
3016 * window when the cursor is at the given column. Note that
3017 * 0 <= column - get_page_start(column) < COLS. */
3018size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003019{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003020 assert(COLS > 0);
David Lawrence Ramsey3b2fdb02005-06-28 07:16:13 +00003021
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003022 if (column == 0 || column < COLS - 1)
3023 return 0;
3024 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003025 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003026 else if (COLS > 2)
3027 return column - (COLS - 2);
3028 else
3029 return column - (COLS - 1);
3030 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003031}
3032
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003033/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003034 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003035void reset_cursor(void)
3036{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003037 /* If we haven't opened any files yet, put the cursor in the top
3038 * left corner of the edit window and get out. */
3039 if (edittop == NULL || current == NULL) {
3040 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003041 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003042 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003043
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003044 current_y = current->lineno - edittop->lineno;
3045 if (current_y < editwinrows) {
3046 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003047 wmove(edit, current_y, x - get_page_start(x));
3048 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003049}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003050
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003051/* edit_add() takes care of the job of actually painting a line into the
3052 * edit window. fileptr is the line to be painted, at row yval of the
3053 * window. converted is the actual string to be written to the window,
3054 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003055 * characters. start is the column number of the first character of
3056 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003057 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003058void edit_add(const filestruct *fileptr, const char *converted, int
3059 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003060{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003061#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003062 size_t startpos = actual_x(fileptr->data, start);
3063 /* The position in fileptr->data of the leftmost character
3064 * that displays at least partially on the window. */
3065 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3066 /* The position in fileptr->data of the first character that is
3067 * completely off the window to the right.
3068 *
3069 * Note that endpos might be beyond the null terminator of the
3070 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003071#endif
3072
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003073 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003074 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003075
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003076 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003077 * just the text that needs it). */
3078 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003079
Chris Allegretta7dd77682001-12-08 19:52:28 +00003080#ifdef ENABLE_COLOR
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003081 if (colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003082 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003083
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003084 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3085 int x_start;
3086 /* Starting column for mvwaddnstr. Zero-based. */
3087 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003088 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003089 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003090 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003091 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003092 regmatch_t startmatch;
3093 /* Match position for start_regex. */
3094 regmatch_t endmatch;
3095 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003096
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003097 if (tmpcolor->bright)
3098 wattron(edit, A_BOLD);
3099 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003100 /* Two notes about regexec(). Return value 0 means there is
3101 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003102 * after the match. */
3103
3104 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003105 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003106 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003107
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003108 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003109 * last match. Even though two matches may overlap, we
3110 * want to ignore them, so that we can highlight
3111 * C-strings correctly. */
3112 while (k < endpos) {
3113 /* Note the fifth parameter to regexec(). It says
3114 * not to match the beginning-of-line character
3115 * unless k is 0. If regexec() returns REG_NOMATCH,
3116 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003117 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003118 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003119 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003121 /* Translate the match to the beginning of the
3122 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003123 startmatch.rm_so += k;
3124 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003125 if (startmatch.rm_so == startmatch.rm_eo) {
3126 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003127 statusbar(
3128 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003129 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003130 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003131 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003132 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003133 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003134 x_start = strnlenpt(fileptr->data,
3135 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003136
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003137 index = actual_x(converted, x_start);
3138
3139 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003140 strnlenpt(fileptr->data,
3141 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003142
3143 assert(0 <= x_start && 0 <= paintlen);
3144
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003145 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003146 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003147 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003148 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003149 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003150 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003151 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003152 * First, we have to see if the beginning of the line is
3153 * colored by a start on an earlier line, and an end on
3154 * this line or later.
3155 *
3156 * We find the first line before fileptr matching the
3157 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003158 * end, then go to step two. Otherwise, find the next
3159 * line after start_line matching the end. If that line
3160 * is not before fileptr, then paint the beginning of
3161 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003162 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003163 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003164 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003165 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003166 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003167
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003169 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003170 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003171 /* If there is an end on this line, there is no need
3172 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003173 if (regexec(tmpcolor->end, start_line->data, 0,
3174 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003175 goto step_two;
3176 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003177 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003178 /* No start found, so skip to the next step. */
3179 if (start_line == NULL)
3180 goto step_two;
3181 /* Now start_line is the first line before fileptr
3182 * containing a start match. Is there a start on this
3183 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003184 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003185 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003186 start_col += startmatch.rm_so;
3187 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003188 if (regexec(tmpcolor->end, start_line->data +
3189 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003190 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003191 REG_NOTBOL) == REG_NOMATCH)
3192 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 break;
3194 start_col++;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003195 if (regexec(&tmpcolor->start, start_line->data +
3196 start_col, 1, &startmatch,
3197 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003198 /* No later start on this line. */
3199 goto step_two;
3200 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003201 /* Indeed, there is a start not followed on this line by
3202 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003203
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003204 /* We have already checked that there is no end before
3205 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003206 * the start at all? We don't paint unterminated
3207 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003208 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003209 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003210 regexec(tmpcolor->end, end_line->data, 1,
3211 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003212 end_line = end_line->next;
3213
3214 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003215 if (end_line == NULL || (end_line == fileptr &&
3216 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003217 goto step_two;
3218
3219 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003220 if (end_line != fileptr)
3221 /* If the start of fileptr is on a different line
3222 * from the end, paintlen is -1, meaning that
3223 * everything on the line gets painted. */
3224 paintlen = -1;
3225 else
3226 /* Otherwise, paintlen is the expanded location of
3227 * the end of the match minus the expanded location
3228 * of the beginning of the page. */
3229 paintlen = actual_x(converted,
3230 strnlenpt(fileptr->data, endmatch.rm_eo) -
3231 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003232
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003233 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003234
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003235 step_two:
3236 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003237 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003238
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003239 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003240 if (regexec(&tmpcolor->start,
3241 fileptr->data + start_col, 1, &startmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003242 (start_col == 0) ? 0 :
3243 REG_NOTBOL) == REG_NOMATCH ||
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003244 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003245 /* No more starts on this line. */
3246 break;
3247 /* Translate the match to be relative to the
3248 * beginning of the line. */
3249 startmatch.rm_so += start_col;
3250 startmatch.rm_eo += start_col;
3251
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003252 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003253 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003254 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003255 x_start = strnlenpt(fileptr->data,
3256 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003257
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003258 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003259
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003260 if (regexec(tmpcolor->end,
3261 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003262 (startmatch.rm_eo == 0) ? 0 :
3263 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003265 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003266 endmatch.rm_so += startmatch.rm_eo;
3267 endmatch.rm_eo += startmatch.rm_eo;
3268 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003269 * appear on this page, and is the match more
3270 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003271 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003272 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003273 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003274 strnlenpt(fileptr->data,
3275 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003276
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003277 assert(0 <= x_start && x_start < COLS);
3278
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003279 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003280 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003281 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003282 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003283 /* There is no end on this line. But we haven't
3284 * yet looked for one on later lines. */
3285 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003286
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003287 while (end_line != NULL &&
3288 regexec(tmpcolor->end, end_line->data,
3289 0, NULL, 0) == REG_NOMATCH)
3290 end_line = end_line->next;
3291
3292 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003293 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003294
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003295 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003296 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297 /* We painted to the end of the line, so
3298 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003299 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003300 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003301 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003303 }
3304 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003305
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003306 wattroff(edit, A_BOLD);
3307 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003308 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003309 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003310#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003311
Chris Allegretta7dd77682001-12-08 19:52:28 +00003312#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003313 if (ISSET(MARK_ISSET)
3314 && (fileptr->lineno <= mark_beginbuf->lineno
3315 || fileptr->lineno <= current->lineno)
3316 && (fileptr->lineno >= mark_beginbuf->lineno
3317 || fileptr->lineno >= current->lineno)) {
3318 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003319
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003320 const filestruct *top;
3321 /* Either current or mark_beginbuf, whichever is first. */
3322 size_t top_x;
3323 /* current_x or mark_beginx, corresponding to top. */
3324 const filestruct *bot;
3325 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003326 int x_start;
3327 /* Starting column for mvwaddnstr. Zero-based. */
3328 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003329 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003330 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003331 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003332 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003333
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003334 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003335
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003336 if (top->lineno < fileptr->lineno || top_x < startpos)
3337 top_x = startpos;
3338 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3339 bot_x = endpos;
3340
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003341 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003342 if (top_x < endpos && bot_x > startpos) {
3343 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003344
3345 /* x_start is the expanded location of the beginning of the
3346 * mark minus the beginning of the page. */
3347 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003348
3349 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003350 /* If the end of the mark is off the page, paintlen is
3351 * -1, meaning that everything on the line gets
3352 * painted. */
3353 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003354 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003355 /* Otherwise, paintlen is the expanded location of the
3356 * end of the mark minus the expanded location of the
3357 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003358 paintlen = strnlenpt(fileptr->data, bot_x) -
3359 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003360
3361 /* If x_start is before the beginning of the page, shift
3362 * paintlen x_start characters to compensate, and put
3363 * x_start at the beginning of the page. */
3364 if (x_start < 0) {
3365 paintlen += x_start;
3366 x_start = 0;
3367 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368
3369 assert(x_start >= 0 && x_start <= strlen(converted));
3370
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003371 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003372
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003373 if (paintlen > 0)
3374 paintlen = actual_x(converted + index, paintlen);
3375
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003376 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003377 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003378 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003379 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003380 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003381 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003382#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003383}
3384
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003385/* Just update one line in the edit buffer. This is basically a wrapper
3386 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003387 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003388 * If fileptr != current, then index is considered 0. The line will be
3389 * displayed starting with fileptr->data[index]. Likely args are
3390 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003391void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003392{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003393 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003394 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003395 char *converted;
3396 /* fileptr->data converted to have tabs and control characters
3397 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003398 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003399
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003400 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003401
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003402 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003403
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003404 /* We assume the line numbers are valid. Is that really true? */
3405 assert(line < 0 || line == check_linenumbers(fileptr));
3406
3407 if (line < 0 || line >= editwinrows)
3408 return;
3409
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003410 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003411 mvwaddstr(edit, line, 0, hblank);
3412
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003413 /* Next, convert variables that index the line to their equivalent
3414 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003415 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003416 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003417
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003418 /* Expand the line, replacing tabs with spaces, and control
3419 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003420 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003421
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003422 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003423 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003424 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003425
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003426 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003427 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003428 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003429 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003430}
3431
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003432/* Return a nonzero value if we need an update after moving
3433 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003434 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003435int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003436{
3437 return
3438#ifndef NANO_SMALL
3439 ISSET(MARK_ISSET) ||
3440#endif
3441 get_page_start(old_pww) != get_page_start(placewewant);
3442}
3443
3444/* Return a nonzero value if we need an update after moving vertically.
3445 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003446 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003447int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003448{
3449 return
3450#ifndef NANO_SMALL
3451 ISSET(MARK_ISSET) ||
3452#endif
3453 get_page_start(old_pww) != get_page_start(placewewant);
3454}
3455
3456/* Scroll the edit window in the given direction and the given number
3457 * of lines, and draw new lines on the blank lines left after the
3458 * scrolling. direction is the direction to scroll, either UP or DOWN,
3459 * and nlines is the number of lines to scroll. Don't redraw the old
3460 * topmost or bottommost line (where we assume current is) before
3461 * scrolling or draw the new topmost or bottommost line after scrolling
3462 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003463 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003464void edit_scroll(updown direction, int nlines)
3465{
3466 filestruct *foo;
3467 int i, scroll_rows = 0;
3468
3469 /* Scrolling less than one line or more than editwinrows lines is
3470 * redundant, so don't allow it. */
3471 if (nlines < 1 || nlines > editwinrows)
3472 return;
3473
3474 /* Move the top line of the edit window up or down (depending on the
3475 * value of direction) nlines lines. If there are fewer lines of
3476 * text than that left, move it to the top or bottom line of the
3477 * file (depending on the value of direction). Keep track of
3478 * how many lines we moved in scroll_rows. */
3479 for (i = nlines; i > 0; i--) {
3480 if (direction == UP) {
3481 if (edittop->prev == NULL)
3482 break;
3483 edittop = edittop->prev;
3484 scroll_rows--;
3485 } else {
3486 if (edittop->next == NULL)
3487 break;
3488 edittop = edittop->next;
3489 scroll_rows++;
3490 }
3491 }
3492
3493 /* Scroll the text on the screen up or down scroll_rows lines,
3494 * depending on the value of direction. */
3495 scrollok(edit, TRUE);
3496 wscrl(edit, scroll_rows);
3497 scrollok(edit, FALSE);
3498
3499 foo = edittop;
3500 if (direction != UP) {
3501 int slines = editwinrows - nlines;
3502 for (; slines > 0 && foo != NULL; slines--)
3503 foo = foo->next;
3504 }
3505
3506 /* And draw new lines on the blank top or bottom lines of the edit
3507 * window, depending on the value of direction. Don't draw the new
3508 * topmost or new bottommost line. */
3509 while (scroll_rows != 0 && foo != NULL) {
3510 if (foo->next != NULL)
3511 update_line(foo, 0);
3512 if (direction == UP)
3513 scroll_rows++;
3514 else
3515 scroll_rows--;
3516 foo = foo->next;
3517 }
3518}
3519
3520/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003521 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003522void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003523{
David Lawrence Ramsey54236802005-06-28 05:56:16 +00003524 bool do_refresh = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003525 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003526 const filestruct *foo;
3527
3528 /* If either old_current or current is offscreen, refresh the screen
3529 * and get out. */
3530 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3531 edittop->lineno + editwinrows || current->lineno <
3532 edittop->lineno || current->lineno >= edittop->lineno +
3533 editwinrows) {
3534 edit_refresh();
3535 return;
3536 }
3537
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003538 /* Update old_current and current if we're not on the first page
3539 * and/or we're not on the same page as before. If the mark is on,
3540 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003541 foo = old_current;
3542 while (foo != current) {
3543 if (do_refresh)
3544 update_line(foo, 0);
3545#ifndef NANO_SMALL
3546 if (!ISSET(MARK_ISSET))
3547#endif
3548 break;
3549 if (foo->lineno > current->lineno)
3550 foo = foo->prev;
3551 else
3552 foo = foo->next;
3553 }
3554 if (do_refresh)
3555 update_line(current, current_x);
3556}
3557
Chris Allegretta6df90f52002-07-19 01:08:59 +00003558/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003559void edit_refresh(void)
3560{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003561 if (current->lineno < edittop->lineno ||
3562 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003563 /* Note that edit_update() changes edittop so that it's in range
3564 * of current. Thus, when it then calls edit_refresh(), there
3565 * is no danger of getting an infinite loop. */
3566 edit_update(
3567#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003568 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003569#endif
3570 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003571 else {
3572 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003573 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003574
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003575#ifdef DEBUG
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00003576 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003577#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003578
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003579 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003580 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003581 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003582 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003583 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003584 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003585 }
3586 while (nlines < editwinrows) {
3587 mvwaddstr(edit, nlines, 0, hblank);
3588 nlines++;
3589 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003590 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003591 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003592 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003593}
3594
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003595/* A nice generic routine to update the edit buffer. We keep current in
3596 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003597void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003598{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003599 filestruct *foo = current;
3600
Chris Allegretta6df90f52002-07-19 01:08:59 +00003601 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003602 /* If location is CENTER, we move edittop up (editwinrows / 2)
3603 * lines. This puts current at the center of the screen. If
3604 * location is NONE, we move edittop up current_y lines if
3605 * current_y is in range of the screen, 0 lines if current_y is
3606 * less than 0, or (editwinrows - 1) lines if current_y is
3607 * greater than (editwinrows - 1). This puts current at the
3608 * same place on the screen as before, or at the top or bottom
3609 * of the screen if edittop is beyond either. */
3610 int goal;
3611
3612 if (location == CENTER)
3613 goal = editwinrows / 2;
3614 else {
3615 goal = current_y;
3616
3617 /* Limit goal to (editwinrows - 1) lines maximum. */
3618 if (goal > editwinrows - 1)
3619 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003620 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003621
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003622 for (; goal > 0 && foo->prev != NULL; goal--)
3623 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003624 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003625
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003626 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003627 edit_refresh();
3628}
3629
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003630/* Ask a simple yes/no question, specified in msg, on the statusbar.
3631 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3632 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003633int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003634{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003635 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003636 const char *yesstr; /* String of yes characters accepted. */
3637 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003638 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00003639
3640 assert(msg != NULL);
Chris Allegretta235ab192001-04-12 13:24:40 +00003641
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003642 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003643 * consists of all single-byte characters accepted as valid
3644 * characters for that value. The first value will be the one
3645 * displayed in the shortcuts. Translators: if possible, specify
3646 * both the shortcuts for your language and English. For example,
3647 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003648 yesstr = _("Yy");
3649 nostr = _("Nn");
3650 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003651
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003652 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003653 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003654
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003655 if (COLS < 32)
3656 width = COLS / 2;
3657
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003658 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003659 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003660
Chris Allegretta6232d662002-05-12 19:52:15 +00003661 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003662 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003663 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003664
3665 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003666 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003667 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003668 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003669 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003670
Chris Allegrettadb28e962003-01-28 01:23:40 +00003671 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003672 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003673 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003674
Chris Allegrettadb28e962003-01-28 01:23:40 +00003675 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003676 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003677 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003678
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003679 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003680
3681 blank_statusbar();
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00003682 mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
Chris Allegretta8ce24132001-04-30 11:28:46 +00003683
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003684 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003685
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003686 wrefresh(bottomwin);
3687
Chris Allegrettadb28e962003-01-28 01:23:40 +00003688 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003689 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003690 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003691#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003692 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003693#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003694
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003695 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003696
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003697 if (kbinput == NANO_REFRESH_KEY) {
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003698 total_redraw();
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003699 continue;
3700 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003701 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003702#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003703 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003704 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003705
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003706 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003707 wenclose(bottomwin, mouse_y, mouse_x) &&
3708 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003709 int x = mouse_x / width;
3710 /* Did we click in the first column of shortcuts, or
3711 * the second? */
3712 int y = mouse_y - editwinrows - 3;
3713 /* Did we click in the first row of shortcuts? */
3714
3715 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3716
3717 /* x = 0 means they clicked Yes or No.
3718 * y = 0 means Yes or All. */
3719 ok = -2 * x * y + x - y + 1;
3720
3721 if (ok == 2 && !all)
3722 ok = -2;
3723 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003724 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003725#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003726 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003727 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003728 else if (strchr(yesstr, kbinput) != NULL)
3729 ok = 1;
3730 else if (strchr(nostr, kbinput) != NULL)
3731 ok = 0;
3732 else if (all && strchr(allstr, kbinput) != NULL)
3733 ok = 2;
3734 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003735
Chris Allegrettadb28e962003-01-28 01:23:40 +00003736 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003737}
3738
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003739void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003740{
David Lawrence Ramsey7431fe52005-06-18 15:15:48 +00003741#ifdef USE_SLANG
David Lawrence Ramseyba61cc32005-06-21 20:16:26 +00003742 /* Slang curses emulation brain damage, part 3: Slang doesn't define
3743 * curscr, and even if it did, if we just do what curses does here,
3744 * it'll leave some windows cleared without updating them
3745 * properly. */
David Lawrence Ramsey7431fe52005-06-18 15:15:48 +00003746 SLsmg_touch_screen();
3747 SLsmg_refresh();
3748#else
David Lawrence Ramseyba61cc32005-06-21 20:16:26 +00003749 clearok(curscr, TRUE);
3750 wrefresh(curscr);
David Lawrence Ramsey7431fe52005-06-18 15:15:48 +00003751#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003752}
3753
3754void total_refresh(void)
3755{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003756 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003757 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003758 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003759 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003760}
3761
3762void display_main_list(void)
3763{
3764 bottombars(main_list);
3765}
3766
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003767/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3768 * display the cursor position. Otherwise, we display it only if the
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003769 * character position changed and disable_cursorpos is FALSE.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003770 *
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003771 * If constant is TRUE and disable_cursorpos is TRUE, we set the latter
3772 * to FALSE and update old_i and old_totsize. That way, we leave the
3773 * current statusbar alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003774void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003775{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003776 char c;
3777 filestruct *f;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003778 size_t i = 0;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003779 static size_t old_i = 0, old_totsize = (size_t)-1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003780
Chris Allegrettad26ab912003-01-28 01:16:47 +00003781 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003782
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003783 if (old_totsize == (size_t)-1)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003784 old_totsize = totsize;
3785
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003786 c = current->data[current_x];
3787 f = current->next;
3788 current->data[current_x] = '\0';
3789 current->next = NULL;
3790 get_totals(fileage, current, NULL, &i);
3791 current->data[current_x] = c;
3792 current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003793
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003794 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003795 * somewhere. */
3796 assert(current != filebot || i == totsize);
3797
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003798 if (constant && disable_cursorpos) {
3799 disable_cursorpos = FALSE;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003800 old_i = i;
3801 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003802 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003803 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003804
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003805 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003806 * unconditionally. Otherwise, only display the position when the
3807 * character values have changed. Finally, if disable_cursorpos is
3808 * TRUE, set it to FALSE. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003809 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003810 size_t xpt = xplustabs() + 1;
3811 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003812 int linepct = 100 * current->lineno / totlines;
3813 int colpct = 100 * xpt / cur_len;
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003814 int bytepct = (totsize == 0) ? 0 : 100 * i / totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003815
3816 statusbar(
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00003817 _("line %ld/%lu (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
3818 (long)current->lineno, (unsigned long)totlines, linepct,
3819 (unsigned long)xpt, (unsigned long)cur_len, colpct,
3820 (unsigned long)i, (unsigned long)totsize, bytepct);
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003821 disable_cursorpos = FALSE;
Chris Allegretta2084acc2001-11-29 03:43:08 +00003822 }
3823
3824 old_i = i;
3825 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003826}
3827
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003828void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003829{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003830 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003831}
3832
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003833#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003834/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003835size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003836{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003837 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003838
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003839 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003840 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003841 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003842 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003843
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003844 /* Get the length of the entire line up to a null or a newline. */
3845 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3846 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003847
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003848 /* If the entire line doesn't go more than 8 columns beyond where we
3849 * tried to break it, we should display it as-is. Otherwise, we
3850 * should display it only up to the break. */
3851 if (strnlenpt(ptr, retval) > help_cols + 8)
3852 retval = retval_save;
3853
3854 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003855}
3856
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003857/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003858void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003859{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003860 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003861 /* The line number in help_text of the first displayed help
3862 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003863 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003864 /* no_more means the end of the help text is shown, so don't go
3865 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003866 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003867 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003868
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003869 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003870#ifndef DISABLE_MOUSE
3871 const shortcut *oldshortcut = currshortcut;
3872 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003873 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003874#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003875
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003876 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003877 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003878 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003879 blank_statusbar();
3880
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003881 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003882 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003883
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003884 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003885
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003886#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003887 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003888 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003889 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003890#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003891
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003892 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003893 /* Make sure that the help screen's shortcut list will actually
3894 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003895 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003896 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003897 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003898
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003899 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003900
3901 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003902 int i;
3903 int old_line = line;
3904 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003905 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003906
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003907 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003908#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003909 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003910 {
3911 int mouse_x, mouse_y;
3912 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3913 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003914 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003915#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003916 case NANO_PREVPAGE_KEY:
3917 case NANO_PREVPAGE_FKEY:
3918 if (line > 0) {
3919 line -= editwinrows - 2;
3920 if (line < 0)
3921 line = 0;
3922 }
3923 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003924 case NANO_NEXTPAGE_KEY:
3925 case NANO_NEXTPAGE_FKEY:
3926 if (!no_more)
3927 line += editwinrows - 2;
3928 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003929 case NANO_PREVLINE_KEY:
3930 if (line > 0)
3931 line--;
3932 break;
3933 case NANO_NEXTLINE_KEY:
3934 if (!no_more)
3935 line++;
3936 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003937 }
3938
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003939 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003940 total_redraw();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003941 else {
3942 if (line == old_line && kbinput != ERR)
3943 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003944
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003945 blank_edit();
3946 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003947
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003948 /* Calculate where in the text we should be, based on the
3949 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003950 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003951 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003952 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003953 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954 }
3955
Chris Allegretta4640fe32003-02-10 03:10:03 +00003956 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003957 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003958
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003959 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003960 ptr += j;
3961 if (*ptr == '\n')
3962 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003963 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003964 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003965
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003966 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003967 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003968 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003969
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003970#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003971 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003972#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003973
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003974 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003975 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003976 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003977 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003978 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003979 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003980 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003981
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003982 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003983 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003984
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003985 /* The help_init() at the beginning allocated help_text. Since
3986 * help_text has now been written to the screen, we don't need it
3987 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003988 free(help_text);
3989 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003990}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003991#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003992
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003993/* Highlight the current word being replaced or spell checked. We
3994 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00003995void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003996{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003997 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00003998 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003999
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004000 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004001 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004002 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004003
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004004 assert(y > 0);
4005
4006 if (word_len > y)
4007 y--;
4008
Chris Allegrettafb62f732000-12-05 11:36:41 +00004009 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004010
Chris Allegrettafb62f732000-12-05 11:36:41 +00004011 if (highlight_flag)
4012 wattron(edit, A_REVERSE);
4013
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004014#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004015 /* This is so we can show zero-length regexes. */
4016 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00004017 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004018 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004019#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004020 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004021
4022 if (word_len > y)
4023 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004024
4025 if (highlight_flag)
4026 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004027}
4028
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004029#ifndef NDEBUG
4030/* Return what the current line number should be, starting at edittop
4031 * and ending at fileptr. */
4032int check_linenumbers(const filestruct *fileptr)
4033{
4034 int check_line = 0;
4035 const filestruct *filetmp;
4036
4037 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
4038 check_line++;
4039
4040 return check_line;
4041}
4042#endif
4043
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004044#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004045/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004046void dump_buffer(const filestruct *inptr)
4047{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004048 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004049 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004050 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004051 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004052 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004053 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004054
4055 while (inptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004056 fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004057 inptr = inptr->next;
4058 }
4059}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004060
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004061/* Dump the main filestruct to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004062void dump_buffer_reverse(void)
4063{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004064 const filestruct *fileptr = filebot;
4065
4066 while (fileptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004067 fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
4068 fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004069 fileptr = fileptr->prev;
4070 }
4071}
4072#endif /* DEBUG */
4073
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004074#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004075#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004076#define XLCREDIT_LEN 8
4077
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004078/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004079void do_credits(void)
4080{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004081 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004082 const char *credits[CREDIT_LEN] = {
4083 NULL, /* "The nano text editor" */
4084 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004085 VERSION,
4086 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004087 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004088 "Chris Allegretta",
4089 "Jordi Mallach",
4090 "Adam Rogoyski",
4091 "Rob Siemborski",
4092 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004093 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004094 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004095 "Ken Tyler",
4096 "Sven Guckes",
David Lawrence Ramsey7bf86e12005-06-08 19:50:02 +00004097 "Florian K\xF6nig",
Chris Allegretta598106e2002-01-19 01:59:37 +00004098 "Pauli Virtanen",
4099 "Daniele Medri",
4100 "Clement Laforet",
4101 "Tedi Heriyanto",
4102 "Bill Soudan",
4103 "Christian Weisgerber",
4104 "Erik Andersen",
4105 "Big Gaute",
4106 "Joshua Jensen",
4107 "Ryan Krebs",
4108 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004109 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004110 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004111 "Plattsburgh State University",
4112 "Benet Laboratories",
4113 "Amy Allegretta",
4114 "Linda Young",
4115 "Jeremy Robichaud",
4116 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004117 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004118 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004119 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004120 "Thomas Dickey",
4121 "Pavel Curtis",
4122 "Zeyd Ben-Halim",
4123 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004124 NULL, /* "and anyone else we forgot..." */
4125 NULL, /* "Thank you for using nano!" */
4126 "",
4127 "",
4128 "",
4129 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004130 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004131 "",
4132 "",
4133 "",
4134 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004135 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004136 };
4137
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004138 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004139 N_("The nano text editor"),
4140 N_("version"),
4141 N_("Brought to you by:"),
4142 N_("Special thanks to:"),
4143 N_("The Free Software Foundation"),
4144 N_("For ncurses:"),
4145 N_("and anyone else we forgot..."),
4146 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004147 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004148
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004149 curs_set(0);
4150 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004151 scrollok(edit, TRUE);
4152 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004153 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004154 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004155 blank_statusbar();
4156 blank_bottombars();
4157 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004158 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004159 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004160
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004161 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004162 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004163 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004164
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004165 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004166 char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004167 size_t start_x;
4168
David Lawrence Ramsey631242d2005-03-15 07:06:54 +00004169 /* Make sure every credit is a valid multibyte string, since
4170 * we can't dynamically set the credits to their multibyte
4171 * equivalents when we need to. Sigh... */
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004172 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004173 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004174
4175 what = mallocstrcpy(NULL, _(xlcredits[xlpos]));
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004176 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004177 } else
David Lawrence Ramsey30d0a812005-06-13 14:50:32 +00004178 what = make_valid_mbstring(credits[crpos]);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004179
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004180 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004181 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4182 start_x, what);
4183
4184 free(what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004185 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004186
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004187 napms(700);
4188 scroll(edit);
4189 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004190 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004191 break;
4192 napms(700);
4193 scroll(edit);
4194 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004195 }
4196
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004197 if (kbinput != ERR)
4198 ungetch(kbinput);
4199
4200 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004201 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004202 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004203 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004204}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004205#endif