blob: a0d8318a518e8e51727241518f85ca1985597ae8 [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
David Lawrence Ramsey38f70a52005-07-19 18:46:02 +0000536 * digits: byte sequence mode. If the byte
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +0000537 * 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 Ramsey5ffbec52003-09-16 01:16:49 +00002288
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002289 char *buf_mb = charalloc(mb_cur_max());
2290 int buf_mb_len;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002291
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002292 /* If dollars is TRUE, make room for the "$" at the end of the
2293 * line. */
2294 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2295 len--;
2296
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002297 if (len == 0)
2298 return mallocstrcpy(NULL, "");
2299
2300 start_index = actual_x(buf, start_col);
2301 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002302
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002303 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002304
David Lawrence Ramseyd29b9d52005-06-06 03:17:07 +00002305 /* Allocate enough space for the entire line, accounting for a
2306 * trailing multibyte character and/or tab. */
2307 alloc_len = (mb_cur_max() * (len + 1)) + tabsize;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002308
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002309 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002310 index = 0;
2311
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002312 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002313 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002314 /* We don't display all of buf[start_index] since it starts to
2315 * the left of the screen. */
David Lawrence Ramsey1b9d3f92005-02-11 20:09:11 +00002316 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, NULL,
2317 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002318
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002319 if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002320 if (column < start_col) {
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002321 char *ctrl_buf_mb = charalloc(mb_cur_max());
2322 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002323
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002324 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2325 &ctrl_buf_mb_len);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002326
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002327 for (i = 0; i < ctrl_buf_mb_len; i++)
2328 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002329
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002330 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002331
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002332 free(ctrl_buf_mb);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002333
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002334 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002335 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002336 }
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002337#ifdef ENABLE_UTF8
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002338 else if (ISSET(USE_UTF8) && mbwidth(buf_mb) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002339 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002340 start_col++;
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002341
2342 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002343 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002344#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345 }
2346
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002347 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseybc149412005-02-11 20:23:00 +00002348 buf_mb_len = parse_mbchar(buf + start_index, buf_mb, &bad_char,
2349 NULL);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002350
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002351 /* If buf contains a tab character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002352 if (*buf_mb == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002353#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002354 if (ISSET(WHITESPACE_DISPLAY)) {
2355 int i;
2356
2357 for (i = 0; i < whitespace_len[0]; i++)
2358 converted[index++] = whitespace[i];
2359 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002360#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002361 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002362 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002363 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002364 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002365 start_col++;
2366 }
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002367 /* If buf contains a control character, interpret it. If buf
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002368 * contains an invalid multibyte control character, display it
2369 * as such.*/
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002370 } else if (is_cntrl_mbchar(buf_mb)) {
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002371 char *ctrl_buf_mb = charalloc(mb_cur_max());
2372 int ctrl_buf_mb_len, i;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002373
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002374 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002375 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002376
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002377 ctrl_buf_mb = control_mbrep(buf_mb, ctrl_buf_mb,
2378 &ctrl_buf_mb_len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002379
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002380 for (i = 0; i < ctrl_buf_mb_len; i++)
2381 converted[index++] = ctrl_buf_mb[i];
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002382
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002383 start_col += mbwidth(ctrl_buf_mb);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002384
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002385 free(ctrl_buf_mb);
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002386 /* If buf contains a space character, interpret it. */
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002387 } else if (*buf_mb == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002388#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002389 if (ISSET(WHITESPACE_DISPLAY)) {
2390 int i;
2391
2392 for (i = whitespace_len[0]; i < whitespace_len[0] +
2393 whitespace_len[1]; i++)
2394 converted[index++] = whitespace[i];
2395 } else
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002396#endif
David Lawrence Ramsey6e60db62005-03-10 22:52:21 +00002397 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002398 start_col++;
David Lawrence Ramsey9838a512005-07-06 19:12:41 +00002399 /* If buf contains a non-control character, interpret it. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002400 } else {
2401 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002402
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002403#ifdef ENABLE_UTF8
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002404 /* If buf contains an invalid multibyte non-control
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002405 * character, display it as such. */
David Lawrence Ramsey7a4aaa52005-06-16 02:09:57 +00002406 if (ISSET(USE_UTF8) && bad_char) {
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002407 for (i = 0; i < bad_mbchar_len; i++)
2408 converted[index++] = bad_mbchar[i];
David Lawrence Ramseyf7bcbeb2005-07-18 03:23:37 +00002409
David Lawrence Ramsey61f56732005-07-21 22:12:03 +00002410 start_col += mbwidth(bad_mbchar);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002411 } else {
2412#endif
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002413 for (i = 0; i < buf_mb_len; i++)
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002414 converted[index++] = buf[start_index + i];
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002415
2416 start_col += mbwidth(buf_mb);
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00002417#ifdef ENABLE_UTF8
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002418 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002419#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002420 }
2421
David Lawrence Ramseyb54155c2005-01-12 03:25:57 +00002422 start_index += buf_mb_len;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002423 }
2424
David Lawrence Ramsey6a0d5b82005-06-13 14:00:22 +00002425 free(buf_mb);
2426
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002427 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002428 converted[index] = '\0';
2429
2430 /* Make sure converted takes up no more than len columns. */
2431 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002432 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002433
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002434 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002435}
2436
Chris Allegretta7662c862003-01-13 01:35:15 +00002437/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002438 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002439 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002440 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002441 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002442void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002443{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002444 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002445 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002446
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002447 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002448
Chris Allegrettab3655b42001-10-22 03:15:31 +00002449 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002450 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002451
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00002452 mvwaddnstr(bottomwin, 0, 0, buf, actual_x(buf, COLS - 2));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002453 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002454
2455 if (COLS > 1)
2456 waddch(bottomwin, x_real < wid ? ' ' : '$');
2457 if (COLS > 2) {
2458 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002459 char *expanded = display_string(inputbuf, page_start, wid,
2460 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002461
2462 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002463 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002464
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002465 waddstr(bottomwin, expanded);
2466 free(expanded);
2467 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2468 } else
2469 wmove(bottomwin, 0, COLS - 1);
David Lawrence Ramseyd37f6a32005-03-26 20:41:36 +00002470
Chris Allegrettab3655b42001-10-22 03:15:31 +00002471 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002472}
2473
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002474/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002475 * statusq(). */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002476int nanogetstr(bool allow_tabs, const char *buf, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002477#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002478 filestruct **history_list,
Chris Allegretta5beed502003-01-05 20:41:21 +00002479#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002480 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002481#ifndef DISABLE_TABCOMP
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002482 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002483#endif
David Lawrence Ramsey066713e2005-05-14 23:21:02 +00002484 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002485{
2486 int kbinput;
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002487 bool meta_key, func_key, s_or_t, ran_func, finished;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002488 size_t curranswer_len;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002489#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002490 bool tabbed = FALSE;
David Lawrence Ramseyf1d3d952005-05-26 18:03:17 +00002491 /* Whether we've pressed Tab. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002492#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002493#ifndef NANO_SMALL
2494 char *history = NULL;
2495 /* The current history string. */
2496 char *magichistory = NULL;
2497 /* The temporary string typed at the bottom of the history, if
2498 * any. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002499#ifndef DISABLE_TABCOMP
David Lawrence Ramseyd922f192005-06-02 19:50:18 +00002500 int last_kbinput = ERR;
2501 /* The key we pressed before the current key. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002502 size_t complete_len = 0;
2503 /* The length of the original string that we're trying to
2504 * tab complete, if any. */
2505#endif
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002506#endif /* !NANO_SMALL */
Chris Allegretta09fc4302003-01-16 22:16:38 +00002507
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002508 answer = mallocstrcpy(answer, curranswer);
David Lawrence Ramsey0e0fef02005-05-26 18:05:22 +00002509 curranswer_len = strlen(answer);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002510
David Lawrence Ramsey045d1302005-05-26 05:27:19 +00002511 /* Only put statusbar_x at the end of the string if it's
2512 * uninitialized, if it would be past the end of curranswer, or if
2513 * resetstatuspos is TRUE. Otherwise, leave it alone. This is so
2514 * the cursor position stays at the same place if a prompt-changing
2515 * toggle is pressed. */
2516 if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len ||
2517 resetstatuspos)
2518 statusbar_x = curranswer_len;
2519
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002520 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002521
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002522 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002523
David Lawrence Ramsey10f880c2005-04-29 03:24:43 +00002524 /* Refresh the edit window and the statusbar before getting
2525 * input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002526 wnoutrefresh(edit);
2527 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002528
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002529 /* If we're using restricted mode, we aren't allowed to change the
2530 * name of a file once it has one because that would allow writing
2531 * to files not specified on the command line. In this case,
2532 * disable all keys that would change the text if the filename isn't
2533 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002534 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002535 &s_or_t, &ran_func, &finished, TRUE)) != NANO_CANCEL_KEY &&
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002536 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002537
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002538 assert(statusbar_x <= strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002539
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002540#ifndef DISABLE_TABCOMP
David Lawrence Ramsey22425a22005-04-16 15:57:19 +00002541 if (kbinput != NANO_TAB_KEY)
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002542 tabbed = FALSE;
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002543#endif
Chris Allegretta04d848e2000-11-05 17:54:41 +00002544
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002545 switch (kbinput) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002546 case NANO_TAB_KEY:
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002547#ifndef DISABLE_TABCOMP
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002548#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002549 if (history_list != NULL) {
2550 if (last_kbinput != NANO_TAB_KEY)
2551 complete_len = strlen(answer);
2552
2553 if (complete_len > 0) {
2554 answer = mallocstrcpy(answer,
2555 get_history_completion(history_list,
2556 answer, complete_len));
2557 statusbar_x = strlen(answer);
2558 }
2559 } else
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002560#endif /* !NANO_SMALL */
David Lawrence Ramseye2ce2792005-05-26 05:33:57 +00002561 if (allow_tabs)
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002562 answer = input_tab(answer, &statusbar_x, &tabbed,
2563 list);
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002564#endif /* !DISABLE_TABCOMP */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002565 break;
2566 case NANO_PREVLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002567#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002568 if (history_list != NULL) {
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002569 /* If we're scrolling up at the bottom of the
David Lawrence Ramsey239c3d42005-07-19 05:58:00 +00002570 * history list and answer isn't blank, save answer
2571 * in magichistory. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002572 if ((*history_list)->next == NULL &&
David Lawrence Ramsey239c3d42005-07-19 05:58:00 +00002573 answer[0] != '\0')
2574 magichistory = mallocstrcpy(magichistory,
2575 answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002576
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002577 /* Get the older search from the history list and
2578 * save it in answer. If there is no older search,
2579 * don't do anything. */
2580 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002581 get_history_older(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002582 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002583 statusbar_x = strlen(answer);
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002584 }
David Lawrence Ramsey75f4b7c2005-05-03 21:35:58 +00002585
2586 /* This key has a shortcut list entry when it's used
2587 * to move to an older search, which means that
2588 * finished has been set to TRUE. Set it back to
2589 * FALSE here, so that we aren't kicked out of the
2590 * statusbar prompt. */
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002591 finished = FALSE;
Chris Allegretta5beed502003-01-05 20:41:21 +00002592 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002593#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002594 break;
2595 case NANO_NEXTLINE_KEY:
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002596#ifndef NANO_SMALL
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002597 if (history_list != NULL) {
2598 /* Get the newer search from the history list and
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002599 * save it in answer. If there is no newer search,
2600 * don't do anything. */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002601 if ((history =
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002602 get_history_newer(history_list)) != NULL) {
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002603 answer = mallocstrcpy(answer, history);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002604 statusbar_x = strlen(answer);
Chris Allegrettac30fc242003-08-11 00:32:45 +00002605 }
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002606
2607 /* If, after scrolling down, we're at the bottom of
2608 * the history list, answer is blank, and
2609 * magichistory is set, save magichistory in
2610 * answer. */
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002611 if ((*history_list)->next == NULL &&
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002612 answer[0] == '\0' && magichistory != NULL) {
2613 answer = mallocstrcpy(answer, magichistory);
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002614 statusbar_x = strlen(answer);
David Lawrence Ramsey934f9682005-05-23 16:30:06 +00002615 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002616 }
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002617#endif /* !NANO_SMALL */
David Lawrence Ramseyc504dff2005-04-09 04:10:58 +00002618 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002619 }
David Lawrence Ramseyb56ca1b2005-03-26 20:50:59 +00002620
David Lawrence Ramsey0f83c892005-05-03 03:18:44 +00002621 /* If we have a shortcut with an associated function, break out
2622 * if we're finished after running or trying to run the
2623 * function. */
2624 if (finished)
2625 break;
2626
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002627#if !defined(NANO_SMALL) && !defined(DISABLE_TABCOMP)
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002628 last_kbinput = kbinput;
2629#endif
2630
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002631 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002632 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002633 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002634
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002635#ifndef NANO_SMALL
David Lawrence Ramsey0e581b32005-07-18 07:48:50 +00002636 /* Set the current position in the history list to the bottom and
2637 * free magichistory, if we need to. */
2638 if (history_list != NULL) {
2639 history_reset(*history_list);
2640
2641 if (magichistory != NULL)
2642 free(magichistory);
2643 }
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002644#endif
2645
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002646 /* We finished putting in an answer or ran a normal shortcut's
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002647 * associated function, so reset statusbar_x. */
David Lawrence Ramseycac02932005-01-11 23:05:05 +00002648 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY ||
David Lawrence Ramseye5bc1c42005-05-23 17:19:32 +00002649 ran_func)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002650 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002651
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002652 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002653}
2654
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002655/* Ask a question on the statusbar. Answer will be stored in answer
2656 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002657 * otherwise, the valid shortcut key caught. curranswer is any editable
2658 * text that we want to put up by default.
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002659 *
David Lawrence Ramsey67e3b932005-05-23 18:49:28 +00002660 * The allow_tabs parameter indicates whether we should allow tabs to be
2661 * interpreted. */
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002662int statusq(bool allow_tabs, const shortcut *s, const char *curranswer,
David Lawrence Ramsey1addd602005-06-03 19:28:30 +00002663#ifndef NANO_SMALL
David Lawrence Ramsey34bdc352005-06-02 18:41:31 +00002664 filestruct **history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002665#endif
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002666 const char *msg, ...)
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002667{
2668 va_list ap;
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002669 char *foo = charalloc(((COLS - 4) * mb_cur_max()) + 1);
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002670 int retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002671#ifndef DISABLE_TABCOMP
2672 bool list = FALSE;
2673#endif
2674
2675 bottombars(s);
2676
2677 va_start(ap, msg);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002678 vsnprintf(foo, (COLS - 4) * mb_cur_max(), msg, ap);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002679 va_end(ap);
David Lawrence Ramsey612caef2005-03-31 00:11:43 +00002680 null_at(&foo, actual_x(foo, COLS - 4));
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002681
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002682 retval = nanogetstr(allow_tabs, foo, curranswer,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002683#ifndef NANO_SMALL
David Lawrence Ramsey546f5b32005-05-14 23:14:47 +00002684 history_list,
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002685#endif
2686 s
2687#ifndef DISABLE_TABCOMP
2688 , &list
2689#endif
2690 );
2691 free(foo);
2692 resetstatuspos = FALSE;
2693
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002694 switch (retval) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002695 case NANO_CANCEL_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002696 retval = -1;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002697 resetstatuspos = TRUE;
2698 break;
2699 case NANO_ENTER_KEY:
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002700 retval = (answer[0] == '\0') ? -2 : 0;
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002701 resetstatuspos = TRUE;
2702 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002703 }
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002704
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002705 blank_statusbar();
David Lawrence Ramseycd0210f2005-06-18 14:05:21 +00002706 wnoutrefresh(bottomwin);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002707
2708#ifdef DEBUG
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00002709 fprintf(stderr, "answer = \"%s\"\n", answer);
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002710#endif
2711
2712#ifndef DISABLE_TABCOMP
David Lawrence Ramsey90d505c2005-06-18 22:33:55 +00002713 /* If we've done tab completion, there might be a list of filename
2714 * matches on the edit window at this point. Make sure that they're
2715 * cleared off. */
2716 if (list)
2717 edit_refresh();
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002718#endif
2719
David Lawrence Ramsey6f25a672005-05-20 02:57:05 +00002720 return retval;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002721}
2722
2723void statusq_abort(void)
2724{
2725 resetstatuspos = TRUE;
2726}
2727
Chris Allegrettaf717f982003-02-13 22:25:01 +00002728void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002729{
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002730 int space = COLS;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002731 /* The space we have available for display. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002732 size_t verlen = strlenpt(VERMSG) + 1;
2733 /* The length of the version message in columns, plus one for
2734 * padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002735 const char *prefix;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002736 /* "DIR:", "File:", or "New Buffer". Goes before filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002737 size_t prefixlen;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002738 /* The length of the prefix in columns, plus one for padding. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002739 const char *state;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002740 /* "Modified", "View", or "". Shows the state of this
2741 * buffer. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002742 size_t statelen = 0;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002743 /* The length of the state in columns, or the length of
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002744 * "Modified" if the state is blank. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002745 char *exppath = NULL;
2746 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002747 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002748 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002749 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002750 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002751
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002752 assert(path != NULL || openfile->filename != NULL);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002753 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002754
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002755 wattron(topwin, A_REVERSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002756 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002757
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002758 /* space has to be at least 4: two spaces before the version message,
2759 * at least one character of the version message, and one space
2760 * after the version message. */
2761 if (space < 4)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002762 space = 0;
2763 else {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002764 /* Limit verlen to 1/3 the length of the screen in columns,
2765 * minus three columns for spaces. */
2766 if (verlen > (COLS / 3) - 3)
2767 verlen = (COLS / 3) - 3;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002768 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002769
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002770 if (space >= 4) {
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002771 /* Add a space after the version message, and account for both
2772 * it and the two spaces before it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002773 mvwaddnstr(topwin, 0, 2, VERMSG, actual_x(VERMSG, verlen));
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002774 verlen += 3;
2775
2776 /* Account for the full length of the version message. */
2777 space -= verlen;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002778 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002779
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002780#ifndef DISABLE_BROWSER
2781 /* Don't display the state if we're in the file browser. */
2782 if (path != NULL)
2783 state = "";
2784 else
2785#endif
2786 state = openfile->modified ? _("Modified") : ISSET(VIEW_MODE) ?
2787 _("View") : "";
2788
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002789 statelen = strlenpt((state[0] != '\0') ? state : _("Modified"));
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002790
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002791 /* If possible, add a space before state. */
2792 if (space > 0 && statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 statelen++;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002794 else
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002795 goto the_end;
2796
2797#ifndef DISABLE_BROWSER
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002798 /* path should be a directory if we're in the file browser. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002799 if (path != NULL)
2800 prefix = _("DIR:");
2801 else
2802#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002803 if (openfile->filename[0] == '\0') {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002804 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002805 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002806 } else
2807 prefix = _("File:");
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002808
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002809 prefixlen = strnlenpt(prefix, space - statelen) + 1;
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002810
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002811 /* If newfie is FALSE, add a space after prefix. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002812 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002813 prefixlen++;
2814
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002815 /* If we're not in the file browser, path should be the current
2816 * filename. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002817 if (path == NULL)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002818 path = openfile->filename;
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002819
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002820 /* Account for the full lengths of the prefix and the state. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002821 if (space >= prefixlen + statelen)
2822 space -= prefixlen + statelen;
2823 else
2824 space = 0;
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002825 /* space is now the room we have for the filename. */
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002826
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002827 if (!newfie) {
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002828 size_t lenpt = strlenpt(path), start_col;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002829
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002830 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002831
2832 if (dots) {
2833 start_col = lenpt - space + 3;
2834 space -= 3;
2835 } else
2836 start_col = 0;
2837
2838 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002839 }
2840
2841 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002842 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2843 /* The length of the expanded filename. */
2844
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002845 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyd4dab462005-07-10 23:45:23 +00002846 mvwaddnstr(topwin, 0, verlen + ((space - exppathlen) / 3),
2847 prefix, actual_x(prefix, prefixlen));
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002848 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002849 waddch(topwin, ' ');
2850 waddstr(topwin, exppath);
2851 }
2852 } else {
2853 /* We will say something like "File: ...ename". */
David Lawrence Ramsey90f772b2005-07-11 07:12:33 +00002854 mvwaddnstr(topwin, 0, verlen - 1, prefix, actual_x(prefix,
2855 prefixlen));
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002856 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002857 goto the_end;
2858 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002859 waddnstr(topwin, "...", space + 3);
2860 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002861 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002862 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002863 }
2864
2865 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002866 free(exppath);
2867
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002868 if (state[0] != '\0') {
2869 if (COLS <= 1 || statelen >= COLS - 1)
2870 mvwaddnstr(topwin, 0, 0, state, actual_x(state, COLS));
2871 else {
David Lawrence Ramseycaa86592005-07-10 23:57:32 +00002872 assert(COLS - statelen - 1 >= 0);
David Lawrence Ramseycb4f14b2005-03-24 22:28:25 +00002873
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002874 mvwaddnstr(topwin, 0, COLS - statelen - 1, state,
David Lawrence Ramsey297851a2005-03-25 05:00:32 +00002875 actual_x(state, statelen));
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00002876 }
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002877 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002878
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002879 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002880
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002881 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002882 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002883 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002884}
2885
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002886/* Set the modified flag if it isn't already set, and then update the
2887 * titlebar. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002888void set_modified(void)
2889{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00002890 if (!openfile->modified) {
2891 openfile->modified = TRUE;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002892 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002893 }
2894}
2895
David Lawrence Ramsey5593e202005-06-28 19:49:15 +00002896/* Display a message on the statusbar, and set disable_cursorpos to
2897 * TRUE, so that the message won't be immediately overwritten if
2898 * constant cursor position display is on. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002899void statusbar(const char *msg, ...)
2900{
2901 va_list ap;
2902
2903 va_start(ap, msg);
2904
2905 /* Curses mode is turned off. If we use wmove() now, it will muck
2906 * up the terminal settings. So we just use vfprintf(). */
2907 if (curses_ended) {
2908 vfprintf(stderr, msg, ap);
2909 va_end(ap);
2910 return;
2911 }
2912
2913 /* Blank out the line. */
2914 blank_statusbar();
2915
2916 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002917 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002918 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002919#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002920 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002921
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002922 UNSET(WHITESPACE_DISPLAY);
2923#endif
David Lawrence Ramsey0c23aed2005-02-23 22:10:38 +00002924 bar = charalloc(mb_cur_max() * (COLS - 3));
2925 vsnprintf(bar, mb_cur_max() * (COLS - 3), msg, ap);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002926 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002927 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002928#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2929 if (old_whitespace)
2930 SET(WHITESPACE_DISPLAY);
2931#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002932 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002933 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002934 start_x = (COLS - foo_len - 4) / 2;
2935
2936 wmove(bottomwin, 0, start_x);
2937 wattron(bottomwin, A_REVERSE);
2938
2939 waddstr(bottomwin, "[ ");
2940 waddstr(bottomwin, foo);
2941 free(foo);
2942 waddstr(bottomwin, " ]");
2943 wattroff(bottomwin, A_REVERSE);
2944 wnoutrefresh(bottomwin);
2945 reset_cursor();
2946 wrefresh(edit);
2947 /* Leave the cursor at its position in the edit window, not
2948 * in the statusbar. */
2949 }
2950
David Lawrence Ramseyea014742005-06-17 18:27:00 +00002951 disable_cursorpos = TRUE;
David Lawrence Ramseyc6618532005-06-17 22:33:15 +00002952
2953 /* If we're doing quick statusbar blanking, and constant cursor
2954 * position display is off, blank the statusbar after only one
2955 * keystroke. Otherwise, blank it after twenty-five keystrokes,
2956 * as Pico does. */
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002957 statusblank =
2958#ifndef NANO_SMALL
David Lawrence Ramseybf51aa42005-06-17 21:52:59 +00002959 ISSET(QUICK_BLANK) && !ISSET(CONST_UPDATE) ? 1 :
David Lawrence Ramseye29111f2005-06-17 19:06:25 +00002960#endif
2961 25;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002962}
2963
Chris Allegretta6232d662002-05-12 19:52:15 +00002964void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002965{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002966 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002967
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002968 if (ISSET(NO_HELP))
2969 return;
2970
Chris Allegretta6232d662002-05-12 19:52:15 +00002971 if (s == main_list) {
2972 slen = MAIN_VISIBLE;
David Lawrence Ramsey31b159c2005-05-26 05:17:13 +00002973
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002974 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002975 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002976 slen = length_of_list(s);
2977
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002978 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002979 if (slen > MAIN_VISIBLE)
2980 slen = MAIN_VISIBLE;
2981 }
2982
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002983 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002984 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002985 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002986
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002987 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002988
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002989 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002990 const char *keystr;
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002991 char foo[4] = "";
Chris Allegretta658399a2001-06-14 02:54:22 +00002992
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00002993 /* Yucky sentinel values that we can't handle a better way. */
2994 if (s->ctrlval == NANO_CONTROL_SPACE)
2995 strcpy(foo, "^ ");
2996 else if (s->ctrlval == NANO_CONTROL_8)
2997 strcpy(foo, "^?");
2998 /* Normal values. Assume that the shortcut has an equivalent
2999 * control key, meta key sequence, or both. */
3000 else if (s->ctrlval != NANO_NO_KEY)
3001 sprintf(foo, "^%c", s->ctrlval + 64);
3002 else if (s->metaval != NANO_NO_KEY)
3003 sprintf(foo, "M-%c", toupper(s->metaval));
Chris Allegretta658399a2001-06-14 02:54:22 +00003004
David Lawrence Ramsey6bc26a92005-05-02 21:48:34 +00003005 keystr = foo;
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003006
3007 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003008 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003009 }
3010
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003011 wnoutrefresh(bottomwin);
3012 reset_cursor();
3013 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003014}
3015
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003016/* Write a shortcut key to the help area at the bottom of the window.
3017 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
3018 * to write at most len characters, even if len is very small and
3019 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
3020 * the whole string! We do not bother padding the entry with blanks. */
3021void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003022{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003023 size_t keystroke_len = strlenpt(keystroke) + 1;
3024
David Lawrence Ramsey12054fe2005-01-07 22:37:01 +00003025 assert(keystroke != NULL && desc != NULL);
3026
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003027 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003028 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003029 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003030
3031 if (len > keystroke_len)
3032 len -= keystroke_len;
3033 else
3034 len = 0;
3035
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003036 if (len > 0) {
3037 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003038 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003039 }
3040}
3041
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003042/* nano scrolls horizontally within a line in chunks. This function
3043 * returns the column number of the first character displayed in the
3044 * window when the cursor is at the given column. Note that
3045 * 0 <= column - get_page_start(column) < COLS. */
3046size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003047{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003048 assert(COLS > 0);
David Lawrence Ramsey3b2fdb02005-06-28 07:16:13 +00003049
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003050 if (column == 0 || column < COLS - 1)
3051 return 0;
3052 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003053 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003054 else if (COLS > 2)
3055 return column - (COLS - 2);
3056 else
3057 return column - (COLS - 1);
3058 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003059}
3060
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003061/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003062 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003063void reset_cursor(void)
3064{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003065 /* If we haven't opened any files yet, put the cursor in the top
3066 * left corner of the edit window and get out. */
David Lawrence Ramseydbcaa3b2005-07-08 20:59:24 +00003067 if (openfile == NULL) {
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003068 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003069 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003070 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003071
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003072 openfile->current_y = openfile->current->lineno -
3073 openfile->edittop->lineno;
3074 if (openfile->current_y < editwinrows) {
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003075 size_t x = xplustabs();
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003076 wmove(edit, openfile->current_y, x - get_page_start(x));
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003077 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003078}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003079
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003080/* edit_add() takes care of the job of actually painting a line into the
3081 * edit window. fileptr is the line to be painted, at row yval of the
3082 * window. converted is the actual string to be written to the window,
3083 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003084 * characters. start is the column number of the first character of
3085 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003086 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003087void edit_add(const filestruct *fileptr, const char *converted, int
3088 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003089{
David Lawrence Ramseyad96aff2005-02-22 23:22:37 +00003090#if !defined(NANO_SMALL) || defined(ENABLE_COLOR)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003091 size_t startpos = actual_x(fileptr->data, start);
3092 /* The position in fileptr->data of the leftmost character
3093 * that displays at least partially on the window. */
3094 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3095 /* The position in fileptr->data of the first character that is
3096 * completely off the window to the right.
3097 *
3098 * Note that endpos might be beyond the null terminator of the
3099 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003100#endif
3101
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003102 assert(openfile != NULL && fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003103 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003104
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003105 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003106 * just the text that needs it). */
3107 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003108
Chris Allegretta7dd77682001-12-08 19:52:28 +00003109#ifdef ENABLE_COLOR
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003110 /* If color syntaxes are available and turned on, we need to display
3111 * them. */
3112 if (openfile->colorstrings != NULL && !ISSET(NO_COLOR_SYNTAX)) {
3113 const colortype *tmpcolor = openfile->colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003114
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003115 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3116 int x_start;
3117 /* Starting column for mvwaddnstr. Zero-based. */
3118 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003119 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003120 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003121 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003122 /* Index in converted where we paint. */
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003123 regmatch_t startmatch;
3124 /* Match position for start_regex. */
3125 regmatch_t endmatch;
3126 /* Match position for end_regex. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003127
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003128 if (tmpcolor->bright)
3129 wattron(edit, A_BOLD);
3130 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003131 /* Two notes about regexec(). Return value 0 means there is
3132 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003133 * after the match. */
3134
3135 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003136 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003137 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003138
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003139 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003140 * last match. Even though two matches may overlap, we
3141 * want to ignore them, so that we can highlight
3142 * C-strings correctly. */
3143 while (k < endpos) {
3144 /* Note the fifth parameter to regexec(). It says
3145 * not to match the beginning-of-line character
3146 * unless k is 0. If regexec() returns REG_NOMATCH,
3147 * there are no more matches in the line. */
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003148 if (regexec(tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003149 &startmatch, (k == 0) ? 0 :
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003150 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003151 break;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003152 /* Translate the match to the beginning of the
3153 * line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003154 startmatch.rm_so += k;
3155 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003156 if (startmatch.rm_so == startmatch.rm_eo) {
3157 startmatch.rm_eo++;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003158 statusbar(
3159 _("Refusing zero-length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003160 } else if (startmatch.rm_so < endpos &&
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003161 startmatch.rm_eo > startpos) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003162 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003163 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003164 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003165 x_start = strnlenpt(fileptr->data,
3166 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003167
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003168 index = actual_x(converted, x_start);
3169
3170 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003171 strnlenpt(fileptr->data,
3172 startmatch.rm_eo) - start - x_start);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003173
3174 assert(0 <= x_start && 0 <= paintlen);
3175
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003176 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003177 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003178 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003179 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003180 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003181 } else {
David Lawrence Ramsey85f6a2d2005-06-26 22:59:54 +00003182 /* This is a multi-line regex. There are two steps.
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003183 * First, we have to see if the beginning of the line is
3184 * colored by a start on an earlier line, and an end on
3185 * this line or later.
3186 *
3187 * We find the first line before fileptr matching the
3188 * start. If every match on that line is followed by an
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003189 * end, then go to step two. Otherwise, find the next
3190 * line after start_line matching the end. If that line
3191 * is not before fileptr, then paint the beginning of
3192 * this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003193 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003194 /* The first line before fileptr matching start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003195 regoff_t start_col;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003196 /* Where it starts in that line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003197 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003198
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003199 while (start_line != NULL && regexec(tmpcolor->start,
3200 start_line->data, 1, &startmatch,
3201 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202 /* If there is an end on this line, there is no need
3203 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003204 if (regexec(tmpcolor->end, start_line->data, 0,
3205 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003206 goto step_two;
3207 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003208 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003209 /* No start found, so skip to the next step. */
3210 if (start_line == NULL)
3211 goto step_two;
3212 /* Now start_line is the first line before fileptr
3213 * containing a start match. Is there a start on this
3214 * line not followed by an end on this line? */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003215 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003216 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003217 start_col += startmatch.rm_so;
3218 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003219 if (regexec(tmpcolor->end, start_line->data +
3220 start_col + startmatch.rm_eo, 0, NULL,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003221 (start_col + startmatch.rm_eo == 0) ? 0 :
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003222 REG_NOTBOL) == REG_NOMATCH)
3223 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003224 break;
3225 start_col++;
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003226 if (regexec(tmpcolor->start, start_line->data +
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003227 start_col, 1, &startmatch,
3228 REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003229 /* No later start on this line. */
3230 goto step_two;
3231 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003232 /* Indeed, there is a start not followed on this line by
3233 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003234
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003235 /* We have already checked that there is no end before
3236 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003237 * the start at all? We don't paint unterminated
3238 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003239 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003240 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003241 regexec(tmpcolor->end, end_line->data, 1,
3242 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003243 end_line = end_line->next;
3244
3245 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003246 if (end_line == NULL || (end_line == fileptr &&
3247 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003248 goto step_two;
3249
3250 /* Now paint the start of fileptr. */
David Lawrence Ramsey0c9df572005-01-12 16:20:18 +00003251 if (end_line != fileptr)
3252 /* If the start of fileptr is on a different line
3253 * from the end, paintlen is -1, meaning that
3254 * everything on the line gets painted. */
3255 paintlen = -1;
3256 else
3257 /* Otherwise, paintlen is the expanded location of
3258 * the end of the match minus the expanded location
3259 * of the beginning of the page. */
3260 paintlen = actual_x(converted,
3261 strnlenpt(fileptr->data, endmatch.rm_eo) -
3262 start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003263
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003264 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003265
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003266 step_two:
3267 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003268 start_col = 0;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003269
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003270 while (start_col < endpos) {
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003271 if (regexec(tmpcolor->start, fileptr->data +
3272 start_col, 1, &startmatch, (start_col == 0) ?
3273 0 : REG_NOTBOL) == REG_NOMATCH || start_col +
3274 startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003275 /* No more starts on this line. */
3276 break;
3277 /* Translate the match to be relative to the
3278 * beginning of the line. */
3279 startmatch.rm_so += start_col;
3280 startmatch.rm_eo += start_col;
3281
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003282 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003283 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003284 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003285 x_start = strnlenpt(fileptr->data,
3286 startmatch.rm_so) - start;
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003287
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003288 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003289
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003290 if (regexec(tmpcolor->end,
3291 fileptr->data + startmatch.rm_eo, 1, &endmatch,
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003292 (startmatch.rm_eo == 0) ? 0 :
3293 REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003294 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003295 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003296 endmatch.rm_so += startmatch.rm_eo;
3297 endmatch.rm_eo += startmatch.rm_eo;
3298 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003299 * appear on this page, and is the match more
3300 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003301 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003303 paintlen = actual_x(converted + index,
David Lawrence Ramseyc1e3d942005-01-12 18:23:09 +00003304 strnlenpt(fileptr->data,
3305 endmatch.rm_eo) - start - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003306
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003307 assert(0 <= x_start && x_start < COLS);
3308
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003309 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003310 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003311 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003312 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003313 /* There is no end on this line. But we haven't
3314 * yet looked for one on later lines. */
3315 end_line = fileptr->next;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003316
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003317 while (end_line != NULL &&
3318 regexec(tmpcolor->end, end_line->data,
3319 0, NULL, 0) == REG_NOMATCH)
3320 end_line = end_line->next;
3321
3322 if (end_line != NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003323 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003324
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003325 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003326 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003327 /* We painted to the end of the line, so
3328 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003329 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003330 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003331 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003332 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003333 }
3334 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003335
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003336 wattroff(edit, A_BOLD);
3337 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey202d3c22005-03-10 20:55:11 +00003338 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003339 }
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003340#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003341
Chris Allegretta7dd77682001-12-08 19:52:28 +00003342#ifndef NANO_SMALL
David Lawrence Ramseydb958022005-07-13 20:18:46 +00003343 /* If the mark is on, we need to display it. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003344 if (openfile->mark_set && (fileptr->lineno <=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003345 openfile->mark_begin->lineno || fileptr->lineno <=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003346 openfile->current->lineno) && (fileptr->lineno >=
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003347 openfile->mark_begin->lineno || fileptr->lineno >=
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003348 openfile->current->lineno)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003349 /* fileptr is at least partially selected. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003350 const filestruct *top;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003351 /* Either current or mark_begin, whichever is first. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003352 size_t top_x;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003353 /* current_x or mark_begin_x, corresponding to top. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003354 const filestruct *bot;
3355 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003356 int x_start;
David Lawrence Ramsey5128de82005-07-12 17:40:16 +00003357 /* Starting column for mvwaddnstr(). Zero-based. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003358 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003359 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003360 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003361 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003362 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003363
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003364 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003365
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003366 if (top->lineno < fileptr->lineno || top_x < startpos)
3367 top_x = startpos;
3368 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3369 bot_x = endpos;
3370
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003371 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003372 if (top_x < endpos && bot_x > startpos) {
3373 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003374
3375 /* x_start is the expanded location of the beginning of the
3376 * mark minus the beginning of the page. */
3377 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003378
3379 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003380 /* If the end of the mark is off the page, paintlen is
3381 * -1, meaning that everything on the line gets
3382 * painted. */
3383 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003384 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003385 /* Otherwise, paintlen is the expanded location of the
3386 * end of the mark minus the expanded location of the
3387 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003388 paintlen = strnlenpt(fileptr->data, bot_x) -
3389 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003390
3391 /* If x_start is before the beginning of the page, shift
3392 * paintlen x_start characters to compensate, and put
3393 * x_start at the beginning of the page. */
3394 if (x_start < 0) {
3395 paintlen += x_start;
3396 x_start = 0;
3397 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003398
3399 assert(x_start >= 0 && x_start <= strlen(converted));
3400
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003401 index = actual_x(converted, x_start);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003402
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003403 if (paintlen > 0)
3404 paintlen = actual_x(converted + index, paintlen);
3405
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003406 wattron(edit, A_REVERSE);
David Lawrence Ramsey14ace172005-01-24 21:51:07 +00003407 mvwaddnstr(edit, yval, x_start, converted + index,
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003408 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003409 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003410 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003411 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003412#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003413}
3414
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003415/* Just update one line in the edit buffer. This is basically a wrapper
3416 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003417 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003418 * If fileptr != current, then index is considered 0. The line will be
3419 * displayed starting with fileptr->data[index]. Likely args are
3420 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003421void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003422{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003423 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003424 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003425 char *converted;
3426 /* fileptr->data converted to have tabs and control characters
3427 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003428 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003429
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003430 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003431
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003432 line = fileptr->lineno - openfile->edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003433
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003434 /* We assume the line numbers are valid. Is that really true? */
3435 assert(line < 0 || line == check_linenumbers(fileptr));
3436
3437 if (line < 0 || line >= editwinrows)
3438 return;
3439
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003440 /* First, blank out the line. */
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003441 blank_line(edit, line, 0, COLS);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003442
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003443 /* Next, convert variables that index the line to their equivalent
3444 * positions in the expanded line. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003445 index = (fileptr == openfile->current) ? strnlenpt(fileptr->data,
3446 index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003447 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003448
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003449 /* Expand the line, replacing tabs with spaces, and control
3450 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003451 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003452
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003453 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003454 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003455 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003456
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003457 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003458 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003459 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003460 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003461}
3462
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003463/* Return a nonzero value if we need an update after moving
3464 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003465 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003466int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003467{
3468 return
3469#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003470 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003471#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003472 get_page_start(old_pww) !=
3473 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003474}
3475
3476/* Return a nonzero value if we need an update after moving vertically.
3477 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003478 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003479int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003480{
3481 return
3482#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003483 openfile->mark_set ||
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003484#endif
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003485 get_page_start(old_pww) !=
3486 get_page_start(openfile->placewewant);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003487}
3488
3489/* Scroll the edit window in the given direction and the given number
3490 * of lines, and draw new lines on the blank lines left after the
3491 * scrolling. direction is the direction to scroll, either UP or DOWN,
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003492 * and nlines is the number of lines to scroll. We change edittop, and
3493 * assume that current and current_x are up to date. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003494void edit_scroll(updown direction, int nlines)
3495{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003496 bool do_redraw = need_vertical_update(0);
David Lawrence Ramsey443a7662005-07-14 23:06:22 +00003497 const filestruct *foo;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003498 int i;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003499
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003500 /* Don't bother scrolling less than one line. */
3501 if (nlines < 1)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003502 return;
3503
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003504 /* Part 1: nlines is the number of lines we're going to scroll the
3505 * text of the edit window. */
3506
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003507 /* Move the top line of the edit window up or down (depending on the
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003508 * value of direction) nlines lines, or as many lines as we can if
3509 * there are fewer than nlines lines available. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003510 for (i = nlines; i > 0; i--) {
3511 if (direction == UP) {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003512 if (openfile->edittop->prev == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003513 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003514 openfile->edittop = openfile->edittop->prev;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003515 } else {
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003516 if (openfile->edittop->next == NULL)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003517 break;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003518 openfile->edittop = openfile->edittop->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003519 }
3520 }
3521
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003522 /* Limit nlines to a minimum of the number of lines we could scroll,
3523 * and to a maximum of the number of lines in the edit window. */
3524 nlines -= i;
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003525 if (nlines > editwinrows)
3526 nlines = editwinrows;
3527
3528 /* Scroll the text of the edit window up or down nlines lines,
3529 * depending on the value of direction. */
David Lawrence Ramsey47bb8882005-07-22 22:56:03 +00003530 scrollok(edit, TRUE);
3531 wscrl(edit, (direction == UP) ? -nlines : nlines);
3532 scrollok(edit, FALSE);
3533
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003534 /* Part 2: nlines is the number of lines in the scrolled region of
3535 * the edit window that we need to draw. */
3536
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003537 /* If we scrolled up, we couldn't scroll up all nlines lines, and
David Lawrence Ramseyc0097592005-07-22 23:17:19 +00003538 * we're now at the top of the file, we need to draw the entire edit
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003539 * window. */
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003540 if (direction == UP && i > 0 && openfile->edittop ==
3541 openfile->fileage)
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003542 nlines = editwinrows;
David Lawrence Ramseya7f488b2005-07-17 02:19:47 +00003543
David Lawrence Ramsey945a9132005-07-23 21:06:22 +00003544 /* If the scrolled region contains only one line, and the line
3545 * before it is visible in the edit window, we need to draw it too.
3546 * If the scrolled region contains more than one line, and the lines
3547 * before and after the scrolled region are visible in the edit
3548 * window, we need to draw them too. */
3549 if (nlines == 1)
3550 nlines++;
3551 else
3552 nlines += 2;
David Lawrence Ramseyde0c5eb2005-07-17 22:51:44 +00003553 if (nlines > editwinrows)
3554 nlines = editwinrows;
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003555
3556 /* If we scrolled up, we're on the line before the scrolled
3557 * region. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003558 foo = openfile->edittop;
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003559
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003560 /* If we scrolled down, move down to the line before the scrolled
3561 * region. */
David Lawrence Ramsey14588912005-07-14 20:37:01 +00003562 if (direction == DOWN) {
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003563 for (i = editwinrows - nlines; i > 0 && foo != NULL; i--)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003564 foo = foo->next;
3565 }
3566
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003567 /* Draw new lines on any blank lines before or inside the scrolled
3568 * region. If we scrolled down and we're on the top line, or if we
3569 * scrolled up and we're on the bottom line, the line won't be
3570 * blank, so we don't need to draw it unless the mark is on or we're
3571 * not on the first page. */
3572 for (i = nlines; i > 0 && foo != NULL; i--) {
3573 if ((i == nlines && direction == DOWN) || (i == 1 &&
3574 direction == UP)) {
3575 if (do_redraw)
3576 update_line(foo, (foo == openfile->current) ?
3577 openfile->current_x : 0);
3578 } else
3579 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey4d464372005-07-16 22:50:30 +00003580 openfile->current_x : 0);
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003581 foo = foo->next;
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003582 }
3583}
3584
3585/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003586 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003587void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003588{
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003589 bool do_redraw = need_vertical_update(0) ||
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003590 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003591 const filestruct *foo;
3592
3593 /* If either old_current or current is offscreen, refresh the screen
3594 * and get out. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003595 if (old_current->lineno < openfile->edittop->lineno ||
3596 old_current->lineno >= openfile->edittop->lineno +
3597 editwinrows || openfile->current->lineno <
3598 openfile->edittop->lineno || openfile->current->lineno >=
3599 openfile->edittop->lineno + editwinrows) {
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003600 edit_refresh();
3601 return;
3602 }
3603
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003604 /* Update old_current and current if we're not on the first page
3605 * and/or we're not on the same page as before. If the mark is on,
3606 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003607 foo = old_current;
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003608
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003609 while (foo != openfile->current) {
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003610 if (do_redraw)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003611 update_line(foo, 0);
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003612
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003613#ifndef NANO_SMALL
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003614 if (!openfile->mark_set)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003615#endif
3616 break;
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003617
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003618#ifndef NANO_SMALL
David Lawrence Ramseye5806be2005-07-16 02:12:18 +00003619 foo = (foo->lineno > openfile->current->lineno) ? foo->prev :
3620 foo->next;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003621#endif
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003622 }
David Lawrence Ramseyf00c9612005-07-14 18:01:08 +00003623
David Lawrence Ramsey27865302005-07-23 20:39:41 +00003624 if (do_redraw)
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003625 update_line(openfile->current, openfile->current_x);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003626}
3627
Chris Allegretta6df90f52002-07-19 01:08:59 +00003628/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003629void edit_refresh(void)
3630{
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003631 const filestruct *foo;
3632 int nlines;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003633
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003634 if (openfile->current->lineno < openfile->edittop->lineno ||
3635 openfile->current->lineno >= openfile->edittop->lineno +
3636 editwinrows)
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003637 /* Put the top line of the edit window in range of the current
3638 * line. */
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003639 edit_update(
3640#ifndef NANO_SMALL
David Lawrence Ramseyb2b69762005-06-16 02:13:10 +00003641 ISSET(SMOOTH_SCROLL) ? NONE :
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003642#endif
3643 CENTER);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003644
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003645 foo = openfile->edittop;
3646
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003647#ifdef DEBUG
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003648 fprintf(stderr, "edit_refresh(): edittop->lineno = %ld\n", (long)openfile->edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003649#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003650
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003651 for (nlines = 0; nlines < editwinrows && foo != NULL; nlines++) {
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003652 update_line(foo, (foo == openfile->current) ?
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003653 openfile->current_x : 0);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003654 foo = foo->next;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003655 }
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003656
David Lawrence Ramsey157ce912005-07-16 23:36:10 +00003657 for (; nlines < editwinrows; nlines++)
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003658 blank_line(edit, nlines, 0, COLS);
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003659
3660 reset_cursor();
3661 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003662}
3663
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003664/* Move edittop to put it in range of current, keeping current in the
3665 * same place. location determines how we move it: if it's CENTER, we
3666 * center current, and if it's NONE, we put current current_y lines
3667 * below edittop. */
3668void edit_update(centernone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003669{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003670 filestruct *foo = openfile->current;
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003671 int goal;
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003672
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003673 /* If location is CENTER, we move edittop up (editwinrows / 2)
3674 * lines. This puts current at the center of the screen. If
3675 * location is NONE, we move edittop up current_y lines if current_y
3676 * is in range of the screen, 0 lines if current_y is less than 0,
3677 * or (editwinrows - 1) lines if current_y is greater than
3678 * (editwinrows - 1). This puts current at the same place on the
3679 * screen as before, or at the top or bottom of the screen if
3680 * edittop is beyond either. */
3681 if (location == CENTER)
3682 goal = editwinrows / 2;
3683 else {
3684 goal = openfile->current_y;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003685
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003686 /* Limit goal to (editwinrows - 1) lines maximum. */
3687 if (goal > editwinrows - 1)
3688 goal = editwinrows - 1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003689 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003690
David Lawrence Ramsey5b44f372005-07-16 22:47:12 +00003691 for (; goal > 0 && foo->prev != NULL; goal--)
3692 foo = foo->prev;
3693
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003694 openfile->edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003695}
3696
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003697/* Ask a simple yes/no question, specified in msg, on the statusbar.
3698 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3699 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003700int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003701{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003702 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003703 const char *yesstr; /* String of yes characters accepted. */
3704 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003705 const char *allstr; /* And all, surprise! */
David Lawrence Ramsey3f301dd2005-06-21 19:47:39 +00003706
3707 assert(msg != NULL);
Chris Allegretta235ab192001-04-12 13:24:40 +00003708
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003709 /* yesstr, nostr, and allstr are strings of any length. Each string
David Lawrence Ramseydcb4e3a2005-04-08 20:27:02 +00003710 * consists of all single-byte characters accepted as valid
3711 * characters for that value. The first value will be the one
3712 * displayed in the shortcuts. Translators: if possible, specify
3713 * both the shortcuts for your language and English. For example,
3714 * in French: "OoYy" for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003715 yesstr = _("Yy");
3716 nostr = _("Nn");
3717 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003718
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003719 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003720 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003721
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003722 if (COLS < 32)
3723 width = COLS / 2;
3724
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003725 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003726 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003727
Chris Allegretta6232d662002-05-12 19:52:15 +00003728 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003729 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003730 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003731
3732 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003733 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003734 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003735 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003736 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003737
Chris Allegrettadb28e962003-01-28 01:23:40 +00003738 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003739 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003740 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003741
Chris Allegrettadb28e962003-01-28 01:23:40 +00003742 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003743 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003744 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003745
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003746 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003747
3748 blank_statusbar();
David Lawrence Ramseyd4ea5b62005-06-21 21:03:06 +00003749 mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
Chris Allegretta8ce24132001-04-30 11:28:46 +00003750
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003751 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003752
David Lawrence Ramsey73bf89f2005-06-30 05:56:39 +00003753 /* Refresh the edit window and the statusbar before getting
3754 * input. */
3755 wnoutrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003756 wrefresh(bottomwin);
3757
Chris Allegrettadb28e962003-01-28 01:23:40 +00003758 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003759 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003760 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003761#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003762 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003763#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003764
David Lawrence Ramsey44e0c032005-06-29 19:01:11 +00003765 kbinput = get_kbinput(bottomwin, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003766
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003767 if (kbinput == NANO_REFRESH_KEY) {
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003768 total_redraw();
David Lawrence Ramseyda331532005-06-06 17:00:08 +00003769 continue;
3770 } else if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003771 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003772#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003773 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003774 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003775
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003776 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003777 wenclose(bottomwin, mouse_y, mouse_x) &&
3778 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003779 int x = mouse_x / width;
3780 /* Did we click in the first column of shortcuts, or
3781 * the second? */
3782 int y = mouse_y - editwinrows - 3;
3783 /* Did we click in the first row of shortcuts? */
3784
3785 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3786
3787 /* x = 0 means they clicked Yes or No.
3788 * y = 0 means Yes or All. */
3789 ok = -2 * x * y + x - y + 1;
3790
3791 if (ok == 2 && !all)
3792 ok = -2;
3793 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003794 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003795#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003796 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003797 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003798 else if (strchr(yesstr, kbinput) != NULL)
3799 ok = 1;
3800 else if (strchr(nostr, kbinput) != NULL)
3801 ok = 0;
3802 else if (all && strchr(allstr, kbinput) != NULL)
3803 ok = 2;
3804 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003805
Chris Allegrettadb28e962003-01-28 01:23:40 +00003806 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003807}
3808
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003809void total_redraw(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003810{
David Lawrence Ramseyb386a902005-07-10 02:37:38 +00003811#ifdef USE_SLANG
3812 /* Slang curses emulation brain damage, part 3: Slang doesn't define
3813 * curscr. */
3814 SLsmg_touch_screen();
3815 SLsmg_refresh();
3816#else
3817 wrefresh(curscr);
3818#endif
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003819}
3820
3821void total_refresh(void)
3822{
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003823 total_redraw();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003824 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003825 edit_refresh();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003826 bottombars(currshortcut);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003827}
3828
3829void display_main_list(void)
3830{
3831 bottombars(main_list);
3832}
3833
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003834/* If constant is TRUE, we display the current cursor position only if
3835 * disable_cursorpos is FALSE. Otherwise, we display it
3836 * unconditionally and set disable_cursorpos to FALSE. If constant is
3837 * TRUE and disable_cursorpos is TRUE, we also set disable_cursorpos to
3838 * FALSE, so that we leave the current statusbar alone this time, and
3839 * display the current cursor position next time. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003840void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003841{
David Lawrence Ramsey23c44502005-01-27 20:49:07 +00003842 char c;
3843 filestruct *f;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003844 size_t i, cur_xpt = xplustabs() + 1;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003845 size_t cur_lenpt = strlenpt(openfile->current->data) + 1;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003846 int linepct, colpct, charpct;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003847
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003848 assert(openfile->current != NULL && openfile->fileage != NULL && openfile->totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003849
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003850 c = openfile->current->data[openfile->current_x];
3851 f = openfile->current->next;
3852 openfile->current->data[openfile->current_x] = '\0';
3853 openfile->current->next = NULL;
David Lawrence Ramseyc104ef12005-07-17 01:44:35 +00003854 i = get_totsize(openfile->fileage, openfile->current);
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003855 openfile->current->data[openfile->current_x] = c;
3856 openfile->current->next = f;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003857
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003858 /* Check whether totsize is correct. If it isn't, there is a bug
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003859 * somewhere. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003860 assert(openfile->current != openfile->filebot || i == openfile->totsize);
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003861
David Lawrence Ramseyea014742005-06-17 18:27:00 +00003862 if (constant && disable_cursorpos) {
3863 disable_cursorpos = FALSE;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003864 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003865 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003866
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003867 /* Display the current cursor position on the statusbar, and set
3868 * disable_cursorpos to FALSE. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003869 linepct = 100 * openfile->current->lineno / openfile->totlines;
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003870 colpct = 100 * cur_xpt / cur_lenpt;
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003871 charpct = (openfile->totsize == 0) ? 0 : 100 * i /
3872 openfile->totsize;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003873
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003874 statusbar(
3875 _("line %ld/%lu (%d%%), col %lu/%lu (%d%%), char %lu/%lu (%d%%)"),
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003876 (long)openfile->current->lineno,
3877 (unsigned long)openfile->totlines, linepct,
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003878 (unsigned long)cur_xpt, (unsigned long)cur_lenpt, colpct,
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00003879 (unsigned long)i, (unsigned long)openfile->totsize, charpct);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003880
David Lawrence Ramsey4e05b752005-06-28 20:04:14 +00003881 disable_cursorpos = FALSE;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003882}
3883
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003884void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003885{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003886 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003887}
3888
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003889#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003890/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003891size_t help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003892{
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003893 int help_cols = (COLS > 24) ? COLS - 8 : 24;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003894
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003895 /* Try to break the line at (COLS - 8) columns if we have more than
David Lawrence Ramseycf4db892005-03-22 03:59:32 +00003896 * 24 columns, and at 24 columns otherwise. */
David Lawrence Ramsey40e211b2005-03-19 21:15:30 +00003897 size_t retval = break_line(ptr, help_cols, TRUE);
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003898 size_t retval_save = retval;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003899
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003900 /* Get the length of the entire line up to a null or a newline. */
3901 while (*(ptr + retval) != '\0' && *(ptr + retval) != '\n')
3902 retval += move_mbright(ptr + retval, 0);
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003903
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00003904 /* If the entire line doesn't go more than 8 columns beyond where we
3905 * tried to break it, we should display it as-is. Otherwise, we
3906 * should display it only up to the break. */
3907 if (strnlenpt(ptr, retval) > help_cols + 8)
3908 retval = retval_save;
3909
3910 return retval;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003911}
3912
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003913/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003914void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003915{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003916 int line = 0;
David Lawrence Ramseyeb4d81f2005-03-01 22:47:00 +00003917 /* The line number in help_text of the first displayed help
3918 * line. This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003919 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003920 /* no_more means the end of the help text is shown, so don't go
3921 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003922 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003923 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003924
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003925 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003926#ifndef DISABLE_MOUSE
3927 const shortcut *oldshortcut = currshortcut;
3928 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003929 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003930#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003931
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003932 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003933 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003934 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003935 blank_statusbar();
3936
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003937 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003938 help_init();
David Lawrence Ramsey85616c42005-03-17 18:11:08 +00003939
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003940 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003941
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003942#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003943 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003944 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003945 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003946#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003947
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003948 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003949 /* Make sure that the help screen's shortcut list will actually
3950 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003951 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003952 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003953 }
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00003954
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003955 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003956
3957 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003958 int i;
3959 int old_line = line;
3960 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003961 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003962
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003963 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003964#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003965 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003966 {
3967 int mouse_x, mouse_y;
3968 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3969 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003970 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003971#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003972 case NANO_PREVPAGE_KEY:
3973 case NANO_PREVPAGE_FKEY:
3974 if (line > 0) {
3975 line -= editwinrows - 2;
3976 if (line < 0)
3977 line = 0;
3978 }
3979 break;
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00003980 case NANO_NEXTPAGE_KEY:
3981 case NANO_NEXTPAGE_FKEY:
3982 if (!no_more)
3983 line += editwinrows - 2;
3984 break;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003985 case NANO_PREVLINE_KEY:
3986 if (line > 0)
3987 line--;
3988 break;
3989 case NANO_NEXTLINE_KEY:
3990 if (!no_more)
3991 line++;
3992 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003993 }
3994
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003995 if (kbinput == NANO_REFRESH_KEY)
David Lawrence Ramseyc54c4d12005-06-18 15:49:17 +00003996 total_redraw();
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00003997 else {
3998 if (line == old_line && kbinput != ERR)
3999 goto skip_redisplay;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004000
David Lawrence Ramseyb9ddb802005-03-17 17:56:48 +00004001 blank_edit();
4002 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004003
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004004 /* Calculate where in the text we should be, based on the
4005 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004006 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004007 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004008 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004009 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004010 }
4011
Chris Allegretta4640fe32003-02-10 03:10:03 +00004012 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey9bd56202005-03-18 21:29:33 +00004013 size_t j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004014
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004015 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004016 ptr += j;
4017 if (*ptr == '\n')
4018 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004019 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004020 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00004021
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004022 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00004023 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey9cf1df12005-04-19 03:15:21 +00004024 } while (kbinput != NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00004025
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004026#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00004027 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004028#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00004029
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00004030 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00004031 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00004032 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004033 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00004034 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00004035 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004036 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004037
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00004038 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004039 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00004040
David Lawrence Ramsey52453442004-06-26 15:24:16 +00004041 /* The help_init() at the beginning allocated help_text. Since
4042 * help_text has now been written to the screen, we don't need it
4043 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00004044 free(help_text);
4045 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004046}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00004047#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004048
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004049/* Highlight the current word being replaced or spell checked. We
4050 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004051void do_replace_highlight(bool highlight, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004052{
David Lawrence Ramsey6168cb72005-06-30 03:53:28 +00004053 size_t y = xplustabs(), word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004054
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004055 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004056 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004057 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004058
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004059 assert(y > 0);
4060
4061 if (word_len > y)
4062 y--;
4063
Chris Allegrettafb62f732000-12-05 11:36:41 +00004064 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004065
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004066 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004067 wattron(edit, A_REVERSE);
4068
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004069#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004070 /* This is so we can show zero-length regexes. */
4071 if (word_len == 0)
David Lawrence Ramsey5b9f5222005-06-13 02:22:44 +00004072 waddch(edit, ' ');
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004073 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004074#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004075 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004076
4077 if (word_len > y)
4078 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004079
David Lawrence Ramsey7bde0532005-06-30 03:55:55 +00004080 if (highlight)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004081 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004082}
4083
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004084#ifndef NDEBUG
4085/* Return what the current line number should be, starting at edittop
4086 * and ending at fileptr. */
4087int check_linenumbers(const filestruct *fileptr)
4088{
4089 int check_line = 0;
4090 const filestruct *filetmp;
4091
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004092 for (filetmp = openfile->edittop; filetmp != fileptr;
4093 filetmp = filetmp->next)
David Lawrence Ramseycc814362005-06-05 19:08:59 +00004094 check_line++;
4095
4096 return check_line;
4097}
4098#endif
4099
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004100#ifdef DEBUG
David Lawrence Ramsey1e64db62005-06-14 23:38:41 +00004101/* Dump the filestruct inptr to stderr. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004102void dump_filestruct(const filestruct *inptr)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004103{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004104 if (inptr == openfile->fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004105 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004106 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004107 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004108 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004109 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004110
4111 while (inptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004112 fprintf(stderr, "(%ld) %s\n", (long)inptr->lineno, inptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004113 inptr = inptr->next;
4114 }
4115}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004116
David Lawrence Ramsey4c221672005-07-17 15:40:49 +00004117/* Dump the current buffer's filestruct to stderr in reverse. */
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004118void dump_filestruct_reverse(void)
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004119{
David Lawrence Ramsey6ad59cd2005-07-08 20:09:16 +00004120 const filestruct *fileptr = openfile->filebot;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004121
4122 while (fileptr != NULL) {
David Lawrence Ramsey2cf6d712005-06-28 06:25:34 +00004123 fprintf(stderr, "(%ld) %s\n", (long)fileptr->lineno,
4124 fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004125 fileptr = fileptr->prev;
4126 }
4127}
4128#endif /* DEBUG */
4129
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004130#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004131#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004132#define XLCREDIT_LEN 8
4133
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004134/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004135void do_credits(void)
4136{
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004137 int kbinput = ERR, crpos = 0, xlpos = 0;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004138 const char *credits[CREDIT_LEN] = {
4139 NULL, /* "The nano text editor" */
4140 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004141 VERSION,
4142 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004143 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004144 "Chris Allegretta",
4145 "Jordi Mallach",
4146 "Adam Rogoyski",
4147 "Rob Siemborski",
4148 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004149 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004150 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004151 "Ken Tyler",
4152 "Sven Guckes",
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004153 NULL, /* credits[14], handled below. */
Chris Allegretta598106e2002-01-19 01:59:37 +00004154 "Pauli Virtanen",
4155 "Daniele Medri",
4156 "Clement Laforet",
4157 "Tedi Heriyanto",
4158 "Bill Soudan",
4159 "Christian Weisgerber",
4160 "Erik Andersen",
4161 "Big Gaute",
4162 "Joshua Jensen",
4163 "Ryan Krebs",
4164 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004165 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004166 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004167 "Plattsburgh State University",
4168 "Benet Laboratories",
4169 "Amy Allegretta",
4170 "Linda Young",
4171 "Jeremy Robichaud",
4172 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004173 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004174 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004175 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004176 "Thomas Dickey",
4177 "Pavel Curtis",
4178 "Zeyd Ben-Halim",
4179 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004180 NULL, /* "and anyone else we forgot..." */
4181 NULL, /* "Thank you for using nano!" */
4182 "",
4183 "",
4184 "",
4185 "",
David Lawrence Ramseyea9370f2005-01-12 19:29:44 +00004186 "(c) 1999-2005 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004187 "",
4188 "",
4189 "",
4190 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004191 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004192 };
4193
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004194 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004195 N_("The nano text editor"),
4196 N_("version"),
4197 N_("Brought to you by:"),
4198 N_("Special thanks to:"),
4199 N_("The Free Software Foundation"),
4200 N_("For ncurses:"),
4201 N_("and anyone else we forgot..."),
4202 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004203 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004204
David Lawrence Ramseyb2072b02005-06-28 14:59:38 +00004205 /* credits[14]: Make sure this name is displayed properly, since we
David Lawrence Ramsey62d616b2005-07-06 19:20:32 +00004206 * can't dynamically assign it above, using Unicode 00F6 (Latin
4207 * Small Letter O with Diaresis) if applicable. */
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004208 credits[14] =
David Lawrence Ramsey7eb30a82005-07-17 02:40:07 +00004209#ifdef ENABLE_UTF8
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004210 ISSET(USE_UTF8) ? "Florian K\xC3\xB6nig" :
4211#endif
4212 "Florian K\xF6nig";
4213
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004214 curs_set(0);
4215 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004216 scrollok(edit, TRUE);
4217 blank_titlebar();
David Lawrence Ramsey637b8bb2005-01-17 05:06:55 +00004218 blank_topbar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004219 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004220 blank_statusbar();
4221 blank_bottombars();
4222 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004223 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004224 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004225
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004226 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004227 if ((kbinput = wgetch(edit)) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004228 break;
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004229
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004230 if (crpos < CREDIT_LEN) {
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004231 const char *what;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004232 size_t start_x;
4233
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004234 if (credits[crpos] == NULL) {
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004235 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004236
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004237 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004238 xlpos++;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004239 } else
David Lawrence Ramsey9905b6a2005-06-28 07:26:11 +00004240 what = credits[crpos];
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004241
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004242 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramsey4dc58382005-03-15 06:58:02 +00004243 mvwaddstr(edit, editwinrows - 1 - (editwinrows % 2),
4244 start_x, what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004245 }
David Lawrence Ramsey0099a8f2005-03-15 06:34:09 +00004246
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004247 napms(700);
4248 scroll(edit);
4249 wrefresh(edit);
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004250 if ((kbinput = wgetch(edit)) != ERR)
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004251 break;
4252 napms(700);
4253 scroll(edit);
4254 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004255 }
4256
David Lawrence Ramsey3925bda2005-06-07 03:20:35 +00004257 if (kbinput != ERR)
4258 ungetch(kbinput);
4259
4260 curs_set(1);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004261 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004262 nodelay(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004263 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004264}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004265#endif