blob: aad629f50a92976e710fd3c1b42d3ec7c479e9f0 [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 Ramseyf28f50e2004-01-09 23:04:55 +00005 * Copyright (C) 1999-2004 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 Ramsey74835712004-12-04 17:41:52 +000035static buffer *key_buffer = NULL;
36 /* The default keystroke buffer,
37 * containing all the keystrokes we have
38 * at a given point. */
39static size_t key_buffer_len = 0;
40 /* The length of the default keystroke
41 * buffer. */
42static int statusblank = 0; /* The number of keystrokes left after
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +000043 * we call statusbar(), before we
44 * actually blank the statusbar. */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +000045static bool resetstatuspos = FALSE;
46 /* Should we reset the cursor position
47 * at the statusbar prompt? */
Robert Siemborskid8510b22000-06-06 23:04:06 +000048
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000049/* Control character compatibility:
50 *
51 * - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
52 * VT100, and VT220.
53 * - NANO_TAB_KEY is Ctrl-I, which is Tab under ASCII, ANSI, VT100,
54 * VT220, and VT320.
55 * - NANO_ENTER_KEY is Ctrl-M, which is Enter under ASCII, ANSI, VT100,
56 * VT220, and VT320.
57 * - NANO_XON_KEY is Ctrl-Q, which is XON under ASCII, ANSI, VT100,
58 * VT220, and VT320.
59 * - NANO_XOFF_KEY is Ctrl-S, which is XOFF under ASCII, ANSI, VT100,
60 * VT220, and VT320.
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000061 * - NANO_CONTROL_8 is Ctrl-8 (Ctrl-?), which is Delete under ASCII,
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000062 * ANSI, VT100, and VT220, and which is Backspace under VT320.
63 *
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +000064 * Note: VT220 and VT320 also generate Esc [ 3 ~ for Delete. By
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000065 * default, xterm assumes it's running on a VT320 and generates Ctrl-8
66 * (Ctrl-?) for Backspace and Esc [ 3 ~ for Delete. This causes
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000067 * problems for VT100-derived terminals such as the FreeBSD console,
David Lawrence Ramseya849ab12004-05-01 04:13:06 +000068 * which expect Ctrl-H for Backspace and Ctrl-8 (Ctrl-?) for Delete, and
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000069 * on which the VT320 sequences are translated by the keypad to KEY_DC
70 * and [nothing]. We work around this conflict via the REBIND_DELETE
71 * flag: if it's not set, we assume VT320 compatibility, and if it is,
72 * we assume VT100 compatibility. Thanks to Lee Nelson and Wouter van
73 * Hemel for helping work this conflict out.
74 *
75 * Escape sequence compatibility:
76 *
77 * We support escape sequences for ANSI, VT100, VT220, VT320, the Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000078 * console, the FreeBSD console, the Mach console (a.k.a. the Hurd
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000079 * console), xterm, rxvt, and Eterm. Among these, there are several
80 * conflicts and omissions, outlined as follows:
81 *
82 * - Tab on ANSI == PageUp on FreeBSD console; the former is omitted.
83 * (Ctrl-I is also Tab on ANSI, which we already support.)
84 * - PageDown on FreeBSD console == Center (5) on numeric keypad with
85 * NumLock off on Linux console; the latter is omitted. (The editing
86 * keypad key is more important to have working than the numeric
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +000087 * keypad key, because the latter has no value when NumLock is off.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000088 * - F1 on FreeBSD console == the mouse key on xterm/rxvt/Eterm; the
89 * latter is omitted. (Mouse input will only work properly if the
90 * extended keypad value KEY_MOUSE is generated on mouse events
91 * instead of the escape sequence.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000092 * - F9 on FreeBSD console == PageDown on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000093 * omitted. (The editing keypad is more important to have working
94 * than the function keys, because the functions of the former are not
95 * arbitrary and the functions of the latter are.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000096 * - F10 on FreeBSD console == PageUp on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000097 * omitted. (Same as above.)
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +000098 * - F13 on FreeBSD console == End on Mach console; the former is
David Lawrence Ramsey0381c212004-05-01 01:21:38 +000099 * omitted. (Same as above.)
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000100 * - F15 on FreeBSD console == Shift-Up on rxvt/Eterm; the former is
101 * omitted. (The arrow keys, with or without modifiers, are more
102 * important to have working than the function keys, because the
103 * functions of the former are not arbitrary and the functions of the
104 * latter are.)
105 * - F16 on FreeBSD console == Shift-Down on rxvt/Eterm; the former is
106 * omitted. (Same as above.)
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000107 *
108 * Note that Center (5) on the numeric keypad with NumLock off can also
109 * be the Begin key. */
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000110
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000111#ifndef NANO_SMALL
112/* Reset all the input routines that rely on character sequences. */
113void reset_kbinput(void)
114{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000115 parse_kbinput(NULL, NULL, NULL, TRUE);
116 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000117}
118#endif
119
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000120/* Read in a sequence of keystrokes from win and save them in the
121 * default keystroke buffer. This should only be called when the
122 * default keystroke buffer is empty. */
123void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000124{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000125 int input;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000126
127 /* If the keystroke buffer isn't empty, get out. */
128 if (key_buffer != NULL)
129 return;
130
131 /* Read in the first character using blocking input. */
132 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000133
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000134#ifndef NANO_SMALL
135 allow_pending_sigwinch(TRUE);
136#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000137 input = wgetch(win);
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000138#ifndef NANO_SMALL
139 allow_pending_sigwinch(FALSE);
140#endif
141
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000142 /* Increment the length of the keystroke buffer, save the value of
143 * the keystroke in key, and set key_code to TRUE if the keystroke
144 * is an extended keypad value and hence shouldn't be treated as a
145 * multibyte character. */
146 key_buffer_len++;
147 key_buffer = (buffer *)nmalloc(sizeof(buffer));
148 key_buffer[0].key = input;
149 key_buffer[0].key_code = !is_byte_char(input);
150
151 /* Read in the remaining characters using non-blocking input. */
152 nodelay(win, TRUE);
153
154 while (TRUE) {
155#ifndef NANO_SMALL
156 allow_pending_sigwinch(TRUE);
157#endif
158 input = wgetch(win);
159#ifndef NANO_SMALL
160 allow_pending_sigwinch(FALSE);
161#endif
162
163 /* If there aren't any more characters, stop reading. */
164 if (input == ERR)
165 break;
166
167 /* Otherwise, increment the length of the keystroke buffer, save
168 * the value of the keystroke in key, and set key_code to TRUE
169 * if the keystroke is an extended keypad value and hence
170 * shouldn't be treated as a multibyte character. */
171 key_buffer_len++;
172 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
173 sizeof(buffer));
174 key_buffer[key_buffer_len - 1].key = input;
175 key_buffer[key_buffer_len - 1].key_code = !is_byte_char(input);
176 }
177
178 /* Switch back to non-blocking input. */
179 nodelay(win, FALSE);
180
181#ifdef NANO_WIDE
182 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000183 size_t i;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000184 buffer *clean_key_buffer = NULL;
185 size_t clean_key_buffer_len = 0;
186
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000187 mbtowc(NULL, NULL, 0);
188
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000189 /* Change all complete and valid multibyte keystrokes to
190 * their wide character values, discarding the others. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000191 for (i = 0; i < key_buffer_len; i++) {
192 wchar_t wide_key;
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000193 int wide_key_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000194
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000195 if (key_buffer[i].key_code) {
196 wide_key_len = 1;
197 wide_key = key_buffer[i].key;
198 } else
199 wide_key_len = mbtowc(&wide_key,
200 (const char *)&key_buffer[i].key, 1);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000201
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000202 if (wide_key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000203 clean_key_buffer_len++;
204 clean_key_buffer = (buffer *)nrealloc(clean_key_buffer,
205 clean_key_buffer_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000206
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000207 clean_key_buffer[clean_key_buffer_len - 1].key =
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000208 wide_key;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000209 clean_key_buffer[clean_key_buffer_len - 1].key_code =
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000210 key_buffer[i].key_code;
211 }
212 }
213
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000214 mbtowc(NULL, NULL, 0);
215
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000216 /* Replace the default keystroke buffer with the non-(-1)
217 * keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000218 key_buffer_len = clean_key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000219 free(key_buffer);
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000220 key_buffer = clean_key_buffer;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000221 }
222#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000223}
224
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000225/* Return the length of the default keystroke buffer. */
226size_t get_buffer_len(void)
227{
228 return key_buffer_len;
229}
230
231/* Return the key values stored in the keystroke buffer input,
232 * discarding the key_code values in it. */
233int *buffer_to_keys(buffer *input, size_t input_len)
234{
235 int *sequence = (int *)nmalloc(input_len * sizeof(int));
236 size_t i;
237
238 for (i = 0; i < input_len; i++)
239 sequence[i] = input[i].key;
240
241 return sequence;
242}
243
244/* Add the contents of the keystroke buffer input to the default
245 * keystroke buffer. */
246void unget_input(buffer *input, size_t input_len)
247{
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000248 buffer *clean_input = NULL;
249 size_t clean_input_len = 0;
250
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000251#ifndef NANO_SMALL
252 allow_pending_sigwinch(TRUE);
253 allow_pending_sigwinch(FALSE);
254#endif
255
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000256#ifdef NANO_WIDE
257 if (!ISSET(NO_UTF8)) {
David Lawrence Ramseyf812e4f2004-12-07 17:35:14 +0000258 size_t i;
259
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000260 wctomb(NULL, 0);
261
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000262 /* Keep all valid wide keystrokes, discarding the others. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000263 for (i = 0; i < input_len; i++) {
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000264 char key[MB_LEN_MAX];
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000265 int key_len = input[i].key_code ? 1 :
266 wctomb(key, input[i].key);
David Lawrence Ramseyeae97ca2004-12-07 22:24:03 +0000267
David Lawrence Ramsey263240c2004-12-08 15:47:38 +0000268 if (key_len != -1) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000269 clean_input_len++;
270 clean_input = (buffer *)nrealloc(clean_input,
271 clean_input_len * sizeof(buffer));
272
273 clean_input[clean_input_len - 1].key = input[i].key;
274 clean_input[clean_input_len - 1].key_code =
275 input[i].key_code;
276 }
277 }
David Lawrence Ramsey60448892004-12-08 16:52:52 +0000278
279 wctomb(NULL, 0);
280
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000281 } else {
282#endif
283 clean_input = input;
284 clean_input_len = input_len;
285#ifdef NANO_WIDE
286 }
287#endif
288
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000289 /* If input is empty, get out. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000290 if (clean_input_len == 0)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000291 return;
292
293 /* If adding input would put the default keystroke buffer beyond
294 * maximum capacity, only add enough of input to put it at maximum
295 * capacity. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000296 if (key_buffer_len + clean_input_len < key_buffer_len)
297 clean_input_len = (size_t)-1 - key_buffer_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000298
299 /* Add the length of input to the length of the default keystroke
300 * buffer, and reallocate the default keystroke buffer so that it
301 * has enough room for input. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000302 key_buffer_len += clean_input_len;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000303 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
304 sizeof(buffer));
305
306 /* If the default keystroke buffer wasn't empty before, move its
307 * beginning forward far enough so that we can add input to its
308 * beginning. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000309 if (key_buffer_len > clean_input_len)
310 memmove(key_buffer + clean_input_len, key_buffer,
311 (key_buffer_len - clean_input_len) * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000312
313 /* Copy input to the beginning of the default keystroke buffer. */
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000314 memcpy(key_buffer, clean_input, clean_input_len * sizeof(buffer));
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000315}
316
317/* Put back the character stored in kbinput. If func_key is TRUE and
318 * the character is out of byte range, interpret it as an extended
319 * keypad value. If meta_key is TRUE, put back the Escape character
320 * after putting back kbinput. */
321void unget_kbinput(int kbinput, bool meta_key, bool func_key)
322{
323 buffer input;
324
325 input.key = kbinput;
326 input.key_code = (func_key && !is_byte_char(kbinput));
327
328 unget_input(&input, 1);
329
330 if (meta_key) {
331 input.key = NANO_CONTROL_3;
332 input.key_code = FALSE;
333 unget_input(&input, 1);
334 }
335}
336
337/* Try to read input_len characters from the default keystroke buffer.
338 * If the default keystroke buffer is empty and win isn't NULL, try to
339 * read in more characters from win and add them to the default
340 * keystroke buffer before doing anything else. If the default
341 * keystroke buffer is empty and win is NULL, return NULL. */
342buffer *get_input(WINDOW *win, size_t input_len)
343{
344 buffer *input;
345
346#ifndef NANO_SMALL
347 allow_pending_sigwinch(TRUE);
348 allow_pending_sigwinch(FALSE);
349#endif
350
351 if (key_buffer_len == 0) {
352 if (win != NULL)
353 get_buffer(win);
354
355 if (key_buffer_len == 0)
356 return NULL;
357 }
358
359 /* If input_len is greater than the length of the default keystroke
360 * buffer, only read the number of characters in the default
361 * keystroke buffer. */
362 if (input_len > key_buffer_len)
363 input_len = key_buffer_len;
364
365 /* Subtract input_len from the length of the default keystroke
366 * buffer, and allocate the keystroke buffer input so that it
367 * has enough room for input_len keystrokes. */
368 key_buffer_len -= input_len;
369 input = (buffer *)nmalloc(input_len * sizeof(buffer));
370
371 /* Copy input_len characters from the beginning of the default
372 * keystroke buffer into input. */
373 memcpy(input, key_buffer, input_len * sizeof(buffer));
374
375 /* If the default keystroke buffer is empty, mark it as such. */
376 if (key_buffer_len == 0) {
377 free(key_buffer);
378 key_buffer = NULL;
379 /* If the default keystroke buffer isn't empty, move its
380 * beginning forward far enough back so that the keystrokes in input
381 * are no longer at its beginning. */
382 } else {
383 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
384 sizeof(buffer));
385 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
386 sizeof(buffer));
387 }
388
389 return input;
390}
391
392/* Read in a single character. If it's ignored, swallow it and go on.
393 * Otherwise, try to translate it from ASCII, meta key sequences, escape
394 * sequences, and/or extended keypad values. Set meta_key to TRUE when
395 * we get a meta key sequence, and set func_key to TRUE when we get an
396 * extended keypad value. Supported extended keypad values consist of
397 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
398 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
399 * the function keypad (F1-F16), and the numeric keypad with NumLock
400 * off. Assume nodelay(win) is FALSE. */
401int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
402{
403 int kbinput;
404
405 /* Read in a character and interpret it. Continue doing this until
406 * we get a recognized value or sequence. */
407 while ((kbinput = parse_kbinput(win, meta_key, func_key
408#ifndef NANO_SMALL
409 , FALSE
410#endif
411 )) == ERR);
412
413 return kbinput;
414}
415
416/* Translate ASCII characters, extended keypad values, and escape
417 * sequences into their corresponding key values. Set meta_key to TRUE
418 * when we get a meta key sequence, and set func_key to TRUE when we get
419 * a function key. Assume nodelay(win) is FALSE. */
420int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000421#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000422 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000423#endif
424 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000425
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000426{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000427 static int escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000428 static int word_digits = 0;
429 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000430 int retval = ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000431
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000432 if (reset) {
433 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000434 word_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000435 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000436 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000437
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000438 *meta_key = FALSE;
439 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000440
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000441 /* Read in a character. */
442 while ((kbinput = get_input(win, 1)) == NULL);
443
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000444 if (kbinput->key_code || is_byte_char(kbinput->key)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000445 /* If we got an extended keypad value or an ASCII character,
446 * translate it. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000447 switch (kbinput->key) {
448 case ERR:
449 break;
450 case NANO_CONTROL_3:
451 /* Increment the escape counter. */
452 escapes++;
453 switch (escapes) {
454 case 1:
455 /* One escape: wait for more input. */
456 case 2:
457 /* Two escapes: wait for more input. */
458 break;
459 default:
460 /* More than two escapes: reset the escape
461 * counter and wait for more input. */
462 escapes = 0;
463 }
464 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000465#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000466 /* Since we don't change the default SIGWINCH handler when
467 * NANO_SMALL is defined, KEY_RESIZE is never generated.
468 * Also, Slang and SunOS 5.7-5.9 don't support
469 * KEY_RESIZE. */
470 case KEY_RESIZE:
471 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000472#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000473#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000474 case KEY_SHIFT_L:
475 case KEY_SHIFT_R:
476 case KEY_CONTROL_L:
477 case KEY_CONTROL_R:
478 case KEY_ALT_L:
479 case KEY_ALT_R:
480 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000481#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000482 default:
483 switch (escapes) {
484 case 0:
485 switch (kbinput->key) {
486 case NANO_CONTROL_8:
487 retval = ISSET(REBIND_DELETE) ?
488 NANO_DELETE_KEY :
489 NANO_BACKSPACE_KEY;
490 break;
491 case KEY_DOWN:
492 retval = NANO_NEXTLINE_KEY;
493 break;
494 case KEY_UP:
495 retval = NANO_PREVLINE_KEY;
496 break;
497 case KEY_LEFT:
498 retval = NANO_BACK_KEY;
499 break;
500 case KEY_RIGHT:
501 retval = NANO_FORWARD_KEY;
502 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000503#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000504 /* HP-UX 10 and 11 don't support
505 * KEY_HOME. */
506 case KEY_HOME:
507 retval = NANO_HOME_KEY;
508 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000509#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000510 case KEY_BACKSPACE:
511 retval = NANO_BACKSPACE_KEY;
512 break;
513 case KEY_DC:
514 retval = ISSET(REBIND_DELETE) ?
515 NANO_BACKSPACE_KEY :
516 NANO_DELETE_KEY;
517 break;
518 case KEY_IC:
519 retval = NANO_INSERTFILE_KEY;
520 break;
521 case KEY_NPAGE:
522 retval = NANO_NEXTPAGE_KEY;
523 break;
524 case KEY_PPAGE:
525 retval = NANO_PREVPAGE_KEY;
526 break;
527 case KEY_ENTER:
528 retval = NANO_ENTER_KEY;
529 break;
530 case KEY_A1: /* Home (7) on numeric
531 * keypad with NumLock
532 * off. */
533 retval = NANO_HOME_KEY;
534 break;
535 case KEY_A3: /* PageUp (9) on numeric
536 * keypad with NumLock
537 * off. */
538 retval = NANO_PREVPAGE_KEY;
539 break;
540 case KEY_B2: /* Center (5) on numeric
541 * keypad with NumLock
542 * off. */
543 break;
544 case KEY_C1: /* End (1) on numeric
545 * keypad with NumLock
546 * off. */
547 retval = NANO_END_KEY;
548 break;
549 case KEY_C3: /* PageDown (4) on
550 * numeric keypad with
551 * NumLock off. */
552 retval = NANO_NEXTPAGE_KEY;
553 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000554#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000555 /* Slang doesn't support KEY_BEG. */
556 case KEY_BEG: /* Center (5) on numeric
557 * keypad with NumLock
558 * off. */
559 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000560#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000561#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000562 /* HP-UX 10 and 11 don't support KEY_END. */
563 case KEY_END:
564 retval = NANO_END_KEY;
565 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000566#endif
567#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000568 /* Slang doesn't support KEY_SUSPEND. */
569 case KEY_SUSPEND:
570 retval = NANO_SUSPEND_KEY;
571 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000572#endif
573#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000574 /* Slang doesn't support KEY_SLEFT. */
575 case KEY_SLEFT:
576 retval = NANO_BACK_KEY;
577 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000578#endif
579#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000580 /* Slang doesn't support KEY_SRIGHT. */
581 case KEY_SRIGHT:
582 retval = NANO_FORWARD_KEY;
583 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000584#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000585 default:
586 retval = kbinput->key;
587 break;
588 }
589 break;
590 case 1:
591 /* One escape followed by a non-escape: escape
592 * sequence mode. Reset the escape counter. If
593 * there aren't any other keys waiting, we have
594 * a meta key sequence, so set meta_key to TRUE
595 * and save the lowercase version of the
596 * non-escape character as the result. If there
597 * are other keys waiting, we have a true escape
598 * sequence, so interpret it. */
599 escapes = 0;
600 if (get_buffer_len() == 0) {
601 *meta_key = TRUE;
602 retval = tolower(kbinput->key);
603 } else {
604 buffer *escape_kbinput;
605 int *sequence;
606 size_t seq_len;
607 bool ignore_seq;
608
609 /* Put back the non-escape character, get
610 * the complete escape sequence, translate
611 * its key values into the corresponding key
612 * value, and save that as the result. */
613 unget_input(kbinput, 1);
614 seq_len = get_buffer_len();
615 escape_kbinput = get_input(NULL, seq_len);
616 sequence = buffer_to_keys(escape_kbinput,
617 seq_len);
618 retval = get_escape_seq_kbinput(sequence,
619 seq_len, &ignore_seq);
620
621 /* If the escape sequence is unrecognized
622 * and not ignored, put back all of its
623 * characters except for the initial
624 * escape. */
625 if (retval == ERR && !ignore_seq)
626 unget_input(escape_kbinput, seq_len);
627
628 free(escape_kbinput);
629 }
630 break;
631 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000632 /* Two escapes followed by one or more decimal
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000633 * digits: word sequence mode. If the word
634 * sequence's range is limited to 6XXXX (the
635 * first digit is in the '0' to '6' range and
636 * it's the first digit, or it's in the '0' to
637 * '9' range and it's not the first digit),
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000638 * increment the word sequence counter and
639 * interpret the digit. If the word sequence's
640 * range is not limited to 6XXXX, fall
641 * through. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000642 if (('0' <= kbinput->key && kbinput->key <= '6'
643 && word_digits == 0) ||
644 ('0' <= kbinput->key && kbinput->key <= '9'
645 && word_digits > 0)) {
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000646 int word_kbinput;
647
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000648 word_digits++;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000649 word_kbinput = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000650#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000651 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000652#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000653 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000654
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000655 if (word_kbinput != ERR) {
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000656 /* If we've read in a complete word
657 * sequence, reset the word sequence
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000658 * counter and the escape counter,
659 * and put back the corresponding word
660 * value. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000661 word_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000662 escapes = 0;
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000663 unget_kbinput(word_kbinput, FALSE,
664 FALSE);
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000665 }
666 } else {
667 /* Reset the escape counter. */
668 escapes = 0;
669 if (word_digits == 0)
670 /* Two escapes followed by a non-decimal
671 * digit or a decimal digit that would
672 * create a word sequence greater than
673 * 6XXXX, and we're not in the middle of
674 * a word sequence: control character
675 * sequence mode. Interpret the control
676 * sequence and save the corresponding
677 * control character as the result. */
678 retval = get_control_kbinput(kbinput->key);
679 else {
680 /* If we're in the middle of a word
681 * sequence, reset the word sequence
682 * counter and save the character we got
683 * as the result. */
684 word_digits = 0;
685 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000686 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000687 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000688 break;
689 }
690 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000691
David Lawrence Ramsey95a02242004-12-06 04:14:42 +0000692 /* If we have a result and it's an extended keypad value, set
693 * func_key to TRUE. */
694 if (retval != ERR)
695 *func_key = !is_byte_char(retval);
696 } else
697 /* If we didn't get an extended keypad value or an ASCII
698 * character, leave it as-is. */
699 retval = kbinput->key;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000700
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000701#ifdef DEBUG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000702 fprintf(stderr, "parse_kbinput(): kbinput->key = %d, meta_key = %d, func_key = %d, escapes = %d, word_digits = %d, retval = %d\n", kbinput->key, (int)*meta_key, (int)*func_key, escapes, word_digits, retval);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000703#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704
705 /* Return the result. */
706 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000707}
708
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000709/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000710 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000711 * are generated when the keypad doesn't support the needed keys. If
712 * the escape sequence is recognized but we want to ignore it, return
713 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
714 * set ignore_seq to FALSE. Assume that Escape has already been read
715 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000716int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000717 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000718{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000719 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000720
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000721 *ignore_seq = FALSE;
722
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000723 if (seq_len > 1) {
724 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000725 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000726 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000727 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000728 if (seq_len >= 3) {
729 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000730 case 'P': /* Esc O 2 P == F13 on
731 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000732 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000733 break;
734 case 'Q': /* Esc O 2 Q == F14 on
735 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000736 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000737 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000738 case 'R': /* Esc O 2 R == F15 on
739 * xterm. */
740 retval = KEY_F(15);
741 break;
742 case 'S': /* Esc O 2 S == F16 on
743 * xterm. */
744 retval = KEY_F(16);
745 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000746 }
747 }
748 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000749 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
750 case 'B': /* Esc O B == Down on
751 * VT100/VT320/xterm. */
752 case 'C': /* Esc O C == Right on
753 * VT100/VT320/xterm. */
754 case 'D': /* Esc O D == Left on
755 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000756 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000757 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000758 case 'E': /* Esc O E == Center (5) on numeric keypad
759 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000760 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000761 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000762 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000763 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000764 break;
765 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000766 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000767 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000768 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000769 * NumLock off on VT100/VT220/VT320/xterm/
770 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000771 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000772 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000773 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000774 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000775 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000776 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000777 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000778 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000779 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000780 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000781 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000782 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000783 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000784 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000785 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000786 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000787 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000788 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000789 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000790 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000791 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000792 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000793 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000794 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000795 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000796 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000797 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000798 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000800 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000801 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000802 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000803 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000804 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000805 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000806 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000807 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000808 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000809 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000810 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000811 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000812 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000813 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000814 * NumLock off on VT100/VT220/VT320/xterm/
815 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000816 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000817 break;
818 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000819 * NumLock off on VT100/VT220/VT320/xterm/
820 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000821 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000822 break;
823 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000824 * NumLock off on VT100/VT220/VT320/xterm/
825 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000826 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000827 break;
828 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000829 * NumLock off on VT100/VT220/VT320/xterm/
830 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000831 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000832 break;
833 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000834 * with NumLock off on VT100/VT220/VT320/
835 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000836 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000837 break;
838 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000839 * NumLock off on VT100/VT220/VT320/xterm/
840 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000841 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000842 break;
843 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000844 * with NumLock off on VT100/VT220/VT320/
845 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000846 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000847 break;
848 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000849 * with NumLock off on VT100/VT220/VT320/
850 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000851 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000852 break;
853 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000854 * with NumLock off on VT100/VT220/VT320/
855 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000856 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000857 break;
858 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000859 * keypad with NumLock off on VT100/VT220/
860 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000861 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000862 break;
863 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000864 * with NumLock off on VT100/VT220/VT320/
865 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000866 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000867 break;
868 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000869 * with NumLock off on VT100/VT220/VT320/
870 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000871 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000872 break;
873 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000874 * with NumLock off on VT100/VT220/VT320/
875 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000876 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000877 break;
878 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000879 * with NumLock off on VT100/VT220/VT320/
880 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000881 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000882 break;
883 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000884 * with NumLock off on VT100/VT220/VT320/
885 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000886 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000887 break;
888 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000889 * with NumLock off on VT100/VT220/VT320/
890 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000891 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000892 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000893 }
894 break;
895 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000896 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000897 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000898 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000899 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000900 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000901 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000902 break;
903 }
904 break;
905 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000906 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000907 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000908 if (seq_len >= 3) {
909 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000910 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
911 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000912 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000913 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000914 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
915 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000916 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000917 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000918 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
919 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000920 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000921 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000922 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
923 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000924 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000925 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000926 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
927 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000928 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000929 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000930 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000931 * VT220/VT320/Linux console/
932 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000933 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000934 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000935 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000936 * VT220/VT320/Linux console/
937 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000938 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000939 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000940 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000941 * VT220/VT320/Linux console/
942 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000943 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000944 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000945 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000946 if (seq_len >= 4) {
947 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000948 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000949 if (seq_len >= 5) {
950 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000951 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
952 * xterm. */
953 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
954 * xterm. */
955 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
956 * xterm. */
957 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
958 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000959 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000960 break;
961 }
962 }
963 break;
964 case '5':
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 ; 5 A == Ctrl-Up on
968 * xterm. */
969 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
970 * xterm. */
971 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
972 * xterm. */
973 case 'D': /* Esc [ 1 ; 5 D == Ctrl-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 }
981 }
982 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000983 default: /* Esc [ 1 ~ == Home on
984 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000985 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000986 break;
987 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000988 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000989 break;
990 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000991 if (seq_len >= 3) {
992 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000993 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000994 * VT220/VT320/Linux console/
995 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000996 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000997 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000998 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000999 * VT220/VT320/Linux console/
1000 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001001 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001002 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001003 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001004 * VT220/VT320/Linux console/
1005 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001006 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001007 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001008 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001009 * VT220/VT320/Linux console/
1010 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001012 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001013 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001014 * VT220/VT320/Linux console/
1015 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001016 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001017 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001018 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001019 * VT220/VT320/Linux console/
1020 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001021 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001022 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +00001023 case '8': /* Esc [ 2 8 ~ == F15 on
1024 * VT220/VT320/Linux console/
1025 * rxvt/Eterm. */
1026 retval = KEY_F(15);
1027 break;
1028 case '9': /* Esc [ 2 9 ~ == F16 on
1029 * VT220/VT320/Linux console/
1030 * rxvt/Eterm. */
1031 retval = KEY_F(16);
1032 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001033 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001034 * VT220/VT320/Linux console/
1035 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001036 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001037 break;
1038 }
1039 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001040 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001041 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1042 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001043 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001044 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001045 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001046 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001047 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001048 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001049 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1050 * Linux console/xterm; Esc [ 5 ^ ==
1051 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001052 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001053 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001054 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1055 * Linux console/xterm; Esc [ 6 ^ ==
1056 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001057 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001058 break;
1059 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001060 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001061 break;
1062 case '8': /* Esc [ 8 ~ == End on rxvt. */
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 Ramseycc823ab2004-10-24 22:51:39 +00001065 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001066 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001067 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001068 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001069 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001070 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001071 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001072 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001073 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001074 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001075 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001076 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001077 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001078 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001079 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001080 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001081 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001082 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001083 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001084 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001085 case 'E': /* Esc [ E == Center (5) on numeric keypad
1086 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001087 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001088 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001089 case 'F': /* Esc [ F == End on FreeBSD
1090 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001091 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001092 break;
1093 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001094 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001095 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001096 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001097 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001098 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001099 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001100 break;
1101 case 'I': /* Esc [ I == PageUp on FreeBSD
1102 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001103 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001104 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001105 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001106 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001107 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001108 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001109 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001110 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001111 break;
1112 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001113 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001114 break;
1115 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001116 if (seq_len >= 3) {
1117 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001118 case 'P': /* Esc [ O P == F1 on
1119 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001120 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001121 break;
1122 case 'Q': /* Esc [ O Q == F2 on
1123 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001124 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001125 break;
1126 case 'R': /* Esc [ O R == F3 on
1127 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001128 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001129 break;
1130 case 'S': /* Esc [ O S == F4 on
1131 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001132 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001133 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001134 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001135 } else {
1136 /* Esc [ O == F3 on FreeBSD console. */
1137 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001138 }
1139 break;
1140 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001141 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001142 break;
1143 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001144 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001145 break;
1146 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001147 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001148 break;
1149 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001150 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001151 break;
1152 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001153 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001154 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001155 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001156 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001157 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001158 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001159 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001160 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001161 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001162 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001163 break;
1164 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001165 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001166 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001167 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001168 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001169 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001171 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001172 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001173 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001174 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001175 case 'c': /* Esc [ c == Shift-Right on rxvt/
1176 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001177 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001178 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001179 break;
1180 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001181 if (seq_len >= 3) {
1182 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001183 case 'A': /* Esc [ [ A == F1 on Linux
1184 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001185 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001186 break;
1187 case 'B': /* Esc [ [ B == F2 on Linux
1188 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001189 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001190 break;
1191 case 'C': /* Esc [ [ C == F3 on Linux
1192 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001193 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001194 break;
1195 case 'D': /* Esc [ [ D == F4 on Linux
1196 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001197 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001198 break;
1199 case 'E': /* Esc [ [ E == F5 on Linux
1200 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001201 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001202 break;
1203 }
1204 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001205 break;
1206 }
1207 break;
1208 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001209 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001210
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001211#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001212 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001213#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001214
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001215 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001216}
1217
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001218/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001219 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001220 * to many escape sequences. */
1221int get_escape_seq_abcd(int kbinput)
1222{
1223 switch (tolower(kbinput)) {
1224 case 'a':
1225 return NANO_PREVLINE_KEY;
1226 case 'b':
1227 return NANO_NEXTLINE_KEY;
1228 case 'c':
1229 return NANO_FORWARD_KEY;
1230 case 'd':
1231 return NANO_BACK_KEY;
1232 default:
1233 return ERR;
1234 }
1235}
1236
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001237/* Translate a word sequence: turn a three-digit decimal number from
1238 * 000 to 255 into its corresponding word value. */
1239int get_word_kbinput(int kbinput
1240#ifndef NANO_SMALL
1241 , bool reset
1242#endif
1243 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001244{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001245 static int word_digits = 0;
1246 static int word_kbinput = 0;
1247 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001248
1249#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001250 if (reset) {
1251 word_digits = 0;
1252 word_kbinput = 0;
1253 return ERR;
1254 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001255#endif
1256
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001257 /* Increment the word digit counter. */
1258 word_digits++;
1259
1260 switch (word_digits) {
1261 case 1:
1262 /* One digit: reset the word sequence holder and add the
1263 * digit we got to the 10000's position of the word sequence
1264 * holder. */
1265 word_kbinput = 0;
1266 if ('0' <= kbinput && kbinput <= '6')
1267 word_kbinput += (kbinput - '0') * 10000;
1268 else
1269 /* If the character we got isn't a decimal digit, or if
1270 * it is and it would put the word sequence out of word
1271 * range, save it as the result. */
1272 retval = kbinput;
1273 break;
1274 case 2:
1275 /* Two digits: add the digit we got to the 1000's position
1276 * of the word sequence holder. */
1277 if (('0' <= kbinput && kbinput <= '5') ||
1278 (word_kbinput < 60000 && '6' <= kbinput &&
1279 kbinput <= '9'))
1280 word_kbinput += (kbinput - '0') * 1000;
1281 else
1282 /* If the character we got isn't a decimal digit, or if
1283 * it is and it would put the word sequence out of word
1284 * range, save it as the result. */
1285 retval = kbinput;
1286 break;
1287 case 3:
1288 /* Three digits: add the digit we got to the 100's position
1289 * of the word sequence holder. */
1290 if (('0' <= kbinput && kbinput <= '5') ||
1291 (word_kbinput < 65000 && '6' <= kbinput &&
1292 kbinput <= '9'))
1293 word_kbinput += (kbinput - '0') * 100;
1294 else
1295 /* If the character we got isn't a decimal digit, or if
1296 * it is and it would put the word sequence out of word
1297 * range, save it as the result. */
1298 retval = kbinput;
1299 break;
1300 case 4:
1301 /* Four digits: add the digit we got to the 10's position of
1302 * the word sequence holder. */
1303 if (('0' <= kbinput && kbinput <= '3') ||
1304 (word_kbinput < 65500 && '4' <= kbinput &&
1305 kbinput <= '9'))
1306 word_kbinput += (kbinput - '0') * 10;
1307 else
1308 /* If the character we got isn't a decimal digit, or if
1309 * it is and it would put the word sequence out of word
1310 * range, save it as the result. */
1311 retval = kbinput;
1312 break;
1313 case 5:
1314 /* Five digits: add the digit we got to the 1's position of
1315 * the word sequence holder, and save the corresponding word
1316 * value as the result. */
1317 if (('0' <= kbinput && kbinput <= '5') ||
1318 (word_kbinput < 65530 && '6' <= kbinput &&
1319 kbinput <= '9')) {
1320 word_kbinput += (kbinput - '0');
1321 retval = word_kbinput;
1322 } else
1323 /* If the character we got isn't a decimal digit, or if
1324 * it is and it would put the word sequence out of word
1325 * range, save it as the result. */
1326 retval = kbinput;
1327 break;
1328 default:
1329 /* More than three digits: save the character we got as the
1330 * result. */
1331 retval = kbinput;
1332 break;
1333 }
1334
1335 /* If we have a result, reset the word digit counter and the word
1336 * sequence holder. */
1337 if (retval != ERR) {
1338 word_digits = 0;
1339 word_kbinput = 0;
1340 }
1341
1342#ifdef DEBUG
1343 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1344#endif
1345
1346 return retval;
1347}
1348
1349/* Translate a control character sequence: turn an ASCII non-control
1350 * character into its corresponding control character. */
1351int get_control_kbinput(int kbinput)
1352{
1353 int retval;
1354
1355 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1356 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1357 kbinput == '`')
1358 retval = NANO_CONTROL_SPACE;
1359 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1360 else if ('3' <= kbinput && kbinput <= '7')
1361 retval = kbinput - 24;
1362 /* Ctrl-8 (Ctrl-?) */
1363 else if (kbinput == '8' || kbinput == '?')
1364 retval = NANO_CONTROL_8;
1365 /* Ctrl-A to Ctrl-_ */
1366 else if ('A' <= kbinput && kbinput <= '_')
1367 retval = kbinput - 64;
1368 /* Ctrl-a to Ctrl-~ */
1369 else if ('a' <= kbinput && kbinput <= '~')
1370 retval = kbinput - 96;
1371 else
1372 retval = kbinput;
1373
1374#ifdef DEBUG
1375 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1376#endif
1377
1378 return retval;
1379}
1380
1381/* Read in a string of characters verbatim, and return the length of the
1382 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1383int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1384{
1385 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001386
1387 /* Turn off flow control characters if necessary so that we can type
1388 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001389 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001390 if (ISSET(PRESERVE))
1391 disable_flow_control();
1392 keypad(win, FALSE);
1393
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001394 /* Read in a stream of characters and interpret it if possible. */
1395 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001396
1397 /* Turn flow control characters back on if necessary and turn the
1398 * keypad back on now that we're done. */
1399 if (ISSET(PRESERVE))
1400 enable_flow_control();
1401 keypad(win, TRUE);
1402
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001403 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001404}
1405
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001406/* Read in a stream of all available characters. Translate the first
1407 * few characters of the input into the corresponding word value if
1408 * possible. After that, leave the input as-is. */
1409int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001410{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001411 buffer *kbinput, *sequence;
1412 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001413
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001414 /* Read in the first keystroke. */
1415 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001416
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001417 /* Check whether the first keystroke is a decimal digit. */
1418 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001419#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001420 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001421#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001422 );
1423
1424 /* If the first keystroke isn't a decimal digit, put back the first
1425 * keystroke. */
1426 if (word != ERR)
1427 unget_input(kbinput, 1);
1428 /* Otherwise, read in keystrokes until we have a complete word
1429 * sequence, and put back the corresponding word value. */
1430 else {
1431 buffer word_kbinput;
1432
1433 while (word == ERR) {
1434 while ((kbinput = get_input(win, 1)) == NULL);
1435 word = get_word_kbinput(kbinput->key
1436#ifndef NANO_SMALL
1437 , FALSE
1438#endif
1439 );
1440 }
1441
1442 word_kbinput.key = word;
1443 word_kbinput.key_code = FALSE;
1444
1445 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001446 }
1447
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001448 /* Get the complete sequence, and save the key values in it as the
1449 * result. */
1450 *kbinput_len = get_buffer_len();
1451 sequence = get_input(NULL, *kbinput_len);
1452 retval = buffer_to_keys(sequence, *kbinput_len);
1453 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001454
1455 return retval;
1456}
1457
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001458#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001459/* Check for a mouse event, and if one's taken place, save the
1460 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001461 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1462 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001463 * place on it, figure out which shortcut was clicked and put back the
1464 * equivalent keystroke(s). Return FALSE if no keystrokes were
1465 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001466 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001467bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001468{
1469 MEVENT mevent;
1470
1471 *mouse_x = -1;
1472 *mouse_y = -1;
1473
1474 /* First, get the actual mouse event. */
1475 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001476 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001477
1478 /* Save the screen coordinates where the mouse event took place. */
1479 *mouse_x = mevent.x;
1480 *mouse_y = mevent.y;
1481
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001482 /* If we're allowing shortcuts, the current shortcut list is being
1483 * displayed on the last two lines of the screen, and the mouse
1484 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001485 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001486 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1487 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001488 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001489 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001490 /* The number of shortcuts in the current shortcut list. */
1491 const shortcut *s = currshortcut;
1492 /* The actual shortcut we clicked on, starting at the first
1493 * one in the current shortcut list. */
1494
1495 /* Get the shortcut lists' length. */
1496 if (currshortcut == main_list)
1497 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001498 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001499 currslen = length_of_list(currshortcut);
1500
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001501 /* We don't show any more shortcuts than the main list
1502 * does. */
1503 if (currslen > MAIN_VISIBLE)
1504 currslen = MAIN_VISIBLE;
1505 }
1506
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001507 /* Calculate the width of each shortcut in the list (it's the
1508 * same for all of them). */
1509 if (currslen < 2)
1510 i = COLS / 6;
1511 else
1512 i = COLS / ((currslen / 2) + (currslen % 2));
1513
1514 /* Calculate the y-coordinates relative to the beginning of
1515 * bottomwin, i.e, the bottom three lines of the screen. */
1516 j = *mouse_y - (editwinrows + 3);
1517
1518 /* If we're on the statusbar, beyond the end of the shortcut
1519 * list, or beyond the end of a shortcut on the right side of
1520 * the screen, don't do anything. */
1521 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001522 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001523 j = (*mouse_x / i) * 2 + j;
1524 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001525 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001526
1527 /* Go through the shortcut list to determine which shortcut was
1528 * clicked. */
1529 for (; j > 0; j--)
1530 s = s->next;
1531
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001532 /* And put back the equivalent key. Assume that each shortcut
1533 * has, at the very least, an equivalent control key, an
1534 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001535 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001536 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001537 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001538 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001539
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001540 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001541 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001542 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001543}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001544#endif /* !DISABLE_MOUSE */
1545
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001546const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001547 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001548{
1549 const shortcut *s = s_list;
1550 size_t slen = length_of_list(s_list);
1551
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001552#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001553 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 +00001554#endif
1555
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001556 /* Check for shortcuts. */
1557 for (; slen > 0; slen--) {
1558 /* We've found a shortcut if:
1559 *
1560 * 1. The key exists.
1561 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001562 * 3. meta_key is TRUE and the key is the primary or
1563 * miscellaneous meta sequence in the shortcut list.
1564 * 4. func_key is TRUE and the key is a function key in the
1565 * shortcut list. */
1566
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001567 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1568 (*meta_key == TRUE && (*kbinput == s->metaval ||
1569 *kbinput == s->miscval)) || (*func_key == TRUE &&
1570 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001571 break;
1572 }
1573
1574 s = s->next;
1575 }
1576
1577 /* Translate the shortcut to either its control key or its meta key
1578 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001579 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001580 if (slen > 0) {
1581 if (s->ctrlval != NANO_NO_KEY) {
1582 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001583 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001584 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001585 } else if (s->metaval != NANO_NO_KEY) {
1586 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001587 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001588 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001589 }
1590 return s;
1591 }
1592
1593 return NULL;
1594}
1595
1596#ifndef NANO_SMALL
1597const toggle *get_toggle(int kbinput, bool meta_key)
1598{
1599 const toggle *t = toggles;
1600
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001601#ifdef DEBUG
1602 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1603#endif
1604
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001605 /* Check for toggles. */
1606 for (; t != NULL; t = t->next) {
1607 /* We've found a toggle if meta_key is TRUE and the key is in
David Lawrence Ramseybfcba162004-12-05 06:11:01 +00001608 * the meta key toggle list. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001609 if (meta_key && kbinput == t->val)
1610 break;
1611 }
1612
1613 return t;
1614}
1615#endif /* !NANO_SMALL */
1616
Chris Allegretta6df90f52002-07-19 01:08:59 +00001617/* Return the placewewant associated with current_x. That is, xplustabs
1618 * is the zero-based column position of the cursor. Value is no smaller
1619 * than current_x. */
1620size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001621{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001622 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001623}
1624
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001625/* actual_x() gives the index in str of the character displayed at
1626 * column xplus. That is, actual_x() is the largest value such that
1627 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1628size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001629{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001630 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001631 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001632 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001633 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001634
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001635 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001636
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001637 for (; length < xplus && *str != '\0'; i++, str++) {
1638 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001639 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001640 else if (is_cntrl_char(*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001641 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001642 else
1643 length++;
1644 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001645 assert(length == strnlenpt(str - i, i));
1646 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001647
Chris Allegretta6df90f52002-07-19 01:08:59 +00001648 if (length > xplus)
1649 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001650
Chris Allegretta6df90f52002-07-19 01:08:59 +00001651 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001652}
1653
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001654/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001655 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001656size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001657{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001658 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001659
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001660 assert(buf != NULL);
1661 for (; *buf != '\0' && size != 0; size--, buf++) {
1662 if (*buf == '\t')
1663 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001664 else if (is_cntrl_char(*buf))
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001665 length += 2;
1666 else
1667 length++;
1668 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001669 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001670}
1671
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001672/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001673size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001674{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001675 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001676}
1677
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001678void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001679{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001680 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001681}
1682
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001683void blank_edit(void)
1684{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001685 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001686 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001687 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001688}
1689
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001690void blank_statusbar(void)
1691{
1692 mvwaddstr(bottomwin, 0, 0, hblank);
1693}
1694
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001695void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001696{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001697 if (statusblank > 1)
1698 statusblank--;
1699 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
1700 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001701 blank_statusbar();
1702 wnoutrefresh(bottomwin);
1703 reset_cursor();
1704 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001705 }
1706}
1707
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001708void blank_bottombars(void)
1709{
1710 if (!ISSET(NO_HELP)) {
1711 mvwaddstr(bottomwin, 1, 0, hblank);
1712 mvwaddstr(bottomwin, 2, 0, hblank);
1713 }
1714}
1715
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001716/* Convert buf into a string that can be displayed on screen. The
1717 * caller wants to display buf starting with column start_col, and
1718 * extending for at most len columns. start_col is zero-based. len is
1719 * one-based, so len == 0 means you get "" returned. The returned
1720 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001721char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001722{
1723 size_t start_index;
1724 /* Index in buf of first character shown in return value. */
1725 size_t column;
1726 /* Screen column start_index corresponds to. */
1727 size_t end_index;
1728 /* Index in buf of last character shown in return value. */
1729 size_t alloc_len;
1730 /* The length of memory allocated for converted. */
1731 char *converted;
1732 /* The string we return. */
1733 size_t index;
1734 /* Current position in converted. */
1735
1736 if (len == 0)
1737 return mallocstrcpy(NULL, "");
1738
1739 start_index = actual_x(buf, start_col);
1740 column = strnlenpt(buf, start_index);
1741 assert(column <= start_col);
1742 end_index = actual_x(buf, start_col + len - 1);
1743 alloc_len = strnlenpt(buf, end_index + 1) - column;
1744 if (len > alloc_len + column - start_col)
1745 len = alloc_len + column - start_col;
1746 converted = charalloc(alloc_len + 1);
1747 buf += start_index;
1748 index = 0;
1749
1750 for (; index < alloc_len; buf++) {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001751 if (*buf == '\t') {
1752 converted[index++] =
1753#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1754 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1755#endif
1756 ' ';
1757 while ((column + index) % tabsize)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001758 converted[index++] = ' ';
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001759 } else if (is_cntrl_char(*buf)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001760 converted[index++] = '^';
1761 if (*buf == '\n')
1762 /* Treat newlines embedded in a line as encoded nulls;
1763 * the line in question should be run through unsunder()
1764 * before reaching here. */
1765 converted[index++] = '@';
1766 else if (*buf == NANO_CONTROL_8)
1767 converted[index++] = '?';
1768 else
1769 converted[index++] = *buf + 64;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001770 } else if (*buf == ' ')
1771 converted[index++] =
1772#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1773 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1774#endif
1775 ' ';
1776 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001777 converted[index++] = *buf;
1778 }
1779 assert(len <= alloc_len + column - start_col);
1780 charmove(converted, converted + start_col - column, len);
1781 null_at(&converted, len);
1782
1783 return charealloc(converted, len + 1);
1784}
1785
Chris Allegretta7662c862003-01-13 01:35:15 +00001786/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001787 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001788 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001789 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001790 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001791void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001792{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001793 size_t x_real = strnlenpt(inputbuf, x);
1794 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001795
Chris Allegretta6df90f52002-07-19 01:08:59 +00001796 assert(0 <= x && x <= strlen(inputbuf));
1797
Chris Allegrettab3655b42001-10-22 03:15:31 +00001798 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001799 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001800
Chris Allegretta6df90f52002-07-19 01:08:59 +00001801 mvwaddstr(bottomwin, 0, 0, buf);
1802 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001803
1804 if (COLS > 1)
1805 waddch(bottomwin, x_real < wid ? ' ' : '$');
1806 if (COLS > 2) {
1807 size_t page_start = x_real - x_real % wid;
1808 char *expanded = display_string(inputbuf, page_start, wid);
1809
1810 assert(wid > 0);
1811 assert(strlen(expanded) <= wid);
1812 waddstr(bottomwin, expanded);
1813 free(expanded);
1814 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1815 } else
1816 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001817 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001818}
1819
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001820/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001821 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001822int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001823#ifndef NANO_SMALL
1824 historyheadtype *history_list,
1825#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001826 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001827#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001828 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001829#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001830 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001831{
1832 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001833 bool meta_key, func_key;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001834 static size_t x = (size_t)-1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001835 /* the cursor position in 'answer' */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001836 size_t xend;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001837 /* length of 'answer', the status bar text */
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001838 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001839 /* used by input_tab() */
1840 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001841
Chris Allegretta5beed502003-01-05 20:41:21 +00001842#ifndef NANO_SMALL
1843 /* for history */
1844 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001845 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001846 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001847 int last_kbinput = 0;
1848
1849 /* This variable is used in the search history code. use_cb == 0
1850 means that we're using the existing history and ignoring
1851 currentbuf. use_cb == 1 means that the entry in answer should be
1852 moved to currentbuf or restored from currentbuf to answer.
1853 use_cb == 2 means that the entry in currentbuf should be moved to
1854 answer or restored from answer to currentbuf. */
1855 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001856#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001857 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001858
David Lawrence Ramsey4dd723a2004-10-05 02:29:52 +00001859 /* Only put x at the end of the string if it's uninitialized, if it
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001860 would be past the end of the string as it is, or if
1861 resetstatuspos is TRUE. Otherwise, leave it alone. This is so
1862 the cursor position stays at the same place if a prompt-changing
1863 toggle is pressed. */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001864 if (x == (size_t)-1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001865 x = xend;
1866
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001867 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001868 if (xend > 0)
1869 strcpy(answer, def);
1870 else
1871 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001872
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001873#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001874 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001875#endif
1876
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001877 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001878
Chris Allegretta6df90f52002-07-19 01:08:59 +00001879 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001880
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001881 /* Make sure any editor screen updates are displayed before getting
1882 input */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00001883 wnoutrefresh(edit);
1884 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00001885
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001886 /* If we're using restricted mode, we aren't allowed to change the
1887 * name of a file once it has one because that would allow writing
1888 * to files not specified on the command line. In this case,
1889 * disable all keys that would change the text if the filename isn't
1890 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001891 while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001892 NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001893 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001894#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001895 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001896#endif
1897
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001898 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1899 if (kbinput == t->funcval)
1900 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001901
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001902 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001903
Chris Allegrettab3655b42001-10-22 03:15:31 +00001904#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001905 /* Have to do this here, it would be too late to do it
1906 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001907 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001908 do_help();
1909 break;
1910 }
1911#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001912#ifndef NANO_SMALL
1913 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001914 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001915 break;
1916#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001917
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001918 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001919 }
1920 }
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001921 assert(x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001922
Chris Allegretta04d848e2000-11-05 17:54:41 +00001923 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001924 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00001925
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001926 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001927#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001928 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001929 {
1930 int mouse_x, mouse_y;
1931 get_mouseinput(&mouse_x, &mouse_y, TRUE);
1932 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001933 break;
1934#endif
David Lawrence Ramsey72d8e542004-09-25 00:45:07 +00001935 case NANO_REFRESH_KEY:
1936 total_refresh();
1937 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001938 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001939#ifndef NANO_SMALL
1940 if (ISSET(SMART_HOME)) {
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001941 size_t old_x = x;
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001942
1943 for (x = 0; isblank(answer[x]) && x < xend; x++)
1944 ;
1945
1946 if (x == old_x || x == xend)
1947 x = 0;
1948 } else
1949#endif
1950 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001951 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001952 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001953 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001954 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001955 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001956 if (x < xend)
1957 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001958 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001959 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001960 /* If we're using restricted mode, the filename isn't blank,
1961 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001962 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1963 if (x < xend) {
1964 charmove(answer + x, answer + x + 1, xend - x);
1965 xend--;
1966 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001967 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001968 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001969 case NANO_CUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001970 /* If we're using restricted mode, the filename isn't blank,
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00001971 * and we're at the "Write File" prompt, disable Cut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001972 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1973 null_at(&answer, 0);
1974 xend = 0;
1975 x = 0;
1976 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001977 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001978 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001979 /* If we're using restricted mode, the filename isn't blank,
1980 * and we're at the "Write File" prompt, disable
1981 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001982 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1983 if (x > 0) {
1984 charmove(answer + x - 1, answer + x, xend - x + 1);
1985 x--;
1986 xend--;
1987 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001988 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001989 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001990 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001991#ifndef NANO_SMALL
1992 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001993 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001994 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001995 history_list->current = (historytype *)history_list;
1996 history_list->len = strlen(answer);
1997 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001998
Chris Allegretta7662c862003-01-13 01:35:15 +00001999 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002000 complete = get_history_completion(history_list, answer);
2001 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002002 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002003 answer = mallocstrcpy(answer, complete);
2004 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00002005 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002006#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00002007 else
2008#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00002009#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002010#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002011 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00002012 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00002013
Chris Allegretta327abda2003-01-17 05:04:17 +00002014 answer = input_tab(answer, x, &tabbed, &shift, list);
2015 xend = strlen(answer);
2016 x += shift;
2017 if (x > xend)
2018 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00002019 }
2020#endif
2021 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00002022 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00002023 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002024 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002025 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002026 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002027#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002028 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002029
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002030 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
2031 isn't NULL, and currentbuf is different from answer,
2032 it means that we're scrolling up at the top of the
2033 search history, and we need to save the current
2034 answer in currentbuf; do this and reset use_cb to
2035 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002036 if (currentbuf == NULL || (use_cb == 1 &&
2037 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002038 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002039 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002040 }
2041
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002042 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2043 is different from answer, it means that we're
2044 scrolling up at the bottom of the search history, and
2045 we need to make the string in currentbuf the current
2046 answer; do this, blow away currentbuf since we don't
2047 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002048 if (currentbuf != NULL && use_cb == 2 &&
2049 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002050 answer = mallocstrcpy(answer, currentbuf);
2051 free(currentbuf);
2052 currentbuf = NULL;
2053 xend = strlen(answer);
2054 use_cb = 0;
2055
2056 /* else get older search from the history list and save
2057 it in answer; if there is no older search, blank out
2058 answer */
2059 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002060 answer = mallocstrcpy(answer, history);
2061 xend = strlen(history);
2062 } else {
2063 answer = mallocstrcpy(answer, "");
2064 xend = 0;
2065 }
2066 x = xend;
2067 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002068#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002069 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002070 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002071#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002072 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002073
2074 /* get newer search from the history list and save it
2075 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002076 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002077 answer = mallocstrcpy(answer, history);
2078 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002079
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002080 /* if there is no newer search, we're here */
2081
2082 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2083 that we're scrolling down at the bottom of the search
2084 history and we need to make the string in currentbuf
2085 the current answer; do this, blow away currentbuf
2086 since we don't need it anymore, and set use_cb to
2087 1 */
2088 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002089 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002090 free(currentbuf);
2091 currentbuf = NULL;
2092 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002093 use_cb = 1;
2094
2095 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2096 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002097 the search history and the current answer (if it's
2098 not blank) needs to be saved in currentbuf; do this,
2099 blank out answer (if necessary), and set use_cb to
2100 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002101 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002102 if (answer[0] != '\0') {
2103 currentbuf = mallocstrcpy(currentbuf, answer);
2104 answer = mallocstrcpy(answer, "");
2105 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002106 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002107 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002108 }
2109 x = xend;
2110 }
2111#endif
2112 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002113 default:
2114
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002115 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002116#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002117 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00002118 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00002119#endif
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002120 if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00002121 /* We hit a meta key. Do like above. We don't
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00002122 * just put back the letter and let it get
David Lawrence Ramsey82138502003-12-24 08:03:54 +00002123 * caught above cause that screws the
2124 * keypad... */
2125 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00002126 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002127
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002128 /* If we're using restricted mode, the filename isn't blank,
2129 * and we're at the "Write File" prompt, act as though the
2130 * unhandled character we got is a control character and
2131 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002132 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002133 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002134 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00002135 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002136 xend++;
2137 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002138 x++;
2139
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002140#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002141 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002142#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002143 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002144#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002145 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002146#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002147 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002148 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002149 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002150
Chris Allegretta5af58892003-01-17 21:07:38 +00002151 /* We finished putting in an answer; reset x */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002152 x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002153
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002154 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002155}
2156
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002157/* Ask a question on the statusbar. Answer will be stored in answer
2158 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2159 * otherwise, the valid shortcut key caught. def is any editable text
2160 * we want to put up by default.
2161 *
2162 * New arg tabs tells whether or not to allow tab completion. */
2163int statusq(bool allow_tabs, const shortcut *s, const char *def,
2164#ifndef NANO_SMALL
2165 historyheadtype *which_history,
2166#endif
2167 const char *msg, ...)
2168{
2169 va_list ap;
2170 char *foo = charalloc(COLS - 3);
2171 int ret;
2172#ifndef DISABLE_TABCOMP
2173 bool list = FALSE;
2174#endif
2175
2176 bottombars(s);
2177
2178 va_start(ap, msg);
2179 vsnprintf(foo, COLS - 4, msg, ap);
2180 va_end(ap);
2181 foo[COLS - 4] = '\0';
2182
2183 ret = nanogetstr(allow_tabs, foo, def,
2184#ifndef NANO_SMALL
2185 which_history,
2186#endif
2187 s
2188#ifndef DISABLE_TABCOMP
2189 , &list
2190#endif
2191 );
2192 free(foo);
2193 resetstatuspos = FALSE;
2194
2195 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002196 case NANO_FIRSTLINE_KEY:
2197 case NANO_FIRSTLINE_FKEY:
2198 do_first_line();
2199 resetstatuspos = TRUE;
2200 break;
2201 case NANO_LASTLINE_KEY:
2202 case NANO_LASTLINE_FKEY:
2203 do_last_line();
2204 resetstatuspos = TRUE;
2205 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002206#ifndef DISABLE_JUSTIFY
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002207 case NANO_PARABEGIN_KEY:
2208 case NANO_PARABEGIN_ALTKEY1:
2209 case NANO_PARABEGIN_ALTKEY2:
2210 do_para_begin();
2211 resetstatuspos = TRUE;
2212 break;
2213 case NANO_PARAEND_KEY:
2214 case NANO_PARAEND_ALTKEY1:
2215 case NANO_PARAEND_ALTKEY2:
2216 do_para_end();
2217 resetstatuspos = TRUE;
2218 break;
2219 case NANO_FULLJUSTIFY_KEY:
2220 case NANO_FULLJUSTIFY_ALTKEY:
2221 if (!ISSET(VIEW_MODE))
2222 do_full_justify();
2223 resetstatuspos = TRUE;
2224 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002225#endif
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002226 case NANO_CANCEL_KEY:
2227 ret = -1;
2228 resetstatuspos = TRUE;
2229 break;
2230 case NANO_ENTER_KEY:
2231 ret = (answer[0] == '\0') ? -2 : 0;
2232 resetstatuspos = TRUE;
2233 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002234 }
2235 blank_statusbar();
2236
2237#ifdef DEBUG
2238 fprintf(stderr, "I got \"%s\"\n", answer);
2239#endif
2240
2241#ifndef DISABLE_TABCOMP
2242 /* if we've done tab completion, there might be a list of
2243 filename matches on the edit window at this point; make sure
2244 they're cleared off. */
2245 if (list)
2246 edit_refresh();
2247#endif
2248
2249 return ret;
2250}
2251
2252void statusq_abort(void)
2253{
2254 resetstatuspos = TRUE;
2255}
2256
Chris Allegrettaf717f982003-02-13 22:25:01 +00002257void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002258{
David Lawrence Ramseybce3aad2004-12-05 06:02:39 +00002259 int space;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002260 /* The space we have available for display. */
2261 size_t verlen = strlen(VERMSG) + 1;
2262 /* The length of the version message. */
2263 const char *prefix;
2264 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2265 size_t prefixlen;
2266 /* strlen(prefix) + 1. */
2267 const char *state;
2268 /* "Modified", "View", or spaces the length of "Modified".
2269 * Tells the state of this buffer. */
2270 size_t statelen = 0;
2271 /* strlen(state) + 1. */
2272 char *exppath = NULL;
2273 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002274 size_t exppathlen = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002275 /* strlen(exppath) + 1. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002276 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002277 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002278 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002279 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002280
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002281 assert(path != NULL || filename != NULL);
2282 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002283
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002284 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002285
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002286 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002287
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002288 if (COLS <= 5 || COLS - 5 < verlen)
2289 space = 0;
2290 else {
2291 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002292 /* Reserve 2/3 of the screen plus one column for after the
2293 * version message. */
2294 if (space < COLS - (COLS / 3) + 1)
2295 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002296 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002297
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002298 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002299 /* The version message should only take up 1/3 of the screen
2300 * minus one column. */
2301 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002302 waddstr(topwin, " ");
2303 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002304
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002305 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002306 state = _("Modified");
2307 else if (path == NULL && ISSET(VIEW_MODE))
2308 state = _("View");
2309 else {
2310 if (space > 0)
2311 statelen = strnlen(_("Modified"), space - 1) + 1;
2312 state = &hblank[COLS - statelen];
2313 }
2314 statelen = strnlen(state, COLS);
2315 /* We need a space before state. */
2316 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2317 statelen++;
2318
2319 assert(space >= 0);
2320 if (space == 0 || statelen >= space)
2321 goto the_end;
2322
2323#ifndef DISABLE_BROWSER
2324 if (path != NULL)
2325 prefix = _("DIR:");
2326 else
2327#endif
2328 if (filename[0] == '\0') {
2329 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002330 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002331 } else
2332 prefix = _("File:");
2333 assert(statelen < space);
2334 prefixlen = strnlen(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002335 /* If newfie is FALSE, we need a space after prefix. */
2336 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002337 prefixlen++;
2338
2339 if (path == NULL)
2340 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002341 if (space >= prefixlen + statelen)
2342 space -= prefixlen + statelen;
2343 else
2344 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002345 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002346 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002347 size_t lenpt = strlenpt(path), start_col;
2348
2349 if (lenpt > space)
2350 start_col = actual_x(path, lenpt - space);
2351 else
2352 start_col = 0;
2353 exppath = display_string(path, start_col, space);
2354 dots = (lenpt > space);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002355 exppathlen = strlen(exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002356 }
2357
2358 if (!dots) {
2359 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002360 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002361 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002362 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002363 assert(strlen(prefix) + 1 == prefixlen);
2364 waddch(topwin, ' ');
2365 waddstr(topwin, exppath);
2366 }
2367 } else {
2368 /* We will say something like "File: ...ename". */
2369 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002370 if (space == 0 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002371 goto the_end;
2372 waddch(topwin, ' ');
2373 waddnstr(topwin, "...", space);
2374 if (space <= 3)
2375 goto the_end;
2376 space -= 3;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002377 assert(exppathlen == space + 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002378 waddnstr(topwin, exppath + 3, space);
2379 }
2380
2381 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002382 free(exppath);
2383
2384 if (COLS <= 1 || statelen >= COLS - 1)
2385 mvwaddnstr(topwin, 0, 0, state, COLS);
2386 else {
2387 assert(COLS - statelen - 2 >= 0);
2388 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2389 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2390 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002391
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002392 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002393
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002394 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002395 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002396 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002397}
2398
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002399/* If modified is not already set, set it and update titlebar. */
2400void set_modified(void)
2401{
2402 if (!ISSET(MODIFIED)) {
2403 SET(MODIFIED);
2404 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002405 }
2406}
2407
2408void statusbar(const char *msg, ...)
2409{
2410 va_list ap;
2411
2412 va_start(ap, msg);
2413
2414 /* Curses mode is turned off. If we use wmove() now, it will muck
2415 * up the terminal settings. So we just use vfprintf(). */
2416 if (curses_ended) {
2417 vfprintf(stderr, msg, ap);
2418 va_end(ap);
2419 return;
2420 }
2421
2422 /* Blank out the line. */
2423 blank_statusbar();
2424
2425 if (COLS >= 4) {
2426 char *bar;
2427 char *foo;
2428 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002429#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002430 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002431 UNSET(WHITESPACE_DISPLAY);
2432#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002433 bar = charalloc(COLS - 3);
2434 vsnprintf(bar, COLS - 3, msg, ap);
2435 va_end(ap);
2436 foo = display_string(bar, 0, COLS - 4);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002437#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2438 if (old_whitespace)
2439 SET(WHITESPACE_DISPLAY);
2440#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002441 free(bar);
2442 foo_len = strlen(foo);
2443 start_x = (COLS - foo_len - 4) / 2;
2444
2445 wmove(bottomwin, 0, start_x);
2446 wattron(bottomwin, A_REVERSE);
2447
2448 waddstr(bottomwin, "[ ");
2449 waddstr(bottomwin, foo);
2450 free(foo);
2451 waddstr(bottomwin, " ]");
2452 wattroff(bottomwin, A_REVERSE);
2453 wnoutrefresh(bottomwin);
2454 reset_cursor();
2455 wrefresh(edit);
2456 /* Leave the cursor at its position in the edit window, not
2457 * in the statusbar. */
2458 }
2459
2460 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002461 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002462}
2463
Chris Allegretta6232d662002-05-12 19:52:15 +00002464void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002465{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002466 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002467
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002468 if (ISSET(NO_HELP))
2469 return;
2470
Chris Allegretta6232d662002-05-12 19:52:15 +00002471 if (s == main_list) {
2472 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002473 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002474 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002475 slen = length_of_list(s);
2476
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002477 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002478 if (slen > MAIN_VISIBLE)
2479 slen = MAIN_VISIBLE;
2480 }
2481
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002482 /* There will be this many characters per column. We need at least
2483 * 3 to display anything properly.*/
2484 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002485
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002486 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002487
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002488 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002489 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002490
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002491 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002492#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002493 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002494 keystr = _("Up");
2495 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002496#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002497 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00002498
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002499 if (s->ctrlval == NANO_CONTROL_SPACE)
2500 strcpy(foo, "^ ");
2501 else if (s->ctrlval == NANO_CONTROL_8)
2502 strcpy(foo, "^?");
2503 /* Normal values. Assume that the shortcut has an
2504 * equivalent control key, meta key sequence, or both. */
2505 else if (s->ctrlval != NANO_NO_KEY)
2506 sprintf(foo, "^%c", s->ctrlval + 64);
2507 else if (s->metaval != NANO_NO_KEY)
2508 sprintf(foo, "M-%c", toupper(s->metaval));
2509
2510 keystr = foo;
2511#ifndef NANO_SMALL
2512 }
2513#endif
2514
2515 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002516 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002517 }
2518
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002519 wnoutrefresh(bottomwin);
2520 reset_cursor();
2521 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002522}
2523
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002524/* Write a shortcut key to the help area at the bottom of the window.
2525 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2526 * to write at most len characters, even if len is very small and
2527 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2528 * the whole string! We do not bother padding the entry with blanks. */
2529void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002530{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002531 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002532 wattron(bottomwin, A_REVERSE);
2533 waddnstr(bottomwin, keystroke, len);
2534 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002535 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002536 if (len > 0) {
2537 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002538 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002539 }
2540}
2541
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002542/* And so start the display update routines. */
2543
2544#ifndef NDEBUG
2545int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002546{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002547 int check_line = 0;
2548 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002549
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002550 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2551 check_line++;
2552 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002553}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002554#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002555
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002556/* nano scrolls horizontally within a line in chunks. This function
2557 * returns the column number of the first character displayed in the
2558 * window when the cursor is at the given column. Note that
2559 * 0 <= column - get_page_start(column) < COLS. */
2560size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002561{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002562 assert(COLS > 0);
2563 if (column == 0 || column < COLS - 1)
2564 return 0;
2565 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002566 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002567 else if (COLS > 2)
2568 return column - (COLS - 2);
2569 else
2570 return column - (COLS - 1);
2571 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002572}
2573
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002574/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002575 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002576void reset_cursor(void)
2577{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002578 /* If we haven't opened any files yet, put the cursor in the top
2579 * left corner of the edit window and get out. */
2580 if (edittop == NULL || current == NULL) {
2581 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002582 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002583 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002584
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002585 current_y = current->lineno - edittop->lineno;
2586 if (current_y < editwinrows) {
2587 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002588 wmove(edit, current_y, x - get_page_start(x));
2589 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002590}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002591
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002592/* edit_add() takes care of the job of actually painting a line into the
2593 * edit window. fileptr is the line to be painted, at row yval of the
2594 * window. converted is the actual string to be written to the window,
2595 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002596 * characters. start is the column number of the first character of
2597 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002598 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002599void edit_add(const filestruct *fileptr, const char *converted, int
2600 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002601{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002602#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2603 size_t startpos = actual_x(fileptr->data, start);
2604 /* The position in fileptr->data of the leftmost character
2605 * that displays at least partially on the window. */
2606 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2607 /* The position in fileptr->data of the first character that is
2608 * completely off the window to the right.
2609 *
2610 * Note that endpos might be beyond the null terminator of the
2611 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002612#endif
2613
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002614 assert(fileptr != NULL && converted != NULL);
2615 assert(strlen(converted) <= COLS);
2616
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002617 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002618 * just the text that needs it). */
2619 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002620
Chris Allegretta7dd77682001-12-08 19:52:28 +00002621#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002622 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002623 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002624
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002625 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2626 int x_start;
2627 /* Starting column for mvwaddnstr. Zero-based. */
2628 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002629 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002630 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002631 regmatch_t startmatch; /* match position for start_regexp */
2632 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002633
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002634 if (tmpcolor->bright)
2635 wattron(edit, A_BOLD);
2636 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002637 /* Two notes about regexec(). Return value 0 means there is
2638 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002639 * after the match. */
2640
2641 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002642 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002643 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002644
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002645 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002646 * last match. Even though two matches may overlap, we
2647 * want to ignore them, so that we can highlight
2648 * C-strings correctly. */
2649 while (k < endpos) {
2650 /* Note the fifth parameter to regexec(). It says
2651 * not to match the beginning-of-line character
2652 * unless k is 0. If regexec() returns REG_NOMATCH,
2653 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002654 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002655 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002656 break;
2657 /* Translate the match to the beginning of the line. */
2658 startmatch.rm_so += k;
2659 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002660 if (startmatch.rm_so == startmatch.rm_eo) {
2661 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002662 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002663 } else if (startmatch.rm_so < endpos &&
2664 startmatch.rm_eo > startpos) {
2665 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002666 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002667 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002668 x_start = strnlenpt(fileptr->data,
2669 startmatch.rm_so) - start;
2670 paintlen = strnlenpt(fileptr->data,
2671 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002672 if (paintlen > COLS - x_start)
2673 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002674
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002675 assert(0 <= x_start && 0 < paintlen &&
2676 x_start + paintlen <= COLS);
2677 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002678 converted + x_start, paintlen);
2679 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002680 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002681 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002682 } else {
2683 /* This is a multi-line regexp. There are two steps.
2684 * First, we have to see if the beginning of the line is
2685 * colored by a start on an earlier line, and an end on
2686 * this line or later.
2687 *
2688 * We find the first line before fileptr matching the
2689 * start. If every match on that line is followed by an
2690 * end, then go to step two. Otherwise, find the next line
2691 * after start_line matching the end. If that line is not
2692 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002693
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002694 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002695 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002696 regoff_t start_col;
2697 /* where it starts in that line */
2698 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002699
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002700 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002701 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002702 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002703 /* If there is an end on this line, there is no need
2704 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002705 if (regexec(tmpcolor->end, start_line->data, 0,
2706 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002707 goto step_two;
2708 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002709 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002710 /* No start found, so skip to the next step. */
2711 if (start_line == NULL)
2712 goto step_two;
2713 /* Now start_line is the first line before fileptr
2714 * containing a start match. Is there a start on this
2715 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002716
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002717 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002718 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002719 start_col += startmatch.rm_so;
2720 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002721 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002722 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002723 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2724 REG_NOTBOL) == REG_NOMATCH)
2725 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002726 break;
2727 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002728 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002729 start_line->data + start_col, 1,
2730 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002731 /* No later start on this line. */
2732 goto step_two;
2733 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002734 /* Indeed, there is a start not followed on this line by
2735 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002736
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002737 /* We have already checked that there is no end before
2738 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002739 * the start at all? We don't paint unterminated
2740 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002741 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002742 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00002743 regexec(tmpcolor->end, end_line->data, 1,
2744 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002745 end_line = end_line->next;
2746
2747 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002748 if (end_line == NULL ||
2749 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002750 goto step_two;
2751
2752 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002753 paintlen = end_line != fileptr ? COLS :
2754 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002755 if (paintlen > COLS)
2756 paintlen = COLS;
2757
2758 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002759 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002760
2761 /* We have already painted the whole line. */
2762 if (paintlen == COLS)
2763 goto skip_step_two;
2764
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002765 step_two:
2766 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002767 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002768 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002769 if (regexec(&tmpcolor->start,
2770 fileptr->data + start_col, 1, &startmatch,
2771 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2772 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002773 /* No more starts on this line. */
2774 break;
2775 /* Translate the match to be relative to the
2776 * beginning of the line. */
2777 startmatch.rm_so += start_col;
2778 startmatch.rm_eo += start_col;
2779
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002780 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002781 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002782 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002783 x_start = strnlenpt(fileptr->data,
2784 startmatch.rm_so) - start;
2785 if (regexec(tmpcolor->end,
2786 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2787 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002788 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002789 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002790 endmatch.rm_so += startmatch.rm_eo;
2791 endmatch.rm_eo += startmatch.rm_eo;
2792 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002793 * appear on this page, and is the match more
2794 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002795 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002796 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002797 paintlen = strnlenpt(fileptr->data,
2798 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002799 if (x_start + paintlen > COLS)
2800 paintlen = COLS - x_start;
2801
2802 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002803 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002804 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002805 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002806 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002807 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002808 /* There is no end on this line. But we haven't
2809 * yet looked for one on later lines. */
2810 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002811 while (end_line != NULL &&
2812 regexec(tmpcolor->end, end_line->data, 0,
2813 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002814 end_line = end_line->next;
2815 if (end_line != NULL) {
2816 assert(0 <= x_start && x_start < COLS);
2817 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002818 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002819 /* We painted to the end of the line, so
2820 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002821 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002822 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002823 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002824 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002825 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002826 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002827
Chris Allegrettace452fb2003-02-03 02:56:44 +00002828 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002829 wattroff(edit, A_BOLD);
2830 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2831 } /* for tmpcolor in colorstrings */
2832 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002833#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002834
Chris Allegretta7dd77682001-12-08 19:52:28 +00002835#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002836 if (ISSET(MARK_ISSET)
2837 && (fileptr->lineno <= mark_beginbuf->lineno
2838 || fileptr->lineno <= current->lineno)
2839 && (fileptr->lineno >= mark_beginbuf->lineno
2840 || fileptr->lineno >= current->lineno)) {
2841 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002842
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002843 const filestruct *top;
2844 /* Either current or mark_beginbuf, whichever is first. */
2845 size_t top_x;
2846 /* current_x or mark_beginx, corresponding to top. */
2847 const filestruct *bot;
2848 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002849 int x_start;
2850 /* Starting column for mvwaddnstr. Zero-based. */
2851 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002852 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002853 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002854
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002855 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002856
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002857 if (top->lineno < fileptr->lineno || top_x < startpos)
2858 top_x = startpos;
2859 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2860 bot_x = endpos;
2861
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002862 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002863 if (top_x < endpos && bot_x > startpos) {
2864 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002865
2866 /* x_start is the expanded location of the beginning of the
2867 * mark minus the beginning of the page. */
2868 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002869
2870 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002871 /* If the end of the mark is off the page, paintlen is
2872 * -1, meaning that everything on the line gets
2873 * painted. */
2874 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002875 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002876 /* Otherwise, paintlen is the expanded location of the
2877 * end of the mark minus the expanded location of the
2878 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002879 paintlen = strnlenpt(fileptr->data, bot_x)
2880 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002881
2882 /* If x_start is before the beginning of the page, shift
2883 * paintlen x_start characters to compensate, and put
2884 * x_start at the beginning of the page. */
2885 if (x_start < 0) {
2886 paintlen += x_start;
2887 x_start = 0;
2888 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002889
2890 assert(x_start >= 0 && x_start <= strlen(converted));
2891
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002892 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002893 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002894 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002895 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002896 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002897#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002898}
2899
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002900/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002901 * edit_add().
2902 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002903 * If fileptr != current, then index is considered 0. The line will be
2904 * displayed starting with fileptr->data[index]. Likely args are
2905 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002906void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002907{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002908 int line;
2909 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002910 char *converted;
2911 /* fileptr->data converted to have tabs and control characters
2912 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002913 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002914
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002915 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002916
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002917 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002918
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002919 /* We assume the line numbers are valid. Is that really true? */
2920 assert(line < 0 || line == check_linenumbers(fileptr));
2921
2922 if (line < 0 || line >= editwinrows)
2923 return;
2924
2925 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002926 mvwaddstr(edit, line, 0, hblank);
2927
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002928 /* Next, convert variables that index the line to their equivalent
2929 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002930 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002931 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002932
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002933 /* Expand the line, replacing Tab by spaces, and control characters
2934 * by their display form. */
2935 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002936
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002937 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002938 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002939 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002940
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002941 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002942 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002943 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002944 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002945}
2946
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002947/* Return a nonzero value if we need an update after moving
2948 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002949 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002950int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002951{
2952 return
2953#ifndef NANO_SMALL
2954 ISSET(MARK_ISSET) ||
2955#endif
2956 get_page_start(old_pww) != get_page_start(placewewant);
2957}
2958
2959/* Return a nonzero value if we need an update after moving vertically.
2960 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002961 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002962int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002963{
2964 return
2965#ifndef NANO_SMALL
2966 ISSET(MARK_ISSET) ||
2967#endif
2968 get_page_start(old_pww) != get_page_start(placewewant);
2969}
2970
2971/* Scroll the edit window in the given direction and the given number
2972 * of lines, and draw new lines on the blank lines left after the
2973 * scrolling. direction is the direction to scroll, either UP or DOWN,
2974 * and nlines is the number of lines to scroll. Don't redraw the old
2975 * topmost or bottommost line (where we assume current is) before
2976 * scrolling or draw the new topmost or bottommost line after scrolling
2977 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002978 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002979void edit_scroll(updown direction, int nlines)
2980{
2981 filestruct *foo;
2982 int i, scroll_rows = 0;
2983
2984 /* Scrolling less than one line or more than editwinrows lines is
2985 * redundant, so don't allow it. */
2986 if (nlines < 1 || nlines > editwinrows)
2987 return;
2988
2989 /* Move the top line of the edit window up or down (depending on the
2990 * value of direction) nlines lines. If there are fewer lines of
2991 * text than that left, move it to the top or bottom line of the
2992 * file (depending on the value of direction). Keep track of
2993 * how many lines we moved in scroll_rows. */
2994 for (i = nlines; i > 0; i--) {
2995 if (direction == UP) {
2996 if (edittop->prev == NULL)
2997 break;
2998 edittop = edittop->prev;
2999 scroll_rows--;
3000 } else {
3001 if (edittop->next == NULL)
3002 break;
3003 edittop = edittop->next;
3004 scroll_rows++;
3005 }
3006 }
3007
3008 /* Scroll the text on the screen up or down scroll_rows lines,
3009 * depending on the value of direction. */
3010 scrollok(edit, TRUE);
3011 wscrl(edit, scroll_rows);
3012 scrollok(edit, FALSE);
3013
3014 foo = edittop;
3015 if (direction != UP) {
3016 int slines = editwinrows - nlines;
3017 for (; slines > 0 && foo != NULL; slines--)
3018 foo = foo->next;
3019 }
3020
3021 /* And draw new lines on the blank top or bottom lines of the edit
3022 * window, depending on the value of direction. Don't draw the new
3023 * topmost or new bottommost line. */
3024 while (scroll_rows != 0 && foo != NULL) {
3025 if (foo->next != NULL)
3026 update_line(foo, 0);
3027 if (direction == UP)
3028 scroll_rows++;
3029 else
3030 scroll_rows--;
3031 foo = foo->next;
3032 }
3033}
3034
3035/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003036 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003037void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003038{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003039 int do_refresh = need_vertical_update(0) ||
3040 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003041 const filestruct *foo;
3042
3043 /* If either old_current or current is offscreen, refresh the screen
3044 * and get out. */
3045 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3046 edittop->lineno + editwinrows || current->lineno <
3047 edittop->lineno || current->lineno >= edittop->lineno +
3048 editwinrows) {
3049 edit_refresh();
3050 return;
3051 }
3052
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003053 /* Update old_current and current if we're not on the first page
3054 * and/or we're not on the same page as before. If the mark is on,
3055 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003056 foo = old_current;
3057 while (foo != current) {
3058 if (do_refresh)
3059 update_line(foo, 0);
3060#ifndef NANO_SMALL
3061 if (!ISSET(MARK_ISSET))
3062#endif
3063 break;
3064 if (foo->lineno > current->lineno)
3065 foo = foo->prev;
3066 else
3067 foo = foo->next;
3068 }
3069 if (do_refresh)
3070 update_line(current, current_x);
3071}
3072
Chris Allegretta6df90f52002-07-19 01:08:59 +00003073/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003074void edit_refresh(void)
3075{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003076 if (current->lineno < edittop->lineno ||
3077 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003078 /* Note that edit_update() changes edittop so that it's in range
3079 * of current. Thus, when it then calls edit_refresh(), there
3080 * is no danger of getting an infinite loop. */
3081 edit_update(
3082#ifndef NANO_SMALL
3083 ISSET(SMOOTHSCROLL) ? NONE :
3084#endif
3085 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003086 else {
3087 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003088 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003089
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003090#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003091 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003092#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003093
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003094 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003095 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003096 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003097 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003098 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003099 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003100 }
3101 while (nlines < editwinrows) {
3102 mvwaddstr(edit, nlines, 0, hblank);
3103 nlines++;
3104 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003105 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003106 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003107 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003108}
3109
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003110/* A nice generic routine to update the edit buffer. We keep current in
3111 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003112void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003113{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003114 filestruct *foo = current;
3115
Chris Allegretta6df90f52002-07-19 01:08:59 +00003116 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003117 /* If location is CENTER, we move edittop up (editwinrows / 2)
3118 * lines. This puts current at the center of the screen. If
3119 * location is NONE, we move edittop up current_y lines if
3120 * current_y is in range of the screen, 0 lines if current_y is
3121 * less than 0, or (editwinrows - 1) lines if current_y is
3122 * greater than (editwinrows - 1). This puts current at the
3123 * same place on the screen as before, or at the top or bottom
3124 * of the screen if edittop is beyond either. */
3125 int goal;
3126
3127 if (location == CENTER)
3128 goal = editwinrows / 2;
3129 else {
3130 goal = current_y;
3131
3132 /* Limit goal to (editwinrows - 1) lines maximum. */
3133 if (goal > editwinrows - 1)
3134 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003135 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003136
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003137 for (; goal > 0 && foo->prev != NULL; goal--)
3138 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003139 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003140
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003141 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003142 edit_refresh();
3143}
3144
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003145/* Ask a simple yes/no question, specified in msg, on the statusbar.
3146 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3147 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003148int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003149{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003150 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003151 const char *yesstr; /* String of yes characters accepted. */
3152 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003153 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003154
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003155 /* yesstr, nostr, and allstr are strings of any length. Each string
3156 * consists of all characters accepted as a valid character for that
3157 * value. The first value will be the one displayed in the
3158 * shortcuts. Translators: if possible, specify both the shortcuts
3159 * for your language and English. For example, in French: "OoYy"
3160 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003161 yesstr = _("Yy");
3162 nostr = _("Nn");
3163 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003164
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003165 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003166 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003167
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003168 if (COLS < 32)
3169 width = COLS / 2;
3170
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003171 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003172 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003173
Chris Allegretta6232d662002-05-12 19:52:15 +00003174 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003175 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003176 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003177
3178 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003179 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003180 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003181 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003182 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003183
Chris Allegrettadb28e962003-01-28 01:23:40 +00003184 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003185 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003186 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003187
Chris Allegrettadb28e962003-01-28 01:23:40 +00003188 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003189 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003190 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003191
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003192 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003193
3194 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003195 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003196
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003197 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003198
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003199 wrefresh(bottomwin);
3200
Chris Allegrettadb28e962003-01-28 01:23:40 +00003201 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003202 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003203 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003204#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003205 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003206#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003207
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003208 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003209
3210 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003211 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003212#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003213 /* Look, ma! We get to duplicate lots of code from
3214 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003215 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003216 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003217
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003218 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003219 wenclose(bottomwin, mouse_y, mouse_x) &&
3220 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003221 int x = mouse_x / width;
3222 /* Did we click in the first column of shortcuts, or
3223 * the second? */
3224 int y = mouse_y - editwinrows - 3;
3225 /* Did we click in the first row of shortcuts? */
3226
3227 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3228
3229 /* x = 0 means they clicked Yes or No.
3230 * y = 0 means Yes or All. */
3231 ok = -2 * x * y + x - y + 1;
3232
3233 if (ok == 2 && !all)
3234 ok = -2;
3235 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003236 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003237#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003238 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003239 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003240 else if (strchr(yesstr, kbinput) != NULL)
3241 ok = 1;
3242 else if (strchr(nostr, kbinput) != NULL)
3243 ok = 0;
3244 else if (all && strchr(allstr, kbinput) != NULL)
3245 ok = 2;
3246 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003247
Chris Allegrettadb28e962003-01-28 01:23:40 +00003248 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003249}
3250
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003251void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003252{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003253 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003254 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003255 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003256 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003257 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003258 wnoutrefresh(bottomwin);
3259 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003260 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003261 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003262 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003263 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003264 edit_refresh();
3265 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003266}
3267
3268void display_main_list(void)
3269{
3270 bottombars(main_list);
3271}
3272
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003273/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3274 * display the cursor position. Otherwise, we display it only if the
3275 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003276 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003277 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3278 * old_i and old_totsize. That way, we leave the current statusbar
3279 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003280void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003281{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003282 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003283 size_t i = 0;
3284 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003285 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003286
Chris Allegrettad26ab912003-01-28 01:16:47 +00003287 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003288
3289 if (old_totsize == -1)
3290 old_totsize = totsize;
3291
Chris Allegrettad26ab912003-01-28 01:16:47 +00003292 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3293 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003294 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003295 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003296 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003297
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003298 /* Check whether totsize is correct. Else there is a bug
3299 * somewhere. */
3300 assert(current != filebot || i == totsize);
3301
Chris Allegrettad26ab912003-01-28 01:16:47 +00003302 if (constant && ISSET(DISABLE_CURPOS)) {
3303 UNSET(DISABLE_CURPOS);
3304 old_i = i;
3305 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003306 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003307 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003308
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003309 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003310 * unconditionally; otherwise, only display the position when the
3311 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003312 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003313 size_t xpt = xplustabs() + 1;
3314 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003315 int linepct = 100 * current->lineno / totlines;
3316 int colpct = 100 * xpt / cur_len;
3317 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3318
3319 statusbar(
3320 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3321 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003322 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003323 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003324 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003325 }
3326
3327 old_i = i;
3328 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003329}
3330
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003331void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003332{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003333 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003334}
3335
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003336#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003337/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003338int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003339{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003340 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003341
3342 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3343 ptr++;
3344 j++;
3345 }
3346 if (j == COLS - 5) {
3347 /* Don't wrap at the first of two spaces following a period. */
3348 if (*ptr == ' ' && *(ptr + 1) == ' ')
3349 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003350 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003351 while (*ptr != ' ' && j > 0) {
3352 ptr--;
3353 j--;
3354 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003355 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003356 if (j == 0)
3357 j = COLS - 5;
3358 }
3359 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3360 return j;
3361}
3362
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003363/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003364void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003365{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003366 int line = 0;
3367 /* The line number in help_text of the first displayed help line.
3368 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003369 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003370 /* no_more means the end of the help text is shown, so don't go
3371 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003372 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003373 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003374
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003375 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003376#ifndef DISABLE_MOUSE
3377 const shortcut *oldshortcut = currshortcut;
3378 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003379 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003380#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003381
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003382 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003383 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003384 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003385 blank_statusbar();
3386
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003387 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003388 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003389 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003390
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003391#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003392 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003393 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003394 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003395#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003396
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003397 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003398 /* Make sure that the help screen's shortcut list will actually
3399 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003400 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003401 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003402 }
3403 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003404
3405 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003406 int i;
3407 int old_line = line;
3408 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003409 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003410
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003411 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003412#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003413 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003414 {
3415 int mouse_x, mouse_y;
3416 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3417 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003418 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003419#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003420 case NANO_NEXTPAGE_KEY:
3421 case NANO_NEXTPAGE_FKEY:
3422 if (!no_more)
3423 line += editwinrows - 2;
3424 break;
3425 case NANO_PREVPAGE_KEY:
3426 case NANO_PREVPAGE_FKEY:
3427 if (line > 0) {
3428 line -= editwinrows - 2;
3429 if (line < 0)
3430 line = 0;
3431 }
3432 break;
3433 case NANO_PREVLINE_KEY:
3434 if (line > 0)
3435 line--;
3436 break;
3437 case NANO_NEXTLINE_KEY:
3438 if (!no_more)
3439 line++;
3440 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003441 }
3442
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003443 if (line == old_line && kbinput != ERR)
3444 goto skip_redisplay;
3445
3446 blank_edit();
3447
3448 assert(COLS > 5);
3449
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003450 /* Calculate where in the text we should be, based on the
3451 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003452 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003453 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003454 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003455 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003456 }
3457
Chris Allegretta4640fe32003-02-10 03:10:03 +00003458 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003459 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003460
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003461 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003462 ptr += j;
3463 if (*ptr == '\n')
3464 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003465 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003466 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003467
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003468 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003469 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003470 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3471 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003472
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003473#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003474 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003475#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003476
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003477 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003478 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003479 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003480 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003481 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003482 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003483 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003484
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003485 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003486 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003487
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003488 /* The help_init() at the beginning allocated help_text. Since
3489 * help_text has now been written to the screen, we don't need it
3490 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003491 free(help_text);
3492 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003493}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003494#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003495
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003496/* Highlight the current word being replaced or spell checked. We
3497 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003498void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003499{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003500 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003501 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003502
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003503 y = get_page_start(y) + COLS - y;
3504 /* Now y is the number of characters we can display on this
3505 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003506
3507 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003508
Chris Allegrettafb62f732000-12-05 11:36:41 +00003509 if (highlight_flag)
3510 wattron(edit, A_REVERSE);
3511
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003512#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003513 /* This is so we can show zero-length regexes. */
3514 if (word_len == 0)
3515 waddstr(edit, " ");
3516 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003517#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003518 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003519
3520 if (word_len > y)
3521 waddch(edit, '$');
3522 else if (word_len == y)
3523 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003524
3525 if (highlight_flag)
3526 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003527}
3528
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003529#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003530/* Dump the passed-in file structure to stderr. */
3531void dump_buffer(const filestruct *inptr)
3532{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003533 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003534 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003535 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003536 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003537 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003538 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003539
3540 while (inptr != NULL) {
3541 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3542 inptr = inptr->next;
3543 }
3544}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003545
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003546/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003547void dump_buffer_reverse(void)
3548{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003549 const filestruct *fileptr = filebot;
3550
3551 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003552 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003553 fileptr = fileptr->prev;
3554 }
3555}
3556#endif /* DEBUG */
3557
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003558#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003559#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003560#define XLCREDIT_LEN 8
3561
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003562/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003563void do_credits(void)
3564{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003565 int crpos = 0, xlpos = 0;
3566 const char *credits[CREDIT_LEN] = {
3567 NULL, /* "The nano text editor" */
3568 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003569 VERSION,
3570 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003571 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003572 "Chris Allegretta",
3573 "Jordi Mallach",
3574 "Adam Rogoyski",
3575 "Rob Siemborski",
3576 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003577 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003578 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003579 "Ken Tyler",
3580 "Sven Guckes",
3581 "Florian König",
3582 "Pauli Virtanen",
3583 "Daniele Medri",
3584 "Clement Laforet",
3585 "Tedi Heriyanto",
3586 "Bill Soudan",
3587 "Christian Weisgerber",
3588 "Erik Andersen",
3589 "Big Gaute",
3590 "Joshua Jensen",
3591 "Ryan Krebs",
3592 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003593 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003594 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003595 "Plattsburgh State University",
3596 "Benet Laboratories",
3597 "Amy Allegretta",
3598 "Linda Young",
3599 "Jeremy Robichaud",
3600 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003601 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003602 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003603 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003604 "Thomas Dickey",
3605 "Pavel Curtis",
3606 "Zeyd Ben-Halim",
3607 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003608 NULL, /* "and anyone else we forgot..." */
3609 NULL, /* "Thank you for using nano!" */
3610 "",
3611 "",
3612 "",
3613 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003614 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003615 "",
3616 "",
3617 "",
3618 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003619 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003620 };
3621
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003622 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003623 N_("The nano text editor"),
3624 N_("version"),
3625 N_("Brought to you by:"),
3626 N_("Special thanks to:"),
3627 N_("The Free Software Foundation"),
3628 N_("For ncurses:"),
3629 N_("and anyone else we forgot..."),
3630 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003631 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003632
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003633 curs_set(0);
3634 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003635 scrollok(edit, TRUE);
3636 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003637 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003638 blank_statusbar();
3639 blank_bottombars();
3640 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003641 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003642 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003643
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003644 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3645 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003646 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003647 if (crpos < CREDIT_LEN) {
3648 const char *what = credits[crpos];
3649 size_t start_x;
3650
3651 if (what == NULL) {
3652 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003653 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003654 xlpos++;
3655 }
3656 start_x = COLS / 2 - strlen(what) / 2 - 1;
David Lawrence Ramseyeb711b02004-12-05 22:24:39 +00003657 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x,
3658 what);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003659 }
3660 napms(700);
3661 scroll(edit);
3662 wrefresh(edit);
3663 if (wgetch(edit) != ERR)
3664 break;
3665 napms(700);
3666 scroll(edit);
3667 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003668 }
3669
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003670 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003671 nodelay(edit, FALSE);
3672 curs_set(1);
3673 display_main_list();
3674 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003675}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003676#endif