blob: 5ff803f02c1c56785f47c3513eae786b4dfa55c9 [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#ifdef NANO_WIDE
116 /* Reset the multibyte and wide character interpreter states. */
117 if (!ISSET(NO_UTF8)) {
118 mbtowc(NULL, NULL, 0);
119 wctomb(NULL, 0);
120 }
121#endif
122 parse_kbinput(NULL, NULL, NULL, TRUE);
123 get_word_kbinput(0, TRUE);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000124}
125#endif
126
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000127/* Read in a sequence of keystrokes from win and save them in the
128 * default keystroke buffer. This should only be called when the
129 * default keystroke buffer is empty. */
130void get_buffer(WINDOW *win)
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000131{
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000132 int input;
133 size_t i = 0;
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +0000134
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000135#ifdef NANO_WIDE
136 size_t wide_key_buffer_len = 0;
137 buffer *wide_key_buffer = NULL;
138#endif
139
140 /* If the keystroke buffer isn't empty, get out. */
141 if (key_buffer != NULL)
142 return;
143
144 /* Read in the first character using blocking input. */
145 nodelay(win, FALSE);
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000146
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000147#ifndef NANO_SMALL
148 allow_pending_sigwinch(TRUE);
149#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000150 input = wgetch(win);
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000151#ifndef NANO_SMALL
152 allow_pending_sigwinch(FALSE);
153#endif
154
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000155 /* Increment the length of the keystroke buffer, save the value of
156 * the keystroke in key, and set key_code to TRUE if the keystroke
157 * is an extended keypad value and hence shouldn't be treated as a
158 * multibyte character. */
159 key_buffer_len++;
160 key_buffer = (buffer *)nmalloc(sizeof(buffer));
161 key_buffer[0].key = input;
162 key_buffer[0].key_code = !is_byte_char(input);
163
164 /* Read in the remaining characters using non-blocking input. */
165 nodelay(win, TRUE);
166
167 while (TRUE) {
168#ifndef NANO_SMALL
169 allow_pending_sigwinch(TRUE);
170#endif
171 input = wgetch(win);
172#ifndef NANO_SMALL
173 allow_pending_sigwinch(FALSE);
174#endif
175
176 /* If there aren't any more characters, stop reading. */
177 if (input == ERR)
178 break;
179
180 /* Otherwise, increment the length of the keystroke buffer, save
181 * the value of the keystroke in key, and set key_code to TRUE
182 * if the keystroke is an extended keypad value and hence
183 * shouldn't be treated as a multibyte character. */
184 key_buffer_len++;
185 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
186 sizeof(buffer));
187 key_buffer[key_buffer_len - 1].key = input;
188 key_buffer[key_buffer_len - 1].key_code = !is_byte_char(input);
189 }
190
191 /* Switch back to non-blocking input. */
192 nodelay(win, FALSE);
193
194#ifdef NANO_WIDE
195 if (!ISSET(NO_UTF8)) {
196 /* Change all incomplete or invalid multibyte keystrokes to -1,
197 * and change all complete and valid multibyte keystrokes to
198 * their wide character value. */
199 for (i = 0; i < key_buffer_len; i++) {
200 wchar_t wide_key;
201
202 if (!key_buffer[i].key_code) {
203 key_buffer[i].key = mbtowc(&wide_key,
204 (const char *)&key_buffer[i].key, 1);
205 if (key_buffer[i].key != -1)
206 key_buffer[i].key = wide_key;
207 }
208 }
209
210 /* Save all of the non-(-1) keystrokes in another buffer. */
211 for (i = 0; i < key_buffer_len; i++) {
212 if (key_buffer[i].key != -1) {
213 wide_key_buffer_len++;
214 wide_key_buffer = (buffer *)nrealloc(wide_key_buffer,
215 wide_key_buffer_len * sizeof(buffer));
216
217 wide_key_buffer[wide_key_buffer_len - 1].key =
218 key_buffer[i].key;
219 wide_key_buffer[wide_key_buffer_len - 1].key_code =
220 key_buffer[i].key_code;
221 }
222 }
223
224 /* Replace the default keystroke buffer with the non-(-1)
225 * keystroke buffer. */
226 key_buffer_len = wide_key_buffer_len;
227 free(key_buffer);
228 key_buffer = wide_key_buffer;
229 }
230#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000231}
232
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000233/* Return the length of the default keystroke buffer. */
234size_t get_buffer_len(void)
235{
236 return key_buffer_len;
237}
238
239/* Return the key values stored in the keystroke buffer input,
240 * discarding the key_code values in it. */
241int *buffer_to_keys(buffer *input, size_t input_len)
242{
243 int *sequence = (int *)nmalloc(input_len * sizeof(int));
244 size_t i;
245
246 for (i = 0; i < input_len; i++)
247 sequence[i] = input[i].key;
248
249 return sequence;
250}
251
252/* Add the contents of the keystroke buffer input to the default
253 * keystroke buffer. */
254void unget_input(buffer *input, size_t input_len)
255{
256#ifndef NANO_SMALL
257 allow_pending_sigwinch(TRUE);
258 allow_pending_sigwinch(FALSE);
259#endif
260
261 /* If input is empty, get out. */
262 if (input_len == 0)
263 return;
264
265 /* If adding input would put the default keystroke buffer beyond
266 * maximum capacity, only add enough of input to put it at maximum
267 * capacity. */
268 if (key_buffer_len + input_len < key_buffer_len)
269 input_len = (size_t)-1 - key_buffer_len;
270
271 /* Add the length of input to the length of the default keystroke
272 * buffer, and reallocate the default keystroke buffer so that it
273 * has enough room for input. */
274 key_buffer_len += input_len;
275 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
276 sizeof(buffer));
277
278 /* If the default keystroke buffer wasn't empty before, move its
279 * beginning forward far enough so that we can add input to its
280 * beginning. */
281 if (key_buffer_len > input_len)
282 memmove(key_buffer + input_len, key_buffer,
283 (key_buffer_len - input_len) * sizeof(buffer));
284
285 /* Copy input to the beginning of the default keystroke buffer. */
286 memcpy(key_buffer, input, input_len * sizeof(buffer));
287}
288
289/* Put back the character stored in kbinput. If func_key is TRUE and
290 * the character is out of byte range, interpret it as an extended
291 * keypad value. If meta_key is TRUE, put back the Escape character
292 * after putting back kbinput. */
293void unget_kbinput(int kbinput, bool meta_key, bool func_key)
294{
295 buffer input;
296
297 input.key = kbinput;
298 input.key_code = (func_key && !is_byte_char(kbinput));
299
300 unget_input(&input, 1);
301
302 if (meta_key) {
303 input.key = NANO_CONTROL_3;
304 input.key_code = FALSE;
305 unget_input(&input, 1);
306 }
307}
308
309/* Try to read input_len characters from the default keystroke buffer.
310 * If the default keystroke buffer is empty and win isn't NULL, try to
311 * read in more characters from win and add them to the default
312 * keystroke buffer before doing anything else. If the default
313 * keystroke buffer is empty and win is NULL, return NULL. */
314buffer *get_input(WINDOW *win, size_t input_len)
315{
316 buffer *input;
317
318#ifndef NANO_SMALL
319 allow_pending_sigwinch(TRUE);
320 allow_pending_sigwinch(FALSE);
321#endif
322
323 if (key_buffer_len == 0) {
324 if (win != NULL)
325 get_buffer(win);
326
327 if (key_buffer_len == 0)
328 return NULL;
329 }
330
331 /* If input_len is greater than the length of the default keystroke
332 * buffer, only read the number of characters in the default
333 * keystroke buffer. */
334 if (input_len > key_buffer_len)
335 input_len = key_buffer_len;
336
337 /* Subtract input_len from the length of the default keystroke
338 * buffer, and allocate the keystroke buffer input so that it
339 * has enough room for input_len keystrokes. */
340 key_buffer_len -= input_len;
341 input = (buffer *)nmalloc(input_len * sizeof(buffer));
342
343 /* Copy input_len characters from the beginning of the default
344 * keystroke buffer into input. */
345 memcpy(input, key_buffer, input_len * sizeof(buffer));
346
347 /* If the default keystroke buffer is empty, mark it as such. */
348 if (key_buffer_len == 0) {
349 free(key_buffer);
350 key_buffer = NULL;
351 /* If the default keystroke buffer isn't empty, move its
352 * beginning forward far enough back so that the keystrokes in input
353 * are no longer at its beginning. */
354 } else {
355 memmove(key_buffer, key_buffer + input_len, key_buffer_len *
356 sizeof(buffer));
357 key_buffer = (buffer *)nrealloc(key_buffer, key_buffer_len *
358 sizeof(buffer));
359 }
360
361 return input;
362}
363
364/* Read in a single character. If it's ignored, swallow it and go on.
365 * Otherwise, try to translate it from ASCII, meta key sequences, escape
366 * sequences, and/or extended keypad values. Set meta_key to TRUE when
367 * we get a meta key sequence, and set func_key to TRUE when we get an
368 * extended keypad value. Supported extended keypad values consist of
369 * [arrow key], Ctrl-[arrow key], Shift-[arrow key], Enter, Backspace,
370 * the editing keypad (Insert, Delete, Home, End, PageUp, and PageDown),
371 * the function keypad (F1-F16), and the numeric keypad with NumLock
372 * off. Assume nodelay(win) is FALSE. */
373int get_kbinput(WINDOW *win, bool *meta_key, bool *func_key)
374{
375 int kbinput;
376
377 /* Read in a character and interpret it. Continue doing this until
378 * we get a recognized value or sequence. */
379 while ((kbinput = parse_kbinput(win, meta_key, func_key
380#ifndef NANO_SMALL
381 , FALSE
382#endif
383 )) == ERR);
384
385 return kbinput;
386}
387
388/* Translate ASCII characters, extended keypad values, and escape
389 * sequences into their corresponding key values. Set meta_key to TRUE
390 * when we get a meta key sequence, and set func_key to TRUE when we get
391 * a function key. Assume nodelay(win) is FALSE. */
392int parse_kbinput(WINDOW *win, bool *meta_key, bool *func_key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000393#ifndef NANO_SMALL
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +0000394 , bool reset
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000395#endif
396 )
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000397
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000398{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +0000399 static int escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000400 static int word_digits = 0;
401 buffer *kbinput;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000402 int retval = ERR;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000403 bool no_func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000404
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000405 if (reset) {
406 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000407 word_digits = 0;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000408 return ERR;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000409 }
David Lawrence Ramsey369732f2004-02-16 20:32:40 +0000410
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000411 *meta_key = FALSE;
412 *func_key = FALSE;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000413
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000414 /* Read in a character. */
415 while ((kbinput = get_input(win, 1)) == NULL);
416
417 /* If we got an extended keypad value or an ASCII character,
418 * translate it. */
419 if (kbinput->key_code || is_byte_char(kbinput->key)) {
420 switch (kbinput->key) {
421 case ERR:
422 break;
423 case NANO_CONTROL_3:
424 /* Increment the escape counter. */
425 escapes++;
426 switch (escapes) {
427 case 1:
428 /* One escape: wait for more input. */
429 case 2:
430 /* Two escapes: wait for more input. */
431 break;
432 default:
433 /* More than two escapes: reset the escape
434 * counter and wait for more input. */
435 escapes = 0;
436 }
437 break;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000438#if !defined(NANO_SMALL) && defined(KEY_RESIZE)
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000439 /* Since we don't change the default SIGWINCH handler when
440 * NANO_SMALL is defined, KEY_RESIZE is never generated.
441 * Also, Slang and SunOS 5.7-5.9 don't support
442 * KEY_RESIZE. */
443 case KEY_RESIZE:
444 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000445#endif
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000446#ifdef PDCURSES
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000447 case KEY_SHIFT_L:
448 case KEY_SHIFT_R:
449 case KEY_CONTROL_L:
450 case KEY_CONTROL_R:
451 case KEY_ALT_L:
452 case KEY_ALT_R:
453 break;
David Lawrence Ramseyd8974452004-06-04 22:28:55 +0000454#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000455 default:
456 switch (escapes) {
457 case 0:
458 switch (kbinput->key) {
459 case NANO_CONTROL_8:
460 retval = ISSET(REBIND_DELETE) ?
461 NANO_DELETE_KEY :
462 NANO_BACKSPACE_KEY;
463 break;
464 case KEY_DOWN:
465 retval = NANO_NEXTLINE_KEY;
466 break;
467 case KEY_UP:
468 retval = NANO_PREVLINE_KEY;
469 break;
470 case KEY_LEFT:
471 retval = NANO_BACK_KEY;
472 break;
473 case KEY_RIGHT:
474 retval = NANO_FORWARD_KEY;
475 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000476#ifdef KEY_HOME
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000477 /* HP-UX 10 and 11 don't support
478 * KEY_HOME. */
479 case KEY_HOME:
480 retval = NANO_HOME_KEY;
481 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000482#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000483 case KEY_BACKSPACE:
484 retval = NANO_BACKSPACE_KEY;
485 break;
486 case KEY_DC:
487 retval = ISSET(REBIND_DELETE) ?
488 NANO_BACKSPACE_KEY :
489 NANO_DELETE_KEY;
490 break;
491 case KEY_IC:
492 retval = NANO_INSERTFILE_KEY;
493 break;
494 case KEY_NPAGE:
495 retval = NANO_NEXTPAGE_KEY;
496 break;
497 case KEY_PPAGE:
498 retval = NANO_PREVPAGE_KEY;
499 break;
500 case KEY_ENTER:
501 retval = NANO_ENTER_KEY;
502 break;
503 case KEY_A1: /* Home (7) on numeric
504 * keypad with NumLock
505 * off. */
506 retval = NANO_HOME_KEY;
507 break;
508 case KEY_A3: /* PageUp (9) on numeric
509 * keypad with NumLock
510 * off. */
511 retval = NANO_PREVPAGE_KEY;
512 break;
513 case KEY_B2: /* Center (5) on numeric
514 * keypad with NumLock
515 * off. */
516 break;
517 case KEY_C1: /* End (1) on numeric
518 * keypad with NumLock
519 * off. */
520 retval = NANO_END_KEY;
521 break;
522 case KEY_C3: /* PageDown (4) on
523 * numeric keypad with
524 * NumLock off. */
525 retval = NANO_NEXTPAGE_KEY;
526 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000527#ifdef KEY_BEG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000528 /* Slang doesn't support KEY_BEG. */
529 case KEY_BEG: /* Center (5) on numeric
530 * keypad with NumLock
531 * off. */
532 break;
David Lawrence Ramsey16eb5182004-06-03 20:26:12 +0000533#endif
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000534#ifdef KEY_END
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000535 /* HP-UX 10 and 11 don't support KEY_END. */
536 case KEY_END:
537 retval = NANO_END_KEY;
538 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000539#endif
540#ifdef KEY_SUSPEND
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000541 /* Slang doesn't support KEY_SUSPEND. */
542 case KEY_SUSPEND:
543 retval = NANO_SUSPEND_KEY;
544 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000545#endif
546#ifdef KEY_SLEFT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000547 /* Slang doesn't support KEY_SLEFT. */
548 case KEY_SLEFT:
549 retval = NANO_BACK_KEY;
550 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000551#endif
552#ifdef KEY_SRIGHT
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000553 /* Slang doesn't support KEY_SRIGHT. */
554 case KEY_SRIGHT:
555 retval = NANO_FORWARD_KEY;
556 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000557#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000558 default:
559 retval = kbinput->key;
560 break;
561 }
562 break;
563 case 1:
564 /* One escape followed by a non-escape: escape
565 * sequence mode. Reset the escape counter. If
566 * there aren't any other keys waiting, we have
567 * a meta key sequence, so set meta_key to TRUE
568 * and save the lowercase version of the
569 * non-escape character as the result. If there
570 * are other keys waiting, we have a true escape
571 * sequence, so interpret it. */
572 escapes = 0;
573 if (get_buffer_len() == 0) {
574 *meta_key = TRUE;
575 retval = tolower(kbinput->key);
576 } else {
577 buffer *escape_kbinput;
578 int *sequence;
579 size_t seq_len;
580 bool ignore_seq;
581
582 /* Put back the non-escape character, get
583 * the complete escape sequence, translate
584 * its key values into the corresponding key
585 * value, and save that as the result. */
586 unget_input(kbinput, 1);
587 seq_len = get_buffer_len();
588 escape_kbinput = get_input(NULL, seq_len);
589 sequence = buffer_to_keys(escape_kbinput,
590 seq_len);
591 retval = get_escape_seq_kbinput(sequence,
592 seq_len, &ignore_seq);
593
594 /* If the escape sequence is unrecognized
595 * and not ignored, put back all of its
596 * characters except for the initial
597 * escape. */
598 if (retval == ERR && !ignore_seq)
599 unget_input(escape_kbinput, seq_len);
600
601 free(escape_kbinput);
602 }
603 break;
604 case 2:
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000605 /* Two escapes followed by one or more decimal
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000606 * digits: word sequence mode. If the word
607 * sequence's range is limited to 6XXXX (the
608 * first digit is in the '0' to '6' range and
609 * it's the first digit, or it's in the '0' to
610 * '9' range and it's not the first digit),
611 * increment the word sequence counter,
612 * interpret the digit, and save the
613 * corresponding word value as the result. If
614 * the word sequence's range is not limited to
615 * 6XXXX, fall through. */
616 if (('0' <= kbinput->key && kbinput->key <= '6'
617 && word_digits == 0) ||
618 ('0' <= kbinput->key && kbinput->key <= '9'
619 && word_digits > 0)) {
620 word_digits++;
621 retval = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000622#ifndef NANO_SMALL
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000623 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000624#endif
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000625 );
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000626
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000627 if (retval != ERR) {
628 /* If we've read in a complete word
629 * sequence, reset the word sequence
630 * counter and the escape counter, and
631 * mark it so that it isn't interpreted
632 * as an extended keypad value. */
633 word_digits = 0;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000634 escapes = 0;
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000635 no_func_key = TRUE;
636 }
637 } else {
638 /* Reset the escape counter. */
639 escapes = 0;
640 if (word_digits == 0)
641 /* Two escapes followed by a non-decimal
642 * digit or a decimal digit that would
643 * create a word sequence greater than
644 * 6XXXX, and we're not in the middle of
645 * a word sequence: control character
646 * sequence mode. Interpret the control
647 * sequence and save the corresponding
648 * control character as the result. */
649 retval = get_control_kbinput(kbinput->key);
650 else {
651 /* If we're in the middle of a word
652 * sequence, reset the word sequence
653 * counter and save the character we got
654 * as the result. */
655 word_digits = 0;
656 retval = kbinput->key;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000657 }
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +0000658 }
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000659 break;
660 }
661 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000662 }
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +0000663
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000664 /* If we have a result and it's an extended keypad value, set
665 * func_key to TRUE. */
666 if (retval != ERR)
667 *func_key = !is_byte_char(retval);
668
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000669#ifdef DEBUG
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000670 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 +0000671#endif
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000672
673 /* Return the result. */
674 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000675}
676
David Lawrence Ramsey58f6d832004-01-27 07:12:47 +0000677/* Translate escape sequences, most of which correspond to extended
David Lawrence Ramsey832db762004-11-27 23:28:39 +0000678 * keypad values, into their corresponding key values. These sequences
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000679 * are generated when the keypad doesn't support the needed keys. If
680 * the escape sequence is recognized but we want to ignore it, return
681 * ERR and set ignore_seq to TRUE; if it's unrecognized, return ERR and
682 * set ignore_seq to FALSE. Assume that Escape has already been read
683 * in. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000684int get_escape_seq_kbinput(const int *sequence, size_t seq_len, bool
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000685 *ignore_seq)
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +0000686{
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000687 int retval = ERR;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000688
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000689 *ignore_seq = FALSE;
690
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000691 if (seq_len > 1) {
692 switch (sequence[0]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000693 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000694 switch (sequence[1]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000695 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000696 if (seq_len >= 3) {
697 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000698 case 'P': /* Esc O 2 P == F13 on
699 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000700 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000701 break;
702 case 'Q': /* Esc O 2 Q == F14 on
703 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000704 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000705 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000706 case 'R': /* Esc O 2 R == F15 on
707 * xterm. */
708 retval = KEY_F(15);
709 break;
710 case 'S': /* Esc O 2 S == F16 on
711 * xterm. */
712 retval = KEY_F(16);
713 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000714 }
715 }
716 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000717 case 'A': /* Esc O A == Up on VT100/VT320/xterm. */
718 case 'B': /* Esc O B == Down on
719 * VT100/VT320/xterm. */
720 case 'C': /* Esc O C == Right on
721 * VT100/VT320/xterm. */
722 case 'D': /* Esc O D == Left on
723 * VT100/VT320/xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000724 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000725 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000726 case 'E': /* Esc O E == Center (5) on numeric keypad
727 * with NumLock off on xterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000728 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000729 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000730 case 'F': /* Esc O F == End on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000731 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000732 break;
733 case 'H': /* Esc O H == Home on xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000734 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000735 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000736 case 'M': /* Esc O M == Enter on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000737 * NumLock off on VT100/VT220/VT320/xterm/
738 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000739 retval = NANO_ENTER_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000740 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000741 case 'P': /* Esc O P == F1 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000742 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000743 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000744 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000745 case 'Q': /* Esc O Q == F2 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000746 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000747 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000748 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000749 case 'R': /* Esc O R == F3 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000750 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000751 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000752 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000753 case 'S': /* Esc O S == F4 on VT100/VT220/VT320/Mach
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000754 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000755 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000756 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000757 case 'T': /* Esc O T == F5 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000758 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000759 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000760 case 'U': /* Esc O U == F6 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000761 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000762 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000763 case 'V': /* Esc O V == F7 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000764 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000765 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000766 case 'W': /* Esc O W == F8 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000767 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000768 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000769 case 'X': /* Esc O X == F9 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000770 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000771 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +0000772 case 'Y': /* Esc O Y == F10 on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000773 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000774 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000775 case 'a': /* Esc O a == Ctrl-Up on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000776 case 'b': /* Esc O b == Ctrl-Down on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000777 case 'c': /* Esc O c == Ctrl-Right on rxvt. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000778 case 'd': /* Esc O d == Ctrl-Left on rxvt. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000779 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000780 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000781 case 'j': /* Esc O j == '*' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000782 * NumLock off on VT100/VT220/VT320/xterm/
783 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000784 retval = '*';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000785 break;
786 case 'k': /* Esc O k == '+' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000787 * NumLock off on VT100/VT220/VT320/xterm/
788 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000789 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000790 break;
791 case 'l': /* Esc O l == ',' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000792 * NumLock off on VT100/VT220/VT320/xterm/
793 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000794 retval = '+';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000795 break;
796 case 'm': /* Esc O m == '-' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000797 * NumLock off on VT100/VT220/VT320/xterm/
798 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000799 retval = '-';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000800 break;
801 case 'n': /* Esc O n == Delete (.) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000802 * with NumLock off on VT100/VT220/VT320/
803 * xterm/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000804 retval = NANO_DELETE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000805 break;
806 case 'o': /* Esc O o == '/' on numeric keypad with
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000807 * NumLock off on VT100/VT220/VT320/xterm/
808 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000809 retval = '/';
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000810 break;
811 case 'p': /* Esc O p == Insert (0) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000812 * with NumLock off on VT100/VT220/VT320/
813 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000814 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000815 break;
816 case 'q': /* Esc O q == End (1) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000817 * with NumLock off on VT100/VT220/VT320/
818 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000819 retval = NANO_END_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000820 break;
821 case 'r': /* Esc O r == Down (2) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000822 * with NumLock off on VT100/VT220/VT320/
823 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000824 retval = NANO_NEXTLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000825 break;
826 case 's': /* Esc O s == PageDown (3) on numeric
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000827 * keypad with NumLock off on VT100/VT220/
828 * VT320/rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000829 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000830 break;
831 case 't': /* Esc O t == Left (4) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000832 * with NumLock off on VT100/VT220/VT320/
833 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000834 retval = NANO_BACK_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000835 break;
836 case 'u': /* Esc O u == Center (5) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000837 * with NumLock off on VT100/VT220/VT320/
838 * rxvt/Eterm. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +0000839 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000840 break;
841 case 'v': /* Esc O v == Right (6) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000842 * with NumLock off on VT100/VT220/VT320/
843 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000844 retval = NANO_FORWARD_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000845 break;
846 case 'w': /* Esc O w == Home (7) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000847 * with NumLock off on VT100/VT220/VT320/
848 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000849 retval = NANO_HOME_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000850 break;
851 case 'x': /* Esc O x == Up (8) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000852 * with NumLock off on VT100/VT220/VT320/
853 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000854 retval = NANO_PREVLINE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000855 break;
856 case 'y': /* Esc O y == PageUp (9) on numeric keypad
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000857 * with NumLock off on VT100/VT220/VT320/
858 * rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000859 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +0000860 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000861 }
862 break;
863 case 'o':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000864 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000865 case 'a': /* Esc o a == Ctrl-Up on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000866 case 'b': /* Esc o b == Ctrl-Down on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000867 case 'c': /* Esc o c == Ctrl-Right on Eterm. */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000868 case 'd': /* Esc o d == Ctrl-Left on Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000869 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000870 break;
871 }
872 break;
873 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000874 switch (sequence[1]) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000875 case '1':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000876 if (seq_len >= 3) {
877 switch (sequence[2]) {
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000878 case '1': /* Esc [ 1 1 ~ == F1 on rxvt/
879 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000880 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000881 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000882 case '2': /* Esc [ 1 2 ~ == F2 on rxvt/
883 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000884 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000885 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000886 case '3': /* Esc [ 1 3 ~ == F3 on rxvt/
887 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000888 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000889 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000890 case '4': /* Esc [ 1 4 ~ == F4 on rxvt/
891 * Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000892 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000893 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000894 case '5': /* Esc [ 1 5 ~ == F5 on xterm/
895 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000896 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000897 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000898 case '7': /* Esc [ 1 7 ~ == F6 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000899 * VT220/VT320/Linux console/
900 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000901 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000902 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000903 case '8': /* Esc [ 1 8 ~ == F7 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000904 * VT220/VT320/Linux console/
905 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000906 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000907 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000908 case '9': /* Esc [ 1 9 ~ == F8 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000909 * VT220/VT320/Linux console/
910 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000911 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000912 break;
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000913 case ';':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000914 if (seq_len >= 4) {
915 switch (sequence[3]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000916 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000917 if (seq_len >= 5) {
918 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000919 case 'A': /* Esc [ 1 ; 2 A == Shift-Up on
920 * xterm. */
921 case 'B': /* Esc [ 1 ; 2 B == Shift-Down on
922 * xterm. */
923 case 'C': /* Esc [ 1 ; 2 C == Shift-Right on
924 * xterm. */
925 case 'D': /* Esc [ 1 ; 2 D == Shift-Left on
926 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000927 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000928 break;
929 }
930 }
931 break;
932 case '5':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000933 if (seq_len >= 5) {
934 switch (sequence[4]) {
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000935 case 'A': /* Esc [ 1 ; 5 A == Ctrl-Up on
936 * xterm. */
937 case 'B': /* Esc [ 1 ; 5 B == Ctrl-Down on
938 * xterm. */
939 case 'C': /* Esc [ 1 ; 5 C == Ctrl-Right on
940 * xterm. */
941 case 'D': /* Esc [ 1 ; 5 D == Ctrl-Left on
942 * xterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000943 retval = get_escape_seq_abcd(sequence[4]);
David Lawrence Ramseyee383db2004-02-06 03:07:10 +0000944 break;
945 }
946 }
947 break;
948 }
949 }
950 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000951 default: /* Esc [ 1 ~ == Home on
952 * VT320/Linux console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000953 retval = NANO_HOME_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000954 break;
955 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +0000956 }
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000957 break;
958 case '2':
David Lawrence Ramsey74835712004-12-04 17:41:52 +0000959 if (seq_len >= 3) {
960 switch (sequence[2]) {
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000961 case '0': /* Esc [ 2 0 ~ == F9 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000962 * VT220/VT320/Linux console/
963 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000964 retval = KEY_F(9);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000965 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000966 case '1': /* Esc [ 2 1 ~ == F10 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000967 * VT220/VT320/Linux console/
968 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000969 retval = KEY_F(10);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000970 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000971 case '3': /* Esc [ 2 3 ~ == F11 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000972 * VT220/VT320/Linux console/
973 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000974 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000975 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000976 case '4': /* Esc [ 2 4 ~ == F12 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000977 * VT220/VT320/Linux console/
978 * xterm/rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000979 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000980 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000981 case '5': /* Esc [ 2 5 ~ == F13 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000982 * VT220/VT320/Linux console/
983 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000984 retval = KEY_F(13);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000985 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +0000986 case '6': /* Esc [ 2 6 ~ == F14 on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +0000987 * VT220/VT320/Linux console/
988 * rxvt/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +0000989 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +0000990 break;
David Lawrence Ramsey8381fdd2004-11-01 22:40:02 +0000991 case '8': /* Esc [ 2 8 ~ == F15 on
992 * VT220/VT320/Linux console/
993 * rxvt/Eterm. */
994 retval = KEY_F(15);
995 break;
996 case '9': /* Esc [ 2 9 ~ == F16 on
997 * VT220/VT320/Linux console/
998 * rxvt/Eterm. */
999 retval = KEY_F(16);
1000 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001001 default: /* Esc [ 2 ~ == Insert on
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001002 * VT220/VT320/Linux console/
1003 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001004 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001005 break;
1006 }
1007 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001008 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001009 case '3': /* Esc [ 3 ~ == Delete on VT220/VT320/
1010 * Linux console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001011 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001012 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001013 case '4': /* Esc [ 4 ~ == End on VT220/VT320/Linux
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001014 * console/xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001015 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001016 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001017 case '5': /* Esc [ 5 ~ == PageUp on VT220/VT320/
1018 * Linux console/xterm; Esc [ 5 ^ ==
1019 * PageUp on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001020 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001021 break;
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001022 case '6': /* Esc [ 6 ~ == PageDown on VT220/VT320/
1023 * Linux console/xterm; Esc [ 6 ^ ==
1024 * PageDown on Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001025 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001026 break;
1027 case '7': /* Esc [ 7 ~ == Home on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001028 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001029 break;
1030 case '8': /* Esc [ 8 ~ == End on rxvt. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001031 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001032 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001033 case '9': /* Esc [ 9 == Delete on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001034 retval = NANO_DELETE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001035 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001036 case '@': /* Esc [ @ == Insert on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001037 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001038 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001039 case 'A': /* Esc [ A == Up on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001040 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001041 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001042 case 'B': /* Esc [ B == Down on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001043 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001044 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001045 case 'C': /* Esc [ C == Right on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001046 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001047 * rxvt/Eterm. */
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001048 case 'D': /* Esc [ D == Left on ANSI/VT220/Linux
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001049 * console/FreeBSD console/Mach console/
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001050 * rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001051 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001052 break;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001053 case 'E': /* Esc [ E == Center (5) on numeric keypad
1054 * with NumLock off on FreeBSD console. */
David Lawrence Ramseye65e6392004-06-04 18:18:17 +00001055 *ignore_seq = TRUE;
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001056 break;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001057 case 'F': /* Esc [ F == End on FreeBSD
1058 * console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001059 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001060 break;
1061 case 'G': /* Esc [ G == PageDown on FreeBSD
David Lawrence Ramsey0a258082004-04-23 18:02:37 +00001062 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001063 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001064 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001065 case 'H': /* Esc [ H == Home on ANSI/VT220/FreeBSD
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001066 * console/Mach console/Eterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001067 retval = NANO_HOME_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001068 break;
1069 case 'I': /* Esc [ I == PageUp on FreeBSD
1070 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001071 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001072 break;
David Lawrence Ramsey0381c212004-05-01 01:21:38 +00001073 case 'L': /* Esc [ L == Insert on ANSI/FreeBSD
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001074 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001075 retval = NANO_INSERTFILE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001076 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001077 case 'M': /* Esc [ M == F1 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001078 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001079 break;
1080 case 'N': /* Esc [ N == F2 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001081 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001082 break;
1083 case 'O':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001084 if (seq_len >= 3) {
1085 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001086 case 'P': /* Esc [ O P == F1 on
1087 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001088 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001089 break;
1090 case 'Q': /* Esc [ O Q == F2 on
1091 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001092 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001093 break;
1094 case 'R': /* Esc [ O R == F3 on
1095 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001096 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001097 break;
1098 case 'S': /* Esc [ O S == F4 on
1099 * xterm. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001100 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001101 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001102 }
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001103 } else {
1104 /* Esc [ O == F3 on FreeBSD console. */
1105 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001106 }
1107 break;
1108 case 'P': /* Esc [ P == F4 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001109 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001110 break;
1111 case 'Q': /* Esc [ Q == F5 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001112 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001113 break;
1114 case 'R': /* Esc [ R == F6 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001115 retval = KEY_F(6);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001116 break;
1117 case 'S': /* Esc [ S == F7 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001118 retval = KEY_F(7);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001119 break;
1120 case 'T': /* Esc [ T == F8 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001121 retval = KEY_F(8);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001122 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001123 case 'U': /* Esc [ U == PageDown on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001124 retval = NANO_NEXTPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001125 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001126 case 'V': /* Esc [ V == PageUp on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001127 retval = NANO_PREVPAGE_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001128 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001129 case 'W': /* Esc [ W == F11 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001130 retval = KEY_F(11);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001131 break;
1132 case 'X': /* Esc [ X == F12 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001133 retval = KEY_F(12);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001134 break;
David Lawrence Ramseycc823ab2004-10-24 22:51:39 +00001135 case 'Y': /* Esc [ Y == End on Mach console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001136 retval = NANO_END_KEY;
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001137 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001138 case 'Z': /* Esc [ Z == F14 on FreeBSD console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001139 retval = KEY_F(14);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001140 break;
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001141 case 'a': /* Esc [ a == Shift-Up on rxvt/Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001142 case 'b': /* Esc [ b == Shift-Down on rxvt/Eterm. */
David Lawrence Ramsey973a96b2004-06-22 14:30:18 +00001143 case 'c': /* Esc [ c == Shift-Right on rxvt/
1144 * Eterm. */
David Lawrence Ramsey9b5bd422004-01-06 01:45:04 +00001145 case 'd': /* Esc [ d == Shift-Left on rxvt/Eterm. */
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001146 retval = get_escape_seq_abcd(sequence[1]);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001147 break;
1148 case '[':
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001149 if (seq_len >= 3) {
1150 switch (sequence[2]) {
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001151 case 'A': /* Esc [ [ A == F1 on Linux
1152 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001153 retval = KEY_F(1);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001154 break;
1155 case 'B': /* Esc [ [ B == F2 on Linux
1156 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001157 retval = KEY_F(2);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001158 break;
1159 case 'C': /* Esc [ [ C == F3 on Linux
1160 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001161 retval = KEY_F(3);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001162 break;
1163 case 'D': /* Esc [ [ D == F4 on Linux
1164 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001165 retval = KEY_F(4);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001166 break;
1167 case 'E': /* Esc [ [ E == F5 on Linux
1168 * console. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001169 retval = KEY_F(5);
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001170 break;
1171 }
1172 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001173 break;
1174 }
1175 break;
1176 }
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001177 }
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001178
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001179#ifdef DEBUG
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001180 fprintf(stderr, "get_escape_seq_kbinput(): retval = %d, ignore_seq = %d\n", retval, (int)*ignore_seq);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001181#endif
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001182
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001183 return retval;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001184}
1185
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001186/* Return the equivalent arrow key value for the case-insensitive
David Lawrence Ramseyb7e5cf62004-02-07 03:39:48 +00001187 * letters A (up), B (down), C (right), and D (left). These are common
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001188 * to many escape sequences. */
1189int get_escape_seq_abcd(int kbinput)
1190{
1191 switch (tolower(kbinput)) {
1192 case 'a':
1193 return NANO_PREVLINE_KEY;
1194 case 'b':
1195 return NANO_NEXTLINE_KEY;
1196 case 'c':
1197 return NANO_FORWARD_KEY;
1198 case 'd':
1199 return NANO_BACK_KEY;
1200 default:
1201 return ERR;
1202 }
1203}
1204
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001205/* Translate a word sequence: turn a three-digit decimal number from
1206 * 000 to 255 into its corresponding word value. */
1207int get_word_kbinput(int kbinput
1208#ifndef NANO_SMALL
1209 , bool reset
1210#endif
1211 )
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001212{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001213 static int word_digits = 0;
1214 static int word_kbinput = 0;
1215 int retval = ERR;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001216
1217#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001218 if (reset) {
1219 word_digits = 0;
1220 word_kbinput = 0;
1221 return ERR;
1222 }
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001223#endif
1224
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001225 /* Increment the word digit counter. */
1226 word_digits++;
1227
1228 switch (word_digits) {
1229 case 1:
1230 /* One digit: reset the word sequence holder and add the
1231 * digit we got to the 10000's position of the word sequence
1232 * holder. */
1233 word_kbinput = 0;
1234 if ('0' <= kbinput && kbinput <= '6')
1235 word_kbinput += (kbinput - '0') * 10000;
1236 else
1237 /* If the character we got isn't a decimal digit, or if
1238 * it is and it would put the word sequence out of word
1239 * range, save it as the result. */
1240 retval = kbinput;
1241 break;
1242 case 2:
1243 /* Two digits: add the digit we got to the 1000's position
1244 * of the word sequence holder. */
1245 if (('0' <= kbinput && kbinput <= '5') ||
1246 (word_kbinput < 60000 && '6' <= kbinput &&
1247 kbinput <= '9'))
1248 word_kbinput += (kbinput - '0') * 1000;
1249 else
1250 /* If the character we got isn't a decimal digit, or if
1251 * it is and it would put the word sequence out of word
1252 * range, save it as the result. */
1253 retval = kbinput;
1254 break;
1255 case 3:
1256 /* Three digits: add the digit we got to the 100's position
1257 * of the word sequence holder. */
1258 if (('0' <= kbinput && kbinput <= '5') ||
1259 (word_kbinput < 65000 && '6' <= kbinput &&
1260 kbinput <= '9'))
1261 word_kbinput += (kbinput - '0') * 100;
1262 else
1263 /* If the character we got isn't a decimal digit, or if
1264 * it is and it would put the word sequence out of word
1265 * range, save it as the result. */
1266 retval = kbinput;
1267 break;
1268 case 4:
1269 /* Four digits: add the digit we got to the 10's position of
1270 * the word sequence holder. */
1271 if (('0' <= kbinput && kbinput <= '3') ||
1272 (word_kbinput < 65500 && '4' <= kbinput &&
1273 kbinput <= '9'))
1274 word_kbinput += (kbinput - '0') * 10;
1275 else
1276 /* If the character we got isn't a decimal digit, or if
1277 * it is and it would put the word sequence out of word
1278 * range, save it as the result. */
1279 retval = kbinput;
1280 break;
1281 case 5:
1282 /* Five digits: add the digit we got to the 1's position of
1283 * the word sequence holder, and save the corresponding word
1284 * value as the result. */
1285 if (('0' <= kbinput && kbinput <= '5') ||
1286 (word_kbinput < 65530 && '6' <= kbinput &&
1287 kbinput <= '9')) {
1288 word_kbinput += (kbinput - '0');
1289 retval = word_kbinput;
1290 } else
1291 /* If the character we got isn't a decimal digit, or if
1292 * it is and it would put the word sequence out of word
1293 * range, save it as the result. */
1294 retval = kbinput;
1295 break;
1296 default:
1297 /* More than three digits: save the character we got as the
1298 * result. */
1299 retval = kbinput;
1300 break;
1301 }
1302
1303 /* If we have a result, reset the word digit counter and the word
1304 * sequence holder. */
1305 if (retval != ERR) {
1306 word_digits = 0;
1307 word_kbinput = 0;
1308 }
1309
1310#ifdef DEBUG
1311 fprintf(stderr, "get_word_kbinput(): kbinput = %d, word_digits = %d, word_kbinput = %d, retval = %d\n", kbinput, word_digits, word_kbinput, retval);
1312#endif
1313
1314 return retval;
1315}
1316
1317/* Translate a control character sequence: turn an ASCII non-control
1318 * character into its corresponding control character. */
1319int get_control_kbinput(int kbinput)
1320{
1321 int retval;
1322
1323 /* Ctrl-2 (Ctrl-Space, Ctrl-@, Ctrl-`) */
1324 if (kbinput == '2' || kbinput == ' ' || kbinput == '@' ||
1325 kbinput == '`')
1326 retval = NANO_CONTROL_SPACE;
1327 /* Ctrl-3 (Ctrl-[, Esc) to Ctrl-7 (Ctrl-_) */
1328 else if ('3' <= kbinput && kbinput <= '7')
1329 retval = kbinput - 24;
1330 /* Ctrl-8 (Ctrl-?) */
1331 else if (kbinput == '8' || kbinput == '?')
1332 retval = NANO_CONTROL_8;
1333 /* Ctrl-A to Ctrl-_ */
1334 else if ('A' <= kbinput && kbinput <= '_')
1335 retval = kbinput - 64;
1336 /* Ctrl-a to Ctrl-~ */
1337 else if ('a' <= kbinput && kbinput <= '~')
1338 retval = kbinput - 96;
1339 else
1340 retval = kbinput;
1341
1342#ifdef DEBUG
1343 fprintf(stderr, "get_control_kbinput(): kbinput = %d, retval = %d\n", kbinput, retval);
1344#endif
1345
1346 return retval;
1347}
1348
1349/* Read in a string of characters verbatim, and return the length of the
1350 * string in kbinput_len. Assume nodelay(win) is FALSE. */
1351int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
1352{
1353 int *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001354
1355 /* Turn off flow control characters if necessary so that we can type
1356 * them in verbatim, and turn the keypad off so that we don't get
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001357 * extended keypad values. */
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001358 if (ISSET(PRESERVE))
1359 disable_flow_control();
1360 keypad(win, FALSE);
1361
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001362 /* Read in a stream of characters and interpret it if possible. */
1363 retval = parse_verbatim_kbinput(win, kbinput_len);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001364
1365 /* Turn flow control characters back on if necessary and turn the
1366 * keypad back on now that we're done. */
1367 if (ISSET(PRESERVE))
1368 enable_flow_control();
1369 keypad(win, TRUE);
1370
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001371 return retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001372}
1373
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001374/* Read in a stream of all available characters. Translate the first
1375 * few characters of the input into the corresponding word value if
1376 * possible. After that, leave the input as-is. */
1377int *parse_verbatim_kbinput(WINDOW *win, size_t *kbinput_len)
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001378{
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001379 buffer *kbinput, *sequence;
1380 int word, *retval;
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001381
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001382 /* Read in the first keystroke. */
1383 while ((kbinput = get_input(win, 1)) == NULL);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001384
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001385 /* Check whether the first keystroke is a decimal digit. */
1386 word = get_word_kbinput(kbinput->key
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001387#ifndef NANO_SMALL
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001388 , FALSE
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001389#endif
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001390 );
1391
1392 /* If the first keystroke isn't a decimal digit, put back the first
1393 * keystroke. */
1394 if (word != ERR)
1395 unget_input(kbinput, 1);
1396 /* Otherwise, read in keystrokes until we have a complete word
1397 * sequence, and put back the corresponding word value. */
1398 else {
1399 buffer word_kbinput;
1400
1401 while (word == ERR) {
1402 while ((kbinput = get_input(win, 1)) == NULL);
1403 word = get_word_kbinput(kbinput->key
1404#ifndef NANO_SMALL
1405 , FALSE
1406#endif
1407 );
1408 }
1409
1410 word_kbinput.key = word;
1411 word_kbinput.key_code = FALSE;
1412
1413 unget_input(&word_kbinput, 1);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001414 }
1415
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001416 /* Get the complete sequence, and save the key values in it as the
1417 * result. */
1418 *kbinput_len = get_buffer_len();
1419 sequence = get_input(NULL, *kbinput_len);
1420 retval = buffer_to_keys(sequence, *kbinput_len);
1421 free(sequence);
David Lawrence Ramsey48ae9862004-05-28 17:23:33 +00001422
1423 return retval;
1424}
1425
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001426#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00001427/* Check for a mouse event, and if one's taken place, save the
1428 * coordinates where it took place in mouse_x and mouse_y. After that,
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001429 * assuming allow_shortcuts is FALSE, if the shortcut list on the
1430 * bottom two lines of the screen is visible and the mouse event took
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001431 * place on it, figure out which shortcut was clicked and put back the
1432 * equivalent keystroke(s). Return FALSE if no keystrokes were
1433 * put back, or TRUE if at least one was. Assume that KEY_MOUSE has
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001434 * already been read in. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001435bool get_mouseinput(int *mouse_x, int *mouse_y, bool allow_shortcuts)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001436{
1437 MEVENT mevent;
1438
1439 *mouse_x = -1;
1440 *mouse_y = -1;
1441
1442 /* First, get the actual mouse event. */
1443 if (getmouse(&mevent) == ERR)
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001444 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001445
1446 /* Save the screen coordinates where the mouse event took place. */
1447 *mouse_x = mevent.x;
1448 *mouse_y = mevent.y;
1449
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001450 /* If we're allowing shortcuts, the current shortcut list is being
1451 * displayed on the last two lines of the screen, and the mouse
1452 * event took place inside it, we need to figure out which shortcut
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00001453 * was clicked and put back the equivalent keystroke(s) for it. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001454 if (allow_shortcuts && !ISSET(NO_HELP) && wenclose(bottomwin,
1455 *mouse_y, *mouse_x)) {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001456 int i, j;
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001457 size_t currslen;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001458 /* The number of shortcuts in the current shortcut list. */
1459 const shortcut *s = currshortcut;
1460 /* The actual shortcut we clicked on, starting at the first
1461 * one in the current shortcut list. */
1462
1463 /* Get the shortcut lists' length. */
1464 if (currshortcut == main_list)
1465 currslen = MAIN_VISIBLE;
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001466 else {
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001467 currslen = length_of_list(currshortcut);
1468
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001469 /* We don't show any more shortcuts than the main list
1470 * does. */
1471 if (currslen > MAIN_VISIBLE)
1472 currslen = MAIN_VISIBLE;
1473 }
1474
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001475 /* Calculate the width of each shortcut in the list (it's the
1476 * same for all of them). */
1477 if (currslen < 2)
1478 i = COLS / 6;
1479 else
1480 i = COLS / ((currslen / 2) + (currslen % 2));
1481
1482 /* Calculate the y-coordinates relative to the beginning of
1483 * bottomwin, i.e, the bottom three lines of the screen. */
1484 j = *mouse_y - (editwinrows + 3);
1485
1486 /* If we're on the statusbar, beyond the end of the shortcut
1487 * list, or beyond the end of a shortcut on the right side of
1488 * the screen, don't do anything. */
1489 if (j < 0 || (*mouse_x / i) >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001490 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001491 j = (*mouse_x / i) * 2 + j;
1492 if (j >= currslen)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001493 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001494
1495 /* Go through the shortcut list to determine which shortcut was
1496 * clicked. */
1497 for (; j > 0; j--)
1498 s = s->next;
1499
David Lawrence Ramseydb6015c2004-09-11 21:41:13 +00001500 /* And put back the equivalent key. Assume that each shortcut
1501 * has, at the very least, an equivalent control key, an
1502 * equivalent primary meta key sequence, or both. */
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001503 if (s->ctrlval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001504 unget_kbinput(s->ctrlval, FALSE, FALSE);
David Lawrence Ramseyfe0d3662004-08-26 01:43:16 +00001505 else if (s->metaval != NANO_NO_KEY)
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001506 unget_kbinput(s->metaval, TRUE, FALSE);
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001507
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001508 return TRUE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001509 }
David Lawrence Ramseyebd0d7c2004-07-01 18:59:52 +00001510 return FALSE;
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001511}
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001512#endif /* !DISABLE_MOUSE */
1513
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001514const shortcut *get_shortcut(const shortcut *s_list, int *kbinput, bool
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001515 *meta_key, bool *func_key)
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001516{
1517 const shortcut *s = s_list;
1518 size_t slen = length_of_list(s_list);
1519
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001520#ifdef DEBUG
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001521 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 +00001522#endif
1523
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001524 /* Check for shortcuts. */
1525 for (; slen > 0; slen--) {
1526 /* We've found a shortcut if:
1527 *
1528 * 1. The key exists.
1529 * 2. The key is a control key in the shortcut list.
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001530 * 3. meta_key is TRUE and the key is the primary or
1531 * miscellaneous meta sequence in the shortcut list.
1532 * 4. func_key is TRUE and the key is a function key in the
1533 * shortcut list. */
1534
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001535 if (*kbinput != NANO_NO_KEY && (*kbinput == s->ctrlval ||
1536 (*meta_key == TRUE && (*kbinput == s->metaval ||
1537 *kbinput == s->miscval)) || (*func_key == TRUE &&
1538 *kbinput == s->funcval))) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001539 break;
1540 }
1541
1542 s = s->next;
1543 }
1544
1545 /* Translate the shortcut to either its control key or its meta key
1546 * equivalent. Assume that the shortcut has an equivalent control
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001547 * key, an equivalent primary meta key sequence, or both. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001548 if (slen > 0) {
1549 if (s->ctrlval != NANO_NO_KEY) {
1550 *meta_key = FALSE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001551 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001552 *kbinput = s->ctrlval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001553 } else if (s->metaval != NANO_NO_KEY) {
1554 *meta_key = TRUE;
David Lawrence Ramsey74835712004-12-04 17:41:52 +00001555 *func_key = FALSE;
David Lawrence Ramsey1483ee32004-11-29 00:30:07 +00001556 *kbinput = s->metaval;
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001557 }
1558 return s;
1559 }
1560
1561 return NULL;
1562}
1563
1564#ifndef NANO_SMALL
1565const toggle *get_toggle(int kbinput, bool meta_key)
1566{
1567 const toggle *t = toggles;
1568
David Lawrence Ramsey08eab722004-11-27 06:43:06 +00001569#ifdef DEBUG
1570 fprintf(stderr, "get_toggle(): kbinput = %d, meta_key = %d\n", kbinput, (int)meta_key);
1571#endif
1572
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001573 /* Check for toggles. */
1574 for (; t != NULL; t = t->next) {
1575 /* We've found a toggle if meta_key is TRUE and the key is in
1576 * the meta toggle list. */
1577 if (meta_key && kbinput == t->val)
1578 break;
1579 }
1580
1581 return t;
1582}
1583#endif /* !NANO_SMALL */
1584
Chris Allegretta6df90f52002-07-19 01:08:59 +00001585/* Return the placewewant associated with current_x. That is, xplustabs
1586 * is the zero-based column position of the cursor. Value is no smaller
1587 * than current_x. */
1588size_t xplustabs(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001589{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001590 return strnlenpt(current->data, current_x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001591}
1592
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001593/* actual_x() gives the index in str of the character displayed at
1594 * column xplus. That is, actual_x() is the largest value such that
1595 * strnlenpt(str, actual_x(str, xplus)) <= xplus. */
1596size_t actual_x(const char *str, size_t xplus)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001597{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001598 size_t i = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001599 /* The position in str, returned. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001600 size_t length = 0;
David Lawrence Ramsey09b34ed2004-09-24 21:48:40 +00001601 /* The screen display width to str[i]. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001602
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001603 assert(str != NULL);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001604
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001605 for (; length < xplus && *str != '\0'; i++, str++) {
1606 if (*str == '\t')
David Lawrence Ramsey0362c582003-09-30 03:31:56 +00001607 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001608 else if (is_cntrl_char(*str))
Chris Allegretta6df90f52002-07-19 01:08:59 +00001609 length += 2;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001610 else
1611 length++;
1612 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001613 assert(length == strnlenpt(str - i, i));
1614 assert(i <= strlen(str - i));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001615
Chris Allegretta6df90f52002-07-19 01:08:59 +00001616 if (length > xplus)
1617 i--;
David Lawrence Ramseyf21cd102002-06-13 00:40:19 +00001618
Chris Allegretta6df90f52002-07-19 01:08:59 +00001619 return i;
Robert Siemborskid8510b22000-06-06 23:04:06 +00001620}
1621
David Lawrence Ramseya3370c42004-04-05 01:08:14 +00001622/* A strlen() with tabs factored in, similar to xplustabs(). How many
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001623 * columns wide are the first size characters of buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001624size_t strnlenpt(const char *buf, size_t size)
Robert Siemborskid8510b22000-06-06 23:04:06 +00001625{
Chris Allegretta6df90f52002-07-19 01:08:59 +00001626 size_t length = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001627
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001628 assert(buf != NULL);
1629 for (; *buf != '\0' && size != 0; size--, buf++) {
1630 if (*buf == '\t')
1631 length += tabsize - (length % tabsize);
David Lawrence Ramsey1601c282004-10-21 22:06:40 +00001632 else if (is_cntrl_char(*buf))
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001633 length += 2;
1634 else
1635 length++;
1636 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001637 return length;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001638}
1639
David Lawrence Ramsey5dcba302003-09-28 19:15:18 +00001640/* How many columns wide is buf? */
Chris Allegretta6df90f52002-07-19 01:08:59 +00001641size_t strlenpt(const char *buf)
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001642{
David Lawrence Ramsey0b047c52004-03-29 23:09:08 +00001643 return strnlenpt(buf, (size_t)-1);
Chris Allegrettad4fa0d32002-03-05 19:55:55 +00001644}
1645
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001646void blank_titlebar(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001647{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001648 mvwaddstr(topwin, 0, 0, hblank);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001649}
1650
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001651void blank_edit(void)
1652{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00001653 int i;
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00001654 for (i = 0; i < editwinrows; i++)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001655 mvwaddstr(edit, i, 0, hblank);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001656}
1657
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001658void blank_statusbar(void)
1659{
1660 mvwaddstr(bottomwin, 0, 0, hblank);
1661}
1662
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001663void check_statusblank(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001664{
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001665 if (statusblank > 1)
1666 statusblank--;
1667 else if (statusblank == 1 && !ISSET(CONSTUPDATE)) {
1668 statusblank = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00001669 blank_statusbar();
1670 wnoutrefresh(bottomwin);
1671 reset_cursor();
1672 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001673 }
1674}
1675
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001676void blank_bottombars(void)
1677{
1678 if (!ISSET(NO_HELP)) {
1679 mvwaddstr(bottomwin, 1, 0, hblank);
1680 mvwaddstr(bottomwin, 2, 0, hblank);
1681 }
1682}
1683
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001684/* Convert buf into a string that can be displayed on screen. The
1685 * caller wants to display buf starting with column start_col, and
1686 * extending for at most len columns. start_col is zero-based. len is
1687 * one-based, so len == 0 means you get "" returned. The returned
1688 * string is dynamically allocated, and should be freed. */
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00001689char *display_string(const char *buf, size_t start_col, size_t len)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001690{
1691 size_t start_index;
1692 /* Index in buf of first character shown in return value. */
1693 size_t column;
1694 /* Screen column start_index corresponds to. */
1695 size_t end_index;
1696 /* Index in buf of last character shown in return value. */
1697 size_t alloc_len;
1698 /* The length of memory allocated for converted. */
1699 char *converted;
1700 /* The string we return. */
1701 size_t index;
1702 /* Current position in converted. */
1703
1704 if (len == 0)
1705 return mallocstrcpy(NULL, "");
1706
1707 start_index = actual_x(buf, start_col);
1708 column = strnlenpt(buf, start_index);
1709 assert(column <= start_col);
1710 end_index = actual_x(buf, start_col + len - 1);
1711 alloc_len = strnlenpt(buf, end_index + 1) - column;
1712 if (len > alloc_len + column - start_col)
1713 len = alloc_len + column - start_col;
1714 converted = charalloc(alloc_len + 1);
1715 buf += start_index;
1716 index = 0;
1717
1718 for (; index < alloc_len; buf++) {
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001719 if (*buf == '\t') {
1720 converted[index++] =
1721#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1722 ISSET(WHITESPACE_DISPLAY) ? whitespace[0] :
1723#endif
1724 ' ';
1725 while ((column + index) % tabsize)
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001726 converted[index++] = ' ';
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001727 } else if (is_cntrl_char(*buf)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001728 converted[index++] = '^';
1729 if (*buf == '\n')
1730 /* Treat newlines embedded in a line as encoded nulls;
1731 * the line in question should be run through unsunder()
1732 * before reaching here. */
1733 converted[index++] = '@';
1734 else if (*buf == NANO_CONTROL_8)
1735 converted[index++] = '?';
1736 else
1737 converted[index++] = *buf + 64;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00001738 } else if (*buf == ' ')
1739 converted[index++] =
1740#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
1741 ISSET(WHITESPACE_DISPLAY) ? whitespace[1] :
1742#endif
1743 ' ';
1744 else
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001745 converted[index++] = *buf;
1746 }
1747 assert(len <= alloc_len + column - start_col);
1748 charmove(converted, converted + start_col - column, len);
1749 null_at(&converted, len);
1750
1751 return charealloc(converted, len + 1);
1752}
1753
Chris Allegretta7662c862003-01-13 01:35:15 +00001754/* Repaint the statusbar when getting a character in nanogetstr(). buf
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001755 * should be no longer than max(0, COLS - 4).
Chris Allegretta6df90f52002-07-19 01:08:59 +00001756 *
Chris Allegretta7662c862003-01-13 01:35:15 +00001757 * Note that we must turn on A_REVERSE here, since do_help() turns it
Chris Allegretta6df90f52002-07-19 01:08:59 +00001758 * off! */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001759void nanoget_repaint(const char *buf, const char *inputbuf, size_t x)
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001760{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001761 size_t x_real = strnlenpt(inputbuf, x);
1762 int wid = COLS - strlen(buf) - 2;
Chris Allegretta0d1e8d62000-11-02 15:30:24 +00001763
Chris Allegretta6df90f52002-07-19 01:08:59 +00001764 assert(0 <= x && x <= strlen(inputbuf));
1765
Chris Allegrettab3655b42001-10-22 03:15:31 +00001766 wattron(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001767 blank_statusbar();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001768
Chris Allegretta6df90f52002-07-19 01:08:59 +00001769 mvwaddstr(bottomwin, 0, 0, buf);
1770 waddch(bottomwin, ':');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00001771
1772 if (COLS > 1)
1773 waddch(bottomwin, x_real < wid ? ' ' : '$');
1774 if (COLS > 2) {
1775 size_t page_start = x_real - x_real % wid;
1776 char *expanded = display_string(inputbuf, page_start, wid);
1777
1778 assert(wid > 0);
1779 assert(strlen(expanded) <= wid);
1780 waddstr(bottomwin, expanded);
1781 free(expanded);
1782 wmove(bottomwin, 0, COLS - wid + x_real - page_start);
1783 } else
1784 wmove(bottomwin, 0, COLS - 1);
Chris Allegrettab3655b42001-10-22 03:15:31 +00001785 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa0e957b2000-10-24 22:25:36 +00001786}
1787
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00001788/* Get the input from the keyboard; this should only be called from
Chris Allegretta6df90f52002-07-19 01:08:59 +00001789 * statusq(). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001790int nanogetstr(bool allow_tabs, const char *buf, const char *def,
Chris Allegretta5beed502003-01-05 20:41:21 +00001791#ifndef NANO_SMALL
1792 historyheadtype *history_list,
1793#endif
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001794 const shortcut *s
Rocco Corsi06aca1c2001-01-11 05:30:31 +00001795#ifndef DISABLE_TABCOMP
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001796 , bool *list
Chris Allegrettabe77c612000-11-24 14:00:16 +00001797#endif
Chris Allegretta65f075d2003-02-13 03:03:49 +00001798 )
Chris Allegretta6df90f52002-07-19 01:08:59 +00001799{
1800 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001801 bool meta_key, func_key;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001802 static size_t x = (size_t)-1;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001803 /* the cursor position in 'answer' */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001804 size_t xend;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001805 /* length of 'answer', the status bar text */
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001806 bool tabbed = FALSE;
Chris Allegretta6df90f52002-07-19 01:08:59 +00001807 /* used by input_tab() */
1808 const shortcut *t;
Chris Allegretta598106e2002-01-19 01:59:37 +00001809
Chris Allegretta5beed502003-01-05 20:41:21 +00001810#ifndef NANO_SMALL
1811 /* for history */
1812 char *history = NULL;
Chris Allegretta8031f832003-01-09 05:29:58 +00001813 char *currentbuf = NULL;
Chris Allegretta5beed502003-01-05 20:41:21 +00001814 char *complete = NULL;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001815 int last_kbinput = 0;
1816
1817 /* This variable is used in the search history code. use_cb == 0
1818 means that we're using the existing history and ignoring
1819 currentbuf. use_cb == 1 means that the entry in answer should be
1820 moved to currentbuf or restored from currentbuf to answer.
1821 use_cb == 2 means that the entry in currentbuf should be moved to
1822 answer or restored from answer to currentbuf. */
1823 int use_cb = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001824#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00001825 xend = strlen(def);
Chris Allegretta09fc4302003-01-16 22:16:38 +00001826
David Lawrence Ramsey4dd723a2004-10-05 02:29:52 +00001827 /* Only put x at the end of the string if it's uninitialized, if it
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001828 would be past the end of the string as it is, or if
1829 resetstatuspos is TRUE. Otherwise, leave it alone. This is so
1830 the cursor position stays at the same place if a prompt-changing
1831 toggle is pressed. */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001832 if (x == (size_t)-1 || x > xend || resetstatuspos)
Chris Allegretta09fc4302003-01-16 22:16:38 +00001833 x = xend;
1834
Chris Allegrettae1e0fd62003-04-15 01:15:09 +00001835 answer = charealloc(answer, xend + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001836 if (xend > 0)
1837 strcpy(answer, def);
1838 else
1839 answer[0] = '\0';
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001840
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001841#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001842 currshortcut = s;
Chris Allegretta6fe61492001-05-21 12:56:25 +00001843#endif
1844
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001845 /* Get the input! */
Chris Allegretta31925e42000-11-02 04:40:39 +00001846
Chris Allegretta6df90f52002-07-19 01:08:59 +00001847 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001848
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001849 /* Make sure any editor screen updates are displayed before getting
1850 input */
David Lawrence Ramsey0fb841a2004-07-01 17:04:23 +00001851 wnoutrefresh(edit);
1852 wrefresh(bottomwin);
Chris Allegretta022b96f2000-11-14 17:47:58 +00001853
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001854 /* If we're using restricted mode, we aren't allowed to change the
1855 * name of a file once it has one because that would allow writing
1856 * to files not specified on the command line. In this case,
1857 * disable all keys that would change the text if the filename isn't
1858 * blank and we're at the "Write File" prompt. */
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00001859 while ((kbinput = get_kbinput(bottomwin, &meta_key, &func_key)) !=
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00001860 NANO_CANCEL_KEY && kbinput != NANO_ENTER_KEY) {
Chris Allegrettaa8c22572002-02-15 19:17:02 +00001861 for (t = s; t != NULL; t = t->next) {
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001862#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00001863 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001864#endif
1865
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001866 /* Temporary hack to interpret NANO_HELP_FKEY correctly. */
1867 if (kbinput == t->funcval)
1868 kbinput = t->ctrlval;
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001869
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001870 if (kbinput == t->ctrlval && is_cntrl_char(kbinput)) {
Chris Allegretta5bf51d32000-11-16 06:01:10 +00001871
Chris Allegrettab3655b42001-10-22 03:15:31 +00001872#ifndef DISABLE_HELP
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00001873 /* Have to do this here, it would be too late to do it
1874 in statusq() */
David Lawrence Ramseyd7f5ad92004-03-04 19:30:53 +00001875 if (kbinput == NANO_HELP_KEY) {
Chris Allegrettab3655b42001-10-22 03:15:31 +00001876 do_help();
1877 break;
1878 }
1879#endif
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001880#ifndef NANO_SMALL
1881 /* Have to handle these here too, for the time being */
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001882 if (kbinput == NANO_PREVLINE_KEY || kbinput == NANO_NEXTLINE_KEY)
David Lawrence Ramseya593f532003-11-28 19:47:42 +00001883 break;
1884#endif
Chris Allegretta5af58892003-01-17 21:07:38 +00001885
David Lawrence Ramsey1576d532004-03-19 21:46:34 +00001886 return t->ctrlval;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001887 }
1888 }
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001889 assert(x <= xend && xend == strlen(answer));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001890
Chris Allegretta04d848e2000-11-05 17:54:41 +00001891 if (kbinput != '\t')
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00001892 tabbed = FALSE;
Chris Allegretta04d848e2000-11-05 17:54:41 +00001893
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001894 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00001895#ifndef DISABLE_MOUSE
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001896 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00001897 {
1898 int mouse_x, mouse_y;
1899 get_mouseinput(&mouse_x, &mouse_y, TRUE);
1900 }
Chris Allegretta6b58acd2001-04-12 03:01:53 +00001901 break;
1902#endif
David Lawrence Ramsey72d8e542004-09-25 00:45:07 +00001903 case NANO_REFRESH_KEY:
1904 total_refresh();
1905 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001906 case NANO_HOME_KEY:
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001907#ifndef NANO_SMALL
1908 if (ISSET(SMART_HOME)) {
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00001909 size_t old_x = x;
David Lawrence Ramseyc7acf692004-05-22 20:15:20 +00001910
1911 for (x = 0; isblank(answer[x]) && x < xend; x++)
1912 ;
1913
1914 if (x == old_x || x == xend)
1915 x = 0;
1916 } else
1917#endif
1918 x = 0;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001919 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00001920 case NANO_END_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001921 x = xend;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001922 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001923 case NANO_FORWARD_KEY:
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001924 if (x < xend)
1925 x++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001926 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001927 case NANO_DELETE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001928 /* If we're using restricted mode, the filename isn't blank,
1929 * and we're at the "Write File" prompt, disable Delete. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001930 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1931 if (x < xend) {
1932 charmove(answer + x, answer + x + 1, xend - x);
1933 xend--;
1934 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001935 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001936 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001937 case NANO_CUT_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001938 /* If we're using restricted mode, the filename isn't blank,
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00001939 * and we're at the "Write File" prompt, disable Cut. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001940 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1941 null_at(&answer, 0);
1942 xend = 0;
1943 x = 0;
1944 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001945 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001946 case NANO_BACKSPACE_KEY:
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00001947 /* If we're using restricted mode, the filename isn't blank,
1948 * and we're at the "Write File" prompt, disable
1949 * Backspace. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00001950 if (!ISSET(RESTRICTED) || filename[0] == '\0' || s != writefile_list) {
1951 if (x > 0) {
1952 charmove(answer + x - 1, answer + x, xend - x + 1);
1953 x--;
1954 xend--;
1955 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001956 }
Chris Allegretta04d848e2000-11-05 17:54:41 +00001957 break;
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001958 case NANO_TAB_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001959#ifndef NANO_SMALL
1960 /* tab history completion */
Chris Allegretta7662c862003-01-13 01:35:15 +00001961 if (history_list != NULL) {
David Lawrence Ramsey4d7c2602003-08-17 02:48:43 +00001962 if (!complete || last_kbinput != NANO_TAB_KEY) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001963 history_list->current = (historytype *)history_list;
1964 history_list->len = strlen(answer);
1965 }
Chris Allegretta6df90f52002-07-19 01:08:59 +00001966
Chris Allegretta7662c862003-01-13 01:35:15 +00001967 if (history_list->len > 0) {
Chris Allegretta5beed502003-01-05 20:41:21 +00001968 complete = get_history_completion(history_list, answer);
1969 xend = strlen(complete);
Chris Allegretta6df90f52002-07-19 01:08:59 +00001970 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001971 answer = mallocstrcpy(answer, complete);
1972 }
Chris Allegretta7da4e9f2000-11-06 02:57:22 +00001973 }
Chris Allegretta5beed502003-01-05 20:41:21 +00001974#ifndef DISABLE_TABCOMP
Chris Allegretta327abda2003-01-17 05:04:17 +00001975 else
1976#endif
Chris Allegrettabe77c612000-11-24 14:00:16 +00001977#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00001978#ifndef DISABLE_TABCOMP
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00001979 if (allow_tabs) {
Chris Allegretta327abda2003-01-17 05:04:17 +00001980 int shift = 0;
Chris Allegretta5beed502003-01-05 20:41:21 +00001981
Chris Allegretta327abda2003-01-17 05:04:17 +00001982 answer = input_tab(answer, x, &tabbed, &shift, list);
1983 xend = strlen(answer);
1984 x += shift;
1985 if (x > xend)
1986 x = xend;
Chris Allegretta5beed502003-01-05 20:41:21 +00001987 }
1988#endif
1989 break;
Chris Allegretta35dac582001-03-21 15:07:20 +00001990 case NANO_BACK_KEY:
Chris Allegretta6df90f52002-07-19 01:08:59 +00001991 if (x > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001992 x--;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00001993 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00001994 case NANO_PREVLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00001995#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00001996 if (history_list != NULL) {
Chris Allegretta8031f832003-01-09 05:29:58 +00001997
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00001998 /* if currentbuf is NULL, or if use_cb is 1, currentbuf
1999 isn't NULL, and currentbuf is different from answer,
2000 it means that we're scrolling up at the top of the
2001 search history, and we need to save the current
2002 answer in currentbuf; do this and reset use_cb to
2003 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002004 if (currentbuf == NULL || (use_cb == 1 &&
2005 strcmp(currentbuf, answer) != 0)) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002006 currentbuf = mallocstrcpy(currentbuf, answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002007 use_cb = 0;
Chris Allegretta8031f832003-01-09 05:29:58 +00002008 }
2009
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002010 /* if currentbuf isn't NULL, use_cb is 2, and currentbuf
2011 is different from answer, it means that we're
2012 scrolling up at the bottom of the search history, and
2013 we need to make the string in currentbuf the current
2014 answer; do this, blow away currentbuf since we don't
2015 need it anymore, and reset use_cb to 0 */
David Lawrence Ramseyb8c479a2004-07-31 14:10:23 +00002016 if (currentbuf != NULL && use_cb == 2 &&
2017 strcmp(currentbuf, answer) != 0) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002018 answer = mallocstrcpy(answer, currentbuf);
2019 free(currentbuf);
2020 currentbuf = NULL;
2021 xend = strlen(answer);
2022 use_cb = 0;
2023
2024 /* else get older search from the history list and save
2025 it in answer; if there is no older search, blank out
2026 answer */
2027 } else if ((history = get_history_older(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002028 answer = mallocstrcpy(answer, history);
2029 xend = strlen(history);
2030 } else {
2031 answer = mallocstrcpy(answer, "");
2032 xend = 0;
2033 }
2034 x = xend;
2035 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002036#endif
Chris Allegretta54abd942003-01-09 23:43:12 +00002037 break;
David Lawrence Ramseyc2c5a512004-01-23 19:26:17 +00002038 case NANO_NEXTLINE_KEY:
Chris Allegretta5beed502003-01-05 20:41:21 +00002039#ifndef NANO_SMALL
Chris Allegretta09fc4302003-01-16 22:16:38 +00002040 if (history_list != NULL) {
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002041
2042 /* get newer search from the history list and save it
2043 in answer */
Chris Allegretta7662c862003-01-13 01:35:15 +00002044 if ((history = get_history_newer(history_list)) != NULL) {
Chris Allegretta5beed502003-01-05 20:41:21 +00002045 answer = mallocstrcpy(answer, history);
2046 xend = strlen(history);
Chris Allegretta8031f832003-01-09 05:29:58 +00002047
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002048 /* if there is no newer search, we're here */
2049
2050 /* if currentbuf isn't NULL and use_cb isn't 2, it means
2051 that we're scrolling down at the bottom of the search
2052 history and we need to make the string in currentbuf
2053 the current answer; do this, blow away currentbuf
2054 since we don't need it anymore, and set use_cb to
2055 1 */
2056 } else if (currentbuf != NULL && use_cb != 2) {
Chris Allegretta8031f832003-01-09 05:29:58 +00002057 answer = mallocstrcpy(answer, currentbuf);
Chris Allegretta09fc4302003-01-16 22:16:38 +00002058 free(currentbuf);
2059 currentbuf = NULL;
2060 xend = strlen(answer);
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002061 use_cb = 1;
2062
2063 /* otherwise, if currentbuf is NULL and use_cb isn't 2,
2064 it means that we're scrolling down at the bottom of
Chris Allegrettac30fc242003-08-11 00:32:45 +00002065 the search history and the current answer (if it's
2066 not blank) needs to be saved in currentbuf; do this,
2067 blank out answer (if necessary), and set use_cb to
2068 2 */
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002069 } else if (use_cb != 2) {
Chris Allegrettac30fc242003-08-11 00:32:45 +00002070 if (answer[0] != '\0') {
2071 currentbuf = mallocstrcpy(currentbuf, answer);
2072 answer = mallocstrcpy(answer, "");
2073 }
Chris Allegretta5beed502003-01-05 20:41:21 +00002074 xend = 0;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002075 use_cb = 2;
Chris Allegretta5beed502003-01-05 20:41:21 +00002076 }
2077 x = xend;
2078 }
2079#endif
2080 break;
Chris Allegretta658399a2001-06-14 02:54:22 +00002081 default:
2082
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002083 for (t = s; t != NULL; t = t->next) {
Chris Allegretta658399a2001-06-14 02:54:22 +00002084#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002085 fprintf(stderr, "Aha! \'%c\' (%d)\n", kbinput,
Chris Allegretta598106e2002-01-19 01:59:37 +00002086 kbinput);
Chris Allegretta658399a2001-06-14 02:54:22 +00002087#endif
David Lawrence Ramsey4d44d2d2004-08-01 22:35:31 +00002088 if (meta_key && (kbinput == t->metaval || kbinput == t->miscval))
David Lawrence Ramsey32613fa2004-05-24 18:40:41 +00002089 /* We hit a meta key. Do like above. We don't
David Lawrence Ramseydfca1c42004-08-25 16:37:06 +00002090 * just put back the letter and let it get
David Lawrence Ramsey82138502003-12-24 08:03:54 +00002091 * caught above cause that screws the
2092 * keypad... */
2093 return kbinput;
Chris Allegretta658399a2001-06-14 02:54:22 +00002094 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002095
David Lawrence Ramsey32e3b882004-05-29 01:20:17 +00002096 /* If we're using restricted mode, the filename isn't blank,
2097 * and we're at the "Write File" prompt, act as though the
2098 * unhandled character we got is a control character and
2099 * throw it away. */
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00002100 if (is_cntrl_char(kbinput) || (ISSET(RESTRICTED) && filename[0] != '\0' && s == writefile_list))
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002101 break;
David Lawrence Ramsey70047ee2003-06-14 20:41:34 +00002102 answer = charealloc(answer, xend + 2);
David Lawrence Ramsey9eff7462003-09-16 02:04:00 +00002103 charmove(answer + x + 1, answer + x, xend - x + 1);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002104 xend++;
2105 answer[x] = kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002106 x++;
2107
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002108#ifdef DEBUG
Jordi Mallachf9390af2003-08-05 19:31:12 +00002109 fprintf(stderr, "input \'%c\' (%d)\n", kbinput, kbinput);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002110#endif
Chris Allegretta5beed502003-01-05 20:41:21 +00002111 } /* switch (kbinput) */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002112#ifndef NANO_SMALL
Chris Allegretta5beed502003-01-05 20:41:21 +00002113 last_kbinput = kbinput;
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002114#endif
Chris Allegretta6df90f52002-07-19 01:08:59 +00002115 nanoget_repaint(buf, answer, x);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002116 wrefresh(bottomwin);
Chris Allegretta6df90f52002-07-19 01:08:59 +00002117 } /* while (kbinput ...) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002118
Chris Allegretta5af58892003-01-17 21:07:38 +00002119 /* We finished putting in an answer; reset x */
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00002120 x = (size_t)-1;
Chris Allegretta5af58892003-01-17 21:07:38 +00002121
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002122 return kbinput;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002123}
2124
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002125/* Ask a question on the statusbar. Answer will be stored in answer
2126 * global. Returns -1 on aborted enter, -2 on a blank string, and 0
2127 * otherwise, the valid shortcut key caught. def is any editable text
2128 * we want to put up by default.
2129 *
2130 * New arg tabs tells whether or not to allow tab completion. */
2131int statusq(bool allow_tabs, const shortcut *s, const char *def,
2132#ifndef NANO_SMALL
2133 historyheadtype *which_history,
2134#endif
2135 const char *msg, ...)
2136{
2137 va_list ap;
2138 char *foo = charalloc(COLS - 3);
2139 int ret;
2140#ifndef DISABLE_TABCOMP
2141 bool list = FALSE;
2142#endif
2143
2144 bottombars(s);
2145
2146 va_start(ap, msg);
2147 vsnprintf(foo, COLS - 4, msg, ap);
2148 va_end(ap);
2149 foo[COLS - 4] = '\0';
2150
2151 ret = nanogetstr(allow_tabs, foo, def,
2152#ifndef NANO_SMALL
2153 which_history,
2154#endif
2155 s
2156#ifndef DISABLE_TABCOMP
2157 , &list
2158#endif
2159 );
2160 free(foo);
2161 resetstatuspos = FALSE;
2162
2163 switch (ret) {
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002164 case NANO_FIRSTLINE_KEY:
2165 case NANO_FIRSTLINE_FKEY:
2166 do_first_line();
2167 resetstatuspos = TRUE;
2168 break;
2169 case NANO_LASTLINE_KEY:
2170 case NANO_LASTLINE_FKEY:
2171 do_last_line();
2172 resetstatuspos = TRUE;
2173 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002174#ifndef DISABLE_JUSTIFY
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002175 case NANO_PARABEGIN_KEY:
2176 case NANO_PARABEGIN_ALTKEY1:
2177 case NANO_PARABEGIN_ALTKEY2:
2178 do_para_begin();
2179 resetstatuspos = TRUE;
2180 break;
2181 case NANO_PARAEND_KEY:
2182 case NANO_PARAEND_ALTKEY1:
2183 case NANO_PARAEND_ALTKEY2:
2184 do_para_end();
2185 resetstatuspos = TRUE;
2186 break;
2187 case NANO_FULLJUSTIFY_KEY:
2188 case NANO_FULLJUSTIFY_ALTKEY:
2189 if (!ISSET(VIEW_MODE))
2190 do_full_justify();
2191 resetstatuspos = TRUE;
2192 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002193#endif
David Lawrence Ramsey1f204c02004-10-15 01:39:46 +00002194 case NANO_CANCEL_KEY:
2195 ret = -1;
2196 resetstatuspos = TRUE;
2197 break;
2198 case NANO_ENTER_KEY:
2199 ret = (answer[0] == '\0') ? -2 : 0;
2200 resetstatuspos = TRUE;
2201 break;
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00002202 }
2203 blank_statusbar();
2204
2205#ifdef DEBUG
2206 fprintf(stderr, "I got \"%s\"\n", answer);
2207#endif
2208
2209#ifndef DISABLE_TABCOMP
2210 /* if we've done tab completion, there might be a list of
2211 filename matches on the edit window at this point; make sure
2212 they're cleared off. */
2213 if (list)
2214 edit_refresh();
2215#endif
2216
2217 return ret;
2218}
2219
2220void statusq_abort(void)
2221{
2222 resetstatuspos = TRUE;
2223}
2224
Chris Allegrettaf717f982003-02-13 22:25:01 +00002225void titlebar(const char *path)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002226{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002227 size_t space;
2228 /* The space we have available for display. */
2229 size_t verlen = strlen(VERMSG) + 1;
2230 /* The length of the version message. */
2231 const char *prefix;
2232 /* "File:", "Dir:", or "New Buffer". Goes before filename. */
2233 size_t prefixlen;
2234 /* strlen(prefix) + 1. */
2235 const char *state;
2236 /* "Modified", "View", or spaces the length of "Modified".
2237 * Tells the state of this buffer. */
2238 size_t statelen = 0;
2239 /* strlen(state) + 1. */
2240 char *exppath = NULL;
2241 /* The file name, expanded for display. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002242 size_t exppathlen = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002243 /* strlen(exppath) + 1. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002244 bool newfie = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002245 /* Do we say "New Buffer"? */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002246 bool dots = FALSE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002247 /* Do we put an ellipsis before the path? */
Chris Allegrettaf4b96012001-01-03 07:11:47 +00002248
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002249 assert(path != NULL || filename != NULL);
2250 assert(COLS >= 0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002251
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002252 wattron(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002253
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002254 blank_titlebar();
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002255
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002256 if (COLS <= 5 || COLS - 5 < verlen)
2257 space = 0;
2258 else {
2259 space = COLS - 5 - verlen;
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002260 /* Reserve 2/3 of the screen plus one column for after the
2261 * version message. */
2262 if (space < COLS - (COLS / 3) + 1)
2263 space = COLS - (COLS / 3) + 1;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002264 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002265
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002266 if (COLS > 4) {
David Lawrence Ramsey8328fc22004-05-25 23:34:43 +00002267 /* The version message should only take up 1/3 of the screen
2268 * minus one column. */
2269 mvwaddnstr(topwin, 0, 2, VERMSG, (COLS / 3) - 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002270 waddstr(topwin, " ");
2271 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002272
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002273 if (ISSET(MODIFIED))
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002274 state = _("Modified");
2275 else if (path == NULL && ISSET(VIEW_MODE))
2276 state = _("View");
2277 else {
2278 if (space > 0)
2279 statelen = strnlen(_("Modified"), space - 1) + 1;
2280 state = &hblank[COLS - statelen];
2281 }
2282 statelen = strnlen(state, COLS);
2283 /* We need a space before state. */
2284 if ((ISSET(MODIFIED) || ISSET(VIEW_MODE)) && statelen < COLS)
2285 statelen++;
2286
2287 assert(space >= 0);
2288 if (space == 0 || statelen >= space)
2289 goto the_end;
2290
2291#ifndef DISABLE_BROWSER
2292 if (path != NULL)
2293 prefix = _("DIR:");
2294 else
2295#endif
2296 if (filename[0] == '\0') {
2297 prefix = _("New Buffer");
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002298 newfie = TRUE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002299 } else
2300 prefix = _("File:");
2301 assert(statelen < space);
2302 prefixlen = strnlen(prefix, space - statelen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002303 /* If newfie is FALSE, we need a space after prefix. */
2304 if (!newfie && prefixlen + statelen < space)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002305 prefixlen++;
2306
2307 if (path == NULL)
2308 path = filename;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002309 if (space >= prefixlen + statelen)
2310 space -= prefixlen + statelen;
2311 else
2312 space = 0;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002313 /* space is now the room we have for the file name. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002314 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002315 size_t lenpt = strlenpt(path), start_col;
2316
2317 if (lenpt > space)
2318 start_col = actual_x(path, lenpt - space);
2319 else
2320 start_col = 0;
2321 exppath = display_string(path, start_col, space);
2322 dots = (lenpt > space);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002323 exppathlen = strlen(exppath);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002324 }
2325
2326 if (!dots) {
2327 /* There is room for the whole filename, so we center it. */
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002328 waddnstr(topwin, hblank, (space - exppathlen) / 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002329 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002330 if (!newfie) {
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002331 assert(strlen(prefix) + 1 == prefixlen);
2332 waddch(topwin, ' ');
2333 waddstr(topwin, exppath);
2334 }
2335 } else {
2336 /* We will say something like "File: ...ename". */
2337 waddnstr(topwin, prefix, prefixlen);
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002338 if (space == 0 || newfie)
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002339 goto the_end;
2340 waddch(topwin, ' ');
2341 waddnstr(topwin, "...", space);
2342 if (space <= 3)
2343 goto the_end;
2344 space -= 3;
David Lawrence Ramseyf326ed72004-12-05 05:42:46 +00002345 assert(exppathlen == space + 3);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002346 waddnstr(topwin, exppath + 3, space);
2347 }
2348
2349 the_end:
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002350 free(exppath);
2351
2352 if (COLS <= 1 || statelen >= COLS - 1)
2353 mvwaddnstr(topwin, 0, 0, state, COLS);
2354 else {
2355 assert(COLS - statelen - 2 >= 0);
2356 mvwaddch(topwin, 0, COLS - statelen - 2, ' ');
2357 mvwaddnstr(topwin, 0, COLS - statelen - 1, state, statelen);
2358 }
Chris Allegretta8ce24132001-04-30 11:28:46 +00002359
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002360 wattroff(topwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00002361
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002362 wnoutrefresh(topwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002363 reset_cursor();
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002364 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002365}
2366
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002367/* If modified is not already set, set it and update titlebar. */
2368void set_modified(void)
2369{
2370 if (!ISSET(MODIFIED)) {
2371 SET(MODIFIED);
2372 titlebar(NULL);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002373 }
2374}
2375
2376void statusbar(const char *msg, ...)
2377{
2378 va_list ap;
2379
2380 va_start(ap, msg);
2381
2382 /* Curses mode is turned off. If we use wmove() now, it will muck
2383 * up the terminal settings. So we just use vfprintf(). */
2384 if (curses_ended) {
2385 vfprintf(stderr, msg, ap);
2386 va_end(ap);
2387 return;
2388 }
2389
2390 /* Blank out the line. */
2391 blank_statusbar();
2392
2393 if (COLS >= 4) {
2394 char *bar;
2395 char *foo;
2396 size_t start_x = 0, foo_len;
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002397#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
David Lawrence Ramsey846658e2004-12-05 04:18:26 +00002398 bool old_whitespace = ISSET(WHITESPACE_DISPLAY);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002399 UNSET(WHITESPACE_DISPLAY);
2400#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002401 bar = charalloc(COLS - 3);
2402 vsnprintf(bar, COLS - 3, msg, ap);
2403 va_end(ap);
2404 foo = display_string(bar, 0, COLS - 4);
David Lawrence Ramsey483ea322004-05-29 16:25:30 +00002405#if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
2406 if (old_whitespace)
2407 SET(WHITESPACE_DISPLAY);
2408#endif
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002409 free(bar);
2410 foo_len = strlen(foo);
2411 start_x = (COLS - foo_len - 4) / 2;
2412
2413 wmove(bottomwin, 0, start_x);
2414 wattron(bottomwin, A_REVERSE);
2415
2416 waddstr(bottomwin, "[ ");
2417 waddstr(bottomwin, foo);
2418 free(foo);
2419 waddstr(bottomwin, " ]");
2420 wattroff(bottomwin, A_REVERSE);
2421 wnoutrefresh(bottomwin);
2422 reset_cursor();
2423 wrefresh(edit);
2424 /* Leave the cursor at its position in the edit window, not
2425 * in the statusbar. */
2426 }
2427
2428 SET(DISABLE_CURPOS);
David Lawrence Ramseye5d8f322004-09-30 22:07:21 +00002429 statusblank = 26;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002430}
2431
Chris Allegretta6232d662002-05-12 19:52:15 +00002432void bottombars(const shortcut *s)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002433{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002434 size_t i, colwidth, slen;
Chris Allegrettaa8c22572002-02-15 19:17:02 +00002435
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002436 if (ISSET(NO_HELP))
2437 return;
2438
Chris Allegretta6232d662002-05-12 19:52:15 +00002439 if (s == main_list) {
2440 slen = MAIN_VISIBLE;
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002441 assert(slen <= length_of_list(s));
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002442 } else {
Chris Allegretta6232d662002-05-12 19:52:15 +00002443 slen = length_of_list(s);
2444
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002445 /* Don't show any more shortcuts than the main list does. */
David Lawrence Ramsey8d3e7f32004-05-13 17:28:03 +00002446 if (slen > MAIN_VISIBLE)
2447 slen = MAIN_VISIBLE;
2448 }
2449
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002450 /* There will be this many characters per column. We need at least
2451 * 3 to display anything properly.*/
2452 colwidth = COLS / ((slen / 2) + (slen % 2));
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002453
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00002454 blank_bottombars();
Chris Allegretta658399a2001-06-14 02:54:22 +00002455
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002456 for (i = 0; i < slen; i++, s = s->next) {
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002457 const char *keystr;
Chris Allegretta658399a2001-06-14 02:54:22 +00002458
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002459 /* Yucky sentinel values we can't handle a better way. */
Chris Allegrettaa65ba512003-01-05 20:57:07 +00002460#ifndef NANO_SMALL
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002461 if (s->ctrlval == NANO_HISTORY_KEY)
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002462 keystr = _("Up");
2463 else {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00002464#endif
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002465 char foo[4];
Chris Allegretta658399a2001-06-14 02:54:22 +00002466
David Lawrence Ramsey0ff01a92004-10-25 15:00:38 +00002467 if (s->ctrlval == NANO_CONTROL_SPACE)
2468 strcpy(foo, "^ ");
2469 else if (s->ctrlval == NANO_CONTROL_8)
2470 strcpy(foo, "^?");
2471 /* Normal values. Assume that the shortcut has an
2472 * equivalent control key, meta key sequence, or both. */
2473 else if (s->ctrlval != NANO_NO_KEY)
2474 sprintf(foo, "^%c", s->ctrlval + 64);
2475 else if (s->metaval != NANO_NO_KEY)
2476 sprintf(foo, "M-%c", toupper(s->metaval));
2477
2478 keystr = foo;
2479#ifndef NANO_SMALL
2480 }
2481#endif
2482
2483 wmove(bottomwin, 1 + i % 2, (i / 2) * colwidth);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002484 onekey(keystr, s->desc, colwidth);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002485 }
2486
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002487 wnoutrefresh(bottomwin);
2488 reset_cursor();
2489 wrefresh(edit);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002490}
2491
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002492/* Write a shortcut key to the help area at the bottom of the window.
2493 * keystroke is e.g. "^G" and desc is e.g. "Get Help". We are careful
2494 * to write at most len characters, even if len is very small and
2495 * keystroke and desc are long. Note that waddnstr(,,(size_t)-1) adds
2496 * the whole string! We do not bother padding the entry with blanks. */
2497void onekey(const char *keystroke, const char *desc, size_t len)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002498{
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002499 assert(keystroke != NULL && desc != NULL && len >= 0);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002500 wattron(bottomwin, A_REVERSE);
2501 waddnstr(bottomwin, keystroke, len);
2502 wattroff(bottomwin, A_REVERSE);
David Lawrence Ramseyfa394042004-05-23 21:11:14 +00002503 len -= strlen(keystroke) + 1;
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002504 if (len > 0) {
2505 waddch(bottomwin, ' ');
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00002506 waddnstr(bottomwin, desc, len);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002507 }
2508}
2509
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002510/* And so start the display update routines. */
2511
2512#ifndef NDEBUG
2513int check_linenumbers(const filestruct *fileptr)
Chris Allegretta4da1fc62000-06-21 03:00:43 +00002514{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002515 int check_line = 0;
2516 const filestruct *filetmp;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002517
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002518 for (filetmp = edittop; filetmp != fileptr; filetmp = filetmp->next)
2519 check_line++;
2520 return check_line;
Robert Siemborskid8510b22000-06-06 23:04:06 +00002521}
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002522#endif
Robert Siemborskid8510b22000-06-06 23:04:06 +00002523
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002524/* nano scrolls horizontally within a line in chunks. This function
2525 * returns the column number of the first character displayed in the
2526 * window when the cursor is at the given column. Note that
2527 * 0 <= column - get_page_start(column) < COLS. */
2528size_t get_page_start(size_t column)
Chris Allegretta6df90f52002-07-19 01:08:59 +00002529{
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002530 assert(COLS > 0);
2531 if (column == 0 || column < COLS - 1)
2532 return 0;
2533 else if (COLS > 9)
David Lawrence Ramsey66081d42004-01-22 07:25:31 +00002534 return column - 7 - (column - 7) % (COLS - 8);
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002535 else if (COLS > 2)
2536 return column - (COLS - 2);
2537 else
2538 return column - (COLS - 1);
2539 /* The parentheses are necessary to avoid overflow. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002540}
2541
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002542/* Resets current_y, based on the position of current, and puts the
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002543 * cursor in the edit window at (current_y, current_x). */
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002544void reset_cursor(void)
2545{
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002546 /* If we haven't opened any files yet, put the cursor in the top
2547 * left corner of the edit window and get out. */
2548 if (edittop == NULL || current == NULL) {
2549 wmove(edit, 0, 0);
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002550 return;
David Lawrence Ramsey02517e02004-09-05 21:40:31 +00002551 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002552
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002553 current_y = current->lineno - edittop->lineno;
2554 if (current_y < editwinrows) {
2555 size_t x = xplustabs();
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00002556 wmove(edit, current_y, x - get_page_start(x));
2557 }
David Lawrence Ramsey0341b582002-08-21 16:10:37 +00002558}
Chris Allegretta6df90f52002-07-19 01:08:59 +00002559
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002560/* edit_add() takes care of the job of actually painting a line into the
2561 * edit window. fileptr is the line to be painted, at row yval of the
2562 * window. converted is the actual string to be written to the window,
2563 * with tabs and control characters replaced by strings of regular
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00002564 * characters. start is the column number of the first character of
2565 * this page. That is, the first character of converted corresponds to
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002566 * character number actual_x(fileptr->data, start) of the line. */
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002567void edit_add(const filestruct *fileptr, const char *converted, int
2568 yval, size_t start)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002569{
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002570#if defined(ENABLE_COLOR) || !defined(NANO_SMALL)
2571 size_t startpos = actual_x(fileptr->data, start);
2572 /* The position in fileptr->data of the leftmost character
2573 * that displays at least partially on the window. */
2574 size_t endpos = actual_x(fileptr->data, start + COLS - 1) + 1;
2575 /* The position in fileptr->data of the first character that is
2576 * completely off the window to the right.
2577 *
2578 * Note that endpos might be beyond the null terminator of the
2579 * string. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002580#endif
2581
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002582 assert(fileptr != NULL && converted != NULL);
2583 assert(strlen(converted) <= COLS);
2584
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002585 /* Just paint the string in any case (we'll add color or reverse on
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002586 * just the text that needs it). */
2587 mvwaddstr(edit, yval, 0, converted);
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002588
Chris Allegretta7dd77682001-12-08 19:52:28 +00002589#ifdef ENABLE_COLOR
Chris Allegretta1dd0bc92002-10-13 18:43:45 +00002590 if (colorstrings != NULL && ISSET(COLOR_SYNTAX)) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002591 const colortype *tmpcolor = colorstrings;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002592
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002593 for (; tmpcolor != NULL; tmpcolor = tmpcolor->next) {
2594 int x_start;
2595 /* Starting column for mvwaddnstr. Zero-based. */
2596 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002597 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002598 * characters on a whole line. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002599 regmatch_t startmatch; /* match position for start_regexp */
2600 regmatch_t endmatch; /* match position for end_regexp */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002601
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002602 if (tmpcolor->bright)
2603 wattron(edit, A_BOLD);
2604 wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002605 /* Two notes about regexec(). Return value 0 means there is
2606 * a match. Also, rm_eo is the first non-matching character
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002607 * after the match. */
2608
2609 /* First case, tmpcolor is a single-line expression. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002610 if (tmpcolor->end == NULL) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002611 size_t k = 0;
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002612
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002613 /* We increment k by rm_eo, to move past the end of the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002614 * last match. Even though two matches may overlap, we
2615 * want to ignore them, so that we can highlight
2616 * C-strings correctly. */
2617 while (k < endpos) {
2618 /* Note the fifth parameter to regexec(). It says
2619 * not to match the beginning-of-line character
2620 * unless k is 0. If regexec() returns REG_NOMATCH,
2621 * there are no more matches in the line. */
Chris Allegrettace452fb2003-02-03 02:56:44 +00002622 if (regexec(&tmpcolor->start, &fileptr->data[k], 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002623 &startmatch, k == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002624 break;
2625 /* Translate the match to the beginning of the line. */
2626 startmatch.rm_so += k;
2627 startmatch.rm_eo += k;
David Lawrence Ramsey2ab03f62002-10-17 02:19:31 +00002628 if (startmatch.rm_so == startmatch.rm_eo) {
2629 startmatch.rm_eo++;
Chris Allegretta7c27be42002-05-05 23:03:54 +00002630 statusbar(_("Refusing 0 length regex match"));
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002631 } else if (startmatch.rm_so < endpos &&
2632 startmatch.rm_eo > startpos) {
2633 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002634 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002635 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002636 x_start = strnlenpt(fileptr->data,
2637 startmatch.rm_so) - start;
2638 paintlen = strnlenpt(fileptr->data,
2639 startmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002640 if (paintlen > COLS - x_start)
2641 paintlen = COLS - x_start;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002642
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002643 assert(0 <= x_start && 0 < paintlen &&
2644 x_start + paintlen <= COLS);
2645 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002646 converted + x_start, paintlen);
2647 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002648 k = startmatch.rm_eo;
Chris Allegretta598106e2002-01-19 01:59:37 +00002649 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002650 } else {
2651 /* This is a multi-line regexp. There are two steps.
2652 * First, we have to see if the beginning of the line is
2653 * colored by a start on an earlier line, and an end on
2654 * this line or later.
2655 *
2656 * We find the first line before fileptr matching the
2657 * start. If every match on that line is followed by an
2658 * end, then go to step two. Otherwise, find the next line
2659 * after start_line matching the end. If that line is not
2660 * before fileptr, then paint the beginning of this line. */
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002661
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002662 const filestruct *start_line = fileptr->prev;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002663 /* the first line before fileptr matching start */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002664 regoff_t start_col;
2665 /* where it starts in that line */
2666 const filestruct *end_line;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002667
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002668 while (start_line != NULL &&
Chris Allegrettace452fb2003-02-03 02:56:44 +00002669 regexec(&tmpcolor->start, start_line->data, 1,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002670 &startmatch, 0) == REG_NOMATCH) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002671 /* If there is an end on this line, there is no need
2672 * to look for starts on earlier lines. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002673 if (regexec(tmpcolor->end, start_line->data, 0,
2674 NULL, 0) == 0)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002675 goto step_two;
2676 start_line = start_line->prev;
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002677 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002678 /* No start found, so skip to the next step. */
2679 if (start_line == NULL)
2680 goto step_two;
2681 /* Now start_line is the first line before fileptr
2682 * containing a start match. Is there a start on this
2683 * line not followed by an end on this line? */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002684
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002685 start_col = 0;
David Lawrence Ramsey6aec4b82004-03-15 20:26:30 +00002686 while (TRUE) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002687 start_col += startmatch.rm_so;
2688 startmatch.rm_eo -= startmatch.rm_so;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002689 if (regexec(tmpcolor->end,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002690 start_line->data + start_col + startmatch.rm_eo,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002691 0, NULL, start_col + startmatch.rm_eo == 0 ? 0 :
2692 REG_NOTBOL) == REG_NOMATCH)
2693 /* No end found after this start. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002694 break;
2695 start_col++;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002696 if (regexec(&tmpcolor->start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002697 start_line->data + start_col, 1,
2698 &startmatch, REG_NOTBOL) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002699 /* No later start on this line. */
2700 goto step_two;
2701 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002702 /* Indeed, there is a start not followed on this line by
2703 * an end. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002704
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002705 /* We have already checked that there is no end before
2706 * fileptr and after the start. Is there an end after
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002707 * the start at all? We don't paint unterminated
2708 * starts. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002709 end_line = fileptr;
Chris Allegrettace452fb2003-02-03 02:56:44 +00002710 while (end_line != NULL &&
David Lawrence Ramsey537a8802004-06-24 22:39:24 +00002711 regexec(tmpcolor->end, end_line->data, 1,
2712 &endmatch, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002713 end_line = end_line->next;
2714
2715 /* No end found, or it is too early. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002716 if (end_line == NULL ||
2717 (end_line == fileptr && endmatch.rm_eo <= startpos))
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002718 goto step_two;
2719
2720 /* Now paint the start of fileptr. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002721 paintlen = end_line != fileptr ? COLS :
2722 strnlenpt(fileptr->data, endmatch.rm_eo) - start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002723 if (paintlen > COLS)
2724 paintlen = COLS;
2725
2726 assert(0 < paintlen && paintlen <= COLS);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002727 mvwaddnstr(edit, yval, 0, converted, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002728
2729 /* We have already painted the whole line. */
2730 if (paintlen == COLS)
2731 goto skip_step_two;
2732
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002733 step_two:
2734 /* Second step, we look for starts on this line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002735 start_col = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002736 while (start_col < endpos) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002737 if (regexec(&tmpcolor->start,
2738 fileptr->data + start_col, 1, &startmatch,
2739 start_col == 0 ? 0 : REG_NOTBOL) == REG_NOMATCH ||
2740 start_col + startmatch.rm_so >= endpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002741 /* No more starts on this line. */
2742 break;
2743 /* Translate the match to be relative to the
2744 * beginning of the line. */
2745 startmatch.rm_so += start_col;
2746 startmatch.rm_eo += start_col;
2747
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002748 if (startmatch.rm_so <= startpos)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002749 x_start = 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002750 else
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002751 x_start = strnlenpt(fileptr->data,
2752 startmatch.rm_so) - start;
2753 if (regexec(tmpcolor->end,
2754 fileptr->data + startmatch.rm_eo, 1, &endmatch,
2755 startmatch.rm_eo == 0 ? 0 : REG_NOTBOL) == 0) {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002756 /* Translate the end match to be relative to the
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002757 * beginning of the line. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002758 endmatch.rm_so += startmatch.rm_eo;
2759 endmatch.rm_eo += startmatch.rm_eo;
2760 /* There is an end on this line. But does it
David Lawrence Ramsey94e70942004-05-13 18:04:31 +00002761 * appear on this page, and is the match more
2762 * than zero characters long? */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002763 if (endmatch.rm_eo > startpos &&
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002764 endmatch.rm_eo > startmatch.rm_so) {
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002765 paintlen = strnlenpt(fileptr->data,
2766 endmatch.rm_eo) - start - x_start;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002767 if (x_start + paintlen > COLS)
2768 paintlen = COLS - x_start;
2769
2770 assert(0 <= x_start && 0 < paintlen &&
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002771 x_start + paintlen <= COLS);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002772 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002773 converted + x_start, paintlen);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002774 }
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002775 } else {
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002776 /* There is no end on this line. But we haven't
2777 * yet looked for one on later lines. */
2778 end_line = fileptr->next;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002779 while (end_line != NULL &&
2780 regexec(tmpcolor->end, end_line->data, 0,
2781 NULL, 0) == REG_NOMATCH)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002782 end_line = end_line->next;
2783 if (end_line != NULL) {
2784 assert(0 <= x_start && x_start < COLS);
2785 mvwaddnstr(edit, yval, x_start,
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002786 converted + x_start, COLS - x_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002787 /* We painted to the end of the line, so
2788 * don't bother checking any more starts. */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002789 break;
Chris Allegretta3674c1d2002-05-12 20:43:49 +00002790 }
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002791 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002792 start_col = startmatch.rm_so + 1;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002793 } /* while start_col < endpos */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002794 } /* if (tmp_color->end != NULL) */
Chris Allegretta6c1e6612002-01-19 16:52:34 +00002795
Chris Allegrettace452fb2003-02-03 02:56:44 +00002796 skip_step_two:
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002797 wattroff(edit, A_BOLD);
2798 wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
2799 } /* for tmpcolor in colorstrings */
2800 }
Chris Allegretta598106e2002-01-19 01:59:37 +00002801#endif /* ENABLE_COLOR */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002802
Chris Allegretta7dd77682001-12-08 19:52:28 +00002803#ifndef NANO_SMALL
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002804 if (ISSET(MARK_ISSET)
2805 && (fileptr->lineno <= mark_beginbuf->lineno
2806 || fileptr->lineno <= current->lineno)
2807 && (fileptr->lineno >= mark_beginbuf->lineno
2808 || fileptr->lineno >= current->lineno)) {
2809 /* fileptr is at least partially selected. */
Chris Allegretta2fa11b82001-12-02 04:55:44 +00002810
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002811 const filestruct *top;
2812 /* Either current or mark_beginbuf, whichever is first. */
2813 size_t top_x;
2814 /* current_x or mark_beginx, corresponding to top. */
2815 const filestruct *bot;
2816 size_t bot_x;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002817 int x_start;
2818 /* Starting column for mvwaddnstr. Zero-based. */
2819 int paintlen;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002820 /* Number of chars to paint on this line. There are COLS
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002821 * characters on a whole line. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00002822
David Lawrence Ramsey90e59c12004-11-05 23:03:03 +00002823 mark_order(&top, &top_x, &bot, &bot_x, NULL);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002824
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002825 if (top->lineno < fileptr->lineno || top_x < startpos)
2826 top_x = startpos;
2827 if (bot->lineno > fileptr->lineno || bot_x > endpos)
2828 bot_x = endpos;
2829
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002830 /* The selected bit of fileptr is on this page. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002831 if (top_x < endpos && bot_x > startpos) {
2832 assert(startpos <= top_x);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002833
2834 /* x_start is the expanded location of the beginning of the
2835 * mark minus the beginning of the page. */
2836 x_start = strnlenpt(fileptr->data, top_x) - start;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002837
2838 if (bot_x >= endpos)
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002839 /* If the end of the mark is off the page, paintlen is
2840 * -1, meaning that everything on the line gets
2841 * painted. */
2842 paintlen = -1;
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002843 else
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002844 /* Otherwise, paintlen is the expanded location of the
2845 * end of the mark minus the expanded location of the
2846 * beginning of the mark. */
David Lawrence Ramseye5b2f832004-04-29 06:30:36 +00002847 paintlen = strnlenpt(fileptr->data, bot_x)
2848 - (x_start + start);
David Lawrence Ramsey4dcd0702003-10-03 04:20:28 +00002849
2850 /* If x_start is before the beginning of the page, shift
2851 * paintlen x_start characters to compensate, and put
2852 * x_start at the beginning of the page. */
2853 if (x_start < 0) {
2854 paintlen += x_start;
2855 x_start = 0;
2856 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002857
2858 assert(x_start >= 0 && x_start <= strlen(converted));
2859
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002860 wattron(edit, A_REVERSE);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002861 mvwaddnstr(edit, yval, x_start, converted + x_start, paintlen);
Chris Allegrettabd9e7c32000-10-26 01:44:42 +00002862 wattroff(edit, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002863 }
Chris Allegretta08893e02001-11-29 02:42:27 +00002864 }
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002865#endif /* !NANO_SMALL */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002866}
2867
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002868/* Just update one line in the edit buffer. Basically a wrapper for
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002869 * edit_add().
2870 *
David Lawrence Ramsey07d3feb2004-04-16 05:15:11 +00002871 * If fileptr != current, then index is considered 0. The line will be
2872 * displayed starting with fileptr->data[index]. Likely args are
2873 * current_x or 0. */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002874void update_line(const filestruct *fileptr, size_t index)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002875{
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002876 int line;
2877 /* line in the edit window for CURSES calls */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002878 char *converted;
2879 /* fileptr->data converted to have tabs and control characters
2880 * expanded. */
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002881 size_t page_start;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002882
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002883 assert(fileptr != NULL);
Robert Siemborski53154a72000-06-18 00:11:03 +00002884
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002885 line = fileptr->lineno - edittop->lineno;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002886
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002887 /* We assume the line numbers are valid. Is that really true? */
2888 assert(line < 0 || line == check_linenumbers(fileptr));
2889
2890 if (line < 0 || line >= editwinrows)
2891 return;
2892
2893 /* First, blank out the line (at a minimum) */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002894 mvwaddstr(edit, line, 0, hblank);
2895
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002896 /* Next, convert variables that index the line to their equivalent
2897 * positions in the expanded line. */
David Lawrence Ramsey2dd7ed12003-09-29 05:15:24 +00002898 index = (fileptr == current) ? strnlenpt(fileptr->data, index) : 0;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002899 page_start = get_page_start(index);
Chris Allegretta5beed502003-01-05 20:41:21 +00002900
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002901 /* Expand the line, replacing Tab by spaces, and control characters
2902 * by their display form. */
2903 converted = display_string(fileptr->data, page_start, COLS);
Robert Siemborski53875912000-06-16 04:25:30 +00002904
Chris Allegretta4dc03d52002-05-11 03:04:44 +00002905 /* Now, paint the line */
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002906 edit_add(fileptr, converted, line, page_start);
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002907 free(converted);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002908
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002909 if (page_start > 0)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002910 mvwaddch(edit, line, 0, '$');
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00002911 if (strlenpt(fileptr->data) > page_start + COLS)
David Lawrence Ramsey1f28b8f2002-09-27 14:21:59 +00002912 mvwaddch(edit, line, COLS - 1, '$');
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00002913}
2914
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002915/* Return a nonzero value if we need an update after moving
2916 * horizontally. We need one if the mark is on or if old_pww and
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002917 * placewewant are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002918int need_horizontal_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002919{
2920 return
2921#ifndef NANO_SMALL
2922 ISSET(MARK_ISSET) ||
2923#endif
2924 get_page_start(old_pww) != get_page_start(placewewant);
2925}
2926
2927/* Return a nonzero value if we need an update after moving vertically.
2928 * We need one if the mark is on or if old_pww and placewewant
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002929 * are on different pages. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00002930int need_vertical_update(size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002931{
2932 return
2933#ifndef NANO_SMALL
2934 ISSET(MARK_ISSET) ||
2935#endif
2936 get_page_start(old_pww) != get_page_start(placewewant);
2937}
2938
2939/* Scroll the edit window in the given direction and the given number
2940 * of lines, and draw new lines on the blank lines left after the
2941 * scrolling. direction is the direction to scroll, either UP or DOWN,
2942 * and nlines is the number of lines to scroll. Don't redraw the old
2943 * topmost or bottommost line (where we assume current is) before
2944 * scrolling or draw the new topmost or bottommost line after scrolling
2945 * (where we assume current will be), since we don't know where we are
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00002946 * on the page or whether we'll stay there. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00002947void edit_scroll(updown direction, int nlines)
2948{
2949 filestruct *foo;
2950 int i, scroll_rows = 0;
2951
2952 /* Scrolling less than one line or more than editwinrows lines is
2953 * redundant, so don't allow it. */
2954 if (nlines < 1 || nlines > editwinrows)
2955 return;
2956
2957 /* Move the top line of the edit window up or down (depending on the
2958 * value of direction) nlines lines. If there are fewer lines of
2959 * text than that left, move it to the top or bottom line of the
2960 * file (depending on the value of direction). Keep track of
2961 * how many lines we moved in scroll_rows. */
2962 for (i = nlines; i > 0; i--) {
2963 if (direction == UP) {
2964 if (edittop->prev == NULL)
2965 break;
2966 edittop = edittop->prev;
2967 scroll_rows--;
2968 } else {
2969 if (edittop->next == NULL)
2970 break;
2971 edittop = edittop->next;
2972 scroll_rows++;
2973 }
2974 }
2975
2976 /* Scroll the text on the screen up or down scroll_rows lines,
2977 * depending on the value of direction. */
2978 scrollok(edit, TRUE);
2979 wscrl(edit, scroll_rows);
2980 scrollok(edit, FALSE);
2981
2982 foo = edittop;
2983 if (direction != UP) {
2984 int slines = editwinrows - nlines;
2985 for (; slines > 0 && foo != NULL; slines--)
2986 foo = foo->next;
2987 }
2988
2989 /* And draw new lines on the blank top or bottom lines of the edit
2990 * window, depending on the value of direction. Don't draw the new
2991 * topmost or new bottommost line. */
2992 while (scroll_rows != 0 && foo != NULL) {
2993 if (foo->next != NULL)
2994 update_line(foo, 0);
2995 if (direction == UP)
2996 scroll_rows++;
2997 else
2998 scroll_rows--;
2999 foo = foo->next;
3000 }
3001}
3002
3003/* Update any lines between old_current and current that need to be
David Lawrence Ramsey684b1932004-05-31 14:47:12 +00003004 * updated. */
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003005void edit_redraw(const filestruct *old_current, size_t old_pww)
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003006{
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003007 int do_refresh = need_vertical_update(0) ||
3008 need_vertical_update(old_pww);
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003009 const filestruct *foo;
3010
3011 /* If either old_current or current is offscreen, refresh the screen
3012 * and get out. */
3013 if (old_current->lineno < edittop->lineno || old_current->lineno >=
3014 edittop->lineno + editwinrows || current->lineno <
3015 edittop->lineno || current->lineno >= edittop->lineno +
3016 editwinrows) {
3017 edit_refresh();
3018 return;
3019 }
3020
David Lawrence Ramseyce1d7652004-06-01 18:32:36 +00003021 /* Update old_current and current if we're not on the first page
3022 * and/or we're not on the same page as before. If the mark is on,
3023 * update all the lines between old_current and current too. */
David Lawrence Ramsey2ed225f2004-05-28 20:44:09 +00003024 foo = old_current;
3025 while (foo != current) {
3026 if (do_refresh)
3027 update_line(foo, 0);
3028#ifndef NANO_SMALL
3029 if (!ISSET(MARK_ISSET))
3030#endif
3031 break;
3032 if (foo->lineno > current->lineno)
3033 foo = foo->prev;
3034 else
3035 foo = foo->next;
3036 }
3037 if (do_refresh)
3038 update_line(current, current_x);
3039}
3040
Chris Allegretta6df90f52002-07-19 01:08:59 +00003041/* Refresh the screen without changing the position of lines. */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003042void edit_refresh(void)
3043{
Chris Allegretta63d0b482003-01-26 19:47:10 +00003044 if (current->lineno < edittop->lineno ||
3045 current->lineno >= edittop->lineno + editwinrows)
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003046 /* Note that edit_update() changes edittop so that it's in range
3047 * of current. Thus, when it then calls edit_refresh(), there
3048 * is no danger of getting an infinite loop. */
3049 edit_update(
3050#ifndef NANO_SMALL
3051 ISSET(SMOOTHSCROLL) ? NONE :
3052#endif
3053 CENTER);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003054 else {
3055 int nlines = 0;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003056 const filestruct *foo = edittop;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003057
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003058#ifdef DEBUG
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003059 fprintf(stderr, "edit_refresh(): edittop->lineno = %d\n", edittop->lineno);
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003060#endif
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003061
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003062 while (nlines < editwinrows) {
David Lawrence Ramsey9d325a02004-05-29 03:03:52 +00003063 update_line(foo, foo == current ? current_x : 0);
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003064 nlines++;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003065 if (foo->next == NULL)
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003066 break;
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003067 foo = foo->next;
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003068 }
3069 while (nlines < editwinrows) {
3070 mvwaddstr(edit, nlines, 0, hblank);
3071 nlines++;
3072 }
David Lawrence Ramsey1044d742004-02-24 20:41:39 +00003073 reset_cursor();
David Lawrence Ramsey9b13ff32002-12-22 16:30:00 +00003074 wrefresh(edit);
Chris Allegretta6df90f52002-07-19 01:08:59 +00003075 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003076}
3077
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003078/* A nice generic routine to update the edit buffer. We keep current in
3079 * the same place and move edittop to put it in range of current. */
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003080void edit_update(topmidnone location)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003081{
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003082 filestruct *foo = current;
3083
Chris Allegretta6df90f52002-07-19 01:08:59 +00003084 if (location != TOP) {
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003085 /* If location is CENTER, we move edittop up (editwinrows / 2)
3086 * lines. This puts current at the center of the screen. If
3087 * location is NONE, we move edittop up current_y lines if
3088 * current_y is in range of the screen, 0 lines if current_y is
3089 * less than 0, or (editwinrows - 1) lines if current_y is
3090 * greater than (editwinrows - 1). This puts current at the
3091 * same place on the screen as before, or at the top or bottom
3092 * of the screen if edittop is beyond either. */
3093 int goal;
3094
3095 if (location == CENTER)
3096 goal = editwinrows / 2;
3097 else {
3098 goal = current_y;
3099
3100 /* Limit goal to (editwinrows - 1) lines maximum. */
3101 if (goal > editwinrows - 1)
3102 goal = editwinrows - 1;
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003103 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003104
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003105 for (; goal > 0 && foo->prev != NULL; goal--)
3106 foo = foo->prev;
Chris Allegretta6df90f52002-07-19 01:08:59 +00003107 }
David Lawrence Ramsey50c7f2d2004-08-27 17:02:05 +00003108
David Lawrence Ramsey20b83502004-08-26 18:07:58 +00003109 edittop = foo;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003110 edit_refresh();
3111}
3112
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003113/* Ask a simple yes/no question, specified in msg, on the statusbar.
3114 * Return 1 for Y, 0 for N, 2 for All (if all is TRUE when passed in)
3115 * and -1 for abort (^C). */
David Lawrence Ramsey045883a2004-10-05 20:11:31 +00003116int do_yesno(bool all, const char *msg)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003117{
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003118 int ok = -2, width = 16;
David Lawrence Ramsey45eda522004-06-12 21:20:33 +00003119 const char *yesstr; /* String of yes characters accepted. */
3120 const char *nostr; /* Same for no. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003121 const char *allstr; /* And all, surprise! */
Chris Allegretta235ab192001-04-12 13:24:40 +00003122
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003123 /* yesstr, nostr, and allstr are strings of any length. Each string
3124 * consists of all characters accepted as a valid character for that
3125 * value. The first value will be the one displayed in the
3126 * shortcuts. Translators: if possible, specify both the shortcuts
3127 * for your language and English. For example, in French: "OoYy"
3128 * for "Oui". */
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003129 yesstr = _("Yy");
3130 nostr = _("Nn");
3131 allstr = _("Aa");
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003132
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003133 if (!ISSET(NO_HELP)) {
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003134 char shortstr[3]; /* Temp string for Y, N, A. */
Chris Allegretta6232d662002-05-12 19:52:15 +00003135
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003136 if (COLS < 32)
3137 width = COLS / 2;
3138
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003139 /* Write the bottom of the screen. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003140 blank_bottombars();
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003141
Chris Allegretta6232d662002-05-12 19:52:15 +00003142 sprintf(shortstr, " %c", yesstr[0]);
Chris Allegrettadb28e962003-01-28 01:23:40 +00003143 wmove(bottomwin, 1, 0);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003144 onekey(shortstr, _("Yes"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003145
3146 if (all) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003147 wmove(bottomwin, 1, width);
Chris Allegretta6232d662002-05-12 19:52:15 +00003148 shortstr[1] = allstr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003149 onekey(shortstr, _("All"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003150 }
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003151
Chris Allegrettadb28e962003-01-28 01:23:40 +00003152 wmove(bottomwin, 2, 0);
Chris Allegretta6232d662002-05-12 19:52:15 +00003153 shortstr[1] = nostr[0];
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003154 onekey(shortstr, _("No"), width);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003155
Chris Allegrettadb28e962003-01-28 01:23:40 +00003156 wmove(bottomwin, 2, 16);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003157 onekey("^C", _("Cancel"), width);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003158 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003159
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003160 wattron(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003161
3162 blank_statusbar();
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003163 mvwaddnstr(bottomwin, 0, 0, msg, COLS - 1);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003164
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003165 wattroff(bottomwin, A_REVERSE);
Chris Allegretta8ce24132001-04-30 11:28:46 +00003166
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003167 wrefresh(bottomwin);
3168
Chris Allegrettadb28e962003-01-28 01:23:40 +00003169 do {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003170 int kbinput;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003171 bool meta_key, func_key;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003172#ifndef DISABLE_MOUSE
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003173 int mouse_x, mouse_y;
Chris Allegretta235ab192001-04-12 13:24:40 +00003174#endif
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003175
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003176 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003177
3178 if (kbinput == NANO_CANCEL_KEY)
Chris Allegrettadb28e962003-01-28 01:23:40 +00003179 ok = -1;
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003180#ifndef DISABLE_MOUSE
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003181 /* Look, ma! We get to duplicate lots of code from
3182 * do_mouse()!! */
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003183 else if (kbinput == KEY_MOUSE) {
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003184 get_mouseinput(&mouse_x, &mouse_y, FALSE);
Chris Allegretta4ce8e3b2001-02-16 01:49:31 +00003185
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003186 if (mouse_x != -1 && mouse_y != -1 && !ISSET(NO_HELP) &&
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003187 wenclose(bottomwin, mouse_y, mouse_x) &&
3188 mouse_x < (width * 2) && mouse_y >= editwinrows + 3) {
David Lawrence Ramseyf4276942003-12-24 03:33:09 +00003189 int x = mouse_x / width;
3190 /* Did we click in the first column of shortcuts, or
3191 * the second? */
3192 int y = mouse_y - editwinrows - 3;
3193 /* Did we click in the first row of shortcuts? */
3194
3195 assert(0 <= x && x <= 1 && 0 <= y && y <= 1);
3196
3197 /* x = 0 means they clicked Yes or No.
3198 * y = 0 means Yes or All. */
3199 ok = -2 * x * y + x - y + 1;
3200
3201 if (ok == 2 && !all)
3202 ok = -2;
3203 }
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003204 }
Chris Allegrettadb28e962003-01-28 01:23:40 +00003205#endif
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003206 /* Look for the kbinput in the yes, no and (optionally) all
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003207 * strings. */
Chris Allegrettadb28e962003-01-28 01:23:40 +00003208 else if (strchr(yesstr, kbinput) != NULL)
3209 ok = 1;
3210 else if (strchr(nostr, kbinput) != NULL)
3211 ok = 0;
3212 else if (all && strchr(allstr, kbinput) != NULL)
3213 ok = 2;
3214 } while (ok == -2);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003215
Chris Allegrettadb28e962003-01-28 01:23:40 +00003216 return ok;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003217}
3218
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003219void total_refresh(void)
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003220{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003221 clearok(topwin, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003222 clearok(edit, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003223 clearok(bottomwin, TRUE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003224 wnoutrefresh(topwin);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003225 wnoutrefresh(edit);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003226 wnoutrefresh(bottomwin);
3227 doupdate();
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003228 clearok(topwin, FALSE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003229 clearok(edit, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003230 clearok(bottomwin, FALSE);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003231 titlebar(NULL);
David Lawrence Ramsey74835712004-12-04 17:41:52 +00003232 edit_refresh();
3233 /* FIXME: bottomwin needs to be refreshed too. */
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003234}
3235
3236void display_main_list(void)
3237{
3238 bottombars(main_list);
3239}
3240
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003241/* If constant is FALSE, the user typed Ctrl-C, so we unconditionally
3242 * display the cursor position. Otherwise, we display it only if the
3243 * character position changed and DISABLE_CURPOS is not set.
Chris Allegrettad26ab912003-01-28 01:16:47 +00003244 *
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003245 * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
3246 * old_i and old_totsize. That way, we leave the current statusbar
3247 * alone, but next time we will display. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003248void do_cursorpos(bool constant)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003249{
Chris Allegrettad26ab912003-01-28 01:16:47 +00003250 const filestruct *fileptr;
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003251 size_t i = 0;
3252 static size_t old_i = 0;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003253 static long old_totsize = -1;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003254
Chris Allegrettad26ab912003-01-28 01:16:47 +00003255 assert(current != NULL && fileage != NULL && totlines != 0);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003256
3257 if (old_totsize == -1)
3258 old_totsize = totsize;
3259
Chris Allegrettad26ab912003-01-28 01:16:47 +00003260 for (fileptr = fileage; fileptr != current; fileptr = fileptr->next) {
3261 assert(fileptr != NULL);
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003262 i += strlen(fileptr->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003263 }
Chris Allegrettaf27c6972002-02-12 01:57:24 +00003264 i += current_x;
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003265
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003266 /* Check whether totsize is correct. Else there is a bug
3267 * somewhere. */
3268 assert(current != filebot || i == totsize);
3269
Chris Allegrettad26ab912003-01-28 01:16:47 +00003270 if (constant && ISSET(DISABLE_CURPOS)) {
3271 UNSET(DISABLE_CURPOS);
3272 old_i = i;
3273 old_totsize = totsize;
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003274 return;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003275 }
Chris Allegretta14b3ca92002-01-25 21:59:02 +00003276
David Lawrence Ramsey4178db02004-05-23 21:23:23 +00003277 /* If constant is FALSE, display the position on the statusbar
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003278 * unconditionally; otherwise, only display the position when the
3279 * character values have changed. */
Chris Allegrettad26ab912003-01-28 01:16:47 +00003280 if (!constant || old_i != i || old_totsize != totsize) {
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003281 size_t xpt = xplustabs() + 1;
3282 size_t cur_len = strlenpt(current->data) + 1;
Chris Allegrettad26ab912003-01-28 01:16:47 +00003283 int linepct = 100 * current->lineno / totlines;
3284 int colpct = 100 * xpt / cur_len;
3285 int bytepct = totsize == 0 ? 0 : 100 * i / totsize;
3286
3287 statusbar(
3288 _("line %ld/%ld (%d%%), col %lu/%lu (%d%%), char %lu/%ld (%d%%)"),
3289 current->lineno, totlines, linepct,
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003290 (unsigned long)xpt, (unsigned long)cur_len, colpct,
David Lawrence Ramsey7a97e182004-10-30 01:03:15 +00003291 (unsigned long)i, totsize, bytepct);
Chris Allegrettad26ab912003-01-28 01:16:47 +00003292 UNSET(DISABLE_CURPOS);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003293 }
3294
3295 old_i = i;
3296 old_totsize = totsize;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003297}
3298
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003299void do_cursorpos_void(void)
Chris Allegretta2084acc2001-11-29 03:43:08 +00003300{
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003301 do_cursorpos(FALSE);
Chris Allegretta2084acc2001-11-29 03:43:08 +00003302}
3303
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003304#ifndef DISABLE_HELP
Chris Allegretta4640fe32003-02-10 03:10:03 +00003305/* Calculate the next line of help_text, starting at ptr. */
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003306int help_line_len(const char *ptr)
Chris Allegretta4640fe32003-02-10 03:10:03 +00003307{
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003308 int j = 0;
Chris Allegretta4640fe32003-02-10 03:10:03 +00003309
3310 while (*ptr != '\n' && *ptr != '\0' && j < COLS - 5) {
3311 ptr++;
3312 j++;
3313 }
3314 if (j == COLS - 5) {
3315 /* Don't wrap at the first of two spaces following a period. */
3316 if (*ptr == ' ' && *(ptr + 1) == ' ')
3317 j++;
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003318 /* Don't print half a word if we've run out of space. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003319 while (*ptr != ' ' && j > 0) {
3320 ptr--;
3321 j--;
3322 }
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003323 /* Word longer than COLS - 5 chars just gets broken. */
Chris Allegretta4640fe32003-02-10 03:10:03 +00003324 if (j == 0)
3325 j = COLS - 5;
3326 }
3327 assert(j >= 0 && j <= COLS - 4 && (j > 0 || *ptr == '\n'));
3328 return j;
3329}
3330
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003331/* Our dynamic, shortcut-list-compliant help function. */
David Lawrence Ramsey72e51ab2004-07-02 14:31:03 +00003332void do_help(void)
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003333{
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003334 int line = 0;
3335 /* The line number in help_text of the first displayed help line.
3336 * This variable is zero-based. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003337 bool no_more = FALSE;
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003338 /* no_more means the end of the help text is shown, so don't go
3339 * down any more. */
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003340 int kbinput = ERR;
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003341 bool meta_key, func_key;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003342
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003343 bool old_no_help = ISSET(NO_HELP);
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003344#ifndef DISABLE_MOUSE
3345 const shortcut *oldshortcut = currshortcut;
3346 /* We will set currshortcut to allow clicking on the help
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003347 * screen's shortcut list. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003348#endif
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003349
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003350 curs_set(0);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003351 blank_edit();
Chris Allegrettab3655b42001-10-22 03:15:31 +00003352 wattroff(bottomwin, A_REVERSE);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003353 blank_statusbar();
3354
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003355 /* Set help_text as the string to display. */
Chris Allegrettab3655b42001-10-22 03:15:31 +00003356 help_init();
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003357 assert(help_text != NULL);
Chris Allegrettab3655b42001-10-22 03:15:31 +00003358
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003359#ifndef DISABLE_MOUSE
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003360 /* Set currshortcut to allow clicking on the help screen's shortcut
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003361 * list, AFTER help_init(). */
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003362 currshortcut = help_list;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003363#endif
Chris Allegretta6fe61492001-05-21 12:56:25 +00003364
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003365 if (ISSET(NO_HELP)) {
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003366 /* Make sure that the help screen's shortcut list will actually
3367 * be displayed. */
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003368 UNSET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003369 window_init();
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003370 }
3371 bottombars(help_list);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003372
3373 do {
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003374 int i;
3375 int old_line = line;
3376 /* We redisplay the help only if it moved. */
Chris Allegrettaf717f982003-02-13 22:25:01 +00003377 const char *ptr = help_text;
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003378
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003379 switch (kbinput) {
David Lawrence Ramseyf5b256b2003-10-03 20:26:25 +00003380#ifndef DISABLE_MOUSE
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003381 case KEY_MOUSE:
David Lawrence Ramseya0b5ba22004-08-25 15:39:10 +00003382 {
3383 int mouse_x, mouse_y;
3384 get_mouseinput(&mouse_x, &mouse_y, TRUE);
3385 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003386 break;
Chris Allegretta6b58acd2001-04-12 03:01:53 +00003387#endif
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003388 case NANO_NEXTPAGE_KEY:
3389 case NANO_NEXTPAGE_FKEY:
3390 if (!no_more)
3391 line += editwinrows - 2;
3392 break;
3393 case NANO_PREVPAGE_KEY:
3394 case NANO_PREVPAGE_FKEY:
3395 if (line > 0) {
3396 line -= editwinrows - 2;
3397 if (line < 0)
3398 line = 0;
3399 }
3400 break;
3401 case NANO_PREVLINE_KEY:
3402 if (line > 0)
3403 line--;
3404 break;
3405 case NANO_NEXTLINE_KEY:
3406 if (!no_more)
3407 line++;
3408 break;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003409 }
3410
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003411 if (line == old_line && kbinput != ERR)
3412 goto skip_redisplay;
3413
3414 blank_edit();
3415
3416 assert(COLS > 5);
3417
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003418 /* Calculate where in the text we should be, based on the
3419 * page. */
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003420 for (i = 0; i < line; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003421 ptr += help_line_len(ptr);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003422 if (*ptr == '\n')
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003423 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003424 }
3425
Chris Allegretta4640fe32003-02-10 03:10:03 +00003426 for (i = 0; i < editwinrows && *ptr != '\0'; i++) {
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003427 int j = help_line_len(ptr);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003428
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003429 mvwaddnstr(edit, i, 0, ptr, j);
Chris Allegretta4640fe32003-02-10 03:10:03 +00003430 ptr += j;
3431 if (*ptr == '\n')
3432 ptr++;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003433 }
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003434 no_more = (*ptr == '\0');
Chris Allegretta4640fe32003-02-10 03:10:03 +00003435
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003436 skip_redisplay:
David Lawrence Ramseyeb16f432004-09-27 01:04:50 +00003437 kbinput = get_kbinput(edit, &meta_key, &func_key);
David Lawrence Ramsey8037fe02004-07-23 12:30:40 +00003438 } while (kbinput != NANO_CANCEL_KEY && kbinput != NANO_EXIT_KEY &&
3439 kbinput != NANO_EXIT_FKEY);
Chris Allegrettad1627cf2000-12-18 05:03:16 +00003440
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003441#ifndef DISABLE_MOUSE
Chris Allegrettab3655b42001-10-22 03:15:31 +00003442 currshortcut = oldshortcut;
David Lawrence Ramseybe265612004-05-29 20:38:08 +00003443#endif
Chris Allegrettab3655b42001-10-22 03:15:31 +00003444
David Lawrence Ramseye7638ea2004-06-01 19:49:38 +00003445 if (old_no_help) {
Chris Allegretta70444892001-01-07 23:02:02 +00003446 blank_bottombars();
Chris Allegretta4da1fc62000-06-21 03:00:43 +00003447 wrefresh(bottomwin);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003448 SET(NO_HELP);
Chris Allegretta70444892001-01-07 23:02:02 +00003449 window_init();
Chris Allegretta598106e2002-01-19 01:59:37 +00003450 } else
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003451 bottombars(currshortcut);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003452
David Lawrence Ramseyae064bf2004-06-01 20:38:00 +00003453 curs_set(1);
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003454 edit_refresh();
Chris Allegrettac08f50d2001-01-06 18:12:43 +00003455
David Lawrence Ramsey52453442004-06-26 15:24:16 +00003456 /* The help_init() at the beginning allocated help_text. Since
3457 * help_text has now been written to the screen, we don't need it
3458 * anymore. */
David Lawrence Ramseyc5967552002-06-21 03:20:06 +00003459 free(help_text);
3460 help_text = NULL;
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003461}
David Lawrence Ramseyd893fa92004-04-30 04:49:02 +00003462#endif /* !DISABLE_HELP */
Chris Allegrettaa2ea1932000-06-06 05:53:49 +00003463
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003464/* Highlight the current word being replaced or spell checked. We
3465 * expect word to have tabs and control characters expanded. */
Chris Allegretta6df90f52002-07-19 01:08:59 +00003466void do_replace_highlight(int highlight_flag, const char *word)
Chris Allegrettafb62f732000-12-05 11:36:41 +00003467{
David Lawrence Ramsey86e851b2004-07-28 20:46:25 +00003468 size_t y = xplustabs();
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003469 size_t word_len = strlen(word);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003470
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003471 y = get_page_start(y) + COLS - y;
3472 /* Now y is the number of characters we can display on this
3473 * line. */
Chris Allegrettafb62f732000-12-05 11:36:41 +00003474
3475 reset_cursor();
Chris Allegretta598106e2002-01-19 01:59:37 +00003476
Chris Allegrettafb62f732000-12-05 11:36:41 +00003477 if (highlight_flag)
3478 wattron(edit, A_REVERSE);
3479
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003480#ifdef HAVE_REGEX_H
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003481 /* This is so we can show zero-length regexes. */
3482 if (word_len == 0)
3483 waddstr(edit, " ");
3484 else
David Lawrence Ramsey2a4ab6d2003-12-24 08:29:49 +00003485#endif
David Lawrence Ramsey76c4b332003-12-24 08:17:54 +00003486 waddnstr(edit, word, y - 1);
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003487
3488 if (word_len > y)
3489 waddch(edit, '$');
3490 else if (word_len == y)
3491 waddch(edit, word[word_len - 1]);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003492
3493 if (highlight_flag)
3494 wattroff(edit, A_REVERSE);
Chris Allegrettafb62f732000-12-05 11:36:41 +00003495}
3496
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003497#ifdef DEBUG
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003498/* Dump the passed-in file structure to stderr. */
3499void dump_buffer(const filestruct *inptr)
3500{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003501 if (inptr == fileage)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003502 fprintf(stderr, "Dumping file buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003503 else if (inptr == cutbuffer)
Jordi Mallachf9390af2003-08-05 19:31:12 +00003504 fprintf(stderr, "Dumping cutbuffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003505 else
Jordi Mallachf9390af2003-08-05 19:31:12 +00003506 fprintf(stderr, "Dumping a buffer to stderr...\n");
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003507
3508 while (inptr != NULL) {
3509 fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
3510 inptr = inptr->next;
3511 }
3512}
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003513
David Lawrence Ramsey5ffbec52003-09-16 01:16:49 +00003514/* Dump the file structure to stderr in reverse. */
David Lawrence Ramseyaaad3af2003-08-31 16:44:10 +00003515void dump_buffer_reverse(void)
3516{
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003517 const filestruct *fileptr = filebot;
3518
3519 while (fileptr != NULL) {
David Lawrence Ramsey24f10c32004-07-17 20:01:45 +00003520 fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
David Lawrence Ramseyad40fdb2002-09-06 20:35:28 +00003521 fileptr = fileptr->prev;
3522 }
3523}
3524#endif /* DEBUG */
3525
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003526#ifdef NANO_EXTRA
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003527#define CREDIT_LEN 53
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003528#define XLCREDIT_LEN 8
3529
David Lawrence Ramseyfdece462004-01-19 18:15:03 +00003530/* Easter egg: Display credits. Assume nodelay(edit) is FALSE. */
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003531void do_credits(void)
3532{
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003533 int crpos = 0, xlpos = 0;
3534 const char *credits[CREDIT_LEN] = {
3535 NULL, /* "The nano text editor" */
3536 NULL, /* "version" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003537 VERSION,
3538 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003539 NULL, /* "Brought to you by:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003540 "Chris Allegretta",
3541 "Jordi Mallach",
3542 "Adam Rogoyski",
3543 "Rob Siemborski",
3544 "Rocco Corsi",
Chris Allegrettaa8c22572002-02-15 19:17:02 +00003545 "David Lawrence Ramsey",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003546 "David Benbennick",
Chris Allegretta598106e2002-01-19 01:59:37 +00003547 "Ken Tyler",
3548 "Sven Guckes",
3549 "Florian König",
3550 "Pauli Virtanen",
3551 "Daniele Medri",
3552 "Clement Laforet",
3553 "Tedi Heriyanto",
3554 "Bill Soudan",
3555 "Christian Weisgerber",
3556 "Erik Andersen",
3557 "Big Gaute",
3558 "Joshua Jensen",
3559 "Ryan Krebs",
3560 "Albert Chin",
Chris Allegretta598106e2002-01-19 01:59:37 +00003561 "",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003562 NULL, /* "Special thanks to:" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003563 "Plattsburgh State University",
3564 "Benet Laboratories",
3565 "Amy Allegretta",
3566 "Linda Young",
3567 "Jeremy Robichaud",
3568 "Richard Kolb II",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003569 NULL, /* "The Free Software Foundation" */
Chris Allegretta598106e2002-01-19 01:59:37 +00003570 "Linus Torvalds",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003571 NULL, /* "For ncurses:" */
Chris Allegrettadce44ab2002-03-16 01:03:41 +00003572 "Thomas Dickey",
3573 "Pavel Curtis",
3574 "Zeyd Ben-Halim",
3575 "Eric S. Raymond",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003576 NULL, /* "and anyone else we forgot..." */
3577 NULL, /* "Thank you for using nano!" */
3578 "",
3579 "",
3580 "",
3581 "",
David Lawrence Ramsey6481c3f2004-01-09 23:06:54 +00003582 "(c) 1999-2004 Chris Allegretta",
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003583 "",
3584 "",
3585 "",
3586 "",
David Lawrence Ramsey0084eaa2002-11-04 16:05:42 +00003587 "http://www.nano-editor.org/"
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003588 };
3589
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003590 const char *xlcredits[XLCREDIT_LEN] = {
David Lawrence Ramsey576bf332004-07-12 03:10:30 +00003591 N_("The nano text editor"),
3592 N_("version"),
3593 N_("Brought to you by:"),
3594 N_("Special thanks to:"),
3595 N_("The Free Software Foundation"),
3596 N_("For ncurses:"),
3597 N_("and anyone else we forgot..."),
3598 N_("Thank you for using nano!")
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003599 };
Chris Allegrettac4e3d9e2002-07-21 15:44:13 +00003600
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003601 curs_set(0);
3602 nodelay(edit, TRUE);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003603 scrollok(edit, TRUE);
3604 blank_titlebar();
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003605 blank_edit();
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003606 blank_statusbar();
3607 blank_bottombars();
3608 wrefresh(topwin);
Chris Allegretta8b4ca4a2000-11-25 18:21:37 +00003609 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003610 wrefresh(bottomwin);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003611
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003612 for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
3613 if (wgetch(edit) != ERR)
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003614 break;
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003615 if (crpos < CREDIT_LEN) {
3616 const char *what = credits[crpos];
3617 size_t start_x;
3618
3619 if (what == NULL) {
3620 assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
David Lawrence Ramsey837a02b2004-05-18 15:23:31 +00003621 what = _(xlcredits[xlpos]);
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003622 xlpos++;
3623 }
3624 start_x = COLS / 2 - strlen(what) / 2 - 1;
3625 mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
3626 }
3627 napms(700);
3628 scroll(edit);
3629 wrefresh(edit);
3630 if (wgetch(edit) != ERR)
3631 break;
3632 napms(700);
3633 scroll(edit);
3634 wrefresh(edit);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003635 }
3636
David Lawrence Ramseyd7fd2002004-05-18 01:20:36 +00003637 scrollok(edit, FALSE);
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003638 nodelay(edit, FALSE);
3639 curs_set(1);
3640 display_main_list();
3641 total_refresh();
Chris Allegretta598106e2002-01-19 01:59:37 +00003642}
Chris Allegretta8a0de3b2000-11-24 20:45:14 +00003643#endif