blob: 268c4bf8a24f836846f0dd13818eb52717d123d8 [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. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000130void get_key_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
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000193 fprintf(stderr, "get_key_buffer(): key_buffer_len = %lu\n", (unsigned long)key_buffer_len);
David Lawrence Ramseya17a1302005-03-16 14:39:42 +0000194#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. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000198size_t get_key_buffer_len(void)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000199{
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)
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000273 get_key_buffer(win);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000274
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;
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000507 if (get_key_buffer_len() == 0) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000508 *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);
David Lawrence Ramseydb958022005-07-13 20:18:46 +0000520 seq_len = get_key_buffer_len();
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000521 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. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001463 *kbinput_len = get_key_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. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001691 if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001692 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. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00001703 if (*s_or_t == TRUE || get_key_buffer_len() == 0) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001704 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. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001751 if (!ISSET(RESTRICTED) || openfile->filename[0] ==
1752 '\0' || currshortcut != writefile_list)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001753 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. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001759 if (!ISSET(RESTRICTED) || openfile->filename[0] ==
1760 '\0' || currshortcut != writefile_list)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001761 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. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001767 if (!ISSET(RESTRICTED) || openfile->filename[0] ==
1768 '\0' || currshortcut != writefile_list)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001769 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. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00001785 if (!ISSET(RESTRICTED) ||
1786 openfile->filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001787 currshortcut != writefile_list) {
1788 bool got_enter;
1789 /* Whether we got the Enter key. */
1790
1791 do_statusbar_verbatim_input(&got_enter);
1792
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001793 /* If we got the Enter key, set input to the
1794 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001795 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001796 if (got_enter) {
1797 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001798 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001799 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001800 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001801 break;
1802 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001803 /* Handle the normal statusbar prompt shortcuts, setting
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001804 * ran_func to TRUE if we try to run their associated
1805 * functions and setting finished to TRUE to indicate
1806 * that we're done after trying to run their associated
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001807 * functions. */
1808 default:
1809 if (s->func != NULL) {
David Lawrence Ramseycac02932005-01-11 23:05:05 +00001810 *ran_func = TRUE;
1811 if (!ISSET(VIEW_MODE) || s->viewok)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001812 s->func();
1813 }
1814 *finished = TRUE;
1815 }
1816 }
1817 }
1818
1819 return input;
1820}
1821
1822#ifndef DISABLE_MOUSE
1823bool do_statusbar_mouse(void)
1824{
1825 /* FIXME: If we clicked on a location in the statusbar, the cursor
1826 * should move to the location we clicked on. This functionality
1827 * should be in this function. */
1828 int mouse_x, mouse_y;
1829 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1830}
1831#endif
1832
1833void do_statusbar_home(void)
1834{
1835#ifndef NANO_SMALL
1836 if (ISSET(SMART_HOME)) {
1837 size_t statusbar_x_save = statusbar_x;
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001838
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001839 statusbar_x = indent_length(answer);
David Lawrence Ramsey8a31afd2005-01-12 05:10:53 +00001840
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001841 if (statusbar_x == statusbar_x_save ||
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001842 statusbar_x == strlen(answer))
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001843 statusbar_x = 0;
1844 } else
1845#endif
1846 statusbar_x = 0;
1847}
1848
1849void do_statusbar_end(void)
1850{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001851 statusbar_x = strlen(answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001852}
1853
1854void do_statusbar_right(void)
1855{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001856 if (statusbar_x < strlen(answer))
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001857 statusbar_x = move_mbright(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001858}
1859
1860void do_statusbar_left(void)
1861{
1862 if (statusbar_x > 0)
David Lawrence Ramseyd24fbb72005-01-14 21:50:32 +00001863 statusbar_x = move_mbleft(answer, statusbar_x);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001864}
1865
1866void do_statusbar_backspace(void)
1867{
1868 if (statusbar_x > 0) {
1869 do_statusbar_left();
1870 do_statusbar_delete();
1871 }
1872}
1873
1874void do_statusbar_delete(void)
1875{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001876 if (answer[statusbar_x] != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001877 int char_buf_len = parse_mbchar(answer + statusbar_x, NULL,
1878 NULL, NULL);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001879 size_t line_len = strlen(answer + statusbar_x);
1880
1881 assert(statusbar_x < strlen(answer));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001882
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001883 charmove(answer + statusbar_x, answer + statusbar_x +
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001884 char_buf_len, strlen(answer) - statusbar_x -
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00001885 char_buf_len + 1);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001886
1887 null_at(&answer, statusbar_x + line_len - char_buf_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001888 }
1889}
1890
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +00001891/* Move text from the statusbar prompt into oblivion. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001892void do_statusbar_cut_text(void)
1893{
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001894 assert(answer != NULL);
1895
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001896#ifndef NANO_SMALL
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001897 if (ISSET(CUT_TO_END))
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001898 null_at(&answer, statusbar_x);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001899 else {
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001900#endif
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001901 null_at(&answer, 0);
1902 statusbar_x = 0;
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001903#ifndef NANO_SMALL
David Lawrence Ramseyc4c45aa2005-01-14 21:10:14 +00001904 }
David Lawrence Ramseyb80d49f2005-03-26 22:49:46 +00001905#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001906}
1907
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001908#ifndef NANO_SMALL
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001909/* Move to the next word at the statusbar prompt. If allow_punct is
1910 * TRUE, treat punctuation as part of a word. Return TRUE if we started
1911 * on a word, and FALSE otherwise. */
1912bool do_statusbar_next_word(bool allow_punct)
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001913{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001914 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001915 int char_mb_len;
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001916 bool end_line = FALSE, started_on_word = FALSE;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001917
1918 assert(answer != NULL);
1919
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001920 char_mb = charalloc(mb_cur_max());
1921
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001922 /* Move forward until we find the character after the last letter of
1923 * the current word. */
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001924 while (!end_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001925 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1926 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001927
1928 /* If we've found it, stop moving forward through the current
1929 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001930 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001931 break;
1932
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001933 /* If we haven't found it, then we've started on a word, so set
1934 * started_on_word to TRUE. */
1935 started_on_word = TRUE;
1936
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001937 if (answer[statusbar_x] == '\0')
1938 end_line = TRUE;
1939 else
1940 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001941 }
1942
1943 /* Move forward until we find the first letter of the next word. */
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001944 if (answer[statusbar_x] == '\0')
1945 end_line = TRUE;
1946 else
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00001947 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001948
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001949 while (!end_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001950 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1951 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001952
1953 /* If we've found it, stop moving forward through the current
1954 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001955 if (is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001956 break;
1957
David Lawrence Ramsey9d8396d2005-07-08 04:53:51 +00001958 if (answer[statusbar_x] == '\0')
1959 end_line = TRUE;
1960 else
1961 statusbar_x += char_mb_len;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001962 }
1963
1964 free(char_mb);
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001965
1966 /* Return whether we started on a word. */
1967 return started_on_word;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001968}
1969
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001970/* Move to the previous word at the statusbar prompt. If allow_punct is
1971 * TRUE, treat punctuation as part of a word. Return TRUE if we started
1972 * on a word, and FALSE otherwise. */
1973bool do_statusbar_prev_word(bool allow_punct)
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001974{
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001975 char *char_mb;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001976 int char_mb_len;
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001977 bool begin_line = FALSE, started_on_word = FALSE;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001978
1979 assert(answer != NULL);
1980
David Lawrence Ramsey3eeb8232005-01-31 18:59:30 +00001981 char_mb = charalloc(mb_cur_max());
1982
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001983 /* Move backward until we find the character before the first letter
1984 * of the current word. */
1985 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00001986 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
1987 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001988
1989 /* If we've found it, stop moving backward through the current
1990 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001991 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001992 break;
1993
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00001994 /* If we haven't found it, then we've started on a word, so set
1995 * started_on_word to TRUE. */
1996 started_on_word = TRUE;
1997
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00001998 if (statusbar_x == 0)
1999 begin_line = TRUE;
2000 else
2001 statusbar_x = move_mbleft(answer, statusbar_x);
2002 }
2003
2004 /* Move backward until we find the last letter of the previous
2005 * word. */
2006 if (statusbar_x == 0)
2007 begin_line = TRUE;
2008 else
2009 statusbar_x = move_mbleft(answer, statusbar_x);
2010
2011 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002012 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb, NULL,
2013 NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002014
2015 /* If we've found it, stop moving backward through the current
2016 * line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002017 if (is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002018 break;
2019
2020 if (statusbar_x == 0)
2021 begin_line = TRUE;
2022 else
2023 statusbar_x = move_mbleft(answer, statusbar_x);
2024 }
2025
2026 /* If we've found it, move backward until we find the character
2027 * before the first letter of the previous word. */
2028 if (!begin_line) {
2029 if (statusbar_x == 0)
2030 begin_line = TRUE;
2031 else
2032 statusbar_x = move_mbleft(answer, statusbar_x);
2033
2034 while (!begin_line) {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002035 char_mb_len = parse_mbchar(answer + statusbar_x, char_mb,
2036 NULL, NULL);
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002037
2038 /* If we've found it, stop moving backward through the
2039 * current line. */
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002040 if (!is_word_mbchar(char_mb, allow_punct))
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002041 break;
2042
2043 if (statusbar_x == 0)
2044 begin_line = TRUE;
2045 else
2046 statusbar_x = move_mbleft(answer, statusbar_x);
2047 }
2048
2049 /* If we've found it, move forward to the first letter of the
2050 * previous word. */
2051 if (!begin_line)
2052 statusbar_x += char_mb_len;
2053 }
2054
2055 free(char_mb);
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002056
2057 /* Return whether we started on a word. */
2058 return started_on_word;
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002059}
David Lawrence Ramseya8824a12005-06-26 19:03:48 +00002060#endif /* !NANO_SMALL */
David Lawrence Ramseyb80077d2005-01-18 21:25:38 +00002061
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002062void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002063{
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002064 int *kbinput;
2065 size_t kbinput_len, i;
2066 char *output;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002067
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002068 *got_enter = FALSE;
2069
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002070 /* Read in all the verbatim characters. */
2071 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
2072
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002073 /* Display all the verbatim characters at once, not filtering out
2074 * control characters. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002075 output = charalloc(kbinput_len + 1);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002076
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002077 for (i = 0; i < kbinput_len; i++)
2078 output[i] = (char)kbinput[i];
2079 output[i] = '\0';
2080
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002081 do_statusbar_output(output, kbinput_len, got_enter, TRUE);
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002082
2083 free(output);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00002084}
2085
David Lawrence Ramseyfe7d53e2005-06-25 20:56:36 +00002086/* The user typed ouuput_len multibyte characters. Add them to the
2087 * statusbar prompt, setting got_enter to TRUE if we get a newline, and
2088 * filtering out all control characters if allow_cntrls is TRUE. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002089void do_statusbar_output(char *output, size_t output_len, bool
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002090 *got_enter, bool allow_cntrls)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002091{
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002092 size_t answer_len, i = 0;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002093 char *char_buf = charalloc(mb_cur_max());
2094 int char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002095
2096 assert(answer != NULL);
2097
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002098 answer_len = strlen(answer);
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002099 *got_enter = FALSE;
2100
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002101 while (i < output_len) {
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002102 /* If allow_cntrls is FALSE, filter out nulls and newlines,
2103 * since they're control characters. */
2104 if (allow_cntrls) {
2105 /* Null to newline, if needed. */
2106 if (output[i] == '\0')
2107 output[i] = '\n';
2108 /* Newline to Enter, if needed. */
2109 else if (output[i] == '\n') {
2110 /* Set got_enter to TRUE to indicate that we got the
2111 * Enter key, put back the rest of the characters in
2112 * output so that they can be parsed and output again,
2113 * and get out. */
2114 *got_enter = TRUE;
2115 unparse_kbinput(output + i, output_len - i);
2116 return;
2117 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002118 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002119
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002120 /* Interpret the next multibyte character. If it's an invalid
2121 * multibyte character, interpret it as though it's a byte
2122 * character. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002123 char_buf_len = parse_mbchar(output + i, char_buf, NULL, NULL);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002124
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002125 i += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002126
David Lawrence Ramseyefec6412005-03-17 03:52:08 +00002127 /* If allow_cntrls is FALSE, filter out a control character. */
2128 if (!allow_cntrls && is_cntrl_mbchar(output + i - char_buf_len))
2129 continue;
2130
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002131 /* More dangerousness fun =) */
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002132 answer = charealloc(answer, answer_len + (char_buf_len * 2));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002133
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002134 assert(statusbar_x <= answer_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002135
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002136 charmove(&answer[statusbar_x + char_buf_len],
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002137 &answer[statusbar_x], answer_len - statusbar_x +
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002138 char_buf_len);
David Lawrence Ramsey7a3f49c2005-06-22 00:24:11 +00002139 strncpy(&answer[statusbar_x], char_buf, char_buf_len);
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002140 answer_len += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002141
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00002142 statusbar_x += char_buf_len;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002143 }
2144
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002145 free(char_buf);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002146}
2147
David Lawrence Ramseyb199cae2005-03-09 20:35:10 +00002148/* Return the placewewant associated with current_x, i.e, the zero-based
2149 * column position of the cursor. The value will be no smaller than
2150 * current_x. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002151size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002152{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002153 return strnlenpt(openfile->current->data, openfile->current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002154}
2155
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002156/* actual_x() gives the index in str of the character displayed at
2157 * column xplus. That is, actual_x() is the largest value such that
2158 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2159size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002160{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002161 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002162 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002163 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002164 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002165
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002166 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002167
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002168 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002169 int str_len = parse_mbchar(str, NULL, NULL, &length);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002170
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002171 if (length > xplus)
2172 break;
2173
2174 i += str_len;
2175 str += str_len;
2176 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002177
Chris Allegretta6df90f52002-07-19 01:08:59 +00002178 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002179}
2180
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002181/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002182 * columns wide are the first size characters of str? */
2183size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002184{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002185 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002186 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002187
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002188 if (size == 0)
2189 return 0;
2190
2191 assert(str != NULL);
2192
2193 while (*str != '\0') {
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002194 int str_len = parse_mbchar(str, NULL, NULL, &length);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002195
2196 str += str_len;
2197
2198 if (size <= str_len)
2199 break;
2200
2201 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002202 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002203
Chris Allegretta6df90f52002-07-19 01:08:59 +00002204 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002205}
2206
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002207/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002208size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002209{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002210 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002211}
2212
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002213/* Move to (x, y) in win, and display a line of n spaces with the
2214 * current attributes. */
2215void blank_line(WINDOW *win, int y, int x, int n)
2216{
2217 wmove(win, y, x);
2218 for (; n > 0; n--)
2219 waddch(win, ' ');
2220}
2221
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002222void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002223{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002224 blank_line(topwin, 0, 0, COLS);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002225}
2226
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002227void blank_topbar(void)
2228{
2229 if (!ISSET(MORE_SPACE))
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002230 blank_line(topwin, 1, 0, COLS);
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00002231}
2232
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002233void blank_edit(void)
2234{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002235 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002236 for (i = 0; i < editwinrows; i++)
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002237 blank_line(edit, i, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002238}
2239
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002240void blank_statusbar(void)
2241{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002242 blank_line(bottomwin, 0, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002243}
2244
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002245void blank_bottombars(void)
2246{
2247 if (!ISSET(NO_HELP)) {
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002248 blank_line(bottomwin, 1, 0, COLS);
2249 blank_line(bottomwin, 2, 0, COLS);
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00002250 }
2251}
2252
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002253void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002254{
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002255 if (statusblank > 0)
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002256 statusblank--;
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002257
2258 if (statusblank == 0 && !ISSET(CONST_UPDATE)) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002259 blank_statusbar();
2260 wnoutrefresh(bottomwin);
2261 reset_cursor();
2262 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002263 }
2264}
2265
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002266/* Convert buf into a string that can be displayed on screen. The
2267 * caller wants to display buf starting with column start_col, and
2268 * extending for at most len columns. start_col is zero-based. len is
2269 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002270 * string is dynamically allocated, and should be freed. If dollars is
2271 * TRUE, the caller might put "$" at the beginning or end of the line if
2272 * it's too long. */
2273char *display_string(const char *buf, size_t start_col, size_t len, bool
2274 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002275{
2276 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002277 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002278 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002279 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002280 size_t alloc_len;
2281 /* The length of memory allocated for converted. */
2282 char *converted;
2283 /* The string we return. */
2284 size_t index;
2285 /* Current position in converted. */
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002286 bool bad_char;
2287 /* Whether we have an invalid multibyte character. */
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002288#ifdef ENABLE_UTF8
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002289 const char *bad_buf_mb = "\xEF\xBF\xBD";
2290 /* What to display when we have an invalid multibyte
2291 * character: Unicode 0xFFFD (Replacement Character). */
2292 const int bad_buf_mb_len = 3;
2293 /* The length of bad_buf_mb. */
2294#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002295
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002296 char *buf_mb = charalloc(mb_cur_max());
2297 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002298
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002299 /* If dollars is TRUE, make room for the "$" at the end of the
2300 * line. */
2301 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2302 len--;
2303
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002304 if (len == 0)
2305 return mallocstrcpy(NULL, "");
2306
2307 start_index = actual_x(buf, start_col);
2308 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002309
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002310 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002311
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002312 /* Allocate enough space for the entire line, accounting for a
2313 * trailing multibyte character and/or tab. */
2314 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002315
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002316 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002317 index = 0;
2318
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002319 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002320 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002321 /* We don't display all of buf[start_index] since it starts to
2322 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002323 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2324 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002325
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002326 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002327 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002328 char *ctrl_buf_mb = charalloc(mb_cur_max());
2329 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002331 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2332 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 for (i = 0; i < ctrl_buf_mb_len; i++)
2335 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002336
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002337 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002338
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002339 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002340
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002341 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002342 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002343 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002344#ifdef ENABLE_UTF8
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002345 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002346 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002347 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002348
2349 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002350 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002351#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002352 }
2353
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002354 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002355 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2356 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002357
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002358 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002359 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002360#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002361 if (ISSET(WHITESPACE_DISPLAY)) {
2362 int i;
2363
2364 for (i = 0; i < whitespace_len[0]; i++)
2365 converted[index++] = whitespace[i];
2366 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002367#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002368 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002369 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002370 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002371 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002372 start_col++;
2373 }
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002374 /* If buf contains a control character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002375 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002376 int i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002377
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002378 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002379 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002380
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002381#ifdef ENABLE_UTF8
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002382 /* If buf contains an invalid multibyte control character,
2383 * display it as such. */
2384 if (ISSET(USE_UTF8) && bad_char) {
2385 for (i = 0; i < bad_buf_mb_len; i++)
2386 converted[index++] = bad_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002387
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002388 start_col += mbwidth(bad_buf_mb);
2389 } else
2390#endif
2391 {
2392 char *ctrl_buf_mb = charalloc(mb_cur_max());
2393 int ctrl_buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002394
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002395 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2396 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002397
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002398 for (i = 0; i < ctrl_buf_mb_len; i++)
2399 converted[index++] = ctrl_buf_mb[i];
2400
2401 start_col += mbwidth(ctrl_buf_mb);
2402
2403 free(ctrl_buf_mb);
2404 }
2405 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002406 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002407#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002408 if (ISSET(WHITESPACE_DISPLAY)) {
2409 int i;
2410
2411 for (i = whitespace_len[0]; i < whitespace_len[0] +
2412 whitespace_len[1]; i++)
2413 converted[index++] = whitespace[i];
2414 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002415#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002416 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002417 start_col++;
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002418 /* If buf contains a non-control character, interpret it. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002419 } else {
2420 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002421
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002422#ifdef ENABLE_UTF8
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002423 /* If buf contains an invalid multibyte non-control
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002424 * character, display it as such. */
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002425 if (ISSET(USE_UTF8) && bad_char) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002426 for (i = 0; i < bad_buf_mb_len; i++)
2427 converted[index++] = bad_buf_mb[i];
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002428
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002429 start_col += mbwidth(bad_buf_mb);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002430 } else {
2431#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002432 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002433 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002434
2435 start_col += mbwidth(buf_mb);
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002436#ifdef ENABLE_UTF8
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002437 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002438#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002439 }
2440
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002441 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002442 }
2443
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002444 free(buf_mb);
2445
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002446 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002447 converted[index] = '\0';
2448
2449 /* Make sure converted takes up no more than len columns. */
2450 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002451 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002452
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002453 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002454}
2455
Chris Allegretta7662c862003-01-13 01:35:15 +00002456/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002457 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002458 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002459 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002460 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002461void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002462{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002463 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002464 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002465
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002466 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002467
Chris Allegrettab3655b42001-10-22 03:15:31 +00002468 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002469 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002470
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00002471 mvwaddnstr(bottomwin, 0, 0, buf, actual_x(buf, COLS - 2));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002472 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002473
2474 if (COLS > 1)
2475 waddch(bottomwin, x_real < wid ? ' ' : '$');
2476 if (COLS > 2) {
2477 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002478 char *expanded = display_string(inputbuf, page_start, wid,
2479 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002480
2481 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002482 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002483
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002484 waddstr(bottomwin, expanded);
2485 free(expanded);
2486 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2487 } else
2488 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002489
Chris Allegrettab3655b42001-10-22 03:15:31 +00002490 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002491}
2492
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002493/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002494 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002495int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002496#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002497 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002498#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002499 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002500#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002501 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002502#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002503 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002504{
2505 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002506 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002507 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002508#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002509 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002510 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002511#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002512#ifndef NANO_SMALL
2513 char *history = NULL;
2514 /* The current history string. */
2515 char *magichistory = NULL;
2516 /* The temporary string typed at the bottom of the history, if
2517 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002518#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002519 int last_kbinput = ERR;
2520 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002521 size_t complete_len = 0;
2522 /* The length of the original string that we're trying to
2523 * tab complete, if any. */
2524#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002525#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002526
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002527 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002528 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002529
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002530 /* Only put statusbar_x at the end of the string if it's
2531 * uninitialized, if it would be past the end of curranswer, or if
2532 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2533 * the cursor position stays at the same place if a prompt-changing
2534 * toggle is pressed. */
2535 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2536 resetstatuspos)
2537 statusbar_x = curranswer_len;
2538
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002539 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002540
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002541 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002542
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002543 /* Refresh the edit window and the statusbar before getting
2544 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002545 wnoutrefresh(edit);
2546 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002547
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002548 /* If we're using restricted mode, we aren't allowed to change the
2549 * name of a file once it has one because that would allow writing
2550 * to files not specified on the command line. In this case,
2551 * disable all keys that would change the text if the filename isn't
2552 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002553 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002554 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002555 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002556
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002557 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002558
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002559#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002560 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002561 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002562#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002563
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002564 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002565 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002566#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002567#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002568 if (history_list != NULL) {
2569 if (last_kbinput != NANO_TAB_KEY)
2570 complete_len = strlen(answer);
2571
2572 if (complete_len > 0) {
2573 answer = mallocstrcpy(answer,
2574 get_history_completion(history_list,
2575 answer, complete_len));
2576 statusbar_x = strlen(answer);
2577 }
2578 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002579#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002580 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002581 answer = input_tab(answer, &statusbar_x, &tabbed,
2582 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002583#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002584 break;
2585 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002586#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002587 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002588 /* If we're scrolling up at the bottom of the
2589 * history list, answer isn't blank, and
2590 * magichistory isn't set, save answer in
2591 * magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002592 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002593 answer[0] != '\0' && magichistory == NULL)
2594 magichistory = mallocstrcpy(NULL, answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002595
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002596 /* Get the older search from the history list and
2597 * save it in answer. If there is no older search,
2598 * don't do anything. */
2599 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002600 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002601 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002602 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002603 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002604
2605 /* This key has a shortcut list entry when it's used
2606 * to move to an older search, which means that
2607 * finished has been set to TRUE. Set it back to
2608 * FALSE here, so that we aren't kicked out of the
2609 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002610 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002611 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002612#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002613 break;
2614 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002615#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002616 if (history_list != NULL) {
2617 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002618 * save it in answer. If there is no newer search,
2619 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002620 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002621 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002622 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002623 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002624 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002625
2626 /* If, after scrolling down, we're at the bottom of
2627 * the history list, answer is blank, and
2628 * magichistory is set, save magichistory in
2629 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002630 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002631 answer[0] == '\0' && magichistory != NULL) {
2632 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002633 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002634 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002635 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002636#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002637 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002638 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002639
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002640 /* If we have a shortcut with an associated function, break out
2641 * if we're finished after running or trying to run the
2642 * function. */
2643 if (finished)
2644 break;
2645
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002646#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002647 last_kbinput = kbinput;
2648#endif
2649
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002650 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002651 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002652 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002653
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002654#ifndef NANO_SMALL
David Lawrence Ramsey8234f672005-06-02 02:32:39 +00002655 /* Free magichistory if we need to. */
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002656 if (magichistory != NULL)
2657 free(magichistory);
2658#endif
2659
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002660 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002661 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002662 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002663 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002664 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002665
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002666 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002667}
2668
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002669/* Ask a question on the statusbar. Answer will be stored in answer
2670 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002671 * otherwise, the valid shortcut key caught. curranswer is any editable
2672 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002673 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002674 * The allow_tabs parameter indicates whether we should allow tabs to be
2675 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002676int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002677#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002678 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002679#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002680 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002681{
2682 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002683 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002684 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002685#ifndef DISABLE_TABCOMP
2686 bool list = FALSE;
2687#endif
2688
2689 bottombars(s);
2690
2691 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002692 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002693 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002694 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002695
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002696 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002697#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002698 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002699#endif
2700 s
2701#ifndef DISABLE_TABCOMP
2702 , &list
2703#endif
2704 );
2705 free(foo);
2706 resetstatuspos = FALSE;
2707
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002708 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002709 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002710 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002711 resetstatuspos = TRUE;
2712 break;
2713 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002714 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002715 resetstatuspos = TRUE;
2716 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002717 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002718
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002719 blank_statusbar();
David Lawrence Ramseycd0210f2005-06-18 14:05:21 +00002720 wnoutrefresh(bottomwin);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002721
2722#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002723 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002724#endif
2725
2726#ifndef DISABLE_TABCOMP
David Lawrence Ramsey90d505c2005-06-18 22:33:55 +00002727 /* If we've done tab completion, there might be a list of filename
2728 * matches on the edit window at this point. Make sure that they're
2729 * cleared off. */
2730 if (list)
2731 edit_refresh();
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002732#endif
2733
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002734 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002735}
2736
2737void statusq_abort(void)
2738{
2739 resetstatuspos = TRUE;
2740}
2741
Chris Allegrettaf717f982003-02-13 22:25:01 +00002742void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002743{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002744 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002745 /* The space we have available for display. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002746 size_t verlen = strlenpt(VERMSG) + 1;
2747 /* The length of the version message in columns, plus one for
2748 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002749 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002750 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002751 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002752 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002753 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002754 /* "Modified", "View", or "". Shows the state of this
2755 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002756 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002757 /* The length of the state in columns, or the length of
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002758 * "Modified" if the state is blank. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002759 char *exppath = NULL;
2760 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002761 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002762 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002763 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002764 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002765
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002766 assert(path != NULL || openfile->filename != NULL);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002767 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002768
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002770 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002771
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002772 /* space has to be at least 4: two spaces before the version message,
2773 * at least one character of the version message, and one space
2774 * after the version message. */
2775 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002776 space = 0;
2777 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002778 /* Limit verlen to 1/3 the length of the screen in columns,
2779 * minus three columns for spaces. */
2780 if (verlen > (COLS / 3) - 3)
2781 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002782 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002783
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002784 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002785 /* Add a space after the version message, and account for both
2786 * it and the two spaces before it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002787 mvwaddnstr(topwin, 0, 2, VERMSG, actual_x(VERMSG, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002788 verlen += 3;
2789
2790 /* Account for the full length of the version message. */
2791 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002792 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002793
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002794#ifndef DISABLE_BROWSER
2795 /* Don't display the state if we're in the file browser. */
2796 if (path != NULL)
2797 state = "";
2798 else
2799#endif
2800 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2801 _("View") : "";
2802
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002803 statelen = strlenpt((state[0] != '\0') ? state : _("Modified"));
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002804
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002805 /* If possible, add a space before state. */
2806 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002808 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002809 goto the_end;
2810
2811#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002812 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002813 if (path != NULL)
2814 prefix = _("DIR:");
2815 else
2816#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002817 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002818 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002819 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 } else
2821 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002822
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002823 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002824
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002825 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002826 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002827 prefixlen++;
2828
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002829 /* If we're not in the file browser, path should be the current
2830 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002831 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002832 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002833
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002834 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002835 if (space >= prefixlen + statelen)
2836 space -= prefixlen + statelen;
2837 else
2838 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002839 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002840
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002841 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002842 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002843
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002844 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002845
2846 if (dots) {
2847 start_col = lenpt - space + 3;
2848 space -= 3;
2849 } else
2850 start_col = 0;
2851
2852 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002853 }
2854
2855 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002856 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2857 /* The length of the expanded filename. */
2858
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002859 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002860 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2861 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002862 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002863 waddch(topwin, ' ');
2864 waddstr(topwin, exppath);
2865 }
2866 } else {
2867 /* We will say something like "File: ...ename". */
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002868 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2869 prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002870 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002871 goto the_end;
2872 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002873 waddnstr(topwin, "...", space + 3);
2874 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002875 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002876 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002877 }
2878
2879 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002880 free(exppath);
2881
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002882 if (state[0] != '\0') {
2883 if (COLS <= 1 || statelen >= COLS - 1)
2884 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2885 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002886 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002887
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002888 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002889 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002890 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002891 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002892
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002893 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002894
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002895 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002896 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002897 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898}
2899
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002900/* Set the modified flag if it isn't already set, and then update the
2901 * titlebar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002902void set_modified(void)
2903{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002904 if (!openfile->modified) {
2905 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002906 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002907 }
2908}
2909
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002910/* Display a message on the statusbar, and set disable_cursorpos to
2911 * TRUE, so that the message won't be immediately overwritten if
2912 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002913void statusbar(const char *msg, ...)
2914{
2915 va_list ap;
2916
2917 va_start(ap, msg);
2918
2919 /* Curses mode is turned off. If we use wmove() now, it will muck
2920 * up the terminal settings. So we just use vfprintf(). */
2921 if (curses_ended) {
2922 vfprintf(stderr, msg, ap);
2923 va_end(ap);
2924 return;
2925 }
2926
2927 /* Blank out the line. */
2928 blank_statusbar();
2929
2930 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002931 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002932 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002933#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002934 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002935
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002936 UNSET(WHITESPACE_DISPLAY);
2937#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002938 bar = charalloc(mb_cur_max() * (COLS - 3));
2939 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002940 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002941 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002942#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2943 if (old_whitespace)
2944 SET(WHITESPACE_DISPLAY);
2945#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002946 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002947 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002948 start_x = (COLS - foo_len - 4) / 2;
2949
2950 wmove(bottomwin, 0, start_x);
2951 wattron(bottomwin, A_REVERSE);
2952
2953 waddstr(bottomwin, "[ ");
2954 waddstr(bottomwin, foo);
2955 free(foo);
2956 waddstr(bottomwin, " ]");
2957 wattroff(bottomwin, A_REVERSE);
2958 wnoutrefresh(bottomwin);
2959 reset_cursor();
2960 wrefresh(edit);
2961 /* Leave the cursor at its position in the edit window, not
2962 * in the statusbar. */
2963 }
2964
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002965 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002966
2967 /* If we're doing quick statusbar blanking, and constant cursor
2968 * position display is off, blank the statusbar after only one
2969 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2970 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002971 statusblank =
2972#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002973 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002974#endif
2975 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002976}
2977
Chris Allegretta6232d662002-05-12 19:52:15 +00002978void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002979{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002980 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002981
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002982 if (ISSET(NO_HELP))
2983 return;
2984
Chris Allegretta6232d662002-05-12 19:52:15 +00002985 if (s == main_list) {
2986 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002987
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002988 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002989 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002990 slen = length_of_list(s);
2991
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002992 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002993 if (slen > MAIN_VISIBLE)
2994 slen = MAIN_VISIBLE;
2995 }
2996
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002997 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002998 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002999 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003000
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003001 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00003002
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003003 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003004 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00003005 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00003006
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00003007 /* Yucky sentinel values that we can't handle a better way. */
3008 if (s->ctrlval == NANO_CONTROL_SPACE)
3009 strcpy(foo, "^ ");
3010 else if (s->ctrlval == NANO_CONTROL_8)
3011 strcpy(foo, "^?");
3012 /* Normal values. Assume that the shortcut has an equivalent
3013 * control key, meta key sequence, or both. */
3014 else if (s->ctrlval != NANO_NO_KEY)
3015 sprintf(foo, "^%c", s->ctrlval + 64);
3016 else if (s->metaval != NANO_NO_KEY)
3017 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00003018
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00003019 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003020
3021 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003022 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003023 }
3024
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003025 wnoutrefresh(bottomwin);
3026 reset_cursor();
3027 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003028}
3029
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003030/* Write a shortcut key to the help area at the bottom of the window.
3031 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
3032 * to write at most len characters, even if len is very small and
3033 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
3034 * the whole string! We do not bother padding the entry with blanks. */
3035void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003036{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003037 size_t keystroke_len = strlenpt(keystroke) + 1;
3038
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00003039 assert(keystroke != NULL && desc != NULL);
3040
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003041 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003042 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003043 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003044
3045 if (len > keystroke_len)
3046 len -= keystroke_len;
3047 else
3048 len = 0;
3049
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003050 if (len > 0) {
3051 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003052 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003053 }
3054}
3055
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003056/* nano scrolls horizontally within a line in chunks. This function
3057 * returns the column number of the first character displayed in the
3058 * window when the cursor is at the given column. Note that
3059 * 0 <= column - get_page_start(column) < COLS. */
3060size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003061{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003062 assert(COLS > 0);
David Lawrence Ramsey3b2fdb02005-06-28 07:16:13 +00003063
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003064 if (column == 0 || column < COLS - 1)
3065 return 0;
3066 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003067 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003068 else if (COLS > 2)
3069 return column - (COLS - 2);
3070 else
3071 return column - (COLS - 1);
3072 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003073}
3074
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003075/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003076 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003077void reset_cursor(void)
3078{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003079 /* If we haven't opened any files yet, put the cursor in the top
3080 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00003081 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003082 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003083 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003084 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003085
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003086 openfile->current_y = openfile->current->lineno -
3087 openfile->edittop->lineno;
3088 if (openfile->current_y < editwinrows) {
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003089 size_t x = xplustabs();
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003090 wmove(edit, openfile->current_y, x - get_page_start(x));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003091 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003092}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003093
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003094/* edit_add() takes care of the job of actually painting a line into the
3095 * edit window. fileptr is the line to be painted, at row yval of the
3096 * window. converted is the actual string to be written to the window,
3097 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003098 * characters. start is the column number of the first character of
3099 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003100 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003101void edit_add(const filestruct *fileptr, const char *converted, int
3102 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003103{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003104#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003105 size_t startpos = actual_x(fileptr->data, start);
3106 /* The position in fileptr->data of the leftmost character
3107 * that displays at least partially on the window. */
3108 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3109 /* The position in fileptr->data of the first character that is
3110 * completely off the window to the right.
3111 *
3112 * Note that endpos might be beyond the null terminator of the
3113 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003114#endif
3115
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003116 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003117 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003118
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003119 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003120 * just the text that needs it). */
3121 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003122
Chris Allegretta7dd77682001-12-08 19:52:28 +00003123#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003124 /* If color syntaxes are available and turned on, we need to display
3125 * them. */
3126 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
3127 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003128
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003129 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3130 int x_start;
3131 /* Starting column for mvwaddnstr. Zero-based. */
3132 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003133 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003134 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003135 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003136 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003137 regmatch_t startmatch;
3138 /* Match position for start_regex. */
3139 regmatch_t endmatch;
3140 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003141
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003142 if (tmpcolor->bright)
3143 wattron(edit, A_BOLD);
3144 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003145 /* Two notes about regexec(). Return value 0 means there is
3146 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003147 * after the match. */
3148
3149 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003150 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003151 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003152
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003153 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003154 * last match. Even though two matches may overlap, we
3155 * want to ignore them, so that we can highlight
3156 * C-strings correctly. */
3157 while (k < endpos) {
3158 /* Note the fifth parameter to regexec(). It says
3159 * not to match the beginning-of-line character
3160 * unless k is 0. If regexec() returns REG_NOMATCH,
3161 * there are no more matches in the line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003162 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003163 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003164 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003165 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003166 /* Translate the match to the beginning of the
3167 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003168 startmatch.rm_so += k;
3169 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003170 if (startmatch.rm_so == startmatch.rm_eo) {
3171 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003172 statusbar(
3173 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003174 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003175 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003176 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003178 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003179 x_start = strnlenpt(fileptr->data,
3180 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003181
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003182 index = actual_x(converted, x_start);
3183
3184 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003185 strnlenpt(fileptr->data,
3186 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003187
3188 assert(0 <= x_start && 0 <= paintlen);
3189
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003190 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003191 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003192 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003194 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003195 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003196 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003197 * First, we have to see if the beginning of the line is
3198 * colored by a start on an earlier line, and an end on
3199 * this line or later.
3200 *
3201 * We find the first line before fileptr matching the
3202 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003203 * end, then go to step two. Otherwise, find the next
3204 * line after start_line matching the end. If that line
3205 * is not before fileptr, then paint the beginning of
3206 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003207 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003208 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003209 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003210 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003211 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003212
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003213 while (start_line != NULL && regexec(tmpcolor->start,
3214 start_line->data, 1, &startmatch,
3215 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003216 /* If there is an end on this line, there is no need
3217 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003218 if (regexec(tmpcolor->end, start_line->data, 0,
3219 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003220 goto step_two;
3221 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003222 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003223 /* No start found, so skip to the next step. */
3224 if (start_line == NULL)
3225 goto step_two;
3226 /* Now start_line is the first line before fileptr
3227 * containing a start match. Is there a start on this
3228 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003229 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003230 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003231 start_col += startmatch.rm_so;
3232 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003233 if (regexec(tmpcolor->end, start_line->data +
3234 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003235 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003236 REG_NOTBOL) == REG_NOMATCH)
3237 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003238 break;
3239 start_col++;
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003240 if (regexec(tmpcolor->start, start_line->data +
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003241 start_col, 1, &startmatch,
3242 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243 /* No later start on this line. */
3244 goto step_two;
3245 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003246 /* Indeed, there is a start not followed on this line by
3247 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003248
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003249 /* We have already checked that there is no end before
3250 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003251 * the start at all? We don't paint unterminated
3252 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003253 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003254 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003255 regexec(tmpcolor->end, end_line->data, 1,
3256 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003257 end_line = end_line->next;
3258
3259 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003260 if (end_line == NULL || (end_line == fileptr &&
3261 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003262 goto step_two;
3263
3264 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003265 if (end_line != fileptr)
3266 /* If the start of fileptr is on a different line
3267 * from the end, paintlen is -1, meaning that
3268 * everything on the line gets painted. */
3269 paintlen = -1;
3270 else
3271 /* Otherwise, paintlen is the expanded location of
3272 * the end of the match minus the expanded location
3273 * of the beginning of the page. */
3274 paintlen = actual_x(converted,
3275 strnlenpt(fileptr->data, endmatch.rm_eo) -
3276 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003277
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003278 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003279
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003280 step_two:
3281 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003282 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003283
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003284 while (start_col < endpos) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003285 if (regexec(tmpcolor->start, fileptr->data +
3286 start_col, 1, &startmatch, (start_col == 0) ?
3287 0 : REG_NOTBOL) == REG_NOMATCH || start_col +
3288 startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003289 /* No more starts on this line. */
3290 break;
3291 /* Translate the match to be relative to the
3292 * beginning of the line. */
3293 startmatch.rm_so += start_col;
3294 startmatch.rm_eo += start_col;
3295
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003296 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003298 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003299 x_start = strnlenpt(fileptr->data,
3300 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003301
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003302 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003303
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003304 if (regexec(tmpcolor->end,
3305 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003306 (startmatch.rm_eo == 0) ? 0 :
3307 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003308 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003309 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003310 endmatch.rm_so += startmatch.rm_eo;
3311 endmatch.rm_eo += startmatch.rm_eo;
3312 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003313 * appear on this page, and is the match more
3314 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003315 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003316 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003317 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003318 strnlenpt(fileptr->data,
3319 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003320
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003321 assert(0 <= x_start && x_start < COLS);
3322
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003323 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003324 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003325 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003326 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003327 /* There is no end on this line. But we haven't
3328 * yet looked for one on later lines. */
3329 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003330
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003331 while (end_line != NULL &&
3332 regexec(tmpcolor->end, end_line->data,
3333 0, NULL, 0) == REG_NOMATCH)
3334 end_line = end_line->next;
3335
3336 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003337 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003338
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003339 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003340 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003341 /* We painted to the end of the line, so
3342 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003343 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003344 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003345 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003346 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003347 }
3348 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003349
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350 wattroff(edit, A_BOLD);
3351 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003352 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003354#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003355
Chris Allegretta7dd77682001-12-08 19:52:28 +00003356#ifndef NANO_SMALL
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003357 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003358 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003359 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003360 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003361 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003362 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003363 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003364 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003365 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003366 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003367 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368 const filestruct *bot;
3369 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003370 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003371 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003372 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003373 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003374 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003375 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003376 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003377
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003378 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003379
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380 if (top->lineno < fileptr->lineno || top_x < startpos)
3381 top_x = startpos;
3382 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3383 bot_x = endpos;
3384
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003385 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003386 if (top_x < endpos && bot_x > startpos) {
3387 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003388
3389 /* x_start is the expanded location of the beginning of the
3390 * mark minus the beginning of the page. */
3391 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003392
3393 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003394 /* If the end of the mark is off the page, paintlen is
3395 * -1, meaning that everything on the line gets
3396 * painted. */
3397 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003398 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003399 /* Otherwise, paintlen is the expanded location of the
3400 * end of the mark minus the expanded location of the
3401 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003402 paintlen = strnlenpt(fileptr->data, bot_x) -
3403 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003404
3405 /* If x_start is before the beginning of the page, shift
3406 * paintlen x_start characters to compensate, and put
3407 * x_start at the beginning of the page. */
3408 if (x_start < 0) {
3409 paintlen += x_start;
3410 x_start = 0;
3411 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003412
3413 assert(x_start >= 0 && x_start <= strlen(converted));
3414
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003415 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003416
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003417 if (paintlen > 0)
3418 paintlen = actual_x(converted + index, paintlen);
3419
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003420 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003421 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003422 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003423 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003424 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003425 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003426#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003427}
3428
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003429/* Just update one line in the edit buffer. This is basically a wrapper
3430 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003431 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003432 * If fileptr != current, then index is considered 0. The line will be
3433 * displayed starting with fileptr->data[index]. Likely args are
3434 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003435void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003436{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003437 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003438 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003439 char *converted;
3440 /* fileptr->data converted to have tabs and control characters
3441 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003442 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003443
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003444 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003445
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003446 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003447
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003448 /* We assume the line numbers are valid. Is that really true? */
3449 assert(line < 0 || line == check_linenumbers(fileptr));
3450
3451 if (line < 0 || line >= editwinrows)
3452 return;
3453
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003454 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003455 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003456
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003457 /* Next, convert variables that index the line to their equivalent
3458 * positions in the expanded line. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003459 index = (fileptr == openfile->current) ? strnlenpt(fileptr->data,
3460 index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003461 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003462
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003463 /* Expand the line, replacing tabs with spaces, and control
3464 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003465 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003466
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003467 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003468 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003469 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003470
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003471 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003472 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003473 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003474 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003475}
3476
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003477/* Return a nonzero value if we need an update after moving
3478 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003479 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003480int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003481{
3482 return
3483#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003484 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003485#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003486 get_page_start(old_pww) !=
3487 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003488}
3489
3490/* Return a nonzero value if we need an update after moving vertically.
3491 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003492 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003493int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003494{
3495 return
3496#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003497 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003498#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003499 get_page_start(old_pww) !=
3500 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003501}
3502
3503/* Scroll the edit window in the given direction and the given number
3504 * of lines, and draw new lines on the blank lines left after the
3505 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003506 * and nlines is the number of lines to scroll. We change edittop, and
3507 * assume that current and current_x are up to date. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003508void edit_scroll(updown direction, int nlines)
3509{
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00003510 const filestruct *foo;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003511 int i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003512
3513 /* Scrolling less than one line or more than editwinrows lines is
3514 * redundant, so don't allow it. */
3515 if (nlines < 1 || nlines > editwinrows)
3516 return;
3517
3518 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003519 * value of direction) nlines lines, or as many lines as we can if
3520 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003521 for (i = nlines; i > 0; i--) {
3522 if (direction == UP) {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003523 if (openfile->edittop->prev == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003524 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003525 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003526 } else {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003527 if (openfile->edittop->next == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003528 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003529 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003530 }
3531 }
3532
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003533 /* Scroll the text on the screen up or down nlines lines, depending
3534 * on the value of direction. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003535 scrollok(edit, TRUE);
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003536 wscrl(edit, (direction == UP) ? -nlines : nlines);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003537 scrollok(edit, FALSE);
3538
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003539 /* If we scrolled up, we couldn't scroll up all nlines lines, and
3540 * we're now at the top of the file, we need to treat the entire
3541 * screen as the scrolled region, instead of just the top nlines
3542 * lines. */
3543 if (direction == UP && i > 0 && openfile->edittop ==
3544 openfile->fileage)
3545 nlines = editwinrows;
3546
David Lawrence Ramseydbeb5032005-07-17 15:42:21 +00003547 /* Make nlines account for the lines before and after the scrolled
3548 * region, if they're onsccreen. */
3549 nlines += (nlines <= editwinrows - 2) ? 2 :
3550 (nlines == editwinrows - 1) ? 1 : 0;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003551
3552 /* If we scrolled up, we're on the line before the scrolled
3553 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003554 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003555
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003556 /* If we scrolled down, move down to the line before the scrolled
3557 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003558 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003559 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003560 foo = foo->next;
3561 }
3562
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003563 /* Draw new lines on the blank lines before, inside, and after the
3564 * scrolled region. */
3565 for (; nlines > 0 && foo != NULL; nlines--) {
3566 update_line(foo, (foo == openfile->current) ?
3567 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003568 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003569 }
3570}
3571
3572/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003573 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003574void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003575{
David Lawrence Ramsey54236802005-06-28 05:56:16 +00003576 bool do_refresh = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003577 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003578 const filestruct *foo;
3579
3580 /* If either old_current or current is offscreen, refresh the screen
3581 * and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003582 if (old_current->lineno < openfile->edittop->lineno ||
3583 old_current->lineno >= openfile->edittop->lineno +
3584 editwinrows || openfile->current->lineno <
3585 openfile->edittop->lineno || openfile->current->lineno >=
3586 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003587 edit_refresh();
3588 return;
3589 }
3590
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003591 /* Update old_current and current if we're not on the first page
3592 * and/or we're not on the same page as before. If the mark is on,
3593 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003594 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003595
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003596 while (foo != openfile->current) {
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003597 if (do_refresh)
3598 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003599
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003600#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003601 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003602#endif
3603 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003604
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003605#ifndef NANO_SMALL
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003606 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
3607 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003608#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003609 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003610
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003611 if (do_refresh)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003612 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003613}
3614
Chris Allegretta6df90f52002-07-19 01:08:59 +00003615/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003616void edit_refresh(void)
3617{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003618 const filestruct *foo;
3619 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003620
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003621 if (openfile->current->lineno < openfile->edittop->lineno ||
3622 openfile->current->lineno >= openfile->edittop->lineno +
3623 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003624 /* Put the top line of the edit window in range of the current
3625 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003626 edit_update(
3627#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003628 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003629#endif
3630 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003631
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003632 foo = openfile->edittop;
3633
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003634#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003635 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003636#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003637
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003638 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003639 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003640 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003641 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003642 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003643
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003644 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003645 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003646
3647 reset_cursor();
3648 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003649}
3650
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003651/* Move edittop to put it in range of current, keeping current in the
3652 * same place. location determines how we move it: if it's CENTER, we
3653 * center current, and if it's NONE, we put current current_y lines
3654 * below edittop. */
3655void edit_update(centernone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003656{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003657 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003658 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003659
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003660 /* If location is CENTER, we move edittop up (editwinrows / 2)
3661 * lines. This puts current at the center of the screen. If
3662 * location is NONE, we move edittop up current_y lines if current_y
3663 * is in range of the screen, 0 lines if current_y is less than 0,
3664 * or (editwinrows - 1) lines if current_y is greater than
3665 * (editwinrows - 1). This puts current at the same place on the
3666 * screen as before, or at the top or bottom of the screen if
3667 * edittop is beyond either. */
3668 if (location == CENTER)
3669 goal = editwinrows / 2;
3670 else {
3671 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003672
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003673 /* Limit goal to (editwinrows - 1) lines maximum. */
3674 if (goal > editwinrows - 1)
3675 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003676 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003677
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003678 for (; goal > 0 && foo->prev != NULL; goal--)
3679 foo = foo->prev;
3680
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003681 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003682}
3683
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003684/* Ask a simple yes/no question, specified in msg, on the statusbar.
3685 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3686 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003687int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003688{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003689 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003690 const char *yesstr; /* String of yes characters accepted. */
3691 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003692 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00003693
3694 assert(msg != NULL);
Chris Allegretta235ab192001-04-12 13:24:40 +00003695
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003696 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003697 * consists of all single-byte characters accepted as valid
3698 * characters for that value. The first value will be the one
3699 * displayed in the shortcuts. Translators: if possible, specify
3700 * both the shortcuts for your language and English. For example,
3701 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003702 yesstr = _("Yy");
3703 nostr = _("Nn");
3704 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003705
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003706 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003707 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003708
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003709 if (COLS < 32)
3710 width = COLS / 2;
3711
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003712 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003713 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003714
Chris Allegretta6232d662002-05-12 19:52:15 +00003715 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003716 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003717 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003718
3719 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003720 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003721 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003722 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003723 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003724
Chris Allegrettadb28e962003-01-28 01:23:40 +00003725 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003726 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003727 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003728
Chris Allegrettadb28e962003-01-28 01:23:40 +00003729 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003730 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003731 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003732
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003733 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003734
3735 blank_statusbar();
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00003736 mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
Chris Allegretta8ce24132001-04-30 11:28:46 +00003737
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003738 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003739
David Lawrence Ramsey73bf89f2005-06-30 05:56:39 +00003740 /* Refresh the edit window and the statusbar before getting
3741 * input. */
3742 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003743 wrefresh(bottomwin);
3744
Chris Allegrettadb28e962003-01-28 01:23:40 +00003745 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003746 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003747 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003748#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003749 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003750#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003751
David Lawrence Ramsey44e0c032005-06-29 19:01:11 +00003752 kbinput = get_kbinput(bottomwin, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003753
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003754 if (kbinput == NANO_REFRESH_KEY) {
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003755 total_redraw();
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003756 continue;
3757 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003758 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003759#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003760 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003761 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003762
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003763 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003764 wenclose(bottomwin, mouse_y, mouse_x) &&
3765 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003766 int x = mouse_x / width;
3767 /* Did we click in the first column of shortcuts, or
3768 * the second? */
3769 int y = mouse_y - editwinrows - 3;
3770 /* Did we click in the first row of shortcuts? */
3771
3772 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3773
3774 /* x = 0 means they clicked Yes or No.
3775 * y = 0 means Yes or All. */
3776 ok = -2 * x * y + x - y + 1;
3777
3778 if (ok == 2 && !all)
3779 ok = -2;
3780 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003781 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003782#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003783 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003784 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003785 else if (strchr(yesstr, kbinput) != NULL)
3786 ok = 1;
3787 else if (strchr(nostr, kbinput) != NULL)
3788 ok = 0;
3789 else if (all && strchr(allstr, kbinput) != NULL)
3790 ok = 2;
3791 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003792
Chris Allegrettadb28e962003-01-28 01:23:40 +00003793 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003794}
3795
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003796void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003797{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003798#ifdef USE_SLANG
3799 /* Slang curses emulation brain damage, part 3: Slang doesn't define
3800 * curscr. */
3801 SLsmg_touch_screen();
3802 SLsmg_refresh();
3803#else
3804 wrefresh(curscr);
3805#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003806}
3807
3808void total_refresh(void)
3809{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003810 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003811 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003812 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003813 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003814}
3815
3816void display_main_list(void)
3817{
3818 bottombars(main_list);
3819}
3820
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003821/* If constant is TRUE, we display the current cursor position only if
3822 * disable_cursorpos is FALSE. Otherwise, we display it
3823 * unconditionally and set disable_cursorpos to FALSE. If constant is
3824 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3825 * FALSE, so that we leave the current statusbar alone this time, and
3826 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003827void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003828{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003829 char c;
3830 filestruct *f;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003831 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003832 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003833 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003834
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003835 assert(openfile->current != NULL && openfile->fileage != NULL && openfile->totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003836
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003837 c = openfile->current->data[openfile->current_x];
3838 f = openfile->current->next;
3839 openfile->current->data[openfile->current_x] = '\0';
3840 openfile->current->next = NULL;
David Lawrence Ramseyc104ef12005-07-17 01:44:35 +00003841 i = get_totsize(openfile->fileage, openfile->current);
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003842 openfile->current->data[openfile->current_x] = c;
3843 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003844
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003845 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003846 * somewhere. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003847 assert(openfile->current != openfile->filebot || i == openfile->totsize);
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003848
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003849 if (constant && disable_cursorpos) {
3850 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003851 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003852 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003853
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003854 /* Display the current cursor position on the statusbar, and set
3855 * disable_cursorpos to FALSE. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003856 linepct = 100 * openfile->current->lineno / openfile->totlines;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003857 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003858 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3859 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003860
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003861 statusbar(
3862 _("line %ld/%lu (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003863 (long)openfile->current->lineno,
3864 (unsigned long)openfile->totlines, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003865 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003866 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003867
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003868 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003869}
3870
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003871void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003872{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003873 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003874}
3875
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003876#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003877/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003878size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003879{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003880 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003881
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003882 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003883 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003884 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003885 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003886
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003887 /* Get the length of the entire line up to a null or a newline. */
3888 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3889 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003890
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003891 /* If the entire line doesn't go more than 8 columns beyond where we
3892 * tried to break it, we should display it as-is. Otherwise, we
3893 * should display it only up to the break. */
3894 if (strnlenpt(ptr, retval) > help_cols + 8)
3895 retval = retval_save;
3896
3897 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003898}
3899
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003900/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003901void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003902{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003903 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003904 /* The line number in help_text of the first displayed help
3905 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003906 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003907 /* no_more means the end of the help text is shown, so don't go
3908 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003909 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003910 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003911
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003912 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003913#ifndef DISABLE_MOUSE
3914 const shortcut *oldshortcut = currshortcut;
3915 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003916 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003917#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003918
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003919 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003920 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003921 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003922 blank_statusbar();
3923
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003924 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003925 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003926
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003927 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003928
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003929#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003930 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003931 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003932 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003933#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003934
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003936 /* Make sure that the help screen's shortcut list will actually
3937 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003938 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003939 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003940 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003941
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003942 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003943
3944 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003945 int i;
3946 int old_line = line;
3947 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003948 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003949
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003950 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003951#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003952 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003953 {
3954 int mouse_x, mouse_y;
3955 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3956 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003957 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003958#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003959 case NANO_PREVPAGE_KEY:
3960 case NANO_PREVPAGE_FKEY:
3961 if (line > 0) {
3962 line -= editwinrows - 2;
3963 if (line < 0)
3964 line = 0;
3965 }
3966 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003967 case NANO_NEXTPAGE_KEY:
3968 case NANO_NEXTPAGE_FKEY:
3969 if (!no_more)
3970 line += editwinrows - 2;
3971 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003972 case NANO_PREVLINE_KEY:
3973 if (line > 0)
3974 line--;
3975 break;
3976 case NANO_NEXTLINE_KEY:
3977 if (!no_more)
3978 line++;
3979 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003980 }
3981
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003982 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003983 total_redraw();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003984 else {
3985 if (line == old_line && kbinput != ERR)
3986 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003987
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003988 blank_edit();
3989 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003990
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003991 /* Calculate where in the text we should be, based on the
3992 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003993 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003994 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003995 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003996 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003997 }
3998
Chris Allegretta4640fe32003-02-10 03:10:03 +00003999 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00004000 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004001
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004002 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004003 ptr += j;
4004 if (*ptr == '\n')
4005 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004006 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004007 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00004008
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004009 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00004010 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00004011 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00004012
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004013#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00004014 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004015#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00004016
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00004017 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00004018 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00004019 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004020 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00004021 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00004022 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004023 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004024
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00004025 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004026 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00004027
David Lawrence Ramsey52453442004-06-26 15:24:16 +00004028 /* The help_init() at the beginning allocated help_text. Since
4029 * help_text has now been written to the screen, we don't need it
4030 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00004031 free(help_text);
4032 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004033}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00004034#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004035
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004036/* Highlight the current word being replaced or spell checked. We
4037 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004038void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004039{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00004040 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004041
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004042 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004043 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004044 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004045
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004046 assert(y > 0);
4047
4048 if (word_len > y)
4049 y--;
4050
Chris Allegrettafb62f732000-12-05 11:36:41 +00004051 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004052
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004053 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004054 wattron(edit, A_REVERSE);
4055
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004056#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004057 /* This is so we can show zero-length regexes. */
4058 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00004059 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004060 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004061#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004062 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004063
4064 if (word_len > y)
4065 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004066
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004067 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004068 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004069}
4070
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004071#ifndef NDEBUG
4072/* Return what the current line number should be, starting at edittop
4073 * and ending at fileptr. */
4074int check_linenumbers(const filestruct *fileptr)
4075{
4076 int check_line = 0;
4077 const filestruct *filetmp;
4078
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004079 for (filetmp = openfile->edittop; filetmp != fileptr;
4080 filetmp = filetmp->next)
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004081 check_line++;
4082
4083 return check_line;
4084}
4085#endif
4086
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004087#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004088/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004089void dump_filestruct(const filestruct *inptr)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004090{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004091 if (inptr == openfile->fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004092 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004093 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004094 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004095 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004096 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004097
4098 while (inptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004099 fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004100 inptr = inptr->next;
4101 }
4102}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004103
David Lawrence Ramsey4c221672005-07-17 15:40:49 +00004104/* Dump the current buffer's filestruct to stderr in reverse. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004105void dump_filestruct_reverse(void)
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004106{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004107 const filestruct *fileptr = openfile->filebot;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004108
4109 while (fileptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004110 fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
4111 fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004112 fileptr = fileptr->prev;
4113 }
4114}
4115#endif /* DEBUG */
4116
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004117#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004118#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004119#define XLCREDIT_LEN 8
4120
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004121/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004122void do_credits(void)
4123{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004124 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004125 const char *credits[CREDIT_LEN] = {
4126 NULL, /* "The nano text editor" */
4127 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004128 VERSION,
4129 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004130 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004131 "Chris Allegretta",
4132 "Jordi Mallach",
4133 "Adam Rogoyski",
4134 "Rob Siemborski",
4135 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004136 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004137 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004138 "Ken Tyler",
4139 "Sven Guckes",
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004140 NULL, /* credits[14], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00004141 "Pauli Virtanen",
4142 "Daniele Medri",
4143 "Clement Laforet",
4144 "Tedi Heriyanto",
4145 "Bill Soudan",
4146 "Christian Weisgerber",
4147 "Erik Andersen",
4148 "Big Gaute",
4149 "Joshua Jensen",
4150 "Ryan Krebs",
4151 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004152 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004153 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004154 "Plattsburgh State University",
4155 "Benet Laboratories",
4156 "Amy Allegretta",
4157 "Linda Young",
4158 "Jeremy Robichaud",
4159 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004160 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004161 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004162 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004163 "Thomas Dickey",
4164 "Pavel Curtis",
4165 "Zeyd Ben-Halim",
4166 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004167 NULL, /* "and anyone else we forgot..." */
4168 NULL, /* "Thank you for using nano!" */
4169 "",
4170 "",
4171 "",
4172 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004173 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004174 "",
4175 "",
4176 "",
4177 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004178 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004179 };
4180
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004181 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004182 N_("The nano text editor"),
4183 N_("version"),
4184 N_("Brought to you by:"),
4185 N_("Special thanks to:"),
4186 N_("The Free Software Foundation"),
4187 N_("For ncurses:"),
4188 N_("and anyone else we forgot..."),
4189 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004190 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004191
David Lawrence Ramseyb2072b02005-06-28 14:59:38 +00004192 /* credits[14]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00004193 * can't dynamically assign it above, using Unicode 00F6 (Latin
4194 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004195 credits[14] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00004196#ifdef ENABLE_UTF8
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004197 ISSET(USE_UTF8) ? "Florian K\xC3\xB6nig" :
4198#endif
4199 "Florian K\xF6nig";
4200
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004201 curs_set(0);
4202 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004203 scrollok(edit, TRUE);
4204 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004205 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004206 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004207 blank_statusbar();
4208 blank_bottombars();
4209 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004210 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004211 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004212
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004213 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004214 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004215 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004216
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004217 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004218 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004219 size_t start_x;
4220
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004221 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004222 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004223
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004224 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004225 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004226 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004227 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004228
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004229 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004230 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4231 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004232 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004233
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004234 napms(700);
4235 scroll(edit);
4236 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004237 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004238 break;
4239 napms(700);
4240 scroll(edit);
4241 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004242 }
4243
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004244 if (kbinput != ERR)
4245 ungetch(kbinput);
4246
4247 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004248 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004249 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004250 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004251}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004252#endif