blob: 54aeaf27bee625186267e305e7f22a0ceb54db43 [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 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
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 *
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 * *
20 **************************************************************************/
21
Jordi Mallach55381aa2004-11-17 23:17:05 +000022#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
David Lawrence Ramseye21adfa2002-09-13 18:14:04 +000025
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000026#include <stdarg.h>
27#include <string.h>
Chris Allegrettadba37ae2000-07-07 05:13:09 +000028#include <stdlib.h>
Chris Allegretta8a0de3b2000-11-24 20:45:14 +000029#include <unistd.h>
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +000030#include <ctype.h>
Chris Allegretta6232d662002-05-12 19:52:15 +000031#include <assert.h>
Chris Allegrettaa2ea1932000-06-06 05:53:49 +000032#include "proto.h"
33#include "nano.h"
34
David Lawrence Ramsey93c4a562004-12-23 21:32:27 +000035#if defined(HAVE_WCHAR_H) && defined(NANO_WIDE)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +000036#include <wchar.h>
37#endif
38
David Lawrence Ramsey74835712004-12-04 17:41:52 +000039static buffer *key_buffer = NULL;
40 /* The default keystroke buffer,
41 * containing all the keystrokes we have
42 * at a given point. */
43static size_t key_buffer_len = 0;
44 /* The length of the default keystroke
45 * buffer. */
46static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000047 * we call statusbar(), before we
48 * actually blank the statusbar. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +000049static size_t statusbar_x = (size_t)-1;
50 /* The cursor position in answer. */
51static size_t statusbar_xend = 0;
52 /* The length of answer. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000053static bool resetstatuspos = FALSE;
54 /* Should we reset the cursor position
55 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000056
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000057/* Control character compatibility:
58 *
59 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
60 * VT100, and VT220.
61 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
62 * VT220, and VT320.
63 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
64 * VT220, and VT320.
65 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
66 * VT220, and VT320.
67 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
68 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000069 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000070 * ANSI, VT100, and VT220, and which is Backspace under VT320.
71 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000072 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000073 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
74 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000075 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000076 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000077 * on which the VT320 sequences are translated by the keypad to KEY_DC
78 * and [nothing]. We work around this conflict via the REBIND_DELETE
79 * flag: if it's not set, we assume VT320 compatibility, and if it is,
80 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
81 * Hemel for helping work this conflict out.
82 *
83 * Escape sequence compatibility:
84 *
85 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000086 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000087 * console), xterm, rxvt, and Eterm. Among these, there are several
88 * conflicts and omissions, outlined as follows:
89 *
90 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
91 * (Ctrl-I is also Tab on ANSI, which we already support.)
92 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
93 * NumLock off on Linux console; the latter is omitted. (The editing
94 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000095 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000096 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
97 * latter is omitted. (Mouse input will only work properly if the
98 * extended keypad value KEY_MOUSE is generated on mouse events
99 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000100 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000101 * omitted. (The editing keypad is more important to have working
102 * than the function keys, because the functions of the former are not
103 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000104 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000105 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000106 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000107 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000108 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
109 * omitted. (The arrow keys, with or without modifiers, are more
110 * important to have working than the function keys, because the
111 * functions of the former are not arbitrary and the functions of the
112 * latter are.)
113 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
114 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000115 *
116 * Note that Center (5) on the numeric keypad with NumLock off can also
117 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000118
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000119#ifndef NANO_SMALL
120/* Reset all the input routines that rely on character sequences. */
121void reset_kbinput(void)
122{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000123 parse_kbinput(NULL, NULL, NULL, TRUE);
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000124 get_byte_kbinput(0, TRUE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000125 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000126}
127#endif
128
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000129/* Read in a sequence of keystrokes from win and save them in the
130 * default keystroke buffer. This should only be called when the
131 * default keystroke buffer is empty. */
132void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000133{
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000134 int input, input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000135
136 /* If the keystroke buffer isn't empty, get out. */
137 if (key_buffer != NULL)
138 return;
139
140 /* Read in the first character using blocking input. */
141 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000142
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000143#ifndef NANO_SMALL
144 allow_pending_sigwinch(TRUE);
145#endif
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000146
147#ifdef NANO_WIDE
148 if (!ISSET(NO_UTF8)) {
149 wint_t tmp;
150
151 input_key_code = wget_wch(win, &tmp);
152 input = (int)tmp;
153 } else {
154#endif
155 input = wgetch(win);
156 input_key_code = !is_byte_char(input);
157#ifdef NANO_WIDE
158 }
159#endif
160
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000161#ifndef NANO_SMALL
162 allow_pending_sigwinch(FALSE);
163#endif
164
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000165 /* Increment the length of the keystroke buffer, save the value of
166 * the keystroke in key, and set key_code to TRUE if the keystroke
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000167 * is an extended keypad value or FALSE if it isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000168 key_buffer_len++;
169 key_buffer = (buffer *)nmalloc(sizeof(buffer));
170 key_buffer[0].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000171 key_buffer[0].key_code =
172#ifdef NANO_WIDE
173 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
174#endif
175 input_key_code;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000176
177 /* Read in the remaining characters using non-blocking input. */
178 nodelay(win, TRUE);
179
180 while (TRUE) {
181#ifndef NANO_SMALL
182 allow_pending_sigwinch(TRUE);
183#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000184
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000185#ifdef NANO_WIDE
186 if (!ISSET(NO_UTF8)) {
187 wint_t tmp;
188
189 input_key_code = wget_wch(win, &tmp);
190 input = (int)tmp;
191 } else {
192#endif
193 input = wgetch(win);
194 input_key_code = !is_byte_char(input);
195#ifdef NANO_WIDE
196 }
197#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000198 /* If there aren't any more characters, stop reading. */
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000199 if (
200#ifdef NANO_WIDE
201 (!ISSET(NO_UTF8) && input_key_code == ERR) ||
202#endif
203 input == ERR)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000204 break;
205
206 /* Otherwise, increment the length of the keystroke buffer, save
207 * the value of the keystroke in key, and set key_code to TRUE
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000208 * if the keystroke is an extended keypad value or FALSE if it
209 * isn't. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210 key_buffer_len++;
211 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
212 sizeof(buffer));
213 key_buffer[key_buffer_len - 1].key = input;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000214 key_buffer[key_buffer_len - 1].key_code =
215#ifdef NANO_WIDE
216 !ISSET(NO_UTF8) ? (input_key_code == KEY_CODE_YES) :
217#endif
218 input_key_code;
219
220#ifndef NANO_SMALL
221 allow_pending_sigwinch(FALSE);
222#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000223 }
224
225 /* Switch back to non-blocking input. */
226 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000227}
228
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000229/* Return the length of the default keystroke buffer. */
230size_t get_buffer_len(void)
231{
232 return key_buffer_len;
233}
234
235/* Return the key values stored in the keystroke buffer input,
236 * discarding the key_code values in it. */
237int *buffer_to_keys(buffer *input, size_t input_len)
238{
239 int *sequence = (int *)nmalloc(input_len * sizeof(int));
240 size_t i;
241
242 for (i = 0; i < input_len; i++)
243 sequence[i] = input[i].key;
244
245 return sequence;
246}
247
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +0000248/* Return the buffer equivalent of the key values in input, adding
249 * key_code values of FALSE to all of them. */
250buffer *keys_to_buffer(int *input, size_t input_len)
251{
252 buffer *sequence = (buffer *)nmalloc(input_len * sizeof(buffer));
253 size_t i;
254
255 for (i = 0; i < input_len; i++) {
256 sequence[i].key = input[i];
257 sequence[i].key_code = FALSE;
258 }
259
260 return sequence;
261}
262
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000263/* Add the contents of the keystroke buffer input to the default
264 * keystroke buffer. */
265void unget_input(buffer *input, size_t input_len)
266{
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000267 buffer *clean_input = NULL;
268 size_t clean_input_len = 0;
269
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000270#ifndef NANO_SMALL
271 allow_pending_sigwinch(TRUE);
272 allow_pending_sigwinch(FALSE);
273#endif
274
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000275#ifdef NANO_WIDE
276 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000277 size_t i;
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000278 char *key = charalloc(MB_CUR_MAX);
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000279
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000280 /* Keep all valid wide keystrokes, discarding the others. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000281 for (i = 0; i < input_len; i++) {
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000282 int key_len = input[i].key_code ? 1 :
David Lawrence Ramseyc2ac02f2004-12-09 03:05:45 +0000283 wctomb(key, (wchar_t)input[i].key);
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000284
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000285 if (key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000286 clean_input_len++;
287 clean_input = (buffer *)nrealloc(clean_input,
288 clean_input_len * sizeof(buffer));
289
290 clean_input[clean_input_len - 1].key = input[i].key;
291 clean_input[clean_input_len - 1].key_code =
292 input[i].key_code;
293 }
294 }
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000295
David Lawrence Ramsey78ea5e42004-12-12 19:04:56 +0000296 free(key);
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000297 } else {
298#endif
299 clean_input = input;
300 clean_input_len = input_len;
301#ifdef NANO_WIDE
302 }
303#endif
304
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000305 /* If input is empty, get out. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000306 if (clean_input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000307 return;
308
309 /* If adding input would put the default keystroke buffer beyond
310 * maximum capacity, only add enough of input to put it at maximum
311 * capacity. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000312 if (key_buffer_len + clean_input_len < key_buffer_len)
313 clean_input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000314
315 /* Add the length of input to the length of the default keystroke
316 * buffer, and reallocate the default keystroke buffer so that it
317 * has enough room for input. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000318 key_buffer_len += clean_input_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000319 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
320 sizeof(buffer));
321
322 /* If the default keystroke buffer wasn't empty before, move its
323 * beginning forward far enough so that we can add input to its
324 * beginning. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000325 if (key_buffer_len > clean_input_len)
326 memmove(key_buffer + clean_input_len, key_buffer,
327 (key_buffer_len - clean_input_len) * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000328
329 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000330 memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000331}
332
333/* Put back the character stored in kbinput. If func_key is TRUE and
334 * the character is out of byte range, interpret it as an extended
335 * keypad value. If meta_key is TRUE, put back the Escape character
336 * after putting back kbinput. */
337void unget_kbinput(int kbinput, bool meta_key, bool func_key)
338{
339 buffer input;
340
341 input.key = kbinput;
342 input.key_code = (func_key && !is_byte_char(kbinput));
343
344 unget_input(&input, 1);
345
346 if (meta_key) {
347 input.key = NANO_CONTROL_3;
348 input.key_code = FALSE;
349 unget_input(&input, 1);
350 }
351}
352
353/* Try to read input_len characters from the default keystroke buffer.
354 * If the default keystroke buffer is empty and win isn't NULL, try to
355 * read in more characters from win and add them to the default
356 * keystroke buffer before doing anything else. If the default
357 * keystroke buffer is empty and win is NULL, return NULL. */
358buffer *get_input(WINDOW *win, size_t input_len)
359{
360 buffer *input;
361
362#ifndef NANO_SMALL
363 allow_pending_sigwinch(TRUE);
364 allow_pending_sigwinch(FALSE);
365#endif
366
367 if (key_buffer_len == 0) {
368 if (win != NULL)
369 get_buffer(win);
370
371 if (key_buffer_len == 0)
372 return NULL;
373 }
374
375 /* If input_len is greater than the length of the default keystroke
376 * buffer, only read the number of characters in the default
377 * keystroke buffer. */
378 if (input_len > key_buffer_len)
379 input_len = key_buffer_len;
380
381 /* Subtract input_len from the length of the default keystroke
382 * buffer, and allocate the keystroke buffer input so that it
383 * has enough room for input_len keystrokes. */
384 key_buffer_len -= input_len;
385 input = (buffer *)nmalloc(input_len * sizeof(buffer));
386
387 /* Copy input_len characters from the beginning of the default
388 * keystroke buffer into input. */
389 memcpy(input, key_buffer, input_len * sizeof(buffer));
390
391 /* If the default keystroke buffer is empty, mark it as such. */
392 if (key_buffer_len == 0) {
393 free(key_buffer);
394 key_buffer = NULL;
395 /* If the default keystroke buffer isn't empty, move its
396 * beginning forward far enough back so that the keystrokes in input
397 * are no longer at its beginning. */
398 } else {
399 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
400 sizeof(buffer));
401 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
402 sizeof(buffer));
403 }
404
405 return input;
406}
407
408/* Read in a single character. If it's ignored, swallow it and go on.
409 * Otherwise, try to translate it from ASCII, meta key sequences, escape
410 * sequences, and/or extended keypad values. Set meta_key to TRUE when
411 * we get a meta key sequence, and set func_key to TRUE when we get an
412 * extended keypad value. Supported extended keypad values consist of
413 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
414 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
415 * the function keypad (F1-F16), and the numeric keypad with NumLock
416 * off. Assume nodelay(win) is FALSE. */
417int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
418{
419 int kbinput;
420
421 /* Read in a character and interpret it. Continue doing this until
422 * we get a recognized value or sequence. */
423 while ((kbinput = parse_kbinput(win, meta_key, func_key
424#ifndef NANO_SMALL
425 , FALSE
426#endif
427 )) == ERR);
428
429 return kbinput;
430}
431
432/* Translate ASCII characters, extended keypad values, and escape
433 * sequences into their corresponding key values. Set meta_key to TRUE
434 * when we get a meta key sequence, and set func_key to TRUE when we get
435 * a function key. Assume nodelay(win) is FALSE. */
436int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000437#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000438 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000439#endif
440 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000441
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000442{
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000443 static int escapes = 0, byte_digits = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000444 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000445 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000446
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000447#ifndef NANO_SMALL
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000448 if (reset) {
449 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000450 byte_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000451 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000452 }
David Lawrence Ramsey1b1e8b62005-01-02 23:35:19 +0000453#endif
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000454
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000455 *meta_key = FALSE;
456 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000457
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000458 /* Read in a character. */
459 while ((kbinput = get_input(win, 1)) == NULL);
460
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000461 if (kbinput->key_code || is_byte_char(kbinput->key)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000462 /* If we got an extended keypad value or an ASCII character,
463 * translate it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000464 switch (kbinput->key) {
465 case ERR:
466 break;
467 case NANO_CONTROL_3:
468 /* Increment the escape counter. */
469 escapes++;
470 switch (escapes) {
471 case 1:
472 /* One escape: wait for more input. */
473 case 2:
474 /* Two escapes: wait for more input. */
475 break;
476 default:
477 /* More than two escapes: reset the escape
478 * counter and wait for more input. */
479 escapes = 0;
480 }
481 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000482#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000483 /* Since we don't change the default SIGWINCH handler when
484 * NANO_SMALL is defined, KEY_RESIZE is never generated.
485 * Also, Slang and SunOS 5.7-5.9 don't support
486 * KEY_RESIZE. */
487 case KEY_RESIZE:
488 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000489#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000490#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000491 case KEY_SHIFT_L:
492 case KEY_SHIFT_R:
493 case KEY_CONTROL_L:
494 case KEY_CONTROL_R:
495 case KEY_ALT_L:
496 case KEY_ALT_R:
497 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000498#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000499 default:
500 switch (escapes) {
501 case 0:
502 switch (kbinput->key) {
503 case NANO_CONTROL_8:
504 retval = ISSET(REBIND_DELETE) ?
505 NANO_DELETE_KEY :
506 NANO_BACKSPACE_KEY;
507 break;
508 case KEY_DOWN:
509 retval = NANO_NEXTLINE_KEY;
510 break;
511 case KEY_UP:
512 retval = NANO_PREVLINE_KEY;
513 break;
514 case KEY_LEFT:
515 retval = NANO_BACK_KEY;
516 break;
517 case KEY_RIGHT:
518 retval = NANO_FORWARD_KEY;
519 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000520#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000521 /* HP-UX 10 and 11 don't support
522 * KEY_HOME. */
523 case KEY_HOME:
524 retval = NANO_HOME_KEY;
525 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000526#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000527 case KEY_BACKSPACE:
528 retval = NANO_BACKSPACE_KEY;
529 break;
530 case KEY_DC:
531 retval = ISSET(REBIND_DELETE) ?
532 NANO_BACKSPACE_KEY :
533 NANO_DELETE_KEY;
534 break;
535 case KEY_IC:
536 retval = NANO_INSERTFILE_KEY;
537 break;
538 case KEY_NPAGE:
539 retval = NANO_NEXTPAGE_KEY;
540 break;
541 case KEY_PPAGE:
542 retval = NANO_PREVPAGE_KEY;
543 break;
544 case KEY_ENTER:
545 retval = NANO_ENTER_KEY;
546 break;
547 case KEY_A1: /* Home (7) on numeric
548 * keypad with NumLock
549 * off. */
550 retval = NANO_HOME_KEY;
551 break;
552 case KEY_A3: /* PageUp (9) on numeric
553 * keypad with NumLock
554 * off. */
555 retval = NANO_PREVPAGE_KEY;
556 break;
557 case KEY_B2: /* Center (5) on numeric
558 * keypad with NumLock
559 * off. */
560 break;
561 case KEY_C1: /* End (1) on numeric
562 * keypad with NumLock
563 * off. */
564 retval = NANO_END_KEY;
565 break;
566 case KEY_C3: /* PageDown (4) on
567 * numeric keypad with
568 * NumLock off. */
569 retval = NANO_NEXTPAGE_KEY;
570 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000571#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000572 /* Slang doesn't support KEY_BEG. */
573 case KEY_BEG: /* Center (5) on numeric
574 * keypad with NumLock
575 * off. */
576 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000577#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000578#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000579 /* HP-UX 10 and 11 don't support KEY_END. */
580 case KEY_END:
581 retval = NANO_END_KEY;
582 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000583#endif
584#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000585 /* Slang doesn't support KEY_SUSPEND. */
586 case KEY_SUSPEND:
587 retval = NANO_SUSPEND_KEY;
588 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000589#endif
590#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000591 /* Slang doesn't support KEY_SLEFT. */
592 case KEY_SLEFT:
593 retval = NANO_BACK_KEY;
594 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000595#endif
596#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000597 /* Slang doesn't support KEY_SRIGHT. */
598 case KEY_SRIGHT:
599 retval = NANO_FORWARD_KEY;
600 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000601#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000602 default:
603 retval = kbinput->key;
604 break;
605 }
606 break;
607 case 1:
608 /* One escape followed by a non-escape: escape
609 * sequence mode. Reset the escape counter. If
610 * there aren't any other keys waiting, we have
611 * a meta key sequence, so set meta_key to TRUE
612 * and save the lowercase version of the
613 * non-escape character as the result. If there
614 * are other keys waiting, we have a true escape
615 * sequence, so interpret it. */
616 escapes = 0;
617 if (get_buffer_len() == 0) {
618 *meta_key = TRUE;
619 retval = tolower(kbinput->key);
620 } else {
621 buffer *escape_kbinput;
622 int *sequence;
623 size_t seq_len;
624 bool ignore_seq;
625
626 /* Put back the non-escape character, get
627 * the complete escape sequence, translate
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +0000628 * the sequence into its corresponding key
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000629 * value, and save that as the result. */
630 unget_input(kbinput, 1);
631 seq_len = get_buffer_len();
632 escape_kbinput = get_input(NULL, seq_len);
633 sequence = buffer_to_keys(escape_kbinput,
634 seq_len);
635 retval = get_escape_seq_kbinput(sequence,
636 seq_len, &ignore_seq);
637
638 /* If the escape sequence is unrecognized
639 * and not ignored, put back all of its
640 * characters except for the initial
641 * escape. */
642 if (retval == ERR && !ignore_seq)
643 unget_input(escape_kbinput, seq_len);
644
645 free(escape_kbinput);
646 }
647 break;
648 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000649 /* Two escapes followed by one or more decimal
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000650 * digits: byte sequence mode. If the word
651 * sequence's range is limited to 2XX (the first
652 * digit is in the '0' to '2' range and it's the
653 * first digit, or it's in the '0' to '9' range
654 * and it's not the first digit), increment the
655 * byte sequence counter and interpret the
656 * digit. If the byte sequence's range is not
657 * limited to 2XX, fall through. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000658 if (('0' <= kbinput->key && kbinput->key <= '6'
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000659 && byte_digits == 0) ||
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000660 ('0' <= kbinput->key && kbinput->key <= '9'
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000661 && byte_digits > 0)) {
662 int byte_kbinput;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000663
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000664 byte_digits++;
665 byte_kbinput = get_byte_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000666#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000667 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000668#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000669 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000670
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000671 if (byte_kbinput != ERR) {
672 /* If we've read in a complete byte
673 * sequence, reset the byte sequence
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000674 * counter and the escape counter,
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000675 * and put back the corresponding byte
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000676 * value. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000677 byte_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000678 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000679 unget_kbinput(byte_kbinput, FALSE,
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000680 FALSE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000681 }
682 } else {
683 /* Reset the escape counter. */
684 escapes = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000685 if (byte_digits == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000686 /* Two escapes followed by a non-decimal
687 * digit or a decimal digit that would
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000688 * create a byte sequence greater than
689 * 2XX, and we're not in the middle of a
690 * byte sequence: control character
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000691 * sequence mode. Interpret the control
692 * sequence and save the corresponding
693 * control character as the result. */
694 retval = get_control_kbinput(kbinput->key);
695 else {
696 /* If we're in the middle of a word
697 * sequence, reset the word sequence
698 * counter and save the character we got
699 * as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000700 byte_digits = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000701 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000702 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000703 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000704 break;
705 }
706 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000707
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000708 /* If we have a result and it's an extended keypad value, set
709 * func_key to TRUE. */
710 if (retval != ERR)
711 *func_key = !is_byte_char(retval);
712 } else
713 /* If we didn't get an extended keypad value or an ASCII
714 * character, leave it as-is. */
715 retval = kbinput->key;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000716
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000717#ifdef DEBUG
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +0000718 fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, byte_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, byte_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000719#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000720
721 /* Return the result. */
722 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000723}
724
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000725/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000726 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000727 * are generated when the keypad doesn't support the needed keys. If
728 * the escape sequence is recognized but we want to ignore it, return
729 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
730 * set ignore_seq to FALSE. Assume that Escape has already been read
731 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000732int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000733 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000734{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000735 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000736
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000737 *ignore_seq = FALSE;
738
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000739 if (seq_len > 1) {
740 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000741 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000742 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000743 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000744 if (seq_len >= 3) {
745 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000746 case 'P': /* Esc O 2 P == F13 on
747 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000748 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000749 break;
750 case 'Q': /* Esc O 2 Q == F14 on
751 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000752 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000753 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000754 case 'R': /* Esc O 2 R == F15 on
755 * xterm. */
756 retval = KEY_F(15);
757 break;
758 case 'S': /* Esc O 2 S == F16 on
759 * xterm. */
760 retval = KEY_F(16);
761 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000762 }
763 }
764 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000765 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
766 case 'B': /* Esc O B == Down on
767 * VT100/VT320/xterm. */
768 case 'C': /* Esc O C == Right on
769 * VT100/VT320/xterm. */
770 case 'D': /* Esc O D == Left on
771 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000772 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000773 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000774 case 'E': /* Esc O E == Center (5) on numeric keypad
775 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000776 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000777 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000778 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000779 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000780 break;
781 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000782 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000783 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000784 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000785 * NumLock off on VT100/VT220/VT320/xterm/
786 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000787 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000788 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000789 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000790 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000791 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000792 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000793 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000794 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000795 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000796 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000797 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000798 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000800 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000801 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000802 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000803 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000804 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000805 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000806 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000807 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000808 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000810 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000811 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000812 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000813 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000814 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000815 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000816 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000817 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000818 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000819 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000820 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000821 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000822 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000823 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000824 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000825 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000826 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000827 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000828 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000829 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000830 * NumLock off on VT100/VT220/VT320/xterm/
831 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000832 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000833 break;
834 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000835 * NumLock off on VT100/VT220/VT320/xterm/
836 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000837 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000838 break;
839 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000840 * NumLock off on VT100/VT220/VT320/xterm/
841 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000842 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000843 break;
844 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000845 * NumLock off on VT100/VT220/VT320/xterm/
846 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000847 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000848 break;
849 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000850 * with NumLock off on VT100/VT220/VT320/
851 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000852 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000853 break;
854 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000855 * NumLock off on VT100/VT220/VT320/xterm/
856 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000857 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000858 break;
859 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000860 * with NumLock off on VT100/VT220/VT320/
861 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000862 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000863 break;
864 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000865 * with NumLock off on VT100/VT220/VT320/
866 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000867 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000868 break;
869 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000870 * with NumLock off on VT100/VT220/VT320/
871 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000872 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000873 break;
874 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000875 * keypad with NumLock off on VT100/VT220/
876 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000877 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000878 break;
879 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000880 * with NumLock off on VT100/VT220/VT320/
881 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000882 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000883 break;
884 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000885 * with NumLock off on VT100/VT220/VT320/
886 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000887 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000888 break;
889 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000890 * with NumLock off on VT100/VT220/VT320/
891 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000892 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000893 break;
894 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000895 * with NumLock off on VT100/VT220/VT320/
896 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000897 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000898 break;
899 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000900 * with NumLock off on VT100/VT220/VT320/
901 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000902 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000903 break;
904 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000905 * with NumLock off on VT100/VT220/VT320/
906 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000907 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000908 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000909 }
910 break;
911 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000912 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000913 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000914 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000915 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000916 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000917 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000918 break;
919 }
920 break;
921 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000922 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000923 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000924 if (seq_len >= 3) {
925 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
927 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000930 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
931 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000932 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000933 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000934 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
935 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000936 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000937 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000938 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
939 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000940 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000941 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000942 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
943 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000944 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000945 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000946 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000947 * VT220/VT320/Linux console/
948 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000949 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000950 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000951 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000952 * VT220/VT320/Linux console/
953 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000954 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000955 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000956 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000957 * VT220/VT320/Linux console/
958 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000959 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000960 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000961 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000962 if (seq_len >= 4) {
963 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000964 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000965 if (seq_len >= 5) {
966 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000967 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
968 * xterm. */
969 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
970 * xterm. */
971 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
972 * xterm. */
973 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
974 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000975 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000976 break;
977 }
978 }
979 break;
980 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000981 if (seq_len >= 5) {
982 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000983 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
984 * xterm. */
985 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
986 * xterm. */
987 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
988 * xterm. */
989 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
990 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000991 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000992 break;
993 }
994 }
995 break;
996 }
997 }
998 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000999 default: /* Esc [ 1 ~ == Home on
1000 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001002 break;
1003 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001004 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001005 break;
1006 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001007 if (seq_len >= 3) {
1008 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001009 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001010 * VT220/VT320/Linux console/
1011 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001012 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001013 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001014 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001015 * VT220/VT320/Linux console/
1016 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001017 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001018 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001019 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001020 * VT220/VT320/Linux console/
1021 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001022 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001023 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001024 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001025 * VT220/VT320/Linux console/
1026 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001027 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001028 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001029 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001030 * VT220/VT320/Linux console/
1031 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001032 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001033 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001034 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001035 * VT220/VT320/Linux console/
1036 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001037 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001038 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001039 case '8': /* Esc [ 2 8 ~ == F15 on
1040 * VT220/VT320/Linux console/
1041 * rxvt/Eterm. */
1042 retval = KEY_F(15);
1043 break;
1044 case '9': /* Esc [ 2 9 ~ == F16 on
1045 * VT220/VT320/Linux console/
1046 * rxvt/Eterm. */
1047 retval = KEY_F(16);
1048 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001049 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001050 * VT220/VT320/Linux console/
1051 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001053 break;
1054 }
1055 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001056 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001057 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1058 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001059 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001060 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001061 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001062 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001063 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001064 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001065 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1066 * Linux console/xterm; Esc [ 5 ^ ==
1067 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001068 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001069 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001070 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1071 * Linux console/xterm; Esc [ 6 ^ ==
1072 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001073 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001074 break;
1075 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001076 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001077 break;
1078 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001079 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001080 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001081 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001082 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001083 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001084 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001085 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001086 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001087 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001088 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001089 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001090 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001091 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001092 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001093 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001094 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001095 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001096 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001097 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001098 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001099 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001100 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001101 case 'E': /* Esc [ E == Center (5) on numeric keypad
1102 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001103 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001104 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001105 case 'F': /* Esc [ F == End on FreeBSD
1106 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001107 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001108 break;
1109 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001110 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001111 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001112 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001113 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001114 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001116 break;
1117 case 'I': /* Esc [ I == PageUp on FreeBSD
1118 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001119 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001120 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001121 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001122 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001123 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001124 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001126 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001127 break;
1128 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001129 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001130 break;
1131 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001132 if (seq_len >= 3) {
1133 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001134 case 'P': /* Esc [ O P == F1 on
1135 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001136 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001137 break;
1138 case 'Q': /* Esc [ O Q == F2 on
1139 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001140 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001141 break;
1142 case 'R': /* Esc [ O R == F3 on
1143 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001144 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001145 break;
1146 case 'S': /* Esc [ O S == F4 on
1147 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001148 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001149 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001150 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001151 } else {
1152 /* Esc [ O == F3 on FreeBSD console. */
1153 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001154 }
1155 break;
1156 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001157 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001158 break;
1159 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001160 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001161 break;
1162 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001163 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001164 break;
1165 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001166 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001167 break;
1168 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001169 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001171 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001172 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001173 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001174 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001175 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001176 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001177 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001178 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001179 break;
1180 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001181 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001182 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001183 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001184 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001185 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001186 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001187 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001188 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001189 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001190 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001191 case 'c': /* Esc [ c == Shift-Right on rxvt/
1192 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001193 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001194 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001195 break;
1196 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001197 if (seq_len >= 3) {
1198 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001199 case 'A': /* Esc [ [ A == F1 on Linux
1200 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001201 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001202 break;
1203 case 'B': /* Esc [ [ B == F2 on Linux
1204 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001205 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001206 break;
1207 case 'C': /* Esc [ [ C == F3 on Linux
1208 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001209 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001210 break;
1211 case 'D': /* Esc [ [ D == F4 on Linux
1212 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001213 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001214 break;
1215 case 'E': /* Esc [ [ E == F5 on Linux
1216 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001217 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001218 break;
1219 }
1220 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001221 break;
1222 }
1223 break;
1224 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001225 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001226
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001227#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001228 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001229#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001230
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001231 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001232}
1233
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001234/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001235 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001236 * to many escape sequences. */
1237int get_escape_seq_abcd(int kbinput)
1238{
1239 switch (tolower(kbinput)) {
1240 case 'a':
1241 return NANO_PREVLINE_KEY;
1242 case 'b':
1243 return NANO_NEXTLINE_KEY;
1244 case 'c':
1245 return NANO_FORWARD_KEY;
1246 case 'd':
1247 return NANO_BACK_KEY;
1248 default:
1249 return ERR;
1250 }
1251}
1252
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001253/* Translate a byte sequence: turn a three-digit decimal number from
1254 * 000 to 255 into its corresponding byte value. */
1255int get_byte_kbinput(int kbinput
1256#ifndef NANO_SMALL
1257 , bool reset
1258#endif
1259 )
1260{
1261 static int byte_digits = 0, byte_kbinput = 0;
1262 int retval = ERR;
1263
1264#ifndef NANO_SMALL
1265 if (reset) {
1266 byte_digits = 0;
1267 byte_kbinput = 0;
1268 return ERR;
1269 }
1270#endif
1271
1272 /* Increment the byte digit counter. */
1273 byte_digits++;
1274
1275 switch (byte_digits) {
1276 case 1:
1277 /* One digit: reset the byte sequence holder and add the
1278 * digit we got to the 100's position of the byte sequence
1279 * holder. */
1280 byte_kbinput = 0;
1281 if ('0' <= kbinput && kbinput <= '2')
1282 byte_kbinput += (kbinput - '0') * 100;
1283 else
1284 /* If the character we got isn't a decimal digit, or if
1285 * it is and it would put the byte sequence out of byte
1286 * range, save it as the result. */
1287 retval = kbinput;
1288 break;
1289 case 2:
1290 /* Two digits: add the digit we got to the 10's position of
1291 * the byte sequence holder. */
1292 if (('0' <= kbinput && kbinput <= '5') ||
1293 (byte_kbinput < 200 && '6' <= kbinput &&
1294 kbinput <= '9'))
1295 byte_kbinput += (kbinput - '0') * 10;
1296 else
1297 /* If the character we got isn't a decimal digit, or if
1298 * it is and it would put the byte sequence out of byte
1299 * range, save it as the result. */
1300 retval = kbinput;
1301 break;
1302 case 3:
1303 /* Three digits: add the digit we got to the 1's position of
1304 * the byte sequence holder, and save the corresponding word
1305 * value as the result. */
1306 if (('0' <= kbinput && kbinput <= '5') ||
1307 (byte_kbinput < 250 && '6' <= kbinput &&
1308 kbinput <= '9')) {
1309 byte_kbinput += (kbinput - '0');
1310 retval = byte_kbinput;
1311 } else
1312 /* If the character we got isn't a decimal digit, or if
1313 * it is and it would put the word sequence out of word
1314 * range, save it as the result. */
1315 retval = kbinput;
1316 break;
1317 default:
1318 /* More than three digits: save the character we got as the
1319 * result. */
1320 retval = kbinput;
1321 break;
1322 }
1323
1324 /* If we have a result, reset the byte digit counter and the byte
1325 * sequence holder. */
1326 if (retval != ERR) {
1327 byte_digits = 0;
1328 byte_kbinput = 0;
1329 }
1330
1331#ifdef DEBUG
1332 fprintf(stderr, "get_byte_kbinput(): kbinput = %d, byte_digits = %d, byte_kbinput = %d, retval = %d\n", kbinput, byte_digits, byte_kbinput, retval);
1333#endif
1334
1335 return retval;
1336}
1337
1338/* Translate a word sequence: turn a four-digit hexadecimal number from
1339 * 0000 to ffff (case-insensitive) into its corresponding word value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001340int get_word_kbinput(int kbinput
1341#ifndef NANO_SMALL
1342 , bool reset
1343#endif
1344 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001345{
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001346 static int word_digits = 0, word_kbinput = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001347 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001348
1349#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001350 if (reset) {
1351 word_digits = 0;
1352 word_kbinput = 0;
1353 return ERR;
1354 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001355#endif
1356
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001357 /* Increment the word digit counter. */
1358 word_digits++;
1359
1360 switch (word_digits) {
1361 case 1:
1362 /* One digit: reset the word sequence holder and add the
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001363 * digit we got to the 4096's position of the word sequence
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001364 * holder. */
1365 word_kbinput = 0;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001366 if ('0' <= kbinput && kbinput <= '9')
1367 word_kbinput += (kbinput - '0') * 4096;
1368 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1369 word_kbinput += (tolower(kbinput) + 10 - 'a') * 4096;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001370 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001371 /* If the character we got isn't a hexadecimal digit, or
1372 * if it is and it would put the word sequence out of
1373 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001374 retval = kbinput;
1375 break;
1376 case 2:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001377 /* Two digits: add the digit we got to the 256's position of
1378 * the word sequence holder. */
1379 if ('0' <= kbinput && kbinput <= '9')
1380 word_kbinput += (kbinput - '0') * 256;
1381 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1382 word_kbinput += (tolower(kbinput) + 10 - 'a') * 256;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001383 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001384 /* If the character we got isn't a hexadecimal digit, or
1385 * if it is and it would put the word sequence out of
1386 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001387 retval = kbinput;
1388 break;
1389 case 3:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001390 /* Three digits: add the digit we got to the 16's position
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001391 * of the word sequence holder. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001392 if ('0' <= kbinput && kbinput <= '9')
1393 word_kbinput += (kbinput - '0') * 16;
1394 else if ('a' <= tolower(kbinput) && tolower(kbinput) <= 'f')
1395 word_kbinput += (tolower(kbinput) + 10 - 'a') * 16;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001396 else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001397 /* If the character we got isn't a hexadecimal digit, or
1398 * if it is and it would put the word sequence out of
1399 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001400 retval = kbinput;
1401 break;
1402 case 4:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001403 /* Four digits: add the digit we got to the 1's position of
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001404 * the word sequence holder, and save the corresponding word
1405 * value as the result. */
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001406 if ('0' <= kbinput && kbinput <= '9') {
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001407 word_kbinput += (kbinput - '0');
1408 retval = word_kbinput;
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001409 } else if ('a' <= tolower(kbinput) &&
1410 tolower(kbinput) <= 'f') {
1411 word_kbinput += (tolower(kbinput) + 10 - 'a');
1412 retval = word_kbinput;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001413 } else
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001414 /* If the character we got isn't a hexadecimal digit, or
1415 * if it is and it would put the word sequence out of
1416 * word range, save it as the result. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001417 retval = kbinput;
1418 break;
1419 default:
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001420 /* More than four digits: save the character we got as the
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001421 * result. */
1422 retval = kbinput;
1423 break;
1424 }
1425
1426 /* If we have a result, reset the word digit counter and the word
1427 * sequence holder. */
1428 if (retval != ERR) {
1429 word_digits = 0;
1430 word_kbinput = 0;
1431 }
1432
1433#ifdef DEBUG
1434 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1435#endif
1436
1437 return retval;
1438}
1439
1440/* Translate a control character sequence: turn an ASCII non-control
1441 * character into its corresponding control character. */
1442int get_control_kbinput(int kbinput)
1443{
1444 int retval;
1445
1446 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1447 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1448 kbinput == '`')
1449 retval = NANO_CONTROL_SPACE;
1450 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1451 else if ('3' <= kbinput && kbinput <= '7')
1452 retval = kbinput - 24;
1453 /* Ctrl-8 (Ctrl-?) */
1454 else if (kbinput == '8' || kbinput == '?')
1455 retval = NANO_CONTROL_8;
1456 /* Ctrl-A to Ctrl-_ */
1457 else if ('A' <= kbinput && kbinput <= '_')
1458 retval = kbinput - 64;
1459 /* Ctrl-a to Ctrl-~ */
1460 else if ('a' <= kbinput && kbinput <= '~')
1461 retval = kbinput - 96;
1462 else
1463 retval = kbinput;
1464
1465#ifdef DEBUG
1466 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1467#endif
1468
1469 return retval;
1470}
1471
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001472/* Put the output-formatted key values in the input buffer kbinput back
1473 * into the default keystroke buffer, starting at position pos, so that
1474 * they can be parsed again. */
1475void unparse_kbinput(size_t pos, int *kbinput, size_t kbinput_len)
1476{
1477 if (pos < kbinput_len - 1) {
1478 size_t seq_len = kbinput_len - (kbinput_len - pos);
1479 buffer *sequence = keys_to_buffer(&kbinput[pos + 1],
1480 seq_len);
1481
1482 unget_input(sequence, seq_len);
1483 free(sequence);
1484 }
1485}
1486
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001487/* Read in a string of characters verbatim, and return the length of the
1488 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1489int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1490{
1491 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001492
1493 /* Turn off flow control characters if necessary so that we can type
1494 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001495 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001496 if (ISSET(PRESERVE))
1497 disable_flow_control();
1498 keypad(win, FALSE);
1499
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001500 /* Read in a stream of characters and interpret it if possible. */
1501 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001502
1503 /* Turn flow control characters back on if necessary and turn the
1504 * keypad back on now that we're done. */
1505 if (ISSET(PRESERVE))
1506 enable_flow_control();
1507 keypad(win, TRUE);
1508
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001509 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001510}
1511
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001512/* Read in a stream of all available characters. Translate the first
1513 * few characters of the input into the corresponding word value if
1514 * possible. After that, leave the input as-is. */
1515int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001516{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001517 buffer *kbinput, *sequence;
1518 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001519
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001520 /* Read in the first keystroke. */
1521 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001522
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001523 /* Check whether the first keystroke is a hexadecimal digit. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001524 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001525#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001526 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001527#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001528 );
1529
David Lawrence Ramseyf0a53f02005-01-03 19:56:56 +00001530 /* If the first keystroke isn't a hexadecimal digit, put back the
1531 * first keystroke. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001532 if (word != ERR)
1533 unget_input(kbinput, 1);
1534 /* Otherwise, read in keystrokes until we have a complete word
1535 * sequence, and put back the corresponding word value. */
1536 else {
1537 buffer word_kbinput;
1538
1539 while (word == ERR) {
1540 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey6a2f0682004-12-20 01:13:55 +00001541
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001542 word = get_word_kbinput(kbinput->key
1543#ifndef NANO_SMALL
1544 , FALSE
1545#endif
1546 );
1547 }
1548
1549 word_kbinput.key = word;
1550 word_kbinput.key_code = FALSE;
1551
1552 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001553 }
1554
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001555 /* Get the complete sequence, and save the key values in it as the
1556 * result. */
1557 *kbinput_len = get_buffer_len();
1558 sequence = get_input(NULL, *kbinput_len);
1559 retval = buffer_to_keys(sequence, *kbinput_len);
1560 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001561
1562 return retval;
1563}
1564
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001565#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001566/* Check for a mouse event, and if one's taken place, save the
1567 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001568 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1569 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001570 * place on it, figure out which shortcut was clicked and put back the
1571 * equivalent keystroke(s). Return FALSE if no keystrokes were
1572 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001573 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001574bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001575{
1576 MEVENT mevent;
1577
1578 *mouse_x = -1;
1579 *mouse_y = -1;
1580
1581 /* First, get the actual mouse event. */
1582 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001583 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001584
1585 /* Save the screen coordinates where the mouse event took place. */
1586 *mouse_x = mevent.x;
1587 *mouse_y = mevent.y;
1588
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001589 /* If we're allowing shortcuts, the current shortcut list is being
1590 * displayed on the last two lines of the screen, and the mouse
1591 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001592 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001593 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1594 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001595 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001596 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001597 /* The number of shortcuts in the current shortcut list. */
1598 const shortcut *s = currshortcut;
1599 /* The actual shortcut we clicked on, starting at the first
1600 * one in the current shortcut list. */
1601
1602 /* Get the shortcut lists' length. */
1603 if (currshortcut == main_list)
1604 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001605 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001606 currslen = length_of_list(currshortcut);
1607
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001608 /* We don't show any more shortcuts than the main list
1609 * does. */
1610 if (currslen > MAIN_VISIBLE)
1611 currslen = MAIN_VISIBLE;
1612 }
1613
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001614 /* Calculate the width of each shortcut in the list (it's the
1615 * same for all of them). */
1616 if (currslen < 2)
1617 i = COLS / 6;
1618 else
1619 i = COLS / ((currslen / 2) + (currslen % 2));
1620
1621 /* Calculate the y-coordinates relative to the beginning of
1622 * bottomwin, i.e, the bottom three lines of the screen. */
1623 j = *mouse_y - (editwinrows + 3);
1624
1625 /* If we're on the statusbar, beyond the end of the shortcut
1626 * list, or beyond the end of a shortcut on the right side of
1627 * the screen, don't do anything. */
1628 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001629 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001630 j = (*mouse_x / i) * 2 + j;
1631 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001632 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001633
1634 /* Go through the shortcut list to determine which shortcut was
1635 * clicked. */
1636 for (; j > 0; j--)
1637 s = s->next;
1638
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001639 /* And put back the equivalent key. Assume that each shortcut
1640 * has, at the very least, an equivalent control key, an
1641 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001642 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001643 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001644 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001645 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001646
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001647 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001648 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001649 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001650}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001651#endif /* !DISABLE_MOUSE */
1652
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001653const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001654 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001655{
1656 const shortcut *s = s_list;
1657 size_t slen = length_of_list(s_list);
1658
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001659#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001660 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 +00001661#endif
1662
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001663 /* Check for shortcuts. */
1664 for (; slen > 0; slen--) {
1665 /* We've found a shortcut if:
1666 *
1667 * 1. The key exists.
1668 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001669 * 3. meta_key is TRUE and the key is the primary or
1670 * miscellaneous meta sequence in the shortcut list.
1671 * 4. func_key is TRUE and the key is a function key in the
1672 * shortcut list. */
1673
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001674 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1675 (*meta_key == TRUE && (*kbinput == s->metaval ||
1676 *kbinput == s->miscval)) || (*func_key == TRUE &&
1677 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001678 break;
1679 }
1680
1681 s = s->next;
1682 }
1683
1684 /* Translate the shortcut to either its control key or its meta key
1685 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001686 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001687 if (slen > 0) {
1688 if (s->ctrlval != NANO_NO_KEY) {
1689 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001690 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001691 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001692 } else if (s->metaval != NANO_NO_KEY) {
1693 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001694 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001695 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001696 }
1697 return s;
1698 }
1699
1700 return NULL;
1701}
1702
1703#ifndef NANO_SMALL
1704const toggle *get_toggle(int kbinput, bool meta_key)
1705{
1706 const toggle *t = toggles;
1707
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001708#ifdef DEBUG
1709 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1710#endif
1711
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001712 /* Check for toggles. */
1713 for (; t != NULL; t = t->next) {
1714 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001715 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001716 if (meta_key && kbinput == t->val)
1717 break;
1718 }
1719
1720 return t;
1721}
1722#endif /* !NANO_SMALL */
1723
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001724int do_statusbar_input(bool *meta_key, bool *func_key, bool *s_or_t,
1725 bool *finished, bool allow_funcs)
1726{
1727 int input;
1728 /* The character we read in. */
1729 static int *kbinput = NULL;
1730 /* The input buffer. */
1731 static size_t kbinput_len = 0;
1732 /* The length of the input buffer. */
1733 const shortcut *s;
1734 bool have_shortcut;
1735
1736 *s_or_t = FALSE;
1737 *finished = FALSE;
1738
1739 /* Read in a character. */
1740 input = get_kbinput(bottomwin, meta_key, func_key);
1741
1742#ifndef DISABLE_MOUSE
1743 /* If we got a mouse click and it was on a shortcut, read in the
1744 * shortcut character. */
David Lawrence Ramseyb8a2a6d2005-01-02 21:13:36 +00001745 if (allow_funcs && *func_key == TRUE && input == KEY_MOUSE) {
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001746 if (do_mouse())
1747 input = get_kbinput(bottomwin, meta_key, func_key);
1748 else
1749 input = ERR;
1750 }
1751#endif
1752
1753 /* Check for a shortcut in the current list. */
1754 s = get_shortcut(currshortcut, &input, meta_key, func_key);
1755
1756 /* If we got a shortcut from the current list, or a "universal"
1757 * statusbar prompt shortcut, set have_shortcut to TRUE. */
1758 have_shortcut = (s != NULL || input == NANO_REFRESH_KEY ||
1759 input == NANO_HOME_KEY || input == NANO_END_KEY ||
1760 input == NANO_FORWARD_KEY || input == NANO_BACK_KEY ||
1761 input == NANO_BACKSPACE_KEY || input == NANO_DELETE_KEY ||
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001762 input == NANO_CUT_KEY || (*meta_key == TRUE &&
1763 input == NANO_VERBATIM_KEY));
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001764
1765 /* Set s_or_t to TRUE if we got a shortcut. */
1766 *s_or_t = have_shortcut;
1767
1768 if (allow_funcs) {
1769 if (input != ERR && *s_or_t == FALSE && !is_cntrl_char(input)) {
1770 /* If we're using restricted mode, the filename isn't blank,
1771 * and we're at the "Write File" prompt, disable text
1772 * input. */
1773 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1774 currshortcut != writefile_list) {
1775 kbinput_len++;
1776 kbinput = (int *)nrealloc(kbinput, kbinput_len *
1777 sizeof(int));
1778 kbinput[kbinput_len - 1] = input;
1779 }
1780 }
1781
1782 /* If we got a shortcut, or if there aren't any other characters
1783 * waiting after the one we read in, we need to display all the
1784 * characters in the input buffer if it isn't empty. */
1785 if (*s_or_t == TRUE || get_buffer_len() == 0) {
1786 if (kbinput != NULL) {
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001787 bool got_enter;
1788 /* Whether we got the Enter key. */
1789
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001790 /* Display all the characters in the input buffer at
1791 * once. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001792 do_statusbar_output(kbinput, kbinput_len, &got_enter);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001793
1794 /* Empty the input buffer. */
1795 kbinput_len = 0;
1796 free(kbinput);
1797 kbinput = NULL;
1798 }
1799 }
1800
1801 if (have_shortcut) {
1802 switch (input) {
1803 /* Handle the "universal" statusbar prompt shortcuts. */
1804 case NANO_REFRESH_KEY:
1805 total_refresh();
1806 break;
1807 case NANO_HOME_KEY:
1808 do_statusbar_home();
1809 break;
1810 case NANO_END_KEY:
1811 do_statusbar_end();
1812 break;
1813 case NANO_FORWARD_KEY:
1814 do_statusbar_right();
1815 break;
1816 case NANO_BACK_KEY:
1817 do_statusbar_left();
1818 break;
1819 case NANO_BACKSPACE_KEY:
1820 /* If we're using restricted mode, the filename
1821 * isn't blank, and we're at the "Write File"
1822 * prompt, disable Backspace. */
1823 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1824 currshortcut != writefile_list)
1825 do_statusbar_backspace();
1826 break;
1827 case NANO_DELETE_KEY:
1828 /* If we're using restricted mode, the filename
1829 * isn't blank, and we're at the "Write File"
1830 * prompt, disable Delete. */
1831 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1832 currshortcut != writefile_list)
1833 do_statusbar_delete();
1834 break;
1835 case NANO_CUT_KEY:
1836 /* If we're using restricted mode, the filename
1837 * isn't blank, and we're at the "Write File"
1838 * prompt, disable Cut. */
1839 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
1840 currshortcut != writefile_list)
1841 do_statusbar_cut_text();
1842 break;
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001843 case NANO_VERBATIM_KEY:
1844 if (*meta_key == TRUE) {
1845 /* If we're using restricted mode, the filename
1846 * isn't blank, and we're at the "Write File"
1847 * prompt, disable verbatim input. */
1848 if (!ISSET(RESTRICTED) || filename[0] == '\0' ||
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001849 currshortcut != writefile_list) {
1850 bool got_enter;
1851 /* Whether we got the Enter key. */
1852
1853 do_statusbar_verbatim_input(&got_enter);
1854
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001855 /* If we got the Enter key, set input to the
1856 * key value for Enter, and set finished to
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001857 * TRUE to indicate that we're done. */
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001858 if (got_enter) {
1859 input = NANO_ENTER_KEY;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001860 *finished = TRUE;
David Lawrence Ramsey6e1cd062005-01-02 23:50:29 +00001861 }
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001862 }
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001863 break;
1864 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001865 /* Handle the normal statusbar prompt shortcuts, setting
1866 * finished to TRUE to indicate that we're done after
1867 * running or trying to run their associated
1868 * functions. */
1869 default:
1870 if (s->func != NULL) {
1871 if (ISSET(VIEW_MODE) && !s->viewok)
1872 print_view_warning();
1873 else
1874 s->func();
1875 }
1876 *finished = TRUE;
1877 }
1878 }
1879 }
1880
1881 return input;
1882}
1883
1884#ifndef DISABLE_MOUSE
1885bool do_statusbar_mouse(void)
1886{
1887 /* FIXME: If we clicked on a location in the statusbar, the cursor
1888 * should move to the location we clicked on. This functionality
1889 * should be in this function. */
1890 int mouse_x, mouse_y;
1891 return get_mouseinput(&mouse_x, &mouse_y, TRUE);
1892}
1893#endif
1894
1895void do_statusbar_home(void)
1896{
1897#ifndef NANO_SMALL
1898 if (ISSET(SMART_HOME)) {
1899 size_t statusbar_x_save = statusbar_x;
1900 for (statusbar_x = 0; isblank(answer[statusbar_x]) &&
1901 statusbar_x < statusbar_xend; statusbar_x++)
1902 ;
1903 if (statusbar_x == statusbar_x_save ||
1904 statusbar_x == statusbar_xend)
1905 statusbar_x = 0;
1906 } else
1907#endif
1908 statusbar_x = 0;
1909}
1910
1911void do_statusbar_end(void)
1912{
1913 statusbar_x = statusbar_xend;
1914}
1915
1916void do_statusbar_right(void)
1917{
1918 if (statusbar_x < statusbar_xend)
1919 statusbar_x = move_right(answer, statusbar_x);
1920}
1921
1922void do_statusbar_left(void)
1923{
1924 if (statusbar_x > 0)
1925 statusbar_x = move_left(answer, statusbar_x);
1926}
1927
1928void do_statusbar_backspace(void)
1929{
1930 if (statusbar_x > 0) {
1931 do_statusbar_left();
1932 do_statusbar_delete();
1933 }
1934}
1935
1936void do_statusbar_delete(void)
1937{
1938 if (statusbar_x < statusbar_xend) {
1939 int char_len = parse_char(answer + statusbar_x, NULL, NULL
1940#ifdef NANO_WIDE
1941 , NULL
1942#endif
1943 );
1944
1945 charmove(answer + statusbar_x, answer + statusbar_x + char_len,
1946 statusbar_xend - statusbar_x - char_len + 1);
1947 statusbar_xend -= char_len;
1948 }
1949}
1950
1951void do_statusbar_cut_text(void)
1952{
1953 null_at(&answer, 0);
1954 statusbar_x = 0;
1955 statusbar_xend = 0;
1956}
1957
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001958void do_statusbar_verbatim_input(bool *got_enter)
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001959{
1960 int *kbinput; /* Used to hold verbatim input. */
1961 size_t kbinput_len; /* Length of verbatim input. */
1962
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001963 *got_enter = FALSE;
1964
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001965 /* Read in all the verbatim characters. */
1966 kbinput = get_verbatim_kbinput(bottomwin, &kbinput_len);
1967
1968 /* Display all the verbatim characters at once. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001969 do_statusbar_output(kbinput, kbinput_len, got_enter);
David Lawrence Ramsey11c83d32005-01-02 21:26:53 +00001970
1971 free(kbinput);
1972}
1973
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001974void do_statusbar_output(int *kbinput, size_t kbinput_len, bool
1975 *got_enter)
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001976{
1977 size_t i;
1978
1979 char *key =
1980#ifdef NANO_WIDE
1981 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
1982#endif
1983 charalloc(1);
1984
1985 assert(answer != NULL);
1986
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001987 *got_enter = FALSE;
1988
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00001989 for (i = 0; i < kbinput_len; i++) {
1990 int key_len;
1991
1992 /* Null to newline, if needed. */
1993 if (kbinput[i] == '\0')
1994 kbinput[i] = '\n';
1995 /* Newline to Enter, if needed. */
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00001996 else if (kbinput[i] == '\n') {
1997 /* Set got_enter to TRUE to indicate that we got the Enter
1998 * key, put back the rest of the keystrokes in kbinput so
1999 * that they can be parsed again, and get out. */
2000 *got_enter = TRUE;
2001 unparse_kbinput(i, kbinput, kbinput_len);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002002 return;
David Lawrence Ramseyd9ad76b2005-01-02 22:35:31 +00002003 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002004
2005#ifdef NANO_WIDE
2006 /* Change the wide character to its multibyte value. If it's
2007 * invalid, go on to the next character. */
2008 if (!ISSET(NO_UTF8)) {
2009 key_len = wctomb(key, (wchar_t)kbinput[i]);
2010
2011 if (key_len == -1)
2012 continue;
2013 /* Interpret the character as a single-byte sequence. */
2014 } else {
2015#endif
2016 key_len = 1;
2017 key[0] = (unsigned char)kbinput[i];
2018#ifdef NANO_WIDE
2019 }
2020#endif
2021
2022 /* More dangerousness fun =) */
2023 answer = charealloc(answer, statusbar_xend + key_len + 1);
2024
2025 assert(statusbar_x <= statusbar_xend);
2026
2027 charmove(&answer[statusbar_x + key_len], &answer[statusbar_x],
2028 statusbar_xend - statusbar_x + key_len);
2029 charcpy(&answer[statusbar_x], key, key_len);
2030 statusbar_xend += key_len;
2031
2032 do_statusbar_right();
2033 }
2034
2035 free(key);
2036}
2037
Chris Allegretta6df90f52002-07-19 01:08:59 +00002038/* Return the placewewant associated with current_x. That is, xplustabs
2039 * is the zero-based column position of the cursor. Value is no smaller
2040 * than current_x. */
2041size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002042{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002043 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002044}
2045
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002046/* actual_x() gives the index in str of the character displayed at
2047 * column xplus. That is, actual_x() is the largest value such that
2048 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
2049size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002050{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002051 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002052 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002053 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00002054 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002055
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002056 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002057
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002058 while (*str != '\0') {
2059 int str_len = parse_char(str, NULL, &length
2060#ifdef NANO_WIDE
2061 , NULL
2062#endif
2063 );
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002064
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002065 if (length > xplus)
2066 break;
2067
2068 i += str_len;
2069 str += str_len;
2070 }
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00002071
Chris Allegretta6df90f52002-07-19 01:08:59 +00002072 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002073}
2074
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00002075/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002076 * columns wide are the first size characters of str? */
2077size_t strnlenpt(const char *str, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00002078{
Chris Allegretta6df90f52002-07-19 01:08:59 +00002079 size_t length = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002080 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002081
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002082 if (size == 0)
2083 return 0;
2084
2085 assert(str != NULL);
2086
2087 while (*str != '\0') {
2088 int str_len = parse_char(str, NULL, &length
2089#ifdef NANO_WIDE
2090 , NULL
2091#endif
2092 );
2093
2094 str += str_len;
2095
2096 if (size <= str_len)
2097 break;
2098
2099 size -= str_len;
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002100 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002101
Chris Allegretta6df90f52002-07-19 01:08:59 +00002102 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002103}
2104
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00002105/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002106size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002107{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00002108 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00002109}
2110
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002111void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002112{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002113 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002114}
2115
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116void blank_edit(void)
2117{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002118 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002119 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002120 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002121}
2122
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002123void blank_statusbar(void)
2124{
2125 mvwaddstr(bottomwin, 0, 0, hblank);
2126}
2127
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002128void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002129{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002130 if (statusblank > 1)
2131 statusblank--;
2132 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
2133 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002134 blank_statusbar();
2135 wnoutrefresh(bottomwin);
2136 reset_cursor();
2137 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002138 }
2139}
2140
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002141void blank_bottombars(void)
2142{
2143 if (!ISSET(NO_HELP)) {
2144 mvwaddstr(bottomwin, 1, 0, hblank);
2145 mvwaddstr(bottomwin, 2, 0, hblank);
2146 }
2147}
2148
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002149/* buf is a multibyte string to be displayed. We need to expand tabs
2150 * and control characters. How many bytes do we need to display?
2151 * start_col is the column of *buf (usually 0). We display to
2152 * (end_col - 1). */
2153size_t display_string_len(const char *buf, size_t start_col, size_t
2154 end_col)
2155{
2156 size_t retval = 0;
2157
2158 assert(buf != NULL);
2159
2160 /* Throughout the loop, we maintain the fact that *buf displays at
2161 * column start_col. */
2162 while (start_col <= end_col && *buf != '\0') {
2163 int wide_buf, wide_buf_len;
2164 size_t old_col = start_col;
2165#ifdef NANO_WIDE
2166 bool bad_char;
2167#endif
2168
2169 wide_buf_len = parse_char(buf, &wide_buf, &start_col
2170#ifdef NANO_WIDE
2171 , &bad_char
2172#endif
2173 );
2174
2175#ifdef NANO_WIDE
2176 /* If buf contains a null byte or an invalid multibyte
2177 * character, interpret that character as though it's a wide
2178 * character. */
2179 if (!ISSET(NO_UTF8) && bad_char) {
2180 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2181 int bad_wide_buf_len;
2182
2183 /* If we have a control character, add one byte to account
2184 * for the "^" that will be displayed in front of it, and
2185 * translate the character to its visible equivalent as
2186 * returned by control_rep(). */
2187 if (is_cntrl_char(wide_buf)) {
2188 retval++;
2189 wide_buf = control_rep((unsigned char)wide_buf);
2190 }
2191
2192 /* Translate the wide character to its multibyte
2193 * equivalent. */
2194 bad_wide_buf_len = wctomb(bad_wide_buf, (wchar_t)wide_buf);
2195
2196 if (bad_wide_buf_len != -1)
2197 retval += bad_wide_buf_len;
2198
2199 free(bad_wide_buf);
2200 } else {
2201#endif
2202 /* If we have a tab, get its width in bytes using the
2203 * current value of col. */
2204 if (wide_buf == '\t')
2205 retval += start_col - old_col;
2206 /* If we have a control character, add one byte to account
2207 * for the "^" that will be displayed in front of it, and
2208 * then add the number of bytes for its visible equivalent
2209 * as returned by control_rep(). If we have an invalid
2210 * multibyte control character, interpret that character as
2211 * though it's a normal control character. */
2212 else if (is_cntrl_char(wide_buf)) {
2213 char ctrl_wide_buf =
2214 control_rep((unsigned char)wide_buf);
2215
2216 retval++;
2217 retval += parse_char(&ctrl_wide_buf, NULL, NULL
2218#ifdef NANO_WIDE
2219 , NULL
2220#endif
2221 );
2222 /* If we have a normal character, add its width in bytes
2223 * normally. */
2224 } else
2225#ifdef NANO_WIDE
2226 /* If buf contains an invalid multibyte non-control
2227 * character, interpret that character as though it's a
2228 * normal non-control character. */
2229 if (!ISSET(NO_UTF8) && bad_char) {
2230 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2231 int bad_wide_buf_len;
2232
2233 bad_wide_buf_len = wctomb(bad_wide_buf,
2234 (wchar_t)wide_buf);
2235
2236 free(bad_wide_buf);
2237
David Lawrence Ramseyf2824282004-12-29 21:32:22 +00002238 if (bad_wide_buf_len != -1)
2239 retval += bad_wide_buf_len;
2240 else
2241 retval++;
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002242 } else
2243#endif
2244 retval += wide_buf_len;
2245#ifdef NANO_WIDE
2246 }
2247
2248 buf += wide_buf_len;
2249#endif
2250 }
2251
2252 return retval;
2253}
2254
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002255/* Convert buf into a string that can be displayed on screen. The
2256 * caller wants to display buf starting with column start_col, and
2257 * extending for at most len columns. start_col is zero-based. len is
2258 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002259 * string is dynamically allocated, and should be freed. If dollars is
2260 * TRUE, the caller might put "$" at the beginning or end of the line if
2261 * it's too long. */
2262char *display_string(const char *buf, size_t start_col, size_t len, bool
2263 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002264{
2265 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002266 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002267 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002268 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002269 size_t alloc_len;
2270 /* The length of memory allocated for converted. */
2271 char *converted;
2272 /* The string we return. */
2273 size_t index;
2274 /* Current position in converted. */
2275
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002276 /* If dollars is TRUE, make room for the "$" at the end of the
2277 * line. Also make sure that we don't try to display only part of a
2278 * multicolumn character there. */
2279 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2280 len--;
2281
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002282 if (len == 0)
2283 return mallocstrcpy(NULL, "");
2284
2285 start_index = actual_x(buf, start_col);
2286 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002287
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002288 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002289
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002290 alloc_len = display_string_len(buf + start_index, start_col,
2291 start_col + COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002292 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002293 index = 0;
2294
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002295 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002296 buf[start_index] != '\t')) {
2297 int wide_buf, wide_buf_len;
2298
2299 /* We don't display all of buf[start_index] since it starts to
2300 * the left of the screen. */
2301 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2302#ifdef NANO_WIDE
2303 , NULL
2304#endif
2305 );
2306
2307 if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002308 if (column < start_col) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002309 char *ctrl_wide_buf =
2310#ifdef NANO_WIDE
2311 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2312#endif
2313 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002314 int ctrl_wide_buf_len, i;
2315
2316 wide_buf = control_rep((unsigned char)wide_buf);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002317
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002318#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002319 if (!ISSET(NO_UTF8))
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002320 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2321 (wchar_t)wide_buf);
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002322 else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002323#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002324 ctrl_wide_buf_len = 1;
2325 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2326#ifdef NANO_WIDE
2327 }
2328#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002329
2330 for (i = 0; i < ctrl_wide_buf_len; i++)
2331 converted[index++] = ctrl_wide_buf[i];
2332
2333 free(ctrl_wide_buf);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002334
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002335#ifdef NANO_WIDE
2336 if (!ISSET(NO_UTF8)) {
2337 int width = wcwidth((wchar_t)wide_buf);
2338
2339 if (width != -1)
2340 start_col += width;
2341 } else
2342#endif
2343 start_col++;
2344
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002345 start_index += wide_buf_len;
2346 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002347 }
2348#ifdef NANO_WIDE
2349 else if (wcwidth((wchar_t)wide_buf) > 1) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002350 /* If dollars is TRUE, make room for the "$" at the
2351 * beginning of the line. Also make sure that we don't try
2352 * to display only part of a multicolumn character there. */
2353 converted[0] = ' ';
2354 index = 1;
2355 if (dollars && column == start_col) {
2356 converted[1] = ' ';
2357 index = 2;
2358 }
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002359
2360 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002361 start_index += wide_buf_len;
2362 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002363#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002364 }
2365
2366 while (index < alloc_len && buf[start_index] != '\0') {
2367 int wide_buf, wide_buf_len;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002368#ifdef NANO_WIDE
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002369 bool bad_char;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002370#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002371
2372 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2373#ifdef NANO_WIDE
2374 , &bad_char
2375#endif
2376 );
2377
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002378 if (wide_buf == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002379 converted[index++] =
2380#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2381 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2382#endif
2383 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002384 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002385 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002386 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002387 start_col++;
2388 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002389 /* If buf contains a control character, interpret it. If it
2390 * contains an invalid multibyte control character, interpret
2391 * that character as though it's a normal control character. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002392 } else if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002393 char *ctrl_wide_buf =
2394#ifdef NANO_WIDE
2395 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2396#endif
2397 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002398 int ctrl_wide_buf_len, i;
2399
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002400 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002401 start_col++;
2402 wide_buf = control_rep((unsigned char)wide_buf);
2403
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002404#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002405 if (!ISSET(NO_UTF8))
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002406 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2407 (wchar_t)wide_buf);
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002408 else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002409#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002410 ctrl_wide_buf_len = 1;
2411 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2412#ifdef NANO_WIDE
2413 }
2414#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002415
2416 for (i = 0; i < ctrl_wide_buf_len; i++)
2417 converted[index++] = ctrl_wide_buf[i];
2418
2419 free(ctrl_wide_buf);
2420
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002421#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002422 if (!ISSET(NO_UTF8)) {
2423 int width = wcwidth((wchar_t)wide_buf);
2424
2425 if (width != -1)
2426 start_col += width;
2427 } else
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002428#endif
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002429 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002430 } else if (wide_buf == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002431 converted[index++] =
2432#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2433 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2434#endif
2435 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002436 start_col++;
2437 } else {
2438 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002439
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002440#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002441 /* If buf contains an invalid multibyte non-control
2442 * character, interpret that character as though it's a
2443 * normal non-control character. */
2444 if (!ISSET(NO_UTF8) && bad_char) {
2445 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2446 int bad_wide_buf_len;
2447
2448 bad_wide_buf_len = wctomb(bad_wide_buf,
2449 (wchar_t)wide_buf);
2450
2451 for (i = 0; i < bad_wide_buf_len; i++)
2452 converted[index++] = bad_wide_buf[i];
2453
2454 free(bad_wide_buf);
2455 } else {
2456#endif
2457 for (i = 0; i < wide_buf_len; i++)
2458 converted[index++] = buf[start_index + i];
2459#ifdef NANO_WIDE
2460 }
2461
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002462 if (!ISSET(NO_UTF8)) {
2463 int width = wcwidth((wchar_t)wide_buf);
2464
2465 if (width != -1)
2466 start_col += width;
2467 } else
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002468#endif
2469 start_col++;
2470 }
2471
2472 start_index += wide_buf_len;
2473 }
2474
2475 /* Make sure that converted is at most len columns wide. */
2476 converted[index] = '\0';
2477 index = actual_x(converted, len);
2478 null_at(&converted, index);
2479
2480 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002481}
2482
Chris Allegretta7662c862003-01-13 01:35:15 +00002483/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002484 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002485 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002486 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002487 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002488void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002489{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002490 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002491 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002492
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002493 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002494
Chris Allegrettab3655b42001-10-22 03:15:31 +00002495 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002496 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002497
Chris Allegretta6df90f52002-07-19 01:08:59 +00002498 mvwaddstr(bottomwin, 0, 0, buf);
2499 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002500
2501 if (COLS > 1)
2502 waddch(bottomwin, x_real < wid ? ' ' : '$');
2503 if (COLS > 2) {
2504 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002505 char *expanded = display_string(inputbuf, page_start, wid,
2506 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002507
2508 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002509 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002510
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002511 waddstr(bottomwin, expanded);
2512 free(expanded);
2513 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2514 } else
2515 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002516 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002517}
2518
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002519/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002520 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002521int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002522#ifndef NANO_SMALL
2523 historyheadtype *history_list,
2524#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002525 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002526#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002527 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002528#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002529 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002530{
2531 int kbinput;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002532 bool meta_key, func_key, s_or_t, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002533 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002534 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002535
Chris Allegretta5beed502003-01-05 20:41:21 +00002536#ifndef NANO_SMALL
2537 /* for history */
2538 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002539 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002540 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002541 int last_kbinput = 0;
2542
2543 /* This variable is used in the search history code. use_cb == 0
2544 means that we're using the existing history and ignoring
2545 currentbuf. use_cb == 1 means that the entry in answer should be
2546 moved to currentbuf or restored from currentbuf to answer.
2547 use_cb == 2 means that the entry in currentbuf should be moved to
2548 answer or restored from answer to currentbuf. */
2549 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002550#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002551 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002552
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002553 /* Only put statusbar_x at the end of the string if it's
2554 * uninitialized, if it would be past the end of the string as it
2555 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2556 * This is so the cursor position stays at the same place if a
2557 * prompt-changing toggle is pressed. */
2558 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2559 resetstatuspos)
2560 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002561
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002562 answer = charealloc(answer, statusbar_xend + 1);
2563 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002564 strcpy(answer, def);
2565 else
2566 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002567
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002568 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002569
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002570 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002571
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002572 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002573
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002574 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002575 wnoutrefresh(edit);
2576 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002577
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002578 /* If we're using restricted mode, we aren't allowed to change the
2579 * name of a file once it has one because that would allow writing
2580 * to files not specified on the command line. In this case,
2581 * disable all keys that would change the text if the filename isn't
2582 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002583 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
2584 &s_or_t, &finished, TRUE)) != NANO_CANCEL_KEY &&
2585 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002586
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002587 /* If we have a shortcut with an associated function, break out
2588 * if we're finished after running the function. */
2589 if (finished)
2590 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002591
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002592 assert(statusbar_x <= statusbar_xend &&
2593 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002594
Chris Allegretta04d848e2000-11-05 17:54:41 +00002595 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002596 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002597
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002598 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002599 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002600#ifndef NANO_SMALL
2601 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002602 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002603 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002604 history_list->current = (historytype *)history_list;
2605 history_list->len = strlen(answer);
2606 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002607
Chris Allegretta7662c862003-01-13 01:35:15 +00002608 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002609 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002610 statusbar_x = strlen(complete);
2611 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002612 answer = mallocstrcpy(answer, complete);
2613 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002614 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002615#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002616 else
2617#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002618#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002619#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002620 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002621 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002622
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002623 answer = input_tab(answer, statusbar_x, &tabbed, &shift,
2624 list);
2625 statusbar_xend = strlen(answer);
2626 statusbar_x += shift;
2627 if (statusbar_x > statusbar_xend)
2628 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002629 }
2630#endif
2631 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002632 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002633#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002634 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002635
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002636 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2637 isn't NULL, and currentbuf is different from answer,
2638 it means that we're scrolling up at the top of the
2639 search history, and we need to save the current
2640 answer in currentbuf; do this and reset use_cb to
2641 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002642 if (currentbuf == NULL || (use_cb == 1 &&
2643 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002644 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002645 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002646 }
2647
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002648 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2649 is different from answer, it means that we're
2650 scrolling up at the bottom of the search history, and
2651 we need to make the string in currentbuf the current
2652 answer; do this, blow away currentbuf since we don't
2653 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002654 if (currentbuf != NULL && use_cb == 2 &&
2655 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002656 answer = mallocstrcpy(answer, currentbuf);
2657 free(currentbuf);
2658 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002659 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002660 use_cb = 0;
2661
2662 /* else get older search from the history list and save
2663 it in answer; if there is no older search, blank out
2664 answer */
2665 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002666 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002667 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002668 } else {
2669 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002670 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002671 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002672 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002673 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002674#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002675 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002676 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002677#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002678 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002679
2680 /* get newer search from the history list and save it
2681 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002682 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002683 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002684 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002685
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002686 /* if there is no newer search, we're here */
2687
2688 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2689 that we're scrolling down at the bottom of the search
2690 history and we need to make the string in currentbuf
2691 the current answer; do this, blow away currentbuf
2692 since we don't need it anymore, and set use_cb to
2693 1 */
2694 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002695 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002696 free(currentbuf);
2697 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002698 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002699 use_cb = 1;
2700
2701 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2702 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002703 the search history and the current answer (if it's
2704 not blank) needs to be saved in currentbuf; do this,
2705 blank out answer (if necessary), and set use_cb to
2706 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002707 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002708 if (answer[0] != '\0') {
2709 currentbuf = mallocstrcpy(currentbuf, answer);
2710 answer = mallocstrcpy(answer, "");
2711 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002712 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002713 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002714 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002715 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002716 }
2717#endif
2718 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002719 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002720#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002721 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002722#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002723 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002724 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002725 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002726
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002727 /* We finished putting in an answer, so reset statusbar_x. */
2728 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY)
2729 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002730
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002731 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002732}
2733
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002734/* Ask a question on the statusbar. Answer will be stored in answer
2735 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2736 * otherwise, the valid shortcut key caught. def is any editable text
2737 * we want to put up by default.
2738 *
2739 * New arg tabs tells whether or not to allow tab completion. */
2740int statusq(bool allow_tabs, const shortcut *s, const char *def,
2741#ifndef NANO_SMALL
2742 historyheadtype *which_history,
2743#endif
2744 const char *msg, ...)
2745{
2746 va_list ap;
2747 char *foo = charalloc(COLS - 3);
2748 int ret;
2749#ifndef DISABLE_TABCOMP
2750 bool list = FALSE;
2751#endif
2752
2753 bottombars(s);
2754
2755 va_start(ap, msg);
2756 vsnprintf(foo, COLS - 4, msg, ap);
2757 va_end(ap);
2758 foo[COLS - 4] = '\0';
2759
2760 ret = nanogetstr(allow_tabs, foo, def,
2761#ifndef NANO_SMALL
2762 which_history,
2763#endif
2764 s
2765#ifndef DISABLE_TABCOMP
2766 , &list
2767#endif
2768 );
2769 free(foo);
2770 resetstatuspos = FALSE;
2771
2772 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002773 case NANO_CANCEL_KEY:
2774 ret = -1;
2775 resetstatuspos = TRUE;
2776 break;
2777 case NANO_ENTER_KEY:
2778 ret = (answer[0] == '\0') ? -2 : 0;
2779 resetstatuspos = TRUE;
2780 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002781 }
2782 blank_statusbar();
2783
2784#ifdef DEBUG
2785 fprintf(stderr, "I got \"%s\"\n", answer);
2786#endif
2787
2788#ifndef DISABLE_TABCOMP
2789 /* if we've done tab completion, there might be a list of
2790 filename matches on the edit window at this point; make sure
2791 they're cleared off. */
2792 if (list)
2793 edit_refresh();
2794#endif
2795
2796 return ret;
2797}
2798
2799void statusq_abort(void)
2800{
2801 resetstatuspos = TRUE;
2802}
2803
Chris Allegrettaf717f982003-02-13 22:25:01 +00002804void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002805{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002806 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002807 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002808 size_t verlen = strlenpt(VERMSG) + 1;
2809 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002810 const char *prefix;
2811 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2812 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002813 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002814 const char *state;
2815 /* "Modified", "View", or spaces the length of "Modified".
2816 * Tells the state of this buffer. */
2817 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002818 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002819 char *exppath = NULL;
2820 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002821 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002822 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002823 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002824 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002825
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 assert(path != NULL || filename != NULL);
2827 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002830
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002831 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002832
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002833 if (COLS <= 5 || COLS - 5 < verlen)
2834 space = 0;
2835 else {
2836 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002837 /* Reserve 2/3 of the screen plus one column for after the
2838 * version message. */
2839 if (space < COLS - (COLS / 3) + 1)
2840 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002841 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002842
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002843 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002844 /* The version message should only take up 1/3 of the screen
2845 * minus one column. */
2846 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002847 waddstr(topwin, " ");
2848 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002849
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002850 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002851 state = _("Modified");
2852 else if (path == NULL && ISSET(VIEW_MODE))
2853 state = _("View");
2854 else {
2855 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002856 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002857 state = &hblank[COLS - statelen];
2858 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002859 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002860 /* We need a space before state. */
2861 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2862 statelen++;
2863
2864 assert(space >= 0);
2865 if (space == 0 || statelen >= space)
2866 goto the_end;
2867
2868#ifndef DISABLE_BROWSER
2869 if (path != NULL)
2870 prefix = _("DIR:");
2871 else
2872#endif
2873 if (filename[0] == '\0') {
2874 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002875 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002876 } else
2877 prefix = _("File:");
2878 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002879 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002880 /* If newfie is FALSE, we need a space after prefix. */
2881 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002882 prefixlen++;
2883
2884 if (path == NULL)
2885 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002886 if (space >= prefixlen + statelen)
2887 space -= prefixlen + statelen;
2888 else
2889 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002890 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002891 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002892 size_t lenpt = strlenpt(path), start_col;
2893
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002894 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002895
2896 if (dots) {
2897 start_col = lenpt - space + 3;
2898 space -= 3;
2899 } else
2900 start_col = 0;
2901
2902 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002903 }
2904
2905 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002906 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2907 /* The length of the expanded filename. */
2908
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002909 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002910 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002911 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002912 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002913 assert(strlenpt(prefix) + 1 == prefixlen);
2914
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002915 waddch(topwin, ' ');
2916 waddstr(topwin, exppath);
2917 }
2918 } else {
2919 /* We will say something like "File: ...ename". */
2920 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002921 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002922 goto the_end;
2923 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002924 waddnstr(topwin, "...", space + 3);
2925 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002926 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002927 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002928 }
2929
2930 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002931 free(exppath);
2932
2933 if (COLS <= 1 || statelen >= COLS - 1)
2934 mvwaddnstr(topwin, 0, 0, state, COLS);
2935 else {
2936 assert(COLS - statelen - 2 >= 0);
2937 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2938 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2939 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002940
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002941 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002942
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002943 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002944 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002945 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002946}
2947
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002948/* If modified is not already set, set it and update titlebar. */
2949void set_modified(void)
2950{
2951 if (!ISSET(MODIFIED)) {
2952 SET(MODIFIED);
2953 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002954 }
2955}
2956
2957void statusbar(const char *msg, ...)
2958{
2959 va_list ap;
2960
2961 va_start(ap, msg);
2962
2963 /* Curses mode is turned off. If we use wmove() now, it will muck
2964 * up the terminal settings. So we just use vfprintf(). */
2965 if (curses_ended) {
2966 vfprintf(stderr, msg, ap);
2967 va_end(ap);
2968 return;
2969 }
2970
2971 /* Blank out the line. */
2972 blank_statusbar();
2973
2974 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002975 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002976 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002977#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002978 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002979
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002980 UNSET(WHITESPACE_DISPLAY);
2981#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002982 bar = charalloc(COLS - 3);
2983 vsnprintf(bar, COLS - 3, msg, ap);
2984 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002985 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002986#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2987 if (old_whitespace)
2988 SET(WHITESPACE_DISPLAY);
2989#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002990 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002991 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002992 start_x = (COLS - foo_len - 4) / 2;
2993
2994 wmove(bottomwin, 0, start_x);
2995 wattron(bottomwin, A_REVERSE);
2996
2997 waddstr(bottomwin, "[ ");
2998 waddstr(bottomwin, foo);
2999 free(foo);
3000 waddstr(bottomwin, " ]");
3001 wattroff(bottomwin, A_REVERSE);
3002 wnoutrefresh(bottomwin);
3003 reset_cursor();
3004 wrefresh(edit);
3005 /* Leave the cursor at its position in the edit window, not
3006 * in the statusbar. */
3007 }
3008
3009 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00003010 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003011}
3012
Chris Allegretta6232d662002-05-12 19:52:15 +00003013void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003014{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003015 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003016
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003017 if (ISSET(NO_HELP))
3018 return;
3019
Chris Allegretta6232d662002-05-12 19:52:15 +00003020 if (s == main_list) {
3021 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003022 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00003023 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00003024 slen = length_of_list(s);
3025
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003026 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00003027 if (slen > MAIN_VISIBLE)
3028 slen = MAIN_VISIBLE;
3029 }
3030
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003031 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003032 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003033 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003034
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003035 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00003036
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003037 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003038 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00003039
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003040 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00003041#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003042 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003043 keystr = _("Up");
3044 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003045#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003046 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00003047
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003048 if (s->ctrlval == NANO_CONTROL_SPACE)
3049 strcpy(foo, "^ ");
3050 else if (s->ctrlval == NANO_CONTROL_8)
3051 strcpy(foo, "^?");
3052 /* Normal values. Assume that the shortcut has an
3053 * equivalent control key, meta key sequence, or both. */
3054 else if (s->ctrlval != NANO_NO_KEY)
3055 sprintf(foo, "^%c", s->ctrlval + 64);
3056 else if (s->metaval != NANO_NO_KEY)
3057 sprintf(foo, "M-%c", toupper(s->metaval));
3058
3059 keystr = foo;
3060#ifndef NANO_SMALL
3061 }
3062#endif
3063
3064 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003065 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003066 }
3067
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003068 wnoutrefresh(bottomwin);
3069 reset_cursor();
3070 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003071}
3072
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003073/* Write a shortcut key to the help area at the bottom of the window.
3074 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
3075 * to write at most len characters, even if len is very small and
3076 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
3077 * the whole string! We do not bother padding the entry with blanks. */
3078void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003079{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003080 assert(keystroke != NULL && desc != NULL);
3081
3082 size_t keystroke_len = strlenpt(keystroke) + 1;
3083
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003084 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003085 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003086 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003087
3088 if (len > keystroke_len)
3089 len -= keystroke_len;
3090 else
3091 len = 0;
3092
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003093 if (len > 0) {
3094 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003095 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003096 }
3097}
3098
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003099/* And so start the display update routines. */
3100
3101#ifndef NDEBUG
3102int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003103{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003104 int check_line = 0;
3105 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003106
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003107 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3108 check_line++;
3109 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003110}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003111#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003112
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003113/* nano scrolls horizontally within a line in chunks. This function
3114 * returns the column number of the first character displayed in the
3115 * window when the cursor is at the given column. Note that
3116 * 0 <= column - get_page_start(column) < COLS. */
3117size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003118{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003119 assert(COLS > 0);
3120 if (column == 0 || column < COLS - 1)
3121 return 0;
3122 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003123 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003124 else if (COLS > 2)
3125 return column - (COLS - 2);
3126 else
3127 return column - (COLS - 1);
3128 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003129}
3130
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003131/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003132 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003133void reset_cursor(void)
3134{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003135 /* If we haven't opened any files yet, put the cursor in the top
3136 * left corner of the edit window and get out. */
3137 if (edittop == NULL || current == NULL) {
3138 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003139 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003140 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003141
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003142 current_y = current->lineno - edittop->lineno;
3143 if (current_y < editwinrows) {
3144 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003145 wmove(edit, current_y, x - get_page_start(x));
3146 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003147}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003148
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003149/* edit_add() takes care of the job of actually painting a line into the
3150 * edit window. fileptr is the line to be painted, at row yval of the
3151 * window. converted is the actual string to be written to the window,
3152 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003153 * characters. start is the column number of the first character of
3154 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003155 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003156void edit_add(const filestruct *fileptr, const char *converted, int
3157 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003158{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003159#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
3160 size_t startpos = actual_x(fileptr->data, start);
3161 /* The position in fileptr->data of the leftmost character
3162 * that displays at least partially on the window. */
3163 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3164 /* The position in fileptr->data of the first character that is
3165 * completely off the window to the right.
3166 *
3167 * Note that endpos might be beyond the null terminator of the
3168 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003169#endif
3170
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 assert(fileptr != NULL && converted != NULL);
3172 assert(strlen(converted) <= COLS);
3173
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003174 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003175 * just the text that needs it). */
3176 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003177
Chris Allegretta7dd77682001-12-08 19:52:28 +00003178#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003179 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003180 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003181
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003182 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3183 int x_start;
3184 /* Starting column for mvwaddnstr. Zero-based. */
3185 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003186 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003187 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003188 regmatch_t startmatch; /* match position for start_regexp */
3189 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003190
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003191 if (tmpcolor->bright)
3192 wattron(edit, A_BOLD);
3193 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003194 /* Two notes about regexec(). Return value 0 means there is
3195 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003196 * after the match. */
3197
3198 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003199 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003200 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003201
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003202 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003203 * last match. Even though two matches may overlap, we
3204 * want to ignore them, so that we can highlight
3205 * C-strings correctly. */
3206 while (k < endpos) {
3207 /* Note the fifth parameter to regexec(). It says
3208 * not to match the beginning-of-line character
3209 * unless k is 0. If regexec() returns REG_NOMATCH,
3210 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003211 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003212 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003213 break;
3214 /* Translate the match to the beginning of the line. */
3215 startmatch.rm_so += k;
3216 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003217 if (startmatch.rm_so == startmatch.rm_eo) {
3218 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003219 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003220 } else if (startmatch.rm_so < endpos &&
3221 startmatch.rm_eo > startpos) {
3222 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003223 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003224 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003225 x_start = strnlenpt(fileptr->data,
3226 startmatch.rm_so) - start;
3227 paintlen = strnlenpt(fileptr->data,
3228 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003229 if (paintlen > COLS - x_start)
3230 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003231
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003232 assert(0 <= x_start && 0 < paintlen &&
3233 x_start + paintlen <= COLS);
3234 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003235 converted + x_start, paintlen);
3236 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003237 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003238 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003239 } else {
3240 /* This is a multi-line regexp. There are two steps.
3241 * First, we have to see if the beginning of the line is
3242 * colored by a start on an earlier line, and an end on
3243 * this line or later.
3244 *
3245 * We find the first line before fileptr matching the
3246 * start. If every match on that line is followed by an
3247 * end, then go to step two. Otherwise, find the next line
3248 * after start_line matching the end. If that line is not
3249 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003250
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003251 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003252 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003253 regoff_t start_col;
3254 /* where it starts in that line */
3255 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003256
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003257 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003258 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003259 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003260 /* If there is an end on this line, there is no need
3261 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003262 if (regexec(tmpcolor->end, start_line->data, 0,
3263 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003264 goto step_two;
3265 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003266 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003267 /* No start found, so skip to the next step. */
3268 if (start_line == NULL)
3269 goto step_two;
3270 /* Now start_line is the first line before fileptr
3271 * containing a start match. Is there a start on this
3272 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003273
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003274 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003275 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003276 start_col += startmatch.rm_so;
3277 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003278 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003279 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003280 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
3281 REG_NOTBOL) == REG_NOMATCH)
3282 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003283 break;
3284 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003285 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003286 start_line->data + start_col, 1,
3287 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003288 /* No later start on this line. */
3289 goto step_two;
3290 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003291 /* Indeed, there is a start not followed on this line by
3292 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003293
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003294 /* We have already checked that there is no end before
3295 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003296 * the start at all? We don't paint unterminated
3297 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003298 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003299 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003300 regexec(tmpcolor->end, end_line->data, 1,
3301 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302 end_line = end_line->next;
3303
3304 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003305 if (end_line == NULL ||
3306 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003307 goto step_two;
3308
3309 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003310 paintlen = end_line != fileptr ? COLS :
3311 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003312 if (paintlen > COLS)
3313 paintlen = COLS;
3314
3315 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003316 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003317
3318 /* We have already painted the whole line. */
3319 if (paintlen == COLS)
3320 goto skip_step_two;
3321
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003322 step_two:
3323 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003324 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003325 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003326 if (regexec(&tmpcolor->start,
3327 fileptr->data + start_col, 1, &startmatch,
3328 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3329 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003330 /* No more starts on this line. */
3331 break;
3332 /* Translate the match to be relative to the
3333 * beginning of the line. */
3334 startmatch.rm_so += start_col;
3335 startmatch.rm_eo += start_col;
3336
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003337 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003338 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003339 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003340 x_start = strnlenpt(fileptr->data,
3341 startmatch.rm_so) - start;
3342 if (regexec(tmpcolor->end,
3343 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3344 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003345 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003346 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003347 endmatch.rm_so += startmatch.rm_eo;
3348 endmatch.rm_eo += startmatch.rm_eo;
3349 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003350 * appear on this page, and is the match more
3351 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003352 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003354 paintlen = strnlenpt(fileptr->data,
3355 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003356 if (x_start + paintlen > COLS)
3357 paintlen = COLS - x_start;
3358
3359 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003360 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003361 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003362 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003363 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003364 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003365 /* There is no end on this line. But we haven't
3366 * yet looked for one on later lines. */
3367 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003368 while (end_line != NULL &&
3369 regexec(tmpcolor->end, end_line->data, 0,
3370 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003371 end_line = end_line->next;
3372 if (end_line != NULL) {
3373 assert(0 <= x_start && x_start < COLS);
3374 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003375 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003376 /* We painted to the end of the line, so
3377 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003378 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003379 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003380 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003381 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003382 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003383 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003384
Chris Allegrettace452fb2003-02-03 02:56:44 +00003385 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003386 wattroff(edit, A_BOLD);
3387 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3388 } /* for tmpcolor in colorstrings */
3389 }
Chris Allegretta598106e2002-01-19 01:59:37 +00003390#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003391
Chris Allegretta7dd77682001-12-08 19:52:28 +00003392#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003393 if (ISSET(MARK_ISSET)
3394 && (fileptr->lineno <= mark_beginbuf->lineno
3395 || fileptr->lineno <= current->lineno)
3396 && (fileptr->lineno >= mark_beginbuf->lineno
3397 || fileptr->lineno >= current->lineno)) {
3398 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003399
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003400 const filestruct *top;
3401 /* Either current or mark_beginbuf, whichever is first. */
3402 size_t top_x;
3403 /* current_x or mark_beginx, corresponding to top. */
3404 const filestruct *bot;
3405 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003406 int x_start;
3407 /* Starting column for mvwaddnstr. Zero-based. */
3408 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003409 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003410 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003411
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003412 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003413
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003414 if (top->lineno < fileptr->lineno || top_x < startpos)
3415 top_x = startpos;
3416 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3417 bot_x = endpos;
3418
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003419 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003420 if (top_x < endpos && bot_x > startpos) {
3421 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003422
3423 /* x_start is the expanded location of the beginning of the
3424 * mark minus the beginning of the page. */
3425 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003426
3427 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003428 /* If the end of the mark is off the page, paintlen is
3429 * -1, meaning that everything on the line gets
3430 * painted. */
3431 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003432 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003433 /* Otherwise, paintlen is the expanded location of the
3434 * end of the mark minus the expanded location of the
3435 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003436 paintlen = strnlenpt(fileptr->data, bot_x)
3437 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003438
3439 /* If x_start is before the beginning of the page, shift
3440 * paintlen x_start characters to compensate, and put
3441 * x_start at the beginning of the page. */
3442 if (x_start < 0) {
3443 paintlen += x_start;
3444 x_start = 0;
3445 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003446
3447 assert(x_start >= 0 && x_start <= strlen(converted));
3448
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003449 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003450 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003451 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003452 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003453 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003454#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003455}
3456
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003457/* Just update one line in the edit buffer. This is basically a wrapper
3458 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003459 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003460 * If fileptr != current, then index is considered 0. The line will be
3461 * displayed starting with fileptr->data[index]. Likely args are
3462 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003463void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003464{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003465 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003466 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003467 char *converted;
3468 /* fileptr->data converted to have tabs and control characters
3469 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003470 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003471
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003472 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003473
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003474 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003475
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003476 /* We assume the line numbers are valid. Is that really true? */
3477 assert(line < 0 || line == check_linenumbers(fileptr));
3478
3479 if (line < 0 || line >= editwinrows)
3480 return;
3481
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003482 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003483 mvwaddstr(edit, line, 0, hblank);
3484
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003485 /* Next, convert variables that index the line to their equivalent
3486 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003487 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003488 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003489
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003490 /* Expand the line, replacing tabs with spaces, and control
3491 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003492 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003493
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003494 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003495 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003496 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003497
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003498 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003499 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003500 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003501 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003502}
3503
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003504/* Return a nonzero value if we need an update after moving
3505 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003506 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003507int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003508{
3509 return
3510#ifndef NANO_SMALL
3511 ISSET(MARK_ISSET) ||
3512#endif
3513 get_page_start(old_pww) != get_page_start(placewewant);
3514}
3515
3516/* Return a nonzero value if we need an update after moving vertically.
3517 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003518 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003519int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003520{
3521 return
3522#ifndef NANO_SMALL
3523 ISSET(MARK_ISSET) ||
3524#endif
3525 get_page_start(old_pww) != get_page_start(placewewant);
3526}
3527
3528/* Scroll the edit window in the given direction and the given number
3529 * of lines, and draw new lines on the blank lines left after the
3530 * scrolling. direction is the direction to scroll, either UP or DOWN,
3531 * and nlines is the number of lines to scroll. Don't redraw the old
3532 * topmost or bottommost line (where we assume current is) before
3533 * scrolling or draw the new topmost or bottommost line after scrolling
3534 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003535 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003536void edit_scroll(updown direction, int nlines)
3537{
3538 filestruct *foo;
3539 int i, scroll_rows = 0;
3540
3541 /* Scrolling less than one line or more than editwinrows lines is
3542 * redundant, so don't allow it. */
3543 if (nlines < 1 || nlines > editwinrows)
3544 return;
3545
3546 /* Move the top line of the edit window up or down (depending on the
3547 * value of direction) nlines lines. If there are fewer lines of
3548 * text than that left, move it to the top or bottom line of the
3549 * file (depending on the value of direction). Keep track of
3550 * how many lines we moved in scroll_rows. */
3551 for (i = nlines; i > 0; i--) {
3552 if (direction == UP) {
3553 if (edittop->prev == NULL)
3554 break;
3555 edittop = edittop->prev;
3556 scroll_rows--;
3557 } else {
3558 if (edittop->next == NULL)
3559 break;
3560 edittop = edittop->next;
3561 scroll_rows++;
3562 }
3563 }
3564
3565 /* Scroll the text on the screen up or down scroll_rows lines,
3566 * depending on the value of direction. */
3567 scrollok(edit, TRUE);
3568 wscrl(edit, scroll_rows);
3569 scrollok(edit, FALSE);
3570
3571 foo = edittop;
3572 if (direction != UP) {
3573 int slines = editwinrows - nlines;
3574 for (; slines > 0 && foo != NULL; slines--)
3575 foo = foo->next;
3576 }
3577
3578 /* And draw new lines on the blank top or bottom lines of the edit
3579 * window, depending on the value of direction. Don't draw the new
3580 * topmost or new bottommost line. */
3581 while (scroll_rows != 0 && foo != NULL) {
3582 if (foo->next != NULL)
3583 update_line(foo, 0);
3584 if (direction == UP)
3585 scroll_rows++;
3586 else
3587 scroll_rows--;
3588 foo = foo->next;
3589 }
3590}
3591
3592/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003593 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003594void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003595{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003596 int do_refresh = need_vertical_update(0) ||
3597 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003598 const filestruct *foo;
3599
3600 /* If either old_current or current is offscreen, refresh the screen
3601 * and get out. */
3602 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3603 edittop->lineno + editwinrows || current->lineno <
3604 edittop->lineno || current->lineno >= edittop->lineno +
3605 editwinrows) {
3606 edit_refresh();
3607 return;
3608 }
3609
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003610 /* Update old_current and current if we're not on the first page
3611 * and/or we're not on the same page as before. If the mark is on,
3612 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003613 foo = old_current;
3614 while (foo != current) {
3615 if (do_refresh)
3616 update_line(foo, 0);
3617#ifndef NANO_SMALL
3618 if (!ISSET(MARK_ISSET))
3619#endif
3620 break;
3621 if (foo->lineno > current->lineno)
3622 foo = foo->prev;
3623 else
3624 foo = foo->next;
3625 }
3626 if (do_refresh)
3627 update_line(current, current_x);
3628}
3629
Chris Allegretta6df90f52002-07-19 01:08:59 +00003630/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003631void edit_refresh(void)
3632{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003633 if (current->lineno < edittop->lineno ||
3634 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003635 /* Note that edit_update() changes edittop so that it's in range
3636 * of current. Thus, when it then calls edit_refresh(), there
3637 * is no danger of getting an infinite loop. */
3638 edit_update(
3639#ifndef NANO_SMALL
3640 ISSET(SMOOTHSCROLL) ? NONE :
3641#endif
3642 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003643 else {
3644 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003645 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003646
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003647#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003648 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003649#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003650
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003651 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003652 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003653 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003654 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003655 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003656 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003657 }
3658 while (nlines < editwinrows) {
3659 mvwaddstr(edit, nlines, 0, hblank);
3660 nlines++;
3661 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003662 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003663 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003664 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003665}
3666
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003667/* A nice generic routine to update the edit buffer. We keep current in
3668 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003669void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003670{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003671 filestruct *foo = current;
3672
Chris Allegretta6df90f52002-07-19 01:08:59 +00003673 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003674 /* If location is CENTER, we move edittop up (editwinrows / 2)
3675 * lines. This puts current at the center of the screen. If
3676 * location is NONE, we move edittop up current_y lines if
3677 * current_y is in range of the screen, 0 lines if current_y is
3678 * less than 0, or (editwinrows - 1) lines if current_y is
3679 * greater than (editwinrows - 1). This puts current at the
3680 * same place on the screen as before, or at the top or bottom
3681 * of the screen if edittop is beyond either. */
3682 int goal;
3683
3684 if (location == CENTER)
3685 goal = editwinrows / 2;
3686 else {
3687 goal = current_y;
3688
3689 /* Limit goal to (editwinrows - 1) lines maximum. */
3690 if (goal > editwinrows - 1)
3691 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003692 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003693
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003694 for (; goal > 0 && foo->prev != NULL; goal--)
3695 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003696 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003697
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003698 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003699 edit_refresh();
3700}
3701
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003702/* Ask a simple yes/no question, specified in msg, on the statusbar.
3703 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3704 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003705int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003706{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003707 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003708 const char *yesstr; /* String of yes characters accepted. */
3709 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003710 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003711
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003712 /* yesstr, nostr, and allstr are strings of any length. Each string
3713 * consists of all characters accepted as a valid character for that
3714 * value. The first value will be the one displayed in the
3715 * shortcuts. Translators: if possible, specify both the shortcuts
3716 * for your language and English. For example, in French: "OoYy"
3717 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003718 yesstr = _("Yy");
3719 nostr = _("Nn");
3720 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003721
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003722 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003723 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003724
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003725 if (COLS < 32)
3726 width = COLS / 2;
3727
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003728 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003729 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003730
Chris Allegretta6232d662002-05-12 19:52:15 +00003731 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003732 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003733 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003734
3735 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003736 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003737 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003738 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003739 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003740
Chris Allegrettadb28e962003-01-28 01:23:40 +00003741 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003742 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003743 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003744
Chris Allegrettadb28e962003-01-28 01:23:40 +00003745 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003746 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003747 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003748
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003749 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003750
3751 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003752 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003753
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003754 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003755
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 Ramseyeb16f432004-09-27 01:04:50 +00003765 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003766
3767 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003768 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003769#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003770 /* Look, ma! We get to duplicate lots of code from
3771 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003772 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003773 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003774
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003775 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003776 wenclose(bottomwin, mouse_y, mouse_x) &&
3777 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003778 int x = mouse_x / width;
3779 /* Did we click in the first column of shortcuts, or
3780 * the second? */
3781 int y = mouse_y - editwinrows - 3;
3782 /* Did we click in the first row of shortcuts? */
3783
3784 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3785
3786 /* x = 0 means they clicked Yes or No.
3787 * y = 0 means Yes or All. */
3788 ok = -2 * x * y + x - y + 1;
3789
3790 if (ok == 2 && !all)
3791 ok = -2;
3792 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003793 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003794#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003795 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003796 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003797 else if (strchr(yesstr, kbinput) != NULL)
3798 ok = 1;
3799 else if (strchr(nostr, kbinput) != NULL)
3800 ok = 0;
3801 else if (all && strchr(allstr, kbinput) != NULL)
3802 ok = 2;
3803 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003804
Chris Allegrettadb28e962003-01-28 01:23:40 +00003805 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003806}
3807
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003808void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003809{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003810 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003811 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003812 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003813 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003814 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003815 wnoutrefresh(bottomwin);
3816 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003817 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003818 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003819 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003820 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003821 edit_refresh();
3822 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003823}
3824
3825void display_main_list(void)
3826{
3827 bottombars(main_list);
3828}
3829
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003830/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3831 * display the cursor position. Otherwise, we display it only if the
3832 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003833 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003834 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3835 * old_i and old_totsize. That way, we leave the current statusbar
3836 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003837void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003838{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003839 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003840 size_t i = 0;
3841 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003842 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003843
Chris Allegrettad26ab912003-01-28 01:16:47 +00003844 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003845
3846 if (old_totsize == -1)
3847 old_totsize = totsize;
3848
Chris Allegrettad26ab912003-01-28 01:16:47 +00003849 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3850 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003851 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003852 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003853 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003854
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003855 /* Check whether totsize is correct. Else there is a bug
3856 * somewhere. */
3857 assert(current != filebot || i == totsize);
3858
Chris Allegrettad26ab912003-01-28 01:16:47 +00003859 if (constant && ISSET(DISABLE_CURPOS)) {
3860 UNSET(DISABLE_CURPOS);
3861 old_i = i;
3862 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003863 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003864 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003865
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003866 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003867 * unconditionally; otherwise, only display the position when the
3868 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003869 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003870 size_t xpt = xplustabs() + 1;
3871 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003872 int linepct = 100 * current->lineno / totlines;
3873 int colpct = 100 * xpt / cur_len;
3874 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3875
3876 statusbar(
3877 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3878 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003879 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003880 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003881 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003882 }
3883
3884 old_i = i;
3885 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003886}
3887
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003888void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003889{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003890 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003891}
3892
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003893#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003894/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003895int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003896{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003897 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003898
3899 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3900 ptr++;
3901 j++;
3902 }
3903 if (j == COLS - 5) {
3904 /* Don't wrap at the first of two spaces following a period. */
3905 if (*ptr == ' ' && *(ptr + 1) == ' ')
3906 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003907 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003908 while (*ptr != ' ' && j > 0) {
3909 ptr--;
3910 j--;
3911 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003912 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003913 if (j == 0)
3914 j = COLS - 5;
3915 }
3916 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3917 return j;
3918}
3919
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003920/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003921void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003922{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003923 int line = 0;
3924 /* The line number in help_text of the first displayed help line.
3925 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003926 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003927 /* no_more means the end of the help text is shown, so don't go
3928 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003929 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003930 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003931
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003932 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003933#ifndef DISABLE_MOUSE
3934 const shortcut *oldshortcut = currshortcut;
3935 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003936 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003937#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003938
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003939 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003940 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003941 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003942 blank_statusbar();
3943
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003944 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003945 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003946 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003947
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003948#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003949 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003950 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003951 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003952#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003953
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003954 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003955 /* Make sure that the help screen's shortcut list will actually
3956 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003957 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003958 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003959 }
3960 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003961
3962 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003963 int i;
3964 int old_line = line;
3965 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003966 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003967
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003968 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003969#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003970 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003971 {
3972 int mouse_x, mouse_y;
3973 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3974 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003975 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003976#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003977 case NANO_NEXTPAGE_KEY:
3978 case NANO_NEXTPAGE_FKEY:
3979 if (!no_more)
3980 line += editwinrows - 2;
3981 break;
3982 case NANO_PREVPAGE_KEY:
3983 case NANO_PREVPAGE_FKEY:
3984 if (line > 0) {
3985 line -= editwinrows - 2;
3986 if (line < 0)
3987 line = 0;
3988 }
3989 break;
3990 case NANO_PREVLINE_KEY:
3991 if (line > 0)
3992 line--;
3993 break;
3994 case NANO_NEXTLINE_KEY:
3995 if (!no_more)
3996 line++;
3997 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003998 }
3999
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004000 if (line == old_line && kbinput != ERR)
4001 goto skip_redisplay;
4002
4003 blank_edit();
4004
4005 assert(COLS > 5);
4006
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004007 /* Calculate where in the text we should be, based on the
4008 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004009 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004010 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004011 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004012 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004013 }
4014
Chris Allegretta4640fe32003-02-10 03:10:03 +00004015 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004016 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004017
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004018 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004019 ptr += j;
4020 if (*ptr == '\n')
4021 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004022 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004023 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00004024
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004025 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00004026 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004027 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
4028 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00004029
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004030#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00004031 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004032#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00004033
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00004034 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00004035 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00004036 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004037 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00004038 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00004039 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004040 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004041
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00004042 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004043 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00004044
David Lawrence Ramsey52453442004-06-26 15:24:16 +00004045 /* The help_init() at the beginning allocated help_text. Since
4046 * help_text has now been written to the screen, we don't need it
4047 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00004048 free(help_text);
4049 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004050}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00004051#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004052
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004053/* Highlight the current word being replaced or spell checked. We
4054 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00004055void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004056{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00004057 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004058 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004059
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004060 y = get_page_start(y) + COLS - y;
4061 /* Now y is the number of characters we can display on this
4062 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004063
4064 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004065
Chris Allegrettafb62f732000-12-05 11:36:41 +00004066 if (highlight_flag)
4067 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)
4072 waddstr(edit, " ");
4073 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004074#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004075 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004076
4077 if (word_len > y)
4078 waddch(edit, '$');
4079 else if (word_len == y)
4080 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004081
4082 if (highlight_flag)
4083 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004084}
4085
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004086#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004087/* Dump the passed-in file structure to stderr. */
4088void dump_buffer(const filestruct *inptr)
4089{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004090 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004091 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004092 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004093 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004094 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004095 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004096
4097 while (inptr != NULL) {
4098 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4099 inptr = inptr->next;
4100 }
4101}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004102
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004103/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004104void dump_buffer_reverse(void)
4105{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004106 const filestruct *fileptr = filebot;
4107
4108 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004109 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004110 fileptr = fileptr->prev;
4111 }
4112}
4113#endif /* DEBUG */
4114
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004115#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004116#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004117#define XLCREDIT_LEN 8
4118
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004119/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004120void do_credits(void)
4121{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004122 int crpos = 0, xlpos = 0;
4123 const char *credits[CREDIT_LEN] = {
4124 NULL, /* "The nano text editor" */
4125 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004126 VERSION,
4127 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004128 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004129 "Chris Allegretta",
4130 "Jordi Mallach",
4131 "Adam Rogoyski",
4132 "Rob Siemborski",
4133 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004134 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004135 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004136 "Ken Tyler",
4137 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004138#ifdef NANO_WIDE
4139 !ISSET(NO_UTF8) ? "Florian K\xC3\xB6nig" :
4140#endif
4141 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004142 "Pauli Virtanen",
4143 "Daniele Medri",
4144 "Clement Laforet",
4145 "Tedi Heriyanto",
4146 "Bill Soudan",
4147 "Christian Weisgerber",
4148 "Erik Andersen",
4149 "Big Gaute",
4150 "Joshua Jensen",
4151 "Ryan Krebs",
4152 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004153 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004154 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004155 "Plattsburgh State University",
4156 "Benet Laboratories",
4157 "Amy Allegretta",
4158 "Linda Young",
4159 "Jeremy Robichaud",
4160 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004161 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004162 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004163 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004164 "Thomas Dickey",
4165 "Pavel Curtis",
4166 "Zeyd Ben-Halim",
4167 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004168 NULL, /* "and anyone else we forgot..." */
4169 NULL, /* "Thank you for using nano!" */
4170 "",
4171 "",
4172 "",
4173 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00004174 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004175 "",
4176 "",
4177 "",
4178 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004179 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004180 };
4181
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004182 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004183 N_("The nano text editor"),
4184 N_("version"),
4185 N_("Brought to you by:"),
4186 N_("Special thanks to:"),
4187 N_("The Free Software Foundation"),
4188 N_("For ncurses:"),
4189 N_("and anyone else we forgot..."),
4190 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004191 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004192
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004193 curs_set(0);
4194 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004195 scrollok(edit, TRUE);
4196 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004197 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004198 blank_statusbar();
4199 blank_bottombars();
4200 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004201 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004202 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004203
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004204 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4205 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004206 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004207 if (crpos < CREDIT_LEN) {
4208 const char *what = credits[crpos];
4209 size_t start_x;
4210
4211 if (what == NULL) {
4212 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004213 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004214 xlpos++;
4215 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004216 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004217 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4218 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004219 }
4220 napms(700);
4221 scroll(edit);
4222 wrefresh(edit);
4223 if (wgetch(edit) != ERR)
4224 break;
4225 napms(700);
4226 scroll(edit);
4227 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004228 }
4229
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004230 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004231 nodelay(edit, FALSE);
4232 curs_set(1);
4233 display_main_list();
4234 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004235}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004236#endif