blob: a86f771de47b548477f4ac5e5f2819641a4725d1 [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
David Lawrence Ramsey9ac20c82005-01-05 20:41:55 +00002209 * as returned by control_rep(). */
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002210 else if (is_cntrl_char(wide_buf)) {
2211 char ctrl_wide_buf =
2212 control_rep((unsigned char)wide_buf);
2213
2214 retval++;
2215 retval += parse_char(&ctrl_wide_buf, NULL, NULL
2216#ifdef NANO_WIDE
2217 , NULL
2218#endif
2219 );
2220 /* If we have a normal character, add its width in bytes
2221 * normally. */
2222 } else
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002223 retval += wide_buf_len;
2224#ifdef NANO_WIDE
2225 }
2226
2227 buf += wide_buf_len;
2228#endif
2229 }
2230
2231 return retval;
2232}
2233
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002234/* Convert buf into a string that can be displayed on screen. The
2235 * caller wants to display buf starting with column start_col, and
2236 * extending for at most len columns. start_col is zero-based. len is
2237 * one-based, so len == 0 means you get "" returned. The returned
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002238 * string is dynamically allocated, and should be freed. If dollars is
2239 * TRUE, the caller might put "$" at the beginning or end of the line if
2240 * it's too long. */
2241char *display_string(const char *buf, size_t start_col, size_t len, bool
2242 dollars)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002243{
2244 size_t start_index;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002245 /* Index in buf of the first character shown. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002246 size_t column;
David Lawrence Ramsey61a71402004-12-24 15:45:36 +00002247 /* Screen column that start_index corresponds to. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002248 size_t alloc_len;
2249 /* The length of memory allocated for converted. */
2250 char *converted;
2251 /* The string we return. */
2252 size_t index;
2253 /* Current position in converted. */
2254
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002255 /* If dollars is TRUE, make room for the "$" at the end of the
2256 * line. */
2257 if (dollars && len > 0 && strlenpt(buf) > start_col + len)
2258 len--;
2259
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002260 if (len == 0)
2261 return mallocstrcpy(NULL, "");
2262
2263 start_index = actual_x(buf, start_col);
2264 column = strnlenpt(buf, start_index);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002265
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002266 assert(column <= start_col);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002267
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002268 alloc_len = display_string_len(buf + start_index, start_col,
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002269 start_col + len);
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002270#ifdef NANO_WIDE
David Lawrence Ramsey8ec1e2d2005-01-05 18:33:04 +00002271 if (!ISSET(NO_UTF8))
2272 alloc_len += MB_CUR_MAX * 2;
2273 else
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002274#endif
David Lawrence Ramsey8ec1e2d2005-01-05 18:33:04 +00002275 alloc_len += 2;
David Lawrence Ramseybbd63e12005-01-05 16:59:49 +00002276
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002277 converted = charalloc(alloc_len + 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002278 index = 0;
2279
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002280 if (column < start_col || (dollars && column > 0 &&
David Lawrence Ramsey930b1d72005-01-05 05:22:42 +00002281 buf[start_index] != '\t')) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002282 int wide_buf, wide_buf_len;
2283
2284 /* We don't display all of buf[start_index] since it starts to
2285 * the left of the screen. */
2286 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2287#ifdef NANO_WIDE
2288 , NULL
2289#endif
2290 );
2291
2292 if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseyfe3627d2004-12-24 17:52:17 +00002293 if (column < start_col) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002294 char *ctrl_wide_buf =
2295#ifdef NANO_WIDE
2296 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2297#endif
2298 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002299 int ctrl_wide_buf_len, i;
2300
2301 wide_buf = control_rep((unsigned char)wide_buf);
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002302
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002303#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002304 if (!ISSET(NO_UTF8))
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002305 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2306 (wchar_t)wide_buf);
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002307 else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002308#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002309 ctrl_wide_buf_len = 1;
2310 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2311#ifdef NANO_WIDE
2312 }
2313#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002314
2315 for (i = 0; i < ctrl_wide_buf_len; i++)
2316 converted[index++] = ctrl_wide_buf[i];
2317
2318 free(ctrl_wide_buf);
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002319
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002320#ifdef NANO_WIDE
2321 if (!ISSET(NO_UTF8)) {
2322 int width = wcwidth((wchar_t)wide_buf);
2323
2324 if (width != -1)
2325 start_col += width;
2326 } else
2327#endif
2328 start_col++;
2329
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002330 start_index += wide_buf_len;
2331 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002332 }
2333#ifdef NANO_WIDE
2334 else if (wcwidth((wchar_t)wide_buf) > 1) {
David Lawrence Ramsey9dffac92005-01-05 06:09:34 +00002335 converted[index++] = ' ';
David Lawrence Ramseya9b99132004-12-27 23:35:25 +00002336
2337 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002338 start_index += wide_buf_len;
2339 }
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002340#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002341 }
2342
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002343 while (index < alloc_len - 1 && buf[start_index] != '\0') {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002344 int wide_buf, wide_buf_len;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002345#ifdef NANO_WIDE
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002346 bool bad_char;
David Lawrence Ramsey9ec76e52004-12-23 19:55:57 +00002347#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002348
2349 wide_buf_len = parse_char(buf + start_index, &wide_buf, NULL
2350#ifdef NANO_WIDE
2351 , &bad_char
2352#endif
2353 );
2354
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002355 if (wide_buf == '\t') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002356 converted[index++] =
2357#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2358 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
2359#endif
2360 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002361 start_col++;
David Lawrence Ramseyc1958202004-12-27 23:21:34 +00002362 while (start_col % tabsize != 0) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002363 converted[index++] = ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002364 start_col++;
2365 }
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002366 /* If buf contains a control character, interpret it. If it
2367 * contains an invalid multibyte control character, interpret
2368 * that character as though it's a normal control character. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002369 } else if (is_cntrl_char(wide_buf)) {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002370 char *ctrl_wide_buf =
2371#ifdef NANO_WIDE
2372 !ISSET(NO_UTF8) ? charalloc(MB_CUR_MAX) :
2373#endif
2374 charalloc(1);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002375 int ctrl_wide_buf_len, i;
2376
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002377 converted[index++] = '^';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002378 start_col++;
2379 wide_buf = control_rep((unsigned char)wide_buf);
2380
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002381#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002382 if (!ISSET(NO_UTF8))
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002383 ctrl_wide_buf_len = wctomb(ctrl_wide_buf,
2384 (wchar_t)wide_buf);
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002385 else {
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002386#endif
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002387 ctrl_wide_buf_len = 1;
2388 ctrl_wide_buf[0] = (unsigned char)wide_buf;
2389#ifdef NANO_WIDE
2390 }
2391#endif
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002392
2393 for (i = 0; i < ctrl_wide_buf_len; i++)
2394 converted[index++] = ctrl_wide_buf[i];
2395
2396 free(ctrl_wide_buf);
2397
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002398#ifdef NANO_WIDE
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002399 if (!ISSET(NO_UTF8)) {
2400 int width = wcwidth((wchar_t)wide_buf);
2401
2402 if (width != -1)
2403 start_col += width;
2404 } else
David Lawrence Ramseya35bdd12004-12-27 18:53:38 +00002405#endif
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002406 start_col++;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002407 } else if (wide_buf == ' ') {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002408 converted[index++] =
2409#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2410 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
2411#endif
2412 ' ';
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002413 start_col++;
2414 } else {
2415 int i;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002416
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002417#ifdef NANO_WIDE
David Lawrence Ramsey6a643cd2004-12-27 23:11:59 +00002418 /* If buf contains an invalid multibyte non-control
2419 * character, interpret that character as though it's a
2420 * normal non-control character. */
2421 if (!ISSET(NO_UTF8) && bad_char) {
2422 char *bad_wide_buf = charalloc(MB_CUR_MAX);
2423 int bad_wide_buf_len;
2424
2425 bad_wide_buf_len = wctomb(bad_wide_buf,
2426 (wchar_t)wide_buf);
2427
2428 for (i = 0; i < bad_wide_buf_len; i++)
2429 converted[index++] = bad_wide_buf[i];
2430
2431 free(bad_wide_buf);
2432 } else {
2433#endif
2434 for (i = 0; i < wide_buf_len; i++)
2435 converted[index++] = buf[start_index + i];
2436#ifdef NANO_WIDE
2437 }
2438
David Lawrence Ramsey956da0d2005-01-03 06:56:38 +00002439 if (!ISSET(NO_UTF8)) {
2440 int width = wcwidth((wchar_t)wide_buf);
2441
2442 if (width != -1)
2443 start_col += width;
2444 } else
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002445#endif
2446 start_col++;
2447 }
2448
2449 start_index += wide_buf_len;
2450 }
2451
David Lawrence Ramsey6d594a92005-01-05 21:43:43 +00002452 if (index < alloc_len - 1)
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002453 converted[index] = '\0';
2454
2455 /* Make sure converted takes up no more than len columns. */
2456 index = actual_x(converted, len);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002457 null_at(&converted, index);
David Lawrence Ramsey0251bdb2005-01-05 19:05:04 +00002458
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002459 return converted;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002460}
2461
Chris Allegretta7662c862003-01-13 01:35:15 +00002462/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002463 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00002464 *
Chris Allegretta7662c862003-01-13 01:35:15 +00002465 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00002466 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002467void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002468{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002469 size_t x_real = strnlenpt(inputbuf, x);
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002470 int wid = COLS - strlenpt(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00002471
David Lawrence Ramsey08cd7ef2005-01-02 20:30:15 +00002472 assert(x <= strlen(inputbuf));
Chris Allegretta6df90f52002-07-19 01:08:59 +00002473
Chris Allegrettab3655b42001-10-22 03:15:31 +00002474 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002475 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002476
Chris Allegretta6df90f52002-07-19 01:08:59 +00002477 mvwaddstr(bottomwin, 0, 0, buf);
2478 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002479
2480 if (COLS > 1)
2481 waddch(bottomwin, x_real < wid ? ' ' : '$');
2482 if (COLS > 2) {
2483 size_t page_start = x_real - x_real % wid;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002484 char *expanded = display_string(inputbuf, page_start, wid,
2485 FALSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002486
2487 assert(wid > 0);
David Lawrence Ramsey2524a702005-01-03 21:34:55 +00002488 assert(strlenpt(expanded) <= wid);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002489
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002490 waddstr(bottomwin, expanded);
2491 free(expanded);
2492 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
2493 } else
2494 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00002495 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00002496}
2497
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002498/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00002499 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002500int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00002501#ifndef NANO_SMALL
2502 historyheadtype *history_list,
2503#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002504 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00002505#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002506 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00002507#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00002508 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00002509{
2510 int kbinput;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002511 bool meta_key, func_key, s_or_t, finished;
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002512 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00002513 /* used by input_tab() */
Chris Allegretta598106e2002-01-19 01:59:37 +00002514
Chris Allegretta5beed502003-01-05 20:41:21 +00002515#ifndef NANO_SMALL
2516 /* for history */
2517 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00002518 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00002519 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002520 int last_kbinput = 0;
2521
2522 /* This variable is used in the search history code. use_cb == 0
2523 means that we're using the existing history and ignoring
2524 currentbuf. use_cb == 1 means that the entry in answer should be
2525 moved to currentbuf or restored from currentbuf to answer.
2526 use_cb == 2 means that the entry in currentbuf should be moved to
2527 answer or restored from answer to currentbuf. */
2528 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002529#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002530 statusbar_xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002531
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002532 /* Only put statusbar_x at the end of the string if it's
2533 * uninitialized, if it would be past the end of the string as it
2534 * is, or if resetstatuspos is TRUE. Otherwise, leave it alone.
2535 * This is so the cursor position stays at the same place if a
2536 * prompt-changing toggle is pressed. */
2537 if (statusbar_x == (size_t)-1 || statusbar_x > statusbar_xend ||
2538 resetstatuspos)
2539 statusbar_x = statusbar_xend;
Chris Allegretta09fc4302003-01-16 22:16:38 +00002540
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002541 answer = charealloc(answer, statusbar_xend + 1);
2542 if (statusbar_xend > 0)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002543 strcpy(answer, def);
2544 else
2545 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002546
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002547 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00002548
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002549 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00002550
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002551 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002552
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002553 /* Refresh the edit window before getting input. */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00002554 wnoutrefresh(edit);
2555 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00002556
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002557 /* If we're using restricted mode, we aren't allowed to change the
2558 * name of a file once it has one because that would allow writing
2559 * to files not specified on the command line. In this case,
2560 * disable all keys that would change the text if the filename isn't
2561 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002562 while ((kbinput = do_statusbar_input(&meta_key, &func_key,
2563 &s_or_t, &finished, TRUE)) != NANO_CANCEL_KEY &&
2564 kbinput != NANO_ENTER_KEY) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00002565
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002566 /* If we have a shortcut with an associated function, break out
2567 * if we're finished after running the function. */
2568 if (finished)
2569 break;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00002570
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002571 assert(statusbar_x <= statusbar_xend &&
2572 statusbar_xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002573
Chris Allegretta04d848e2000-11-05 17:54:41 +00002574 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002575 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00002576
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002577 switch (kbinput) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002578 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002579#ifndef NANO_SMALL
2580 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00002581 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00002582 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002583 history_list->current = (historytype *)history_list;
2584 history_list->len = strlen(answer);
2585 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00002586
Chris Allegretta7662c862003-01-13 01:35:15 +00002587 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002588 complete = get_history_completion(history_list, answer);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002589 statusbar_x = strlen(complete);
2590 statusbar_xend = statusbar_x;
Chris Allegretta5beed502003-01-05 20:41:21 +00002591 answer = mallocstrcpy(answer, complete);
2592 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002593 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002594#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002595 else
2596#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002597#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002598#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002599 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002600 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002601
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002602 answer = input_tab(answer, statusbar_x, &tabbed, &shift,
2603 list);
2604 statusbar_xend = strlen(answer);
2605 statusbar_x += shift;
2606 if (statusbar_x > statusbar_xend)
2607 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002608 }
2609#endif
2610 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002611 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002612#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002613 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002614
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002615 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2616 isn't NULL, and currentbuf is different from answer,
2617 it means that we're scrolling up at the top of the
2618 search history, and we need to save the current
2619 answer in currentbuf; do this and reset use_cb to
2620 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002621 if (currentbuf == NULL || (use_cb == 1 &&
2622 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002623 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002624 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002625 }
2626
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002627 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2628 is different from answer, it means that we're
2629 scrolling up at the bottom of the search history, and
2630 we need to make the string in currentbuf the current
2631 answer; do this, blow away currentbuf since we don't
2632 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002633 if (currentbuf != NULL && use_cb == 2 &&
2634 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002635 answer = mallocstrcpy(answer, currentbuf);
2636 free(currentbuf);
2637 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002638 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002639 use_cb = 0;
2640
2641 /* else get older search from the history list and save
2642 it in answer; if there is no older search, blank out
2643 answer */
2644 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002645 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002646 statusbar_xend = strlen(history);
Chris Allegretta5beed502003-01-05 20:41:21 +00002647 } else {
2648 answer = mallocstrcpy(answer, "");
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002649 statusbar_xend = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002650 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002651 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002652 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002653#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002654 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002655 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002656#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002657 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002658
2659 /* get newer search from the history list and save it
2660 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002661 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002662 answer = mallocstrcpy(answer, history);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002663 statusbar_xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002664
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002665 /* if there is no newer search, we're here */
2666
2667 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2668 that we're scrolling down at the bottom of the search
2669 history and we need to make the string in currentbuf
2670 the current answer; do this, blow away currentbuf
2671 since we don't need it anymore, and set use_cb to
2672 1 */
2673 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002674 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002675 free(currentbuf);
2676 currentbuf = NULL;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002677 statusbar_xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002678 use_cb = 1;
2679
2680 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2681 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002682 the search history and the current answer (if it's
2683 not blank) needs to be saved in currentbuf; do this,
2684 blank out answer (if necessary), and set use_cb to
2685 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002686 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002687 if (answer[0] != '\0') {
2688 currentbuf = mallocstrcpy(currentbuf, answer);
2689 answer = mallocstrcpy(answer, "");
2690 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002691 statusbar_xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002692 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002693 }
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002694 statusbar_x = statusbar_xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002695 }
2696#endif
2697 break;
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002698 }
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002699#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002700 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002701#endif
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002702 nanoget_repaint(buf, answer, statusbar_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002703 wrefresh(bottomwin);
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002704 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002705
David Lawrence Ramseyc13b7f02005-01-01 07:28:15 +00002706 /* We finished putting in an answer, so reset statusbar_x. */
2707 if (kbinput == NANO_CANCEL_KEY || kbinput == NANO_ENTER_KEY)
2708 statusbar_x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002709
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002710 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002711}
2712
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002713/* Ask a question on the statusbar. Answer will be stored in answer
2714 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2715 * otherwise, the valid shortcut key caught. def is any editable text
2716 * we want to put up by default.
2717 *
2718 * New arg tabs tells whether or not to allow tab completion. */
2719int statusq(bool allow_tabs, const shortcut *s, const char *def,
2720#ifndef NANO_SMALL
2721 historyheadtype *which_history,
2722#endif
2723 const char *msg, ...)
2724{
2725 va_list ap;
2726 char *foo = charalloc(COLS - 3);
2727 int ret;
2728#ifndef DISABLE_TABCOMP
2729 bool list = FALSE;
2730#endif
2731
2732 bottombars(s);
2733
2734 va_start(ap, msg);
2735 vsnprintf(foo, COLS - 4, msg, ap);
2736 va_end(ap);
2737 foo[COLS - 4] = '\0';
2738
2739 ret = nanogetstr(allow_tabs, foo, def,
2740#ifndef NANO_SMALL
2741 which_history,
2742#endif
2743 s
2744#ifndef DISABLE_TABCOMP
2745 , &list
2746#endif
2747 );
2748 free(foo);
2749 resetstatuspos = FALSE;
2750
2751 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002752 case NANO_CANCEL_KEY:
2753 ret = -1;
2754 resetstatuspos = TRUE;
2755 break;
2756 case NANO_ENTER_KEY:
2757 ret = (answer[0] == '\0') ? -2 : 0;
2758 resetstatuspos = TRUE;
2759 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002760 }
2761 blank_statusbar();
2762
2763#ifdef DEBUG
2764 fprintf(stderr, "I got \"%s\"\n", answer);
2765#endif
2766
2767#ifndef DISABLE_TABCOMP
2768 /* if we've done tab completion, there might be a list of
2769 filename matches on the edit window at this point; make sure
2770 they're cleared off. */
2771 if (list)
2772 edit_refresh();
2773#endif
2774
2775 return ret;
2776}
2777
2778void statusq_abort(void)
2779{
2780 resetstatuspos = TRUE;
2781}
2782
Chris Allegrettaf717f982003-02-13 22:25:01 +00002783void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002784{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002785 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002786 /* The space we have available for display. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002787 size_t verlen = strlenpt(VERMSG) + 1;
2788 /* The length of the version message in columns. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002789 const char *prefix;
2790 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2791 size_t prefixlen;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002792 /* The length of the prefix in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002793 const char *state;
2794 /* "Modified", "View", or spaces the length of "Modified".
2795 * Tells the state of this buffer. */
2796 size_t statelen = 0;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002797 /* The length of the state in columns, plus one. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002798 char *exppath = NULL;
2799 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002800 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002801 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002802 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002803 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002804
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002805 assert(path != NULL || filename != NULL);
2806 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002807
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002808 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002809
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002810 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002811
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002812 if (COLS <= 5 || COLS - 5 < verlen)
2813 space = 0;
2814 else {
2815 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002816 /* Reserve 2/3 of the screen plus one column for after the
2817 * version message. */
2818 if (space < COLS - (COLS / 3) + 1)
2819 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002820 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002821
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002822 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002823 /* The version message should only take up 1/3 of the screen
2824 * minus one column. */
2825 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002826 waddstr(topwin, " ");
2827 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002828
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002829 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002830 state = _("Modified");
2831 else if (path == NULL && ISSET(VIEW_MODE))
2832 state = _("View");
2833 else {
2834 if (space > 0)
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002835 statelen = strnlenpt(_("Modified"), space - 1) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002836 state = &hblank[COLS - statelen];
2837 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002838 statelen = strnlenpt(state, COLS);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002839 /* We need a space before state. */
2840 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2841 statelen++;
2842
2843 assert(space >= 0);
2844 if (space == 0 || statelen >= space)
2845 goto the_end;
2846
2847#ifndef DISABLE_BROWSER
2848 if (path != NULL)
2849 prefix = _("DIR:");
2850 else
2851#endif
2852 if (filename[0] == '\0') {
2853 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002854 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002855 } else
2856 prefix = _("File:");
2857 assert(statelen < space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002858 prefixlen = strnlenpt(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002859 /* If newfie is FALSE, we need a space after prefix. */
2860 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002861 prefixlen++;
2862
2863 if (path == NULL)
2864 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002865 if (space >= prefixlen + statelen)
2866 space -= prefixlen + statelen;
2867 else
2868 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002869 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002870 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002871 size_t lenpt = strlenpt(path), start_col;
2872
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002873 dots = (lenpt > space);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002874
2875 if (dots) {
2876 start_col = lenpt - space + 3;
2877 space -= 3;
2878 } else
2879 start_col = 0;
2880
2881 exppath = display_string(path, start_col, space, FALSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002882 }
2883
2884 if (!dots) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002885 size_t exppathlen = newfie ? 0 : strlenpt(exppath);
2886 /* The length of the expanded filename. */
2887
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002888 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002889 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002890 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002891 if (!newfie) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002892 assert(strlenpt(prefix) + 1 == prefixlen);
2893
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002894 waddch(topwin, ' ');
2895 waddstr(topwin, exppath);
2896 }
2897 } else {
2898 /* We will say something like "File: ...ename". */
2899 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002900 if (space <= -3 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002901 goto the_end;
2902 waddch(topwin, ' ');
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002903 waddnstr(topwin, "...", space + 3);
2904 if (space <= 0)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002905 goto the_end;
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002906 waddstr(topwin, exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002907 }
2908
2909 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002910 free(exppath);
2911
2912 if (COLS <= 1 || statelen >= COLS - 1)
2913 mvwaddnstr(topwin, 0, 0, state, COLS);
2914 else {
2915 assert(COLS - statelen - 2 >= 0);
2916 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2917 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2918 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002919
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002920 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002921
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002922 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002923 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002924 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002925}
2926
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002927/* If modified is not already set, set it and update titlebar. */
2928void set_modified(void)
2929{
2930 if (!ISSET(MODIFIED)) {
2931 SET(MODIFIED);
2932 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002933 }
2934}
2935
2936void statusbar(const char *msg, ...)
2937{
2938 va_list ap;
2939
2940 va_start(ap, msg);
2941
2942 /* Curses mode is turned off. If we use wmove() now, it will muck
2943 * up the terminal settings. So we just use vfprintf(). */
2944 if (curses_ended) {
2945 vfprintf(stderr, msg, ap);
2946 va_end(ap);
2947 return;
2948 }
2949
2950 /* Blank out the line. */
2951 blank_statusbar();
2952
2953 if (COLS >= 4) {
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002954 char *bar, *foo;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002955 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002956#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002957 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002958
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002959 UNSET(WHITESPACE_DISPLAY);
2960#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002961 bar = charalloc(COLS - 3);
2962 vsnprintf(bar, COLS - 3, msg, ap);
2963 va_end(ap);
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00002964 foo = display_string(bar, 0, COLS - 4, FALSE);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002965#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2966 if (old_whitespace)
2967 SET(WHITESPACE_DISPLAY);
2968#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002969 free(bar);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00002970 foo_len = strlenpt(foo);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002971 start_x = (COLS - foo_len - 4) / 2;
2972
2973 wmove(bottomwin, 0, start_x);
2974 wattron(bottomwin, A_REVERSE);
2975
2976 waddstr(bottomwin, "[ ");
2977 waddstr(bottomwin, foo);
2978 free(foo);
2979 waddstr(bottomwin, " ]");
2980 wattroff(bottomwin, A_REVERSE);
2981 wnoutrefresh(bottomwin);
2982 reset_cursor();
2983 wrefresh(edit);
2984 /* Leave the cursor at its position in the edit window, not
2985 * in the statusbar. */
2986 }
2987
2988 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002989 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002990}
2991
Chris Allegretta6232d662002-05-12 19:52:15 +00002992void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002993{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002994 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002995
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002996 if (ISSET(NO_HELP))
2997 return;
2998
Chris Allegretta6232d662002-05-12 19:52:15 +00002999 if (s == main_list) {
3000 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003001 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00003002 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00003003 slen = length_of_list(s);
3004
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003005 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00003006 if (slen > MAIN_VISIBLE)
3007 slen = MAIN_VISIBLE;
3008 }
3009
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003010 /* There will be this many characters per column. We need at least
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003011 * 3 to display anything properly. */
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003012 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003013
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003014 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00003015
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003016 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003017 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00003018
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003019 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00003020#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003021 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003022 keystr = _("Up");
3023 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003024#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003025 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00003026
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00003027 if (s->ctrlval == NANO_CONTROL_SPACE)
3028 strcpy(foo, "^ ");
3029 else if (s->ctrlval == NANO_CONTROL_8)
3030 strcpy(foo, "^?");
3031 /* Normal values. Assume that the shortcut has an
3032 * equivalent control key, meta key sequence, or both. */
3033 else if (s->ctrlval != NANO_NO_KEY)
3034 sprintf(foo, "^%c", s->ctrlval + 64);
3035 else if (s->metaval != NANO_NO_KEY)
3036 sprintf(foo, "M-%c", toupper(s->metaval));
3037
3038 keystr = foo;
3039#ifndef NANO_SMALL
3040 }
3041#endif
3042
3043 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003044 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003045 }
3046
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003047 wnoutrefresh(bottomwin);
3048 reset_cursor();
3049 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003050}
3051
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00003052/* Write a shortcut key to the help area at the bottom of the window.
3053 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
3054 * to write at most len characters, even if len is very small and
3055 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
3056 * the whole string! We do not bother padding the entry with blanks. */
3057void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003058{
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003059 assert(keystroke != NULL && desc != NULL);
3060
3061 size_t keystroke_len = strlenpt(keystroke) + 1;
3062
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003063 wattron(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003064 waddnstr(bottomwin, keystroke, actual_x(keystroke, len));
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003065 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003066
3067 if (len > keystroke_len)
3068 len -= keystroke_len;
3069 else
3070 len = 0;
3071
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003072 if (len > 0) {
3073 waddch(bottomwin, ' ');
David Lawrence Ramsey1903ace2004-12-24 00:43:41 +00003074 waddnstr(bottomwin, desc, actual_x(desc, len));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003075 }
3076}
3077
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003078/* And so start the display update routines. */
3079
3080#ifndef NDEBUG
3081int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003082{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003083 int check_line = 0;
3084 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003085
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003086 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
3087 check_line++;
3088 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00003089}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003090#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00003091
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003092/* nano scrolls horizontally within a line in chunks. This function
3093 * returns the column number of the first character displayed in the
3094 * window when the cursor is at the given column. Note that
3095 * 0 <= column - get_page_start(column) < COLS. */
3096size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00003097{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003098 assert(COLS > 0);
3099 if (column == 0 || column < COLS - 1)
3100 return 0;
3101 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00003102 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003103 else if (COLS > 2)
3104 return column - (COLS - 2);
3105 else
3106 return column - (COLS - 1);
3107 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003108}
3109
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003110/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003111 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003112void reset_cursor(void)
3113{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003114 /* If we haven't opened any files yet, put the cursor in the top
3115 * left corner of the edit window and get out. */
3116 if (edittop == NULL || current == NULL) {
3117 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003118 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00003119 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003120
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003121 current_y = current->lineno - edittop->lineno;
3122 if (current_y < editwinrows) {
3123 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003124 wmove(edit, current_y, x - get_page_start(x));
3125 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00003126}
Chris Allegretta6df90f52002-07-19 01:08:59 +00003127
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003128/* edit_add() takes care of the job of actually painting a line into the
3129 * edit window. fileptr is the line to be painted, at row yval of the
3130 * window. converted is the actual string to be written to the window,
3131 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003132 * characters. start is the column number of the first character of
3133 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003134 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003135void edit_add(const filestruct *fileptr, const char *converted, int
3136 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003137{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003138#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
3139 size_t startpos = actual_x(fileptr->data, start);
3140 /* The position in fileptr->data of the leftmost character
3141 * that displays at least partially on the window. */
3142 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
3143 /* The position in fileptr->data of the first character that is
3144 * completely off the window to the right.
3145 *
3146 * Note that endpos might be beyond the null terminator of the
3147 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003148#endif
3149
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003150 assert(fileptr != NULL && converted != NULL);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003151 assert(strlenpt(converted) <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003152
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003153 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003154 * just the text that needs it). */
3155 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003156
Chris Allegretta7dd77682001-12-08 19:52:28 +00003157#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00003158 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003159 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003160
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003161 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
3162 int x_start;
3163 /* Starting column for mvwaddnstr. Zero-based. */
3164 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003165 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003166 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003167 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003168 /* Index in converted where we paint. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003169 regmatch_t startmatch; /* match position for start_regexp */
3170 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003171
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003172 if (tmpcolor->bright)
3173 wattron(edit, A_BOLD);
3174 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003175 /* Two notes about regexec(). Return value 0 means there is
3176 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003177 * after the match. */
3178
3179 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003180 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003181 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003182
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003183 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003184 * last match. Even though two matches may overlap, we
3185 * want to ignore them, so that we can highlight
3186 * C-strings correctly. */
3187 while (k < endpos) {
3188 /* Note the fifth parameter to regexec(). It says
3189 * not to match the beginning-of-line character
3190 * unless k is 0. If regexec() returns REG_NOMATCH,
3191 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00003192 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003193 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003194 break;
3195 /* Translate the match to the beginning of the line. */
3196 startmatch.rm_so += k;
3197 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00003198 if (startmatch.rm_so == startmatch.rm_eo) {
3199 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00003200 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003201 } else if (startmatch.rm_so < endpos &&
3202 startmatch.rm_eo > startpos) {
3203 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003204 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003205 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003206 x_start = strnlenpt(fileptr->data,
3207 startmatch.rm_so) - start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003208
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003209 index = actual_x(converted, x_start);
3210
3211 paintlen = actual_x(converted + index,
3212 strnlenpt(fileptr->data +
3213 startmatch.rm_so, startmatch.rm_eo -
3214 startmatch.rm_so));
3215
3216 assert(0 <= x_start && 0 <= paintlen);
3217
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003218 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003219 converted + index, paintlen);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003220 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003221 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00003222 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003223 } else {
3224 /* This is a multi-line regexp. There are two steps.
3225 * First, we have to see if the beginning of the line is
3226 * colored by a start on an earlier line, and an end on
3227 * this line or later.
3228 *
3229 * We find the first line before fileptr matching the
3230 * start. If every match on that line is followed by an
3231 * end, then go to step two. Otherwise, find the next line
3232 * after start_line matching the end. If that line is not
3233 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003234
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003235 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003236 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003237 regoff_t start_col;
3238 /* where it starts in that line */
3239 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003240
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003241 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00003242 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003243 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003244 /* If there is an end on this line, there is no need
3245 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003246 if (regexec(tmpcolor->end, start_line->data, 0,
3247 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003248 goto step_two;
3249 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003250 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003251 /* No start found, so skip to the next step. */
3252 if (start_line == NULL)
3253 goto step_two;
3254 /* Now start_line is the first line before fileptr
3255 * containing a start match. Is there a start on this
3256 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003257
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003258 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00003259 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003260 start_col += startmatch.rm_so;
3261 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003262 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003263 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003264 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
3265 REG_NOTBOL) == REG_NOMATCH)
3266 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003267 break;
3268 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003269 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003270 start_line->data + start_col, 1,
3271 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003272 /* No later start on this line. */
3273 goto step_two;
3274 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003275 /* Indeed, there is a start not followed on this line by
3276 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003277
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003278 /* We have already checked that there is no end before
3279 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003280 * the start at all? We don't paint unterminated
3281 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003282 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00003283 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00003284 regexec(tmpcolor->end, end_line->data, 1,
3285 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003286 end_line = end_line->next;
3287
3288 /* No end found, or it is too early. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003289 if (end_line == NULL || (end_line == fileptr &&
3290 endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003291 goto step_two;
3292
3293 /* Now paint the start of fileptr. */
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003294 paintlen = (end_line != fileptr) ? -1 :
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003295 actual_x(converted, strnlenpt(fileptr->data,
3296 endmatch.rm_eo) - start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003297
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003298 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003299
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003300 step_two:
3301 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003302 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003303 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003304 if (regexec(&tmpcolor->start,
3305 fileptr->data + start_col, 1, &startmatch,
3306 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
3307 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003308 /* No more starts on this line. */
3309 break;
3310 /* Translate the match to be relative to the
3311 * beginning of the line. */
3312 startmatch.rm_so += start_col;
3313 startmatch.rm_eo += start_col;
3314
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003315 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003316 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003317 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003318 x_start = strnlenpt(fileptr->data,
3319 startmatch.rm_so) - start;
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003320 index = actual_x(converted, x_start);
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003321 if (regexec(tmpcolor->end,
3322 fileptr->data + startmatch.rm_eo, 1, &endmatch,
3323 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003324 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003325 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003326 endmatch.rm_so += startmatch.rm_eo;
3327 endmatch.rm_eo += startmatch.rm_eo;
3328 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00003329 * appear on this page, and is the match more
3330 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003331 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003332 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003333 paintlen = actual_x(converted + index,
3334 strnlenpt(fileptr->data +
3335 startmatch.rm_so, endmatch.rm_eo -
3336 startmatch.rm_so));
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003337
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003338 assert(0 <= x_start && x_start < COLS);
3339
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003340 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003341 converted + index, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003342 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00003343 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003344 /* There is no end on this line. But we haven't
3345 * yet looked for one on later lines. */
3346 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003347 while (end_line != NULL &&
3348 regexec(tmpcolor->end, end_line->data, 0,
3349 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003350 end_line = end_line->next;
3351 if (end_line != NULL) {
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003352
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003353 assert(0 <= x_start && x_start < COLS);
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003354
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003355 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003356 converted + index, -1);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003357 /* We painted to the end of the line, so
3358 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003359 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00003360 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003361 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003362 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003363 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003364 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00003365
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003366 wattroff(edit, A_BOLD);
3367 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
3368 } /* for tmpcolor in colorstrings */
3369 }
Chris Allegretta598106e2002-01-19 01:59:37 +00003370#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003371
Chris Allegretta7dd77682001-12-08 19:52:28 +00003372#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003373 if (ISSET(MARK_ISSET)
3374 && (fileptr->lineno <= mark_beginbuf->lineno
3375 || fileptr->lineno <= current->lineno)
3376 && (fileptr->lineno >= mark_beginbuf->lineno
3377 || fileptr->lineno >= current->lineno)) {
3378 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00003379
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003380 const filestruct *top;
3381 /* Either current or mark_beginbuf, whichever is first. */
3382 size_t top_x;
3383 /* current_x or mark_beginx, corresponding to top. */
3384 const filestruct *bot;
3385 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003386 int x_start;
3387 /* Starting column for mvwaddnstr. Zero-based. */
3388 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003389 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003390 * characters on a whole line. */
David Lawrence Ramsey179f0ea2005-01-04 02:55:45 +00003391 size_t index;
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003392 /* Index in converted where we paint. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003393
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00003394 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003395
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003396 if (top->lineno < fileptr->lineno || top_x < startpos)
3397 top_x = startpos;
3398 if (bot->lineno > fileptr->lineno || bot_x > endpos)
3399 bot_x = endpos;
3400
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003401 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003402 if (top_x < endpos && bot_x > startpos) {
3403 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003404
3405 /* x_start is the expanded location of the beginning of the
3406 * mark minus the beginning of the page. */
3407 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003408
3409 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003410 /* If the end of the mark is off the page, paintlen is
3411 * -1, meaning that everything on the line gets
3412 * painted. */
3413 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003414 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003415 /* Otherwise, paintlen is the expanded location of the
3416 * end of the mark minus the expanded location of the
3417 * beginning of the mark. */
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003418 paintlen = strnlenpt(fileptr->data, bot_x) -
3419 (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00003420
3421 /* If x_start is before the beginning of the page, shift
3422 * paintlen x_start characters to compensate, and put
3423 * x_start at the beginning of the page. */
3424 if (x_start < 0) {
3425 paintlen += x_start;
3426 x_start = 0;
3427 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003428
3429 assert(x_start >= 0 && x_start <= strlen(converted));
3430
David Lawrence Ramsey68e30162005-01-03 22:23:00 +00003431 index = actual_x(converted, x_start);
3432 if (paintlen > 0)
3433 paintlen = actual_x(converted + index, paintlen);
3434
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003435 wattron(edit, A_REVERSE);
David Lawrence Ramsey22e5eff2005-01-03 22:56:38 +00003436 mvwaddnstr(edit, yval, x_start, converted + x_start,
3437 paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00003438 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003439 }
Chris Allegretta08893e02001-11-29 02:42:27 +00003440 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003441#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003442}
3443
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003444/* Just update one line in the edit buffer. This is basically a wrapper
3445 * for edit_add().
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003446 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00003447 * If fileptr != current, then index is considered 0. The line will be
3448 * displayed starting with fileptr->data[index]. Likely args are
3449 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003450void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003451{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003452 int line;
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003453 /* The line in the edit window that we want to update. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003454 char *converted;
3455 /* fileptr->data converted to have tabs and control characters
3456 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003457 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003458
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003459 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00003460
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003461 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003462
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003463 /* We assume the line numbers are valid. Is that really true? */
3464 assert(line < 0 || line == check_linenumbers(fileptr));
3465
3466 if (line < 0 || line >= editwinrows)
3467 return;
3468
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003469 /* First, blank out the line. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003470 mvwaddstr(edit, line, 0, hblank);
3471
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003472 /* Next, convert variables that index the line to their equivalent
3473 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00003474 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003475 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00003476
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003477 /* Expand the line, replacing tabs with spaces, and control
3478 * characters with their displayed forms. */
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00003479 converted = display_string(fileptr->data, page_start, COLS, TRUE);
Robert Siemborski53875912000-06-16 04:25:30 +00003480
David Lawrence Ramseyabc94232004-12-08 23:24:31 +00003481 /* Paint the line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003482 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003483 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003484
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003485 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003486 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003487 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00003488 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003489}
3490
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003491/* Return a nonzero value if we need an update after moving
3492 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003493 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003494int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003495{
3496 return
3497#ifndef NANO_SMALL
3498 ISSET(MARK_ISSET) ||
3499#endif
3500 get_page_start(old_pww) != get_page_start(placewewant);
3501}
3502
3503/* Return a nonzero value if we need an update after moving vertically.
3504 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003505 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003506int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003507{
3508 return
3509#ifndef NANO_SMALL
3510 ISSET(MARK_ISSET) ||
3511#endif
3512 get_page_start(old_pww) != get_page_start(placewewant);
3513}
3514
3515/* Scroll the edit window in the given direction and the given number
3516 * of lines, and draw new lines on the blank lines left after the
3517 * scrolling. direction is the direction to scroll, either UP or DOWN,
3518 * and nlines is the number of lines to scroll. Don't redraw the old
3519 * topmost or bottommost line (where we assume current is) before
3520 * scrolling or draw the new topmost or bottommost line after scrolling
3521 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003522 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003523void edit_scroll(updown direction, int nlines)
3524{
3525 filestruct *foo;
3526 int i, scroll_rows = 0;
3527
3528 /* Scrolling less than one line or more than editwinrows lines is
3529 * redundant, so don't allow it. */
3530 if (nlines < 1 || nlines > editwinrows)
3531 return;
3532
3533 /* Move the top line of the edit window up or down (depending on the
3534 * value of direction) nlines lines. If there are fewer lines of
3535 * text than that left, move it to the top or bottom line of the
3536 * file (depending on the value of direction). Keep track of
3537 * how many lines we moved in scroll_rows. */
3538 for (i = nlines; i > 0; i--) {
3539 if (direction == UP) {
3540 if (edittop->prev == NULL)
3541 break;
3542 edittop = edittop->prev;
3543 scroll_rows--;
3544 } else {
3545 if (edittop->next == NULL)
3546 break;
3547 edittop = edittop->next;
3548 scroll_rows++;
3549 }
3550 }
3551
3552 /* Scroll the text on the screen up or down scroll_rows lines,
3553 * depending on the value of direction. */
3554 scrollok(edit, TRUE);
3555 wscrl(edit, scroll_rows);
3556 scrollok(edit, FALSE);
3557
3558 foo = edittop;
3559 if (direction != UP) {
3560 int slines = editwinrows - nlines;
3561 for (; slines > 0 && foo != NULL; slines--)
3562 foo = foo->next;
3563 }
3564
3565 /* And draw new lines on the blank top or bottom lines of the edit
3566 * window, depending on the value of direction. Don't draw the new
3567 * topmost or new bottommost line. */
3568 while (scroll_rows != 0 && foo != NULL) {
3569 if (foo->next != NULL)
3570 update_line(foo, 0);
3571 if (direction == UP)
3572 scroll_rows++;
3573 else
3574 scroll_rows--;
3575 foo = foo->next;
3576 }
3577}
3578
3579/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003580 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003581void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003582{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003583 int do_refresh = need_vertical_update(0) ||
3584 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003585 const filestruct *foo;
3586
3587 /* If either old_current or current is offscreen, refresh the screen
3588 * and get out. */
3589 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3590 edittop->lineno + editwinrows || current->lineno <
3591 edittop->lineno || current->lineno >= edittop->lineno +
3592 editwinrows) {
3593 edit_refresh();
3594 return;
3595 }
3596
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003597 /* Update old_current and current if we're not on the first page
3598 * and/or we're not on the same page as before. If the mark is on,
3599 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003600 foo = old_current;
3601 while (foo != current) {
3602 if (do_refresh)
3603 update_line(foo, 0);
3604#ifndef NANO_SMALL
3605 if (!ISSET(MARK_ISSET))
3606#endif
3607 break;
3608 if (foo->lineno > current->lineno)
3609 foo = foo->prev;
3610 else
3611 foo = foo->next;
3612 }
3613 if (do_refresh)
3614 update_line(current, current_x);
3615}
3616
Chris Allegretta6df90f52002-07-19 01:08:59 +00003617/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003618void edit_refresh(void)
3619{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003620 if (current->lineno < edittop->lineno ||
3621 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003622 /* Note that edit_update() changes edittop so that it's in range
3623 * of current. Thus, when it then calls edit_refresh(), there
3624 * is no danger of getting an infinite loop. */
3625 edit_update(
3626#ifndef NANO_SMALL
3627 ISSET(SMOOTHSCROLL) ? NONE :
3628#endif
3629 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003630 else {
3631 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003632 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003633
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003634#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003635 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003636#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003637
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003638 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003639 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003640 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003641 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003642 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003643 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003644 }
3645 while (nlines < editwinrows) {
3646 mvwaddstr(edit, nlines, 0, hblank);
3647 nlines++;
3648 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003649 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003650 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003651 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003652}
3653
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003654/* A nice generic routine to update the edit buffer. We keep current in
3655 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003656void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003657{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003658 filestruct *foo = current;
3659
Chris Allegretta6df90f52002-07-19 01:08:59 +00003660 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003661 /* If location is CENTER, we move edittop up (editwinrows / 2)
3662 * lines. This puts current at the center of the screen. If
3663 * location is NONE, we move edittop up current_y lines if
3664 * current_y is in range of the screen, 0 lines if current_y is
3665 * less than 0, or (editwinrows - 1) lines if current_y is
3666 * greater than (editwinrows - 1). This puts current at the
3667 * same place on the screen as before, or at the top or bottom
3668 * of the screen if edittop is beyond either. */
3669 int goal;
3670
3671 if (location == CENTER)
3672 goal = editwinrows / 2;
3673 else {
3674 goal = current_y;
3675
3676 /* Limit goal to (editwinrows - 1) lines maximum. */
3677 if (goal > editwinrows - 1)
3678 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003679 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003680
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003681 for (; goal > 0 && foo->prev != NULL; goal--)
3682 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003683 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003684
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003685 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003686 edit_refresh();
3687}
3688
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003689/* Ask a simple yes/no question, specified in msg, on the statusbar.
3690 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3691 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003692int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003693{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003694 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003695 const char *yesstr; /* String of yes characters accepted. */
3696 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003697 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003698
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003699 /* yesstr, nostr, and allstr are strings of any length. Each string
3700 * consists of all characters accepted as a valid character for that
3701 * value. The first value will be the one displayed in the
3702 * shortcuts. Translators: if possible, specify both the shortcuts
3703 * for your language and English. For example, in French: "OoYy"
3704 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003705 yesstr = _("Yy");
3706 nostr = _("Nn");
3707 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003708
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003709 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003710 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003711
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003712 if (COLS < 32)
3713 width = COLS / 2;
3714
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003715 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003716 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003717
Chris Allegretta6232d662002-05-12 19:52:15 +00003718 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003719 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003720 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003721
3722 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003723 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003724 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003725 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003726 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003727
Chris Allegrettadb28e962003-01-28 01:23:40 +00003728 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003729 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003730 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003731
Chris Allegrettadb28e962003-01-28 01:23:40 +00003732 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003733 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003734 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003735
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003736 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003737
3738 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003739 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003740
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003741 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003742
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003743 wrefresh(bottomwin);
3744
Chris Allegrettadb28e962003-01-28 01:23:40 +00003745 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003746 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003747 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003748#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003749 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003750#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003751
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003752 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003753
3754 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003755 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003756#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003757 /* Look, ma! We get to duplicate lots of code from
3758 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003759 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003760 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003761
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003762 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003763 wenclose(bottomwin, mouse_y, mouse_x) &&
3764 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003765 int x = mouse_x / width;
3766 /* Did we click in the first column of shortcuts, or
3767 * the second? */
3768 int y = mouse_y - editwinrows - 3;
3769 /* Did we click in the first row of shortcuts? */
3770
3771 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3772
3773 /* x = 0 means they clicked Yes or No.
3774 * y = 0 means Yes or All. */
3775 ok = -2 * x * y + x - y + 1;
3776
3777 if (ok == 2 && !all)
3778 ok = -2;
3779 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003780 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003781#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003782 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003783 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003784 else if (strchr(yesstr, kbinput) != NULL)
3785 ok = 1;
3786 else if (strchr(nostr, kbinput) != NULL)
3787 ok = 0;
3788 else if (all && strchr(allstr, kbinput) != NULL)
3789 ok = 2;
3790 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003791
Chris Allegrettadb28e962003-01-28 01:23:40 +00003792 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003793}
3794
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003795void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003796{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003797 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003798 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003799 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003800 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003801 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003802 wnoutrefresh(bottomwin);
3803 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003804 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003805 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003806 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003807 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003808 edit_refresh();
3809 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003810}
3811
3812void display_main_list(void)
3813{
3814 bottombars(main_list);
3815}
3816
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003817/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3818 * display the cursor position. Otherwise, we display it only if the
3819 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003820 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003821 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3822 * old_i and old_totsize. That way, we leave the current statusbar
3823 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003824void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003825{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003826 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003827 size_t i = 0;
3828 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003829 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003830
Chris Allegrettad26ab912003-01-28 01:16:47 +00003831 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003832
3833 if (old_totsize == -1)
3834 old_totsize = totsize;
3835
Chris Allegrettad26ab912003-01-28 01:16:47 +00003836 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3837 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003838 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003839 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003840 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003841
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003842 /* Check whether totsize is correct. Else there is a bug
3843 * somewhere. */
3844 assert(current != filebot || i == totsize);
3845
Chris Allegrettad26ab912003-01-28 01:16:47 +00003846 if (constant && ISSET(DISABLE_CURPOS)) {
3847 UNSET(DISABLE_CURPOS);
3848 old_i = i;
3849 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003850 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003851 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003852
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003853 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003854 * unconditionally; otherwise, only display the position when the
3855 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003856 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003857 size_t xpt = xplustabs() + 1;
3858 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003859 int linepct = 100 * current->lineno / totlines;
3860 int colpct = 100 * xpt / cur_len;
3861 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3862
3863 statusbar(
3864 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3865 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003866 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003867 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003868 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003869 }
3870
3871 old_i = i;
3872 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003873}
3874
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003875void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003876{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003877 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003878}
3879
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003880#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003881/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003882int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003883{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003884 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003885
3886 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3887 ptr++;
3888 j++;
3889 }
3890 if (j == COLS - 5) {
3891 /* Don't wrap at the first of two spaces following a period. */
3892 if (*ptr == ' ' && *(ptr + 1) == ' ')
3893 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003894 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003895 while (*ptr != ' ' && j > 0) {
3896 ptr--;
3897 j--;
3898 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003899 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003900 if (j == 0)
3901 j = COLS - 5;
3902 }
3903 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3904 return j;
3905}
3906
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003907/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003908void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003909{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003910 int line = 0;
3911 /* The line number in help_text of the first displayed help line.
3912 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003913 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003914 /* no_more means the end of the help text is shown, so don't go
3915 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003916 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003917 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003918
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003919 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003920#ifndef DISABLE_MOUSE
3921 const shortcut *oldshortcut = currshortcut;
3922 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003923 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003924#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003925
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003926 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003927 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003928 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003929 blank_statusbar();
3930
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003931 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003932 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003933 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003934
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003935#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003936 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003937 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003938 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003939#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003940
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003941 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003942 /* Make sure that the help screen's shortcut list will actually
3943 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003944 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003945 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003946 }
3947 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003948
3949 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003950 int i;
3951 int old_line = line;
3952 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003953 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003954
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003955 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003956#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003957 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003958 {
3959 int mouse_x, mouse_y;
3960 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3961 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003962 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003963#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003964 case NANO_NEXTPAGE_KEY:
3965 case NANO_NEXTPAGE_FKEY:
3966 if (!no_more)
3967 line += editwinrows - 2;
3968 break;
3969 case NANO_PREVPAGE_KEY:
3970 case NANO_PREVPAGE_FKEY:
3971 if (line > 0) {
3972 line -= editwinrows - 2;
3973 if (line < 0)
3974 line = 0;
3975 }
3976 break;
3977 case NANO_PREVLINE_KEY:
3978 if (line > 0)
3979 line--;
3980 break;
3981 case NANO_NEXTLINE_KEY:
3982 if (!no_more)
3983 line++;
3984 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003985 }
3986
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003987 if (line == old_line && kbinput != ERR)
3988 goto skip_redisplay;
3989
3990 blank_edit();
3991
3992 assert(COLS > 5);
3993
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003994 /* Calculate where in the text we should be, based on the
3995 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003996 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003997 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003998 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003999 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004000 }
4001
Chris Allegretta4640fe32003-02-10 03:10:03 +00004002 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004003 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004004
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004005 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00004006 ptr += j;
4007 if (*ptr == '\n')
4008 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004009 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004010 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00004011
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004012 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00004013 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00004014 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
4015 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00004016
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004017#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00004018 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00004019#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00004020
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00004021 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00004022 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00004023 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004024 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00004025 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00004026 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004027 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004028
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00004029 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004030 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00004031
David Lawrence Ramsey52453442004-06-26 15:24:16 +00004032 /* The help_init() at the beginning allocated help_text. Since
4033 * help_text has now been written to the screen, we don't need it
4034 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00004035 free(help_text);
4036 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004037}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00004038#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00004039
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004040/* Highlight the current word being replaced or spell checked. We
4041 * expect word to have tabs and control characters expanded. */
David Lawrence Ramsey423326f2005-01-03 19:14:39 +00004042void do_replace_highlight(bool highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00004043{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00004044 size_t y = xplustabs();
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004045 size_t word_len = strlenpt(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004046
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004047 y = get_page_start(y) + COLS - y;
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004048 /* Now y is the number of columns that we can display on this
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004049 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00004050
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004051 assert(y > 0);
4052
4053 if (word_len > y)
4054 y--;
4055
Chris Allegrettafb62f732000-12-05 11:36:41 +00004056 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00004057
Chris Allegrettafb62f732000-12-05 11:36:41 +00004058 if (highlight_flag)
4059 wattron(edit, A_REVERSE);
4060
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004061#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00004062 /* This is so we can show zero-length regexes. */
4063 if (word_len == 0)
4064 waddstr(edit, " ");
4065 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00004066#endif
David Lawrence Ramsey913db832005-01-05 05:08:14 +00004067 waddnstr(edit, word, actual_x(word, y));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004068
4069 if (word_len > y)
4070 waddch(edit, '$');
Chris Allegrettafb62f732000-12-05 11:36:41 +00004071
4072 if (highlight_flag)
4073 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00004074}
4075
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004076#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004077/* Dump the passed-in file structure to stderr. */
4078void dump_buffer(const filestruct *inptr)
4079{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004080 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004081 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004082 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00004083 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004084 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00004085 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004086
4087 while (inptr != NULL) {
4088 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
4089 inptr = inptr->next;
4090 }
4091}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004092
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00004093/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00004094void dump_buffer_reverse(void)
4095{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004096 const filestruct *fileptr = filebot;
4097
4098 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00004099 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00004100 fileptr = fileptr->prev;
4101 }
4102}
4103#endif /* DEBUG */
4104
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004105#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004106#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004107#define XLCREDIT_LEN 8
4108
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00004109/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004110void do_credits(void)
4111{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004112 int crpos = 0, xlpos = 0;
4113 const char *credits[CREDIT_LEN] = {
4114 NULL, /* "The nano text editor" */
4115 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004116 VERSION,
4117 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004118 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004119 "Chris Allegretta",
4120 "Jordi Mallach",
4121 "Adam Rogoyski",
4122 "Rob Siemborski",
4123 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00004124 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004125 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00004126 "Ken Tyler",
4127 "Sven Guckes",
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004128#ifdef NANO_WIDE
4129 !ISSET(NO_UTF8) ? "Florian K\xC3\xB6nig" :
4130#endif
4131 "Florian König",
Chris Allegretta598106e2002-01-19 01:59:37 +00004132 "Pauli Virtanen",
4133 "Daniele Medri",
4134 "Clement Laforet",
4135 "Tedi Heriyanto",
4136 "Bill Soudan",
4137 "Christian Weisgerber",
4138 "Erik Andersen",
4139 "Big Gaute",
4140 "Joshua Jensen",
4141 "Ryan Krebs",
4142 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00004143 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004144 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004145 "Plattsburgh State University",
4146 "Benet Laboratories",
4147 "Amy Allegretta",
4148 "Linda Young",
4149 "Jeremy Robichaud",
4150 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004151 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00004152 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004153 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00004154 "Thomas Dickey",
4155 "Pavel Curtis",
4156 "Zeyd Ben-Halim",
4157 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004158 NULL, /* "and anyone else we forgot..." */
4159 NULL, /* "Thank you for using nano!" */
4160 "",
4161 "",
4162 "",
4163 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00004164 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004165 "",
4166 "",
4167 "",
4168 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00004169 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004170 };
4171
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004172 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00004173 N_("The nano text editor"),
4174 N_("version"),
4175 N_("Brought to you by:"),
4176 N_("Special thanks to:"),
4177 N_("The Free Software Foundation"),
4178 N_("For ncurses:"),
4179 N_("and anyone else we forgot..."),
4180 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004181 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00004182
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004183 curs_set(0);
4184 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004185 scrollok(edit, TRUE);
4186 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004187 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004188 blank_statusbar();
4189 blank_bottombars();
4190 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00004191 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004192 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004193
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004194 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
4195 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004196 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004197 if (crpos < CREDIT_LEN) {
4198 const char *what = credits[crpos];
4199 size_t start_x;
4200
4201 if (what == NULL) {
4202 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00004203 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004204 xlpos++;
4205 }
David Lawrence Ramseyfc693212004-12-23 17:43:27 +00004206 start_x = COLS / 2 - strlenpt(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00004207 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
4208 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004209 }
4210 napms(700);
4211 scroll(edit);
4212 wrefresh(edit);
4213 if (wgetch(edit) != ERR)
4214 break;
4215 napms(700);
4216 scroll(edit);
4217 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004218 }
4219
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00004220 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004221 nodelay(edit, FALSE);
4222 curs_set(1);
4223 display_main_list();
4224 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00004225}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00004226#endif